- 统一 ItemDescForm/RewardItem/GoodsItem 的描述格式
- 减少组件属性的 Clone 数量,目前只在合并仓库、组装防御塔时才进行复制
- 删除先前留下的冗余 fallback 代码
This commit is contained in:
SepComet 2026-03-12 15:58:14 +08:00
parent 9e59865368
commit 4962b98714
20 changed files with 263 additions and 435 deletions

View File

@ -106,9 +106,8 @@ namespace GeometryTD.CustomComponent
} }
List<RewardSelectItemRawData> rewardPool = new List<RewardSelectItemRawData>(candidateItems.Count); List<RewardSelectItemRawData> rewardPool = new List<RewardSelectItemRawData>(candidateItems.Count);
for (int i = 0; i < candidateItems.Count; i++) foreach (var item in candidateItems)
{ {
TowerCompItemData item = candidateItems[i];
if (item == null) if (item == null)
{ {
continue; continue;
@ -295,55 +294,7 @@ namespace GeometryTD.CustomComponent
private static RewardSelectItemRawData BuildRewardSelectRawData(TowerCompItemData item) private static RewardSelectItemRawData BuildRewardSelectRawData(TowerCompItemData item)
{ {
return new RewardSelectItemRawData return RewardSelectItemRawDataBuilder.Build(item);
{
RewardId = item.InstanceId,
SlotType = item.SlotType,
Title = item.Name,
TypeText = BuildRewardTypeText(item.SlotType),
Description = BuildRewardDescription(item),
Rarity = item.Rarity,
Tags = item.Tags != null ? (TagType[])item.Tags.Clone() : Array.Empty<TagType>(),
Icon = null,
IsSelectable = true,
SourceItem = item
};
}
private static string BuildRewardTypeText(TowerCompSlotType slotType)
{
return slotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static string BuildRewardDescription(TowerCompItemData item)
{
if (item is MuzzleCompItemData muzzle)
{
int damage = muzzle.AttackDamage != null && muzzle.AttackDamage.Length > 0 ? muzzle.AttackDamage[0] : 0;
return $"Damage: {damage}, Spread: {muzzle.DamageRandomRate:P0}";
}
if (item is BearingCompItemData bearing)
{
float range = bearing.AttackRange != null && bearing.AttackRange.Length > 0 ? bearing.AttackRange[0] : 0f;
float rotateSpeed = bearing.RotateSpeed != null && bearing.RotateSpeed.Length > 0 ? bearing.RotateSpeed[0] : 0f;
return $"Range: {range:0.##}, Rotate Speed: {rotateSpeed:0.##}";
}
if (item is BaseCompItemData baseComp)
{
float attackSpeed = baseComp.AttackSpeed != null && baseComp.AttackSpeed.Length > 0 ? baseComp.AttackSpeed[0] : 0f;
return $"Attack Speed: {attackSpeed:0.##}, Property: {baseComp.AttackPropertyType}";
}
return string.Empty;
} }
} }
} }

View File

@ -284,21 +284,11 @@ namespace GeometryTD.UI
Title = string.IsNullOrWhiteSpace(title) ? $"Item {itemId}" : title, Title = string.IsNullOrWhiteSpace(title) ? $"Item {itemId}" : title,
TypeText = typeText ?? string.Empty, TypeText = typeText ?? string.Empty,
Description = description ?? string.Empty, Description = description ?? string.Empty,
Tags = CloneTags(tags), Tags = tags,
TagRuntimes = CloneTagRuntimes(tagRuntimes) TagRuntimes = tagRuntimes
}; };
} }
private static TagType[] CloneTags(TagType[] tags)
{
return tags != null ? (TagType[])tags.Clone() : System.Array.Empty<TagType>();
}
private static TagRuntimeData[] CloneTagRuntimes(TagRuntimeData[] tagRuntimes)
{
return InventoryCloneUtility.CloneTagRuntimes(tagRuntimes);
}
private static string BuildComponentTypeText(TowerCompSlotType slotType) private static string BuildComponentTypeText(TowerCompSlotType slotType)
{ {
return slotType switch return slotType switch
@ -391,8 +381,8 @@ namespace GeometryTD.UI
Description = seed.Description ?? string.Empty, Description = seed.Description ?? string.Empty,
Price = 0, Price = 0,
ScreenPosition = args.ScreenPosition, ScreenPosition = args.ScreenPosition,
Tags = CloneTags(seed.Tags), Tags = seed.Tags,
TagRuntimes = CloneTagRuntimes(seed.TagRuntimes) TagRuntimes = seed.TagRuntimes
}); });
} }

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 4e2db7f572fa423f8eb29a8c796b952d
timeCreated: 1773300865

View File

@ -28,7 +28,7 @@ namespace GeometryTD.UI
if (rawData.Inventory.Towers != null) if (rawData.Inventory.Towers != null)
{ {
foreach (TowerItemData tower in rawData.Inventory.Towers) foreach (var tower in rawData.Inventory.Towers)
{ {
if (tower == null) if (tower == null)
{ {
@ -50,7 +50,7 @@ namespace GeometryTD.UI
if (rawData.Inventory.MuzzleComponents != null) if (rawData.Inventory.MuzzleComponents != null)
{ {
foreach (MuzzleCompItemData item in rawData.Inventory.MuzzleComponents) foreach (var item in rawData.Inventory.MuzzleComponents)
{ {
if (item == null || item.IsAssembledIntoTower) if (item == null || item.IsAssembledIntoTower)
{ {
@ -191,8 +191,8 @@ namespace GeometryTD.UI
Title = string.IsNullOrWhiteSpace(title) ? $"Item {itemId}" : title, Title = string.IsNullOrWhiteSpace(title) ? $"Item {itemId}" : title,
TypeText = typeText ?? string.Empty, TypeText = typeText ?? string.Empty,
Description = description ?? string.Empty, Description = description ?? string.Empty,
Tags = CloneTags(tags), Tags = tags,
TagRuntimes = CloneTagRuntimes(tagRuntimes) TagRuntimes = tagRuntimes
}; };
} }
@ -217,9 +217,8 @@ namespace GeometryTD.UI
return map; return map;
} }
for (int i = 0; i < items.Count; i++) foreach (var item in items)
{ {
TComp item = items[i];
if (item == null || item.InstanceId <= 0) if (item == null || item.InstanceId <= 0)
{ {
continue; continue;
@ -239,9 +238,8 @@ namespace GeometryTD.UI
return map; return map;
} }
for (int i = 0; i < towers.Count; i++) foreach (var tower in towers)
{ {
TowerItemData tower = towers[i];
if (tower == null || tower.InstanceId <= 0) if (tower == null || tower.InstanceId <= 0)
{ {
continue; continue;
@ -264,9 +262,8 @@ namespace GeometryTD.UI
List<TowerRepoItemContext> participantItems = new List<TowerRepoItemContext>(); List<TowerRepoItemContext> participantItems = new List<TowerRepoItemContext>();
if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null) if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null)
{ {
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count; i++) foreach (var towerId in inventory.ParticipantTowerInstanceIds)
{ {
long towerId = inventory.ParticipantTowerInstanceIds[i];
if (towerId <= 0) if (towerId <= 0)
{ {
continue; continue;

View File

@ -0,0 +1,142 @@
using System;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.UI
{
public partial class RewardSelectFormController
{
private static RewardSelectFormContext BuildContext(RewardSelectFormRawData rawData)
{
if (rawData == null)
{
return null;
}
return new RewardSelectFormContext
{
TipText = string.IsNullOrWhiteSpace(rawData.TipText) ? "Select one reward" : rawData.TipText,
RefreshButtonText = BuildRefreshButtonText(rawData.RefreshCost, rawData.CanRefresh),
CanRefresh = rawData.CanRefresh,
CanGiveUp = rawData.CanGiveUp,
RewardItems = BuildRewardItemContexts(rawData.RewardItems)
};
}
private static string BuildRefreshButtonText(int refreshCost, bool canRefresh)
{
if (!canRefresh)
{
return "Refreshed";
}
if (refreshCost <= 0)
{
return "Refresh";
}
return $"Refresh -{refreshCost}";
}
private static RewardItemContext[] BuildRewardItemContexts(RewardSelectItemRawData[] rawItems)
{
if (rawItems == null || rawItems.Length <= 0)
{
return Array.Empty<RewardItemContext>();
}
RewardItemContext[] contexts = new RewardItemContext[rawItems.Length];
for (int i = 0; i < rawItems.Length; i++)
{
RewardSelectItemRawData rawItem = rawItems[i];
if (rawItem == null)
{
continue;
}
contexts[i] = new RewardItemContext
{
Index = i,
IconArea = new IconAreaContext
{
ComponentSlotType = rawItem.SlotType,
Icon = rawItem.Icon,
Rarity = rawItem.Rarity,
Color = ResolveIconColor(rawItem.SourceItem)
},
Title = rawItem.Title ?? string.Empty,
TypeText = ResolveTypeText(rawItem.TypeText, rawItem.SlotType),
Description = BuildDescription(rawItem),
Tags = BuildTagContexts(rawItem),
};
}
return contexts;
}
private static string BuildDescription(RewardSelectItemRawData rawItem)
{
string baseDescription = rawItem.Description;
string tagDescription = TagDisplayUtility.BuildTagDescriptionText(rawItem.Tags);
if (string.IsNullOrWhiteSpace(tagDescription))
{
return baseDescription;
}
if (string.IsNullOrWhiteSpace(baseDescription))
{
return tagDescription;
}
return $"{baseDescription}\n{tagDescription}";
}
private static Color ResolveIconColor(TowerCompItemData sourceItem)
{
if (sourceItem == null)
{
return Color.white;
}
return IconColorGenerator.GenerateForComponent(sourceItem);
}
private static string ResolveTypeText(string typeText, TowerCompSlotType slotType)
{
if (!string.IsNullOrWhiteSpace(typeText))
{
return typeText;
}
return slotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static TagItemContext[] BuildTagContexts(RewardSelectItemRawData rawItem)
{
string[] tagTexts = TagDisplayUtility.BuildTagTexts(rawItem?.Tags);
if (tagTexts == null || tagTexts.Length <= 0)
{
return Array.Empty<TagItemContext>();
}
TagItemContext[] contexts = new TagItemContext[tagTexts.Length];
for (int i = 0; i < tagTexts.Length; i++)
{
contexts[i] = new TagItemContext
{
TagName = tagTexts[i] ?? string.Empty
};
}
return contexts;
}
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 869dc47fc2a44b53bf56890fdd65af81
timeCreated: 1773300896

View File

@ -153,21 +153,11 @@ namespace GeometryTD.UI
Description = seed.Description ?? string.Empty, Description = seed.Description ?? string.Empty,
Price = 0, Price = 0,
ScreenPosition = args.ScreenPosition, ScreenPosition = args.ScreenPosition,
Tags = CloneTags(seed.Tags), Tags = seed.Tags,
TagRuntimes = CloneTagRuntimes(seed.TagRuntimes) TagRuntimes = seed.TagRuntimes
}); });
} }
private static TagType[] CloneTags(TagType[] tags)
{
return tags != null ? (TagType[])tags.Clone() : System.Array.Empty<TagType>();
}
private static TagRuntimeData[] CloneTagRuntimes(TagRuntimeData[] tagRuntimes)
{
return InventoryCloneUtility.CloneTagRuntimes(tagRuntimes);
}
private void OnRepoItemDragEnded(object sender, GameEventArgs e) private void OnRepoItemDragEnded(object sender, GameEventArgs e)
{ {
if (!IsEventFromCurrentForm(sender)) if (!IsEventFromCurrentForm(sender))
@ -320,9 +310,5 @@ namespace GeometryTD.UI
} }
#endregion #endregion
private static string[] CloneTagTexts(string[] tagTexts)
{
return tagTexts != null ? (string[])tagTexts.Clone() : System.Array.Empty<string>();
}
} }
} }

View File

@ -3,13 +3,10 @@ namespace GeometryTD.UI
public class RewardItemContext : UIContext public class RewardItemContext : UIContext
{ {
public int Index; public int Index;
public long RewardId;
public IconAreaContext IconArea; public IconAreaContext IconArea;
public string Title; public string Title;
public string TypeText; public string TypeText;
public string Description; public string Description;
public TagItemContext[] Tags; public TagItemContext[] Tags;
public bool IsSelectable;
public object UserData;
} }
} }

View File

@ -1,15 +1,12 @@
using System;
using GeometryTD.CustomEvent; using GeometryTD.CustomEvent;
using GeometryTD.DataTable;
using GeometryTD.Definition; using GeometryTD.Definition;
using GameFramework.Event; using GameFramework.Event;
using GeometryTD.CustomUtility;
using UnityEngine; using UnityEngine;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
namespace GeometryTD.UI namespace GeometryTD.UI
{ {
public class RewardSelectFormController : UIFormControllerCommonBase<RewardSelectFormContext, RewardSelectForm> public partial class RewardSelectFormController : UIFormControllerCommonBase<RewardSelectFormContext, RewardSelectForm>
{ {
private RewardSelectFormUseCase _useCase; private RewardSelectFormUseCase _useCase;
@ -79,124 +76,6 @@ namespace GeometryTD.UI
_useCase = rewardSelectUseCase; _useCase = rewardSelectUseCase;
} }
private static RewardSelectFormContext BuildContext(RewardSelectFormRawData rawData)
{
if (rawData == null)
{
return null;
}
return new RewardSelectFormContext
{
TipText = string.IsNullOrWhiteSpace(rawData.TipText) ? "Select one reward" : rawData.TipText,
RefreshButtonText = BuildRefreshButtonText(rawData.RefreshCost, rawData.CanRefresh),
CanRefresh = rawData.CanRefresh,
CanGiveUp = rawData.CanGiveUp,
RewardItems = BuildRewardItemContexts(rawData.RewardItems)
};
}
private static string BuildRefreshButtonText(int refreshCost, bool canRefresh)
{
if (!canRefresh)
{
return "Refreshed";
}
if (refreshCost <= 0)
{
return "Refresh";
}
return $"Refresh -{refreshCost}";
}
private static RewardItemContext[] BuildRewardItemContexts(RewardSelectItemRawData[] rawItems)
{
if (rawItems == null || rawItems.Length <= 0)
{
return System.Array.Empty<RewardItemContext>();
}
RewardItemContext[] contexts = new RewardItemContext[rawItems.Length];
for (int i = 0; i < rawItems.Length; i++)
{
RewardSelectItemRawData rawItem = rawItems[i];
if (rawItem == null)
{
continue;
}
contexts[i] = new RewardItemContext
{
Index = i,
RewardId = rawItem.RewardId,
IconArea = new IconAreaContext
{
ComponentSlotType = rawItem.SlotType,
Icon = rawItem.Icon,
Rarity = rawItem.Rarity,
Color = ResolveIconColor(rawItem)
},
Title = rawItem.Title ?? string.Empty,
TypeText = ResolveTypeText(rawItem),
Description = rawItem.Description ?? string.Empty,
Tags = BuildTagContexts(rawItem.Tags),
IsSelectable = rawItem.IsSelectable,
UserData = rawItem.UserData
};
}
return contexts;
}
private static Color ResolveIconColor(RewardSelectItemRawData rawItem)
{
if (rawItem?.SourceItem == null)
{
return Color.white;
}
return IconColorGenerator.GenerateForComponent(rawItem.SourceItem);
}
private static string ResolveTypeText(RewardSelectItemRawData rawItem)
{
if (!string.IsNullOrWhiteSpace(rawItem.TypeText))
{
return rawItem.TypeText;
}
return rawItem.SlotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static TagItemContext[] BuildTagContexts(TagType[] tags)
{
string[] tagTexts = TagDisplayUtility.BuildTagTexts(tags);
if (tagTexts == null || tagTexts.Length <= 0)
{
return System.Array.Empty<TagItemContext>();
}
TagItemContext[] contexts = new TagItemContext[tagTexts.Length];
for (int i = 0; i < tagTexts.Length; i++)
{
contexts[i] = new TagItemContext
{
TagName = tagTexts[i]
};
}
return contexts;
}
private void OnRewardSelected(object sender, GameEventArgs e) private void OnRewardSelected(object sender, GameEventArgs e)
{ {
if (!IsEventFromCurrentForm(sender) || !(e is RewardSelectItemSelectedEventArgs args)) if (!IsEventFromCurrentForm(sender) || !(e is RewardSelectItemSelectedEventArgs args))
@ -280,4 +159,4 @@ namespace GeometryTD.UI
return false; return false;
} }
} }
} }

View File

@ -5,7 +5,6 @@ namespace GeometryTD.UI
{ {
public class RewardSelectItemRawData public class RewardSelectItemRawData
{ {
public long RewardId;
public TowerCompSlotType SlotType; public TowerCompSlotType SlotType;
public string Title; public string Title;
public string TypeText; public string TypeText;
@ -13,8 +12,6 @@ namespace GeometryTD.UI
public RarityType Rarity; public RarityType Rarity;
public TagType[] Tags; public TagType[] Tags;
public Sprite Icon; public Sprite Icon;
public bool IsSelectable = true;
public TowerCompItemData SourceItem; public TowerCompItemData SourceItem;
public object UserData;
} }
} }

View File

@ -0,0 +1,56 @@
using System;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
namespace GeometryTD.UI
{
public static class RewardSelectItemRawDataBuilder
{
public static RewardSelectItemRawData Build(TowerCompItemData item)
{
return new RewardSelectItemRawData
{
SlotType = item.SlotType,
Title = item.Name,
TypeText = BuildTypeText(item.SlotType),
Description = BuildDescription(item),
Rarity = item.Rarity,
Tags = item.Tags != null ? (TagType[])item.Tags.Clone() : Array.Empty<TagType>(),
Icon = null,
SourceItem = item
};
}
private static string BuildTypeText(TowerCompSlotType slotType)
{
return slotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static string BuildDescription(TowerCompItemData item)
{
if (item is MuzzleCompItemData muzzle)
{
return ItemDescUtility.BuildMuzzleDesc(muzzle);
}
if (item is BearingCompItemData bearing)
{
return ItemDescUtility.BuildBearingDesc(bearing);
}
if (item is BaseCompItemData baseComp)
{
return ItemDescUtility.BuildBaseDesc(baseComp);
}
return string.Empty;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 51c6fdd5a34ab044d96fd416188e7a9f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,7 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
using UnityEngine; using UnityEngine;
using Random = UnityEngine.Random; using Random = UnityEngine.Random;
@ -22,11 +20,6 @@ namespace GeometryTD.UI
private bool _hasRefreshed; private bool _hasRefreshed;
private string _tipText = "Select one reward"; private string _tipText = "Select one reward";
public RewardSelectFormUseCase()
{
ConfigureRewardPool(BuildDefaultRewardPool());
}
public void ConfigureRewardPool( public void ConfigureRewardPool(
IReadOnlyList<RewardSelectItemRawData> rewardPool, IReadOnlyList<RewardSelectItemRawData> rewardPool,
int displayCount = 3, int displayCount = 3,
@ -38,15 +31,14 @@ namespace GeometryTD.UI
_rewardPool.Clear(); _rewardPool.Clear();
if (rewardPool != null) if (rewardPool != null)
{ {
for (int i = 0; i < rewardPool.Count; i++) foreach (var item in rewardPool)
{ {
RewardSelectItemRawData item = rewardPool[i];
if (item == null) if (item == null)
{ {
continue; continue;
} }
_rewardPool.Add(CloneRawItem(item)); _rewardPool.Add(item);
} }
} }
@ -164,7 +156,7 @@ namespace GeometryTD.UI
for (int i = 0; i < finalCount; i++) for (int i = 0; i < finalCount; i++)
{ {
RewardSelectItemRawData source = _rewardPool[indexes[i]]; RewardSelectItemRawData source = _rewardPool[indexes[i]];
results[i] = CloneRawItem(source); results[i] = source;
} }
return results; return results;
@ -209,131 +201,5 @@ namespace GeometryTD.UI
return GameEntry.PlayerInventory.TryConsumeGold(_refreshCost); return GameEntry.PlayerInventory.TryConsumeGold(_refreshCost);
} }
private static List<RewardSelectItemRawData> BuildDefaultRewardPool()
{
BackpackInventoryData inventory = InventorySeedUtility.CreateSampleInventory();
List<RewardSelectItemRawData> rewards = new List<RewardSelectItemRawData>();
if (inventory?.MuzzleComponents != null)
{
for (int i = 0; i < inventory.MuzzleComponents.Count; i++)
{
MuzzleCompItemData item = inventory.MuzzleComponents[i];
if (item == null)
{
continue;
}
rewards.Add(BuildRawItem(item));
}
}
if (inventory?.BearingComponents != null)
{
for (int i = 0; i < inventory.BearingComponents.Count; i++)
{
BearingCompItemData item = inventory.BearingComponents[i];
if (item == null)
{
continue;
}
rewards.Add(BuildRawItem(item));
}
}
if (inventory?.BaseComponents != null)
{
for (int i = 0; i < inventory.BaseComponents.Count; i++)
{
BaseCompItemData item = inventory.BaseComponents[i];
if (item == null)
{
continue;
}
rewards.Add(BuildRawItem(item));
}
}
return rewards;
}
private static RewardSelectItemRawData BuildRawItem(TowerCompItemData item)
{
return new RewardSelectItemRawData
{
RewardId = item.InstanceId,
SlotType = item.SlotType,
Title = item.Name,
TypeText = BuildTypeText(item.SlotType),
Description = BuildDescription(item),
Rarity = item.Rarity,
Tags = item.Tags != null ? (TagType[])item.Tags.Clone() : Array.Empty<TagType>(),
Icon = null,
IsSelectable = true,
SourceItem = item
};
}
private static RewardSelectItemRawData CloneRawItem(RewardSelectItemRawData source)
{
if (source == null)
{
return null;
}
return new RewardSelectItemRawData
{
RewardId = source.RewardId,
SlotType = source.SlotType,
Title = source.Title,
TypeText = source.TypeText,
Description = source.Description,
Rarity = source.Rarity,
Tags = source.Tags != null ? (TagType[])source.Tags.Clone() : Array.Empty<TagType>(),
Icon = source.Icon,
IsSelectable = source.IsSelectable,
SourceItem = source.SourceItem,
UserData = source.UserData
};
}
private static string BuildTypeText(TowerCompSlotType slotType)
{
return slotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static string BuildDescription(TowerCompItemData item)
{
if (item is MuzzleCompItemData muzzle)
{
int damage = muzzle.AttackDamage != null && muzzle.AttackDamage.Length > 0 ? muzzle.AttackDamage[0] : 0;
return $"Damage: {damage}, Spread: {muzzle.DamageRandomRate:P0}";
}
if (item is BearingCompItemData bearing)
{
float range = bearing.AttackRange != null && bearing.AttackRange.Length > 0 ? bearing.AttackRange[0] : 0f;
float rotateSpeed = bearing.RotateSpeed != null && bearing.RotateSpeed.Length > 0 ? bearing.RotateSpeed[0] : 0f;
return $"Range: {range:0.##}, Rotate Speed: {rotateSpeed:0.##}";
}
if (item is BaseCompItemData baseComp)
{
float attackSpeed = baseComp.AttackSpeed != null && baseComp.AttackSpeed.Length > 0 ? baseComp.AttackSpeed[0] : 0f;
return $"Attack Speed: {attackSpeed:0.##}, Property: {baseComp.AttackPropertyType}";
}
return string.Empty;
}
} }
} }

View File

@ -39,13 +39,7 @@ namespace GeometryTD.UI
[SerializeField] private float _sideGap = 16f; [SerializeField] private float _sideGap = 16f;
[SerializeField] private float _anchorItemWidth = 0f; [SerializeField] private float _anchorItemWidth = 0f;
[SerializeField] private Graphic _blankAreaGraphic;
[SerializeField] private bool _disableBlankAreaRaycast = true;
[SerializeField] private bool _closeOnPointerDownOutsideContent = true;
private readonly List<GameObject> _runtimeTagItems = new List<GameObject>(); private readonly List<GameObject> _runtimeTagItems = new List<GameObject>();
private ItemDescFormContext _context; private ItemDescFormContext _context;
@ -84,12 +78,7 @@ namespace GeometryTD.UI
{ {
base.OnOpen(userData); base.OnOpen(userData);
_isOpened = true; _isOpened = true;
if (_disableBlankAreaRaycast && _blankAreaGraphic != null)
{
_blankAreaGraphic.raycastTarget = false;
}
if (!(userData is ItemDescFormContext context)) if (!(userData is ItemDescFormContext context))
{ {
Log.Error("ItemDescFormContext is invalid."); Log.Error("ItemDescFormContext is invalid.");
@ -119,7 +108,7 @@ namespace GeometryTD.UI
private void Update() private void Update()
{ {
if (!_isOpened || !_closeOnPointerDownOutsideContent || _content == null) if (!_isOpened || _content == null)
{ {
return; return;
} }

View File

@ -95,7 +95,7 @@ namespace GeometryTD.UI
public void OnClick() public void OnClick()
{ {
if (_context == null || !_context.IsSelectable) if (_context == null)
{ {
return; return;
} }

View File

@ -148,8 +148,8 @@ namespace GeometryTD.UI
GoodsIndex = item?.GoodsIndex ?? i, GoodsIndex = item?.GoodsIndex ?? i,
Title = item?.Title ?? string.Empty, Title = item?.Title ?? string.Empty,
TypeText = item?.TypeText ?? string.Empty, TypeText = item?.TypeText ?? string.Empty,
Description = item?.Description ?? string.Empty, Description = BuildDescription(item),
TagTexts = BuildTagTexts(item?.Tags), TagTexts = BuildTagTexts(item),
PurchaseButtonText = item != null && item.IsPurchased ? "已购买" : $"购买 {item?.Price ?? 0}", PurchaseButtonText = item != null && item.IsPurchased ? "已购买" : $"购买 {item?.Price ?? 0}",
CanPurchase = item != null && !item.IsPurchased, CanPurchase = item != null && !item.IsPurchased,
IconAreaContext = item?.IconAreaContext IconAreaContext = item?.IconAreaContext
@ -164,9 +164,26 @@ namespace GeometryTD.UI
}; };
} }
private static string[] BuildTagTexts(TagType[] tags) private static string BuildDescription(GoodsItemRawData rawData)
{ {
return TagDisplayUtility.BuildTagTexts(tags); string baseDescription = rawData?.Description ?? string.Empty;
string tagDescription = TagDisplayUtility.BuildTagDescriptionText(rawData?.Tags);
if (string.IsNullOrWhiteSpace(tagDescription))
{
return baseDescription;
}
if (string.IsNullOrWhiteSpace(baseDescription))
{
return tagDescription;
}
return $"{baseDescription}\n{tagDescription}";
}
private static string[] BuildTagTexts(GoodsItemRawData rawData)
{
return TagDisplayUtility.BuildTagTexts(rawData?.Tags);
} }
} }
} }

View File

@ -30,7 +30,7 @@ namespace GeometryTD.UI
return new ShopFormRawData return new ShopFormRawData
{ {
PlayerGold = GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.Gold : 0, PlayerGold = GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.Gold : 0,
GoodsItems = CloneGoodsItems(_currentGoods) GoodsItems = new List<GoodsItemRawData>(_currentGoods)
}; };
} }
@ -93,59 +93,5 @@ namespace GeometryTD.UI
return inventory; return inventory;
} }
private static List<GoodsItemRawData> CloneGoodsItems(List<GoodsItemRawData> source)
{
List<GoodsItemRawData> result = new List<GoodsItemRawData>(source?.Count ?? 0);
if (source == null)
{
return result;
}
foreach (var item in source)
{
if (item == null)
{
continue;
}
result.Add(new GoodsItemRawData
{
GoodsIndex = item.GoodsIndex,
Title = item.Title,
TypeText = item.TypeText,
Description = item.Description,
Price = item.Price,
Tags = item.Tags != null ? (TagType[])item.Tags.Clone() : Array.Empty<TagType>(),
IconAreaContext = item.IconAreaContext == null
? null
: new IconAreaContext
{
Rarity = item.IconAreaContext.Rarity,
ComponentSlotType = item.IconAreaContext.ComponentSlotType,
Color = item.IconAreaContext.Color,
Icon = item.IconAreaContext.Icon
},
SourceItem = CloneSourceItem(item.SourceItem),
IsPurchased = item.IsPurchased
});
}
return result;
}
private static TowerCompItemData CloneSourceItem(TowerCompItemData item)
{
switch (item)
{
case MuzzleCompItemData muzzleComp:
return InventoryCloneUtility.CloneMuzzleComp(muzzleComp);
case BearingCompItemData bearingComp:
return InventoryCloneUtility.CloneBearingComp(bearingComp);
case BaseCompItemData baseComp:
return InventoryCloneUtility.CloneBaseComp(baseComp);
default:
return null;
}
}
} }
} }

View File

@ -290,8 +290,8 @@ MonoBehaviour:
m_faceColor: m_faceColor:
serializedVersion: 2 serializedVersion: 2
rgba: 4294967295 rgba: 4294967295
m_fontSize: 28 m_fontSize: 40
m_fontSizeBase: 28 m_fontSizeBase: 40
m_fontWeight: 400 m_fontWeight: 400
m_enableAutoSizing: 0 m_enableAutoSizing: 0
m_fontSizeMin: 18 m_fontSizeMin: 18

View File

@ -213,7 +213,6 @@ namespace GeometryTD.Tests.EditMode
settlementContext, settlementContext,
new RewardSelectItemRawData new RewardSelectItemRawData
{ {
RewardId = reward.InstanceId,
SlotType = TowerCompSlotType.Muzzle, SlotType = TowerCompSlotType.Muzzle,
SourceItem = reward SourceItem = reward
}); });
@ -247,7 +246,6 @@ namespace GeometryTD.Tests.EditMode
settlementContext, settlementContext,
new RewardSelectItemRawData new RewardSelectItemRawData
{ {
RewardId = reward.InstanceId,
SlotType = TowerCompSlotType.Muzzle, SlotType = TowerCompSlotType.Muzzle,
SourceItem = reward SourceItem = reward
}); });