This commit is contained in:
2026-04-30 19:33:16 +08:00
commit fb2252f688
556 changed files with 69721 additions and 0 deletions
@@ -0,0 +1,41 @@
using GeometryTD.Definition;
using GeometryTD.Procedure;
namespace GeometryTD.UI
{
public sealed partial class NodeMapFormController
{
private static NodeMapFormContext BuildContext(NodeMapFormRawData rawData)
{
NodeItemContext[] nodeItemContexts = System.Array.Empty<NodeItemContext>();
if (rawData?.Nodes != null && rawData.Nodes.Count > 0)
{
nodeItemContexts = new NodeItemContext[rawData.Nodes.Count];
for (int i = 0; i < rawData.Nodes.Count; i++)
{
NodeMapNodeRawData node = rawData.Nodes[i];
nodeItemContexts[i] = new NodeItemContext
{
NodeId = node?.NodeId ?? 0,
SequenceIndex = node?.SequenceIndex ?? i,
NodeType = node?.NodeType ?? RunNodeType.None,
IsLocked = node != null && node.Status == RunNodeStatus.Locked,
IsCurrent = node != null && node.IsCurrentNode,
IsCompleted = node != null && node.Status == RunNodeStatus.Completed,
IsException = node != null && node.Status == RunNodeStatus.Exception,
CanClick = node != null && node.CanEnter
};
}
}
return new NodeMapFormContext
{
Title = rawData?.Title ?? "节点地图",
ProgressText = rawData?.ProgressText ?? "0 / 0",
CurrentNodeText = rawData?.CurrentNodeText ?? "当前节点: 无",
IsRunCompleted = rawData != null && rawData.IsRunCompleted,
NodeItems = nodeItemContexts
};
}
}
}
@@ -0,0 +1,497 @@
using System;
using System.Collections.Generic;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.UI
{
public partial class RepoFormController
{
private RepoFormContext BuildContext(RepoFormRawData rawData)
{
_itemClickActionMap.Clear();
_itemDescSeedMap.Clear();
_compAreaTowerIds.Clear();
if (rawData?.Inventory == null)
{
_participantTowerIds.Clear();
return null;
}
Dictionary<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(rawData.Inventory.MuzzleComponents);
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(rawData.Inventory.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(rawData.Inventory.BaseComponents);
Dictionary<long, TowerItemData> towerMap = BuildTowerMap(rawData.Inventory.Towers);
HashSet<long> selectedSellItemIds = BuildSelectedSellItemSet(rawData.SelectedSellItemIds);
bool isSellState = rawData.State == RepoFormState.Sell;
List<RepoItemContext> componentItems = new List<RepoItemContext>();
List<TowerRepoItemContext> towerItems = new List<TowerRepoItemContext>();
List<RepoItemContext> selectedSellComponentItems = new List<RepoItemContext>();
List<TowerRepoItemContext> selectedSellTowerItems = new List<TowerRepoItemContext>();
if (rawData.Inventory.Towers != null)
{
foreach (TowerItemData tower in rawData.Inventory.Towers)
{
if (tower == null)
{
continue;
}
bool isParticipantTower = rawData.Inventory.ParticipantTowerInstanceIds != null &&
rawData.Inventory.ParticipantTowerInstanceIds.Contains(tower.InstanceId);
bool isSellSelected = isSellState && selectedSellItemIds.Contains(tower.InstanceId);
TowerRepoItemContext towerContext = BuildTowerRepoItemContext(
tower,
muzzleMap,
bearingMap,
baseMap,
RepoItemClickActionType.OpenDetail,
!isSellState,
isSellState,
!isParticipantTower,
isSellSelected,
false);
AddTowerItemContext(towerItems, towerContext);
if (isSellSelected)
{
selectedSellTowerItems.Add(towerContext);
}
AddItemDescSeed(
tower.InstanceId,
tower.Name,
"Tower",
ItemDescUtility.BuildTowerDesc(tower, muzzleMap, bearingMap, baseMap) ?? string.Empty,
tower.Stats?.Tags,
tower.Stats?.TagRuntimes);
}
}
if (rawData.Inventory.MuzzleComponents != null)
{
foreach (MuzzleCompItemData item in rawData.Inventory.MuzzleComponents)
{
if (item == null || item.IsAssembledIntoTower)
{
continue;
}
RepoItemContext componentContext = BuildSellableComponentContext(
item,
TowerCompSlotType.Muzzle,
isSellState,
selectedSellItemIds.Contains(item.InstanceId));
AddComponentItemContext(componentItems, componentContext);
if (componentContext.IsSellSelected)
{
selectedSellComponentItems.Add(componentContext);
}
AddItemDescSeed(
item.InstanceId,
item.Name,
BuildComponentTypeText(item.SlotType),
ItemDescUtility.BuildMuzzleDesc(item) ?? string.Empty,
item.Tags,
null);
}
}
if (rawData.Inventory.BearingComponents != null)
{
foreach (BearingCompItemData item in rawData.Inventory.BearingComponents)
{
if (item == null || item.IsAssembledIntoTower)
{
continue;
}
RepoItemContext componentContext = BuildSellableComponentContext(
item,
TowerCompSlotType.Bearing,
isSellState,
selectedSellItemIds.Contains(item.InstanceId));
AddComponentItemContext(componentItems, componentContext);
if (componentContext.IsSellSelected)
{
selectedSellComponentItems.Add(componentContext);
}
AddItemDescSeed(
item.InstanceId,
item.Name,
BuildComponentTypeText(item.SlotType),
ItemDescUtility.BuildBearingDesc(item) ?? string.Empty,
item.Tags,
null);
}
}
if (rawData.Inventory.BaseComponents != null)
{
foreach (BaseCompItemData item in rawData.Inventory.BaseComponents)
{
if (item == null || item.IsAssembledIntoTower)
{
continue;
}
RepoItemContext componentContext = BuildSellableComponentContext(
item,
TowerCompSlotType.Base,
isSellState,
selectedSellItemIds.Contains(item.InstanceId));
AddComponentItemContext(componentItems, componentContext);
if (componentContext.IsSellSelected)
{
selectedSellComponentItems.Add(componentContext);
}
AddItemDescSeed(
item.InstanceId,
item.Name,
BuildComponentTypeText(item.SlotType),
ItemDescUtility.BuildBaseDesc(item) ?? string.Empty,
item.Tags,
null);
}
}
ParticipantAreaContext participantAreaContext =
BuildParticipantAreaContext(rawData.Inventory, towerMap, muzzleMap, bearingMap, baseMap);
return new RepoFormContext
{
GoldText = $"金币: {rawData.Inventory.Gold}",
State = rawData.State,
ShowSellModeButton = rawData.State == RepoFormState.Assemble,
SellModeButtonText = "出售模式",
ShowCombineArea = rawData.State == RepoFormState.Assemble,
ShowSellArea = rawData.State == RepoFormState.Sell,
CombineAreaContext = new CombineAreaContext(),
SellAreaContext = new SellAreaContext
{
TotalPriceText = $"总价值: {rawData.SelectedSellTotalPrice}",
CanConfirmSell = rawData.State == RepoFormState.Sell && rawData.SelectedSellItemCount > 0,
ComponentItems = selectedSellComponentItems.ToArray(),
TowerItems = selectedSellTowerItems.ToArray()
},
CompAreaContext = new CompAreaContext
{
ComponentItems = componentItems.ToArray(),
TowerItems = towerItems.ToArray()
},
ParticipantAreaContext = participantAreaContext
};
}
private static RepoItemContext BuildSellableComponentContext(
TowerCompItemData item,
TowerCompSlotType slotType,
bool isSellState,
bool isSellSelected)
{
return new RepoItemContext
{
InstanceId = item.InstanceId,
CanDrag = !isSellState,
EnduranceRate01 = ItemDescUtility.ResolveComponentEnduranceRate(item),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = slotType,
IsSellMode = isSellState,
IsSellable = true,
IsSellSelected = isSellState && isSellSelected,
IconAreaContext = BuildIconAreaContext(item)
};
}
private void AddComponentItemContext(List<RepoItemContext> items, RepoItemContext itemContext)
{
if (itemContext == null)
{
return;
}
items.Add(itemContext);
_itemClickActionMap[itemContext.InstanceId] = itemContext.ClickActionType;
}
private void AddTowerItemContext(List<TowerRepoItemContext> items, TowerRepoItemContext itemContext)
{
if (itemContext == null)
{
return;
}
items.Add(itemContext);
_itemClickActionMap[itemContext.InstanceId] = itemContext.ClickActionType;
_compAreaTowerIds.Add(itemContext.InstanceId);
}
private void AddItemDescSeed(
long itemId,
string title,
string typeText,
string description,
TagType[] tags,
TagRuntimeData[] tagRuntimes)
{
if (itemId <= 0)
{
return;
}
_itemDescSeedMap[itemId] = new ItemDescSeed
{
Title = string.IsNullOrWhiteSpace(title) ? $"Item {itemId}" : title,
TypeText = typeText ?? string.Empty,
Description = description ?? string.Empty,
Tags = tags,
TagRuntimes = tagRuntimes
};
}
private static string BuildComponentTypeText(TowerCompSlotType slotType)
{
return slotType switch
{
TowerCompSlotType.Muzzle => "Muzzle Component",
TowerCompSlotType.Bearing => "Bearing Component",
TowerCompSlotType.Base => "Base Component",
TowerCompSlotType.Accessory => "Accessory",
_ => "Component"
};
}
private static Dictionary<long, TComp> BuildComponentMap<TComp>(IReadOnlyList<TComp> items)
where TComp : TowerCompItemData
{
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
if (items == null)
{
return map;
}
foreach (TComp item in items)
{
if (item == null || item.InstanceId <= 0)
{
continue;
}
map[item.InstanceId] = item;
}
return map;
}
private static HashSet<long> BuildSelectedSellItemSet(IReadOnlyList<long> selectedSellItemIds)
{
HashSet<long> selectedIds = new HashSet<long>();
if (selectedSellItemIds == null)
{
return selectedIds;
}
for (int i = 0; i < selectedSellItemIds.Count; i++)
{
long itemId = selectedSellItemIds[i];
if (itemId > 0)
{
selectedIds.Add(itemId);
}
}
return selectedIds;
}
private static Dictionary<long, TowerItemData> BuildTowerMap(IReadOnlyList<TowerItemData> towers)
{
Dictionary<long, TowerItemData> map = new Dictionary<long, TowerItemData>();
if (towers == null)
{
return map;
}
foreach (TowerItemData tower in towers)
{
if (tower == null || tower.InstanceId <= 0)
{
continue;
}
map[tower.InstanceId] = tower;
}
return map;
}
private ParticipantAreaContext BuildParticipantAreaContext(
BackpackInventoryData inventory,
IReadOnlyDictionary<long, TowerItemData> towerMap,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
_participantTowerIds.Clear();
List<TowerRepoItemContext> participantItems = new List<TowerRepoItemContext>();
if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null)
{
foreach (long towerId in inventory.ParticipantTowerInstanceIds)
{
if (towerId <= 0)
{
continue;
}
if (!towerMap.TryGetValue(towerId, out TowerItemData tower) || tower == null)
{
continue;
}
if (!_participantTowerIds.Add(towerId))
{
continue;
}
TowerRepoItemContext towerContext = BuildTowerRepoItemContext(
tower,
muzzleMap,
bearingMap,
baseMap,
RepoItemClickActionType.RemoveParticipant,
false,
false,
false,
false,
false);
if (towerContext != null)
{
participantItems.Add(towerContext);
_itemClickActionMap[towerContext.InstanceId] = towerContext.ClickActionType;
}
}
}
return new ParticipantAreaContext
{
TowerItems = participantItems.ToArray(),
MaxCount = MaxParticipantCount
};
}
private void ApplyParticipantSelection()
{
if (Form == null || _compAreaTowerIds.Count <= 0)
{
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
foreach (long towerId in _compAreaTowerIds)
{
Form.SetRepoItemSelected(towerId, _participantTowerIds.Contains(towerId));
}
}
private void RefreshParticipantAreaOnly()
{
if (_useCase == null || Form == null)
{
return;
}
RepoFormContext latestContext = BuildContext(_useCase.CreateInitialModel());
if (latestContext?.ParticipantAreaContext == null)
{
return;
}
Form.RefreshGoldText(latestContext.GoldText);
Form.RefreshParticipantArea(latestContext.ParticipantAreaContext);
ApplyParticipantSelection();
}
private static TowerRepoItemContext BuildTowerRepoItemContext(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap,
RepoItemClickActionType clickActionType,
bool canDrag,
bool isSellMode,
bool isSellable,
bool isSellSelected,
bool highlightSelected)
{
if (tower == null)
{
return null;
}
return new TowerRepoItemContext
{
InstanceId = tower.InstanceId,
CanDrag = canDrag,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = clickActionType,
ComponentSlotType = TowerCompSlotType.None,
IsSellMode = isSellMode,
IsSellable = isSellable,
IsSellSelected = isSellSelected || highlightSelected,
IconAreaContext = new TowerIconAreaContext
{
Rarity = tower.Rarity,
MuzzleColor = ResolveComponentColor(tower.MuzzleComponentInstanceId, muzzleMap),
BearingColor = ResolveComponentColor(tower.BearingComponentInstanceId, bearingMap),
BaseColor = ResolveComponentColor(tower.BaseComponentInstanceId, baseMap)
}
};
}
private static IconAreaContext BuildIconAreaContext(TowerCompItemData item)
{
if (item == null)
{
return new IconAreaContext
{
ComponentSlotType = TowerCompSlotType.None,
Rarity = RarityType.None,
Color = Color.white,
Icon = null
};
}
return new IconAreaContext
{
ComponentSlotType = item.SlotType,
Rarity = item.Rarity,
Color = IconColorGenerator.GenerateForComponent(item),
Icon = null
};
}
private static Color ResolveComponentColor<TComp>(long instanceId,
IReadOnlyDictionary<long, TComp> componentMap)
where TComp : TowerCompItemData
{
if (instanceId > 0 &&
componentMap != null &&
componentMap.TryGetValue(instanceId, out TComp component) &&
component != null)
{
return IconColorGenerator.GenerateForComponent(component);
}
return Color.white;
}
}
}
@@ -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;
}
}
}