为 RepoForm 添加出售功能,ShopNode 只承载玩家购买组件的逻辑

This commit is contained in:
2026-03-16 17:52:23 +08:00
parent dc2aa59d58
commit 2e54acbc85
33 changed files with 3198 additions and 91 deletions
@@ -1,11 +1,15 @@
using GeometryTD.UI;
namespace GeometryTD.UI
{
public class RepoFormContext : UIContext
{
public string GoldText;
public RepoFormState State;
public bool ShowSellModeButton;
public string SellModeButtonText;
public bool ShowCombineArea;
public bool ShowSellArea;
public CombineAreaContext CombineAreaContext;
public SellAreaContext SellAreaContext;
public CompAreaContext CompAreaContext;
public ParticipantAreaContext ParticipantAreaContext;
}
@@ -0,0 +1,8 @@
namespace GeometryTD.UI
{
public enum RepoFormState
{
Assemble = 0,
Sell = 1
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9110fc764f3044bda40df4a8c02f320b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -11,6 +11,9 @@ namespace GeometryTD.UI
public float EnduranceRate01;
public RepoItemClickActionType ClickActionType;
public TowerCompSlotType ComponentSlotType;
public bool IsSellMode;
public bool IsSellable = true;
public bool IsSellSelected;
public IconAreaContext IconAreaContext;
}
}
@@ -0,0 +1,10 @@
namespace GeometryTD.UI
{
public class SellAreaContext
{
public string TotalPriceText;
public bool CanConfirmSell;
public RepoItemContext[] ComponentItems;
public TowerRepoItemContext[] TowerItems;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f153d1a509df4bb69c6d231df5b60db9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -23,21 +23,44 @@ namespace GeometryTD.UI
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 (var tower in rawData.Inventory.Towers)
foreach (TowerItemData tower in rawData.Inventory.Towers)
{
if (tower == null)
{
continue;
}
TowerRepoItemContext towerContext = BuildTowerRepoItemContext(tower, muzzleMap, bearingMap, baseMap,
RepoItemClickActionType.OpenDetail, true);
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,
@@ -50,23 +73,24 @@ namespace GeometryTD.UI
if (rawData.Inventory.MuzzleComponents != null)
{
foreach (var item in rawData.Inventory.MuzzleComponents)
foreach (MuzzleCompItemData item in rawData.Inventory.MuzzleComponents)
{
if (item == null || item.IsAssembledIntoTower)
{
continue;
}
RepoItemContext componentContext = new RepoItemContext
{
InstanceId = item.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveComponentEnduranceRate(item),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Muzzle,
IconAreaContext = BuildIconAreaContext(item)
};
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,
@@ -86,16 +110,17 @@ namespace GeometryTD.UI
continue;
}
RepoItemContext componentContext = new RepoItemContext
{
InstanceId = item.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveComponentEnduranceRate(item),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Bearing,
IconAreaContext = BuildIconAreaContext(item)
};
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,
@@ -115,16 +140,17 @@ namespace GeometryTD.UI
continue;
}
RepoItemContext componentContext = new RepoItemContext
{
InstanceId = item.InstanceId,
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveComponentEnduranceRate(item),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Base,
IconAreaContext = BuildIconAreaContext(item)
};
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,
@@ -141,7 +167,19 @@ namespace GeometryTD.UI
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(),
@@ -151,6 +189,26 @@ namespace GeometryTD.UI
};
}
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)
@@ -218,7 +276,7 @@ namespace GeometryTD.UI
return map;
}
foreach (var item in items)
foreach (TComp item in items)
{
if (item == null || item.InstanceId <= 0)
{
@@ -231,6 +289,26 @@ namespace GeometryTD.UI
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>();
@@ -239,7 +317,7 @@ namespace GeometryTD.UI
return map;
}
foreach (var tower in towers)
foreach (TowerItemData tower in towers)
{
if (tower == null || tower.InstanceId <= 0)
{
@@ -263,7 +341,7 @@ namespace GeometryTD.UI
List<TowerRepoItemContext> participantItems = new List<TowerRepoItemContext>();
if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null)
{
foreach (var towerId in inventory.ParticipantTowerInstanceIds)
foreach (long towerId in inventory.ParticipantTowerInstanceIds)
{
if (towerId <= 0)
{
@@ -280,8 +358,17 @@ namespace GeometryTD.UI
continue;
}
TowerRepoItemContext towerContext = BuildTowerRepoItemContext(tower, muzzleMap, bearingMap, baseMap,
RepoItemClickActionType.RemoveParticipant, false);
TowerRepoItemContext towerContext = BuildTowerRepoItemContext(
tower,
muzzleMap,
bearingMap,
baseMap,
RepoItemClickActionType.RemoveParticipant,
false,
false,
false,
false,
false);
if (towerContext != null)
{
participantItems.Add(towerContext);
@@ -304,6 +391,11 @@ namespace GeometryTD.UI
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
foreach (long towerId in _compAreaTowerIds)
{
Form.SetRepoItemSelected(towerId, _participantTowerIds.Contains(towerId));
@@ -334,7 +426,11 @@ namespace GeometryTD.UI
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap,
RepoItemClickActionType clickActionType,
bool canDrag)
bool canDrag,
bool isSellMode,
bool isSellable,
bool isSellSelected,
bool highlightSelected)
{
if (tower == null)
{
@@ -348,6 +444,9 @@ namespace GeometryTD.UI
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,
@@ -3,6 +3,7 @@ using GeometryTD.CustomEvent;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
using GameFramework.Event;
using GeometryTD.CustomComponent;
using UnityEngine;
using UnityGameFramework.Runtime;
@@ -43,6 +44,9 @@ namespace GeometryTD.UI
GameEntry.Event.Subscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested);
GameEntry.Event.Subscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested);
GameEntry.Event.Subscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn);
GameEntry.Event.Subscribe(RepoSellModeToggleRequestedEventArgs.EventId, OnRepoSellModeToggleRequested);
GameEntry.Event.Subscribe(RepoSellCancelRequestedEventArgs.EventId, OnRepoSellCancelRequested);
GameEntry.Event.Subscribe(RepoSellConfirmRequestedEventArgs.EventId, OnRepoSellConfirmRequested);
}
protected override void UnsubscribeCustomEvents()
@@ -53,6 +57,9 @@ namespace GeometryTD.UI
GameEntry.Event.Unsubscribe(RepoCombineRequestedEventArgs.EventId, OnRepoCombineRequested);
GameEntry.Event.Unsubscribe(RepoParticipantAssignRequestedEventArgs.EventId, OnRepoParticipantAssignRequested);
GameEntry.Event.Unsubscribe(RepoFormReturnEventArgs.EventId, OnRepoFormReturn);
GameEntry.Event.Unsubscribe(RepoSellModeToggleRequestedEventArgs.EventId, OnRepoSellModeToggleRequested);
GameEntry.Event.Unsubscribe(RepoSellCancelRequestedEventArgs.EventId, OnRepoSellCancelRequested);
GameEntry.Event.Unsubscribe(RepoSellConfirmRequestedEventArgs.EventId, OnRepoSellConfirmRequested);
}
public override int? OpenUI(object userData = null)
@@ -125,6 +132,24 @@ namespace GeometryTD.UI
return;
}
if (_useCase != null && _useCase.State == RepoFormState.Sell)
{
if (_useCase.TryToggleSellSelection(
args.ItemId,
out RepoFormRawData sellModeRawData,
out PlayerInventorySaleFailureReason failureReason))
{
SetContext(BuildContext(sellModeRawData));
RefreshCurrentUI();
}
else if (failureReason == PlayerInventorySaleFailureReason.ParticipantTower)
{
OpenSellBlockedDialog("参战防御塔不能直接出售,请先移出参战区。");
}
return;
}
if (clickActionType == RepoItemClickActionType.RemoveParticipant)
{
if (_useCase == null || Form == null)
@@ -165,6 +190,11 @@ namespace GeometryTD.UI
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
if (!(e is RepoItemDragEndedEventArgs args))
{
return;
@@ -188,6 +218,11 @@ namespace GeometryTD.UI
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
if (!(e is CombineSlotClickedEventArgs args))
{
return;
@@ -257,6 +292,11 @@ namespace GeometryTD.UI
return;
}
if (Context != null && Context.State == RepoFormState.Sell)
{
return;
}
if (!(e is RepoParticipantAssignRequestedEventArgs args))
{
return;
@@ -288,6 +328,65 @@ namespace GeometryTD.UI
RefreshParticipantAreaOnly();
}
private void OnRepoSellModeToggleRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is RepoSellModeToggleRequestedEventArgs) || _useCase == null)
{
return;
}
if (_useCase.State != RepoFormState.Assemble)
{
return;
}
RepoFormRawData rawData = _useCase.EnterSellState();
SetContext(BuildContext(rawData));
RefreshCurrentUI();
}
private void OnRepoSellCancelRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is RepoSellCancelRequestedEventArgs) || _useCase == null)
{
return;
}
if (_useCase.State != RepoFormState.Sell)
{
return;
}
SetContext(BuildContext(_useCase.ExitSellState()));
RefreshCurrentUI();
}
private void OnRepoSellConfirmRequested(object sender, GameEventArgs e)
{
if (!IsEventFromCurrentForm(sender) || !(e is RepoSellConfirmRequestedEventArgs) || _useCase == null)
{
return;
}
if (!_useCase.TryConfirmSellSelection(out RepoFormRawData rawData, out PlayerInventorySaleResult result))
{
if (result != null && result.FailureReason == PlayerInventorySaleFailureReason.ParticipantTower)
{
OpenSellBlockedDialog("参战防御塔不能直接出售,请先移出参战区。");
}
return;
}
SetContext(BuildContext(rawData));
RefreshCurrentUI();
if (GameEntry.UI.GetUIForm(UIFormType.ShopForm) != null)
{
GameEntry.UIRouter.OpenUI(UIFormType.ShopForm);
}
}
private bool IsEventFromCurrentForm(object sender)
{
if (Form == null)
@@ -309,6 +408,18 @@ namespace GeometryTD.UI
return false;
}
private static void OpenSellBlockedDialog(string message)
{
GameEntry.UIRouter.OpenUI(UIFormType.DialogForm, new DialogFormRawData
{
Mode = 1,
Title = "无法出售",
Message = message,
PauseGame = false,
ConfirmText = "知道了"
});
}
#endregion
}
}
@@ -5,5 +5,9 @@ namespace GeometryTD.UI
public class RepoFormRawData
{
public BackpackInventoryData Inventory;
public RepoFormState State;
public long[] SelectedSellItemIds;
public int SelectedSellItemCount;
public int SelectedSellTotalPrice;
}
}
@@ -1,4 +1,6 @@
using GeometryTD.CustomUtility;
using System.Collections.Generic;
using GeometryTD.CustomComponent;
using GeometryTD.CustomUtility;
using GeometryTD.Definition;
namespace GeometryTD.UI
@@ -7,6 +9,8 @@ namespace GeometryTD.UI
{
private const int MaxParticipantCount = 4;
private BackpackInventoryData _fallbackInventory;
private readonly HashSet<long> _selectedSellItemIds = new HashSet<long>();
private RepoFormState _state = RepoFormState.Assemble;
public RepoFormRawData CreateInitialModel()
{
@@ -15,12 +19,23 @@ namespace GeometryTD.UI
: GetOrCreateFallbackInventory();
return new RepoFormRawData
{
Inventory = sample
Inventory = sample,
State = _state,
SelectedSellItemIds = BuildSelectedSellItemArray(),
SelectedSellItemCount = _selectedSellItemIds.Count,
SelectedSellTotalPrice = ResolveSelectedSellTotalPrice()
};
}
public RepoFormState State => _state;
public bool TryAssembleTower(long muzzleItemId, long bearingItemId, long baseItemId)
{
if (_state == RepoFormState.Sell)
{
return false;
}
if (GameEntry.PlayerInventory == null)
{
return false;
@@ -35,6 +50,15 @@ namespace GeometryTD.UI
public ParticipantTowerAssignResult TryAddParticipantTower(long towerItemId)
{
if (_state == RepoFormState.Sell)
{
return new ParticipantTowerAssignResult
{
TowerInstanceId = towerItemId,
FailureReason = ParticipantTowerAssignFailureReason.ParticipantAreaFull
};
}
if (GameEntry.PlayerInventory == null)
{
BackpackInventoryData fallbackInventory = GetOrCreateFallbackInventory();
@@ -44,11 +68,16 @@ namespace GeometryTD.UI
MaxParticipantCount);
}
return GameEntry.PlayerInventory.TryAddParticipantTower(towerItemId, 4);
return GameEntry.PlayerInventory.TryAddParticipantTower(towerItemId, MaxParticipantCount);
}
public bool TryRemoveParticipantTower(long towerItemId)
{
if (_state == RepoFormState.Sell)
{
return false;
}
if (GameEntry.PlayerInventory == null)
{
BackpackInventoryData fallbackInventory = GetOrCreateFallbackInventory();
@@ -61,12 +90,120 @@ namespace GeometryTD.UI
return GameEntry.PlayerInventory.TryRemoveParticipantTower(towerItemId);
}
public RepoFormRawData EnterSellState()
{
_state = RepoFormState.Sell;
_selectedSellItemIds.Clear();
return CreateInitialModel();
}
public RepoFormRawData ExitSellState()
{
_state = RepoFormState.Assemble;
_selectedSellItemIds.Clear();
return CreateInitialModel();
}
public bool TryToggleSellSelection(
long itemId,
out RepoFormRawData rawData,
out PlayerInventorySaleFailureReason failureReason)
{
rawData = null;
failureReason = PlayerInventorySaleFailureReason.None;
if (_state != RepoFormState.Sell || itemId <= 0 || GameEntry.PlayerInventory == null)
{
failureReason = PlayerInventorySaleFailureReason.InvalidSelection;
return false;
}
if (_selectedSellItemIds.Contains(itemId))
{
_selectedSellItemIds.Remove(itemId);
rawData = CreateInitialModel();
return true;
}
if (!GameEntry.PlayerInventory.TryGetSaleCandidate(itemId, out PlayerInventorySaleCandidate candidate) ||
candidate == null)
{
failureReason = PlayerInventorySaleFailureReason.ItemNotFound;
return false;
}
if (!candidate.IsSellable)
{
failureReason = candidate.FailureReason;
return false;
}
_selectedSellItemIds.Add(itemId);
rawData = CreateInitialModel();
return true;
}
public bool TryConfirmSellSelection(out RepoFormRawData rawData, out PlayerInventorySaleResult result)
{
rawData = null;
result = null;
if (_state != RepoFormState.Sell || _selectedSellItemIds.Count <= 0 || GameEntry.PlayerInventory == null)
{
return false;
}
if (!GameEntry.PlayerInventory.TrySellItems(_selectedSellItemIds, out PlayerInventorySaleResult saleResult) ||
saleResult == null ||
!saleResult.IsSuccess)
{
result = saleResult;
rawData = CreateInitialModel();
return false;
}
_selectedSellItemIds.Clear();
result = saleResult;
rawData = CreateInitialModel();
return true;
}
private BackpackInventoryData GetOrCreateFallbackInventory()
{
_fallbackInventory ??= InventorySeedUtility.CreateSampleInventory();
InventoryParticipantUtility.NormalizeParticipantState(_fallbackInventory, MaxParticipantCount);
return _fallbackInventory;
}
private long[] BuildSelectedSellItemArray()
{
if (_selectedSellItemIds.Count <= 0)
{
return System.Array.Empty<long>();
}
long[] itemIds = new long[_selectedSellItemIds.Count];
_selectedSellItemIds.CopyTo(itemIds);
return itemIds;
}
private int ResolveSelectedSellTotalPrice()
{
if (_state != RepoFormState.Sell || _selectedSellItemIds.Count <= 0 || GameEntry.PlayerInventory == null)
{
return 0;
}
int total = 0;
foreach (long itemId in _selectedSellItemIds)
{
if (GameEntry.PlayerInventory.TryGetSaleCandidate(itemId, out PlayerInventorySaleCandidate candidate) &&
candidate != null &&
candidate.IsSellable)
{
total += candidate.Price;
}
}
return total;
}
}
}
@@ -8,6 +8,7 @@ namespace GeometryTD.UI
public class CombineArea : MonoBehaviour, IDropHandler
{
[SerializeField] private CombineSlotItem[] _slots;
private bool _isInteractionEnabled = true;
public void OnInit(CombineAreaContext context)
{
@@ -43,6 +44,11 @@ namespace GeometryTD.UI
public void OnCombineClick()
{
if (!_isInteractionEnabled)
{
return;
}
if (!TryGetBoundItemId(TowerCompSlotType.Muzzle, out long muzzleItemId) ||
!TryGetBoundItemId(TowerCompSlotType.Bearing, out long bearingItemId) ||
!TryGetBoundItemId(TowerCompSlotType.Base, out long baseItemId))
@@ -55,6 +61,11 @@ namespace GeometryTD.UI
public bool TryAssignItem(RepoItemContext itemContext)
{
if (!_isInteractionEnabled)
{
return false;
}
if (itemContext == null || itemContext.ComponentSlotType == TowerCompSlotType.None)
{
return false;
@@ -91,6 +102,11 @@ namespace GeometryTD.UI
public void OnDrop(PointerEventData eventData)
{
if (!_isInteractionEnabled)
{
return;
}
if (eventData == null)
{
return;
@@ -113,6 +129,11 @@ namespace GeometryTD.UI
dragItem.SetDropResult(assigned);
}
public void SetInteractionEnabled(bool enabled)
{
_isInteractionEnabled = enabled;
}
private CombineSlotItem FindSlot(TowerCompSlotType slotType)
{
if (_slots == null)
@@ -14,6 +14,7 @@ namespace GeometryTD.UI
[SerializeField] private Transform _content;
[SerializeField] private TowerRepoItem _towerItemTemplate;
[SerializeField] private int _instancePoolCapacity = 8;
private bool _isInteractionEnabled = true;
private readonly List<TowerRepoItem> _activeItems = new List<TowerRepoItem>();
private readonly HashSet<long> _boundItemIds = new HashSet<long>();
@@ -81,6 +82,11 @@ namespace GeometryTD.UI
public bool CanAssign(IRepoDragItemView dragItem)
{
if (!_isInteractionEnabled)
{
return false;
}
if (dragItem == null || dragItem.InstanceId <= 0)
{
return false;
@@ -106,6 +112,11 @@ namespace GeometryTD.UI
public void OnDrop(PointerEventData eventData)
{
if (!_isInteractionEnabled)
{
return;
}
if (eventData == null)
{
return;
@@ -134,6 +145,11 @@ namespace GeometryTD.UI
GameEntry.Event.Fire(this, RepoParticipantAssignRequestedEventArgs.Create(dragItem.InstanceId));
}
public void SetInteractionEnabled(bool enabled)
{
_isInteractionEnabled = enabled;
}
private void EnsurePool()
{
if (_itemPool != null)
@@ -1,6 +1,7 @@
using GeometryTD.CustomEvent;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityGameFramework.Runtime;
namespace GeometryTD.UI
@@ -8,12 +9,12 @@ namespace GeometryTD.UI
public class RepoForm : UGuiForm
{
[SerializeField] private CombineArea _combineArea;
[SerializeField] private CompArea _compArea;
[SerializeField] private SellArea _sellArea;
[SerializeField] private ParticipantArea _participantArea;
[SerializeField] private TMP_Text _goldText;
[SerializeField] private CommonButton _sellModeButton;
[SerializeField] private TMP_Text _sellModeButtonText;
public void RefreshUI(RepoFormContext context)
{
@@ -23,10 +24,25 @@ namespace GeometryTD.UI
}
RefreshGoldText(context.GoldText);
RefreshStateUI(context);
_combineArea?.OnInit(context.CombineAreaContext);
_compArea?.OnInit(context.CompAreaContext);
_sellArea?.OnInit(context.SellAreaContext);
_participantArea?.OnInit(context.ParticipantAreaContext);
if (_combineArea != null)
{
_combineArea.gameObject.SetActive(context.ShowCombineArea);
_combineArea.SetInteractionEnabled(context.State == RepoFormState.Assemble);
}
if (_sellArea != null)
{
_sellArea.gameObject.SetActive(context.ShowSellArea);
}
_participantArea?.SetInteractionEnabled(context.State == RepoFormState.Assemble);
}
public void RefreshGoldText(string goldText)
@@ -89,6 +105,7 @@ namespace GeometryTD.UI
_combineArea?.OnReset();
_compArea?.OnReset();
_sellArea?.OnReset();
_participantArea?.OnReset();
base.OnClose(isShutdown, userData);
}
@@ -97,5 +114,23 @@ namespace GeometryTD.UI
{
GameEntry.Event.Fire(this, RepoFormReturnEventArgs.Create());
}
public void OnSellModeButtonClick()
{
GameEntry.Event.Fire(this, RepoSellModeToggleRequestedEventArgs.Create());
}
private void RefreshStateUI(RepoFormContext context)
{
if (_sellModeButton != null)
{
_sellModeButton.gameObject.SetActive(context != null && context.ShowSellModeButton);
}
if (_sellModeButtonText != null)
{
_sellModeButtonText.text = context?.SellModeButtonText ?? "出售模式";
}
}
}
}
@@ -13,6 +13,7 @@ namespace GeometryTD.UI
[SerializeField] private IconArea _iconArea;
private static readonly Color SelectedColor = new Color32(255, 216, 102, 255);
private static readonly Color DisabledSellColor = new Color32(96, 96, 96, 255);
private static readonly Color EmptyEnduranceColor = new Color(0.8f, 0f, 0f, 1f);
private static readonly Color FullEnduranceColor = new Color(0f, 0.8f, 0f, 1f);
private static readonly Vector2 DefaultDragGhostSize = new Vector2(64f, 64f);
@@ -72,7 +73,7 @@ namespace GeometryTD.UI
_context = context;
_iconArea.OnInit(context.IconAreaContext);
SetSelected(false);
SetSelected(context.IsSellSelected);
ResetDragState();
}
@@ -104,6 +105,12 @@ namespace GeometryTD.UI
return;
}
if (_context != null && _context.IsSellMode && !_context.IsSellable)
{
_bgImage.color = DisabledSellColor;
return;
}
float enduranceRate = _context != null ? Mathf.Clamp01(_context.EnduranceRate01) : 1f;
_bgImage.color = Color.Lerp(EmptyEnduranceColor, FullEnduranceColor, enduranceRate);
}
@@ -212,6 +219,11 @@ namespace GeometryTD.UI
return false;
}
if (_context.IsSellMode)
{
return false;
}
if (_isSelected && _context.ComponentSlotType != TowerCompSlotType.None)
{
return false;
@@ -0,0 +1,112 @@
using System.Collections.Generic;
using GeometryTD.CustomEvent;
using TMPro;
using UnityEngine;
namespace GeometryTD.UI
{
public class SellArea : MonoBehaviour
{
[SerializeField] private Transform _content;
[SerializeField] private RepoItem _itemTemplate;
[SerializeField] private TowerRepoItem _towerItemTemplate;
[SerializeField] private TMP_Text _totalPrice;
private readonly List<RepoItem> _activeComponentItems = new List<RepoItem>();
private readonly List<TowerRepoItem> _activeTowerItems = new List<TowerRepoItem>();
private SellAreaContext _context;
public void OnInit(SellAreaContext context)
{
OnReset();
_context = context;
if (_totalPrice != null)
{
_totalPrice.text = context?.TotalPriceText ?? string.Empty;
}
if (context == null || _content == null)
{
return;
}
if (context.ComponentItems != null)
{
foreach (RepoItemContext itemContext in context.ComponentItems)
{
if (itemContext == null || _itemTemplate == null)
{
continue;
}
RepoItem item = Instantiate(_itemTemplate, _content);
item.gameObject.SetActive(true);
item.OnInit(itemContext);
_activeComponentItems.Add(item);
}
}
if (context.TowerItems != null)
{
foreach (TowerRepoItemContext itemContext in context.TowerItems)
{
if (itemContext == null || _towerItemTemplate == null)
{
continue;
}
TowerRepoItem item = Instantiate(_towerItemTemplate, _content);
item.gameObject.SetActive(true);
item.OnInit(itemContext);
_activeTowerItems.Add(item);
}
}
}
public void OnReset()
{
for (int i = _activeComponentItems.Count - 1; i >= 0; i--)
{
RepoItem item = _activeComponentItems[i];
if (item != null)
{
Destroy(item.gameObject);
}
}
for (int i = _activeTowerItems.Count - 1; i >= 0; i--)
{
TowerRepoItem item = _activeTowerItems[i];
if (item != null)
{
Destroy(item.gameObject);
}
}
_activeComponentItems.Clear();
_activeTowerItems.Clear();
_context = null;
if (_totalPrice != null)
{
_totalPrice.text = string.Empty;
}
}
public void OnCancelButtonClick()
{
GameEntry.Event.Fire(this, RepoSellCancelRequestedEventArgs.Create());
}
public void OnConfirmButtonClick()
{
if (_context == null || !_context.CanConfirmSell)
{
return;
}
GameEntry.Event.Fire(this, RepoSellConfirmRequestedEventArgs.Create());
}
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 548fcad4dc8202f41b67f48aab7bed13
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: