diff --git a/scripts/inventory/HotBar.cs b/scripts/inventory/HotBar.cs index 04d28fd..0def510 100644 --- a/scripts/inventory/HotBar.cs +++ b/scripts/inventory/HotBar.cs @@ -10,13 +10,15 @@ namespace ColdMint.scripts.inventory; public partial class HotBar : HBoxContainer { private IItemContainer? _itemContainer; - - + private IItemContainerDisplay? _itemContainerDisplay; + public override void _Ready() { base._Ready(); _itemContainer = new UniversalItemContainer(Config.HotBarSize); _itemContainer.SupportSelect = true; + _itemContainerDisplay = new ItemSlotContainerDisplay(this); + _itemContainerDisplay.BindItemContainer(_itemContainer); NodeUtils.DeleteAllChild(this); } diff --git a/scripts/inventory/IItemContainerDisplay.cs b/scripts/inventory/IItemContainerDisplay.cs new file mode 100644 index 0000000..73508b6 --- /dev/null +++ b/scripts/inventory/IItemContainerDisplay.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; + +namespace ColdMint.scripts.inventory; + +public interface IItemContainerDisplay : IEnumerable +{ + /// + /// Bind an item container to the item container display + /// 为物品容器显示器绑定物品容器 + /// + /// + void BindItemContainer(IItemContainer itemContainer); +} \ No newline at end of file diff --git a/scripts/inventory/IItemDisplay.cs b/scripts/inventory/IItemDisplay.cs new file mode 100644 index 0000000..272c2d2 --- /dev/null +++ b/scripts/inventory/IItemDisplay.cs @@ -0,0 +1,34 @@ +namespace ColdMint.scripts.inventory; + +/// +/// IItemDisplay +/// 物品显示器 +/// +public interface IItemDisplay +{ + + /// + /// Call this method to refresh the display when the item's information changes + /// 物品的信息发生变更时,调用此方法刷新显示器 + /// + /// + /// + ///New data for items after changes + ///发生改变后的物品新数据 + /// + /// + void Update(IItem? item); + + /// + /// Show item Display + /// 显示物品显示器 + /// + void ShowSelf(); + + /// + /// Hide item Display + /// 隐藏物品显示器 + /// + void HideSelf(); + +} \ No newline at end of file diff --git a/scripts/inventory/ItemContainerDisplayTemplate.cs b/scripts/inventory/ItemContainerDisplayTemplate.cs new file mode 100644 index 0000000..0799215 --- /dev/null +++ b/scripts/inventory/ItemContainerDisplayTemplate.cs @@ -0,0 +1,127 @@ +using System.Collections; +using System.Collections.Generic; +using ColdMint.scripts.map.events; + +namespace ColdMint.scripts.inventory; + +public abstract class ItemContainerDisplayTemplate : IItemContainerDisplay +{ + protected readonly List ItemDisplayList = []; + private IItemContainer? _itemContainer; + + public void BindItemContainer(IItemContainer itemContainer) + { + if (_itemContainer == itemContainer) + { + return; + } + + if (_itemContainer != null) + { + _itemContainer.SelectedItemChangeEvent -= OnSelectedItemChangeEvent; + } + + _itemContainer = itemContainer; + _itemContainer.SelectedItemChangeEvent += OnSelectedItemChangeEvent; + var totalCapacity = itemContainer.GetTotalCapacity(); + var currentCapacity = ItemDisplayList.Count; + var capacityDifference = totalCapacity - currentCapacity; + var adjustedEndIndex = totalCapacity; + if (capacityDifference > 0) + { + //There are those that need to be added, and we create them. + //有需要添加的,我们创建他们。 + for (var i = 0; i < capacityDifference; i++) + { + AddItemDisplay(); + } + } + else if (capacityDifference < 0) + { + //There are things that need to be hidden + //有需要被隐藏的 + adjustedEndIndex += capacityDifference; + var loopEndIndex = currentCapacity + capacityDifference; + for (var i = currentCapacity - 1; i >= loopEndIndex; i--) + { + var itemDisplay = ItemDisplayList[i]; + itemDisplay.Update(null); + itemDisplay.HideSelf(); + } + } + + UpdateData(itemContainer, adjustedEndIndex); + } + + private void OnSelectedItemChangeEvent(SelectedItemChangeEvent selectedItemChangeEvent) + { + if (_itemContainer == null) + { + return; + } + + var usedCapacity = _itemContainer.GetUsedCapacity(); + UpdateDataForSingleLocation(_itemContainer, selectedItemChangeEvent.OldIndex, usedCapacity); + UpdateDataForSingleLocation(_itemContainer, selectedItemChangeEvent.NewIndex, usedCapacity); + } + + /// + /// Update data + /// 更新数据 + /// + /// + ///Used to batch update the Item data in itemContainer to the display. + ///用于将itemContainer内的Item数据批量更新到显示器内。 + /// + /// + ///Item container data + ///物品容器数据 + /// + /// + ///endIndex + ///结束位置 + /// + /// + ///startIndex + ///起始位置 + /// + private void UpdateData(IItemContainer itemContainer, int endIndex, int startIndex = 0) + { + var usedCapacity = itemContainer.GetUsedCapacity(); + for (var i = startIndex; i < endIndex; i++) + { + var itemDisplay = ItemDisplayList[i]; + itemDisplay.Update(i < usedCapacity ? itemContainer.GetItem(i) : null); + itemDisplay.ShowSelf(); + } + } + + /// + /// Update data for a single location + /// 更新单个位置的数据 + /// + /// + /// + /// + private void UpdateDataForSingleLocation(IItemContainer itemContainer, int index, int usedCapacity) + { + var itemDisplay = ItemDisplayList[index]; + itemDisplay.Update(index < usedCapacity ? itemContainer.GetItem(index) : null); + } + + /// + /// Add item display + /// 添加物品显示器 + /// + protected abstract void AddItemDisplay(); + + public IEnumerator GetEnumerator() + { + return ItemDisplayList.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } +} \ No newline at end of file diff --git a/scripts/inventory/ItemSlotContainerDisplay.cs b/scripts/inventory/ItemSlotContainerDisplay.cs new file mode 100644 index 0000000..26769f2 --- /dev/null +++ b/scripts/inventory/ItemSlotContainerDisplay.cs @@ -0,0 +1,26 @@ +using ColdMint.scripts.utils; +using Godot; + +namespace ColdMint.scripts.inventory; + +public class ItemSlotContainerDisplay(Node rootNode) : ItemContainerDisplayTemplate +{ + private readonly PackedScene? _packedScene = GD.Load("res://prefab/ui/ItemSlot.tscn"); + + protected override void AddItemDisplay() + { + if (_packedScene == null) + { + return; + } + + var itemSlotNode = NodeUtils.InstantiatePackedScene(_packedScene); + if (itemSlotNode == null) + { + return; + } + + ItemDisplayList.Add(itemSlotNode); + NodeUtils.CallDeferredAddChild(rootNode, itemSlotNode); + } +} \ No newline at end of file diff --git a/scripts/inventory/ItemSlotNode.cs b/scripts/inventory/ItemSlotNode.cs index 428afc9..c8507da 100644 --- a/scripts/inventory/ItemSlotNode.cs +++ b/scripts/inventory/ItemSlotNode.cs @@ -10,7 +10,7 @@ namespace ColdMint.scripts.inventory; /// A slot in the inventory /// 物品栏内的一个插槽 /// -public partial class ItemSlotNode : MarginContainer +public partial class ItemSlotNode : MarginContainer, IItemDisplay { private TextureRect? _backgroundTextureRect; private TextureRect? _iconTextureRect; @@ -21,17 +21,6 @@ public partial class ItemSlotNode : MarginContainer private Texture2D? _backgroundTextureWhenSelect; private IItem? _item; - public IItem? Item - { - set - { - //Set item - //设置物品 - _item = value; - UpdateAllDisplay(); - } - } - public override void _Ready() { _backgroundTexture = GD.Load("res://sprites/ui/ItemBarEmpty.png"); @@ -49,8 +38,6 @@ public partial class ItemSlotNode : MarginContainer { if (_isSelect || _iconTextureRect == null) { - //Drag is not allowed if there is no icon or no pile of items. - //如果没有图标或者没有物品堆,那么不允许拖动。 return new Variant(); } @@ -141,35 +128,7 @@ public partial class ItemSlotNode : MarginContainer return _item; } - - /// - /// Clean out the items in the item slot - /// 清理物品槽内的物品 - /// - /// - ///Whether to release a node - ///是否释放节点 - /// - /// - ///Clean up item object references in item slots. - ///清理物品槽内的物品对象引用。 - /// - public void ClearItem(bool queueFree = true) - { - if (_item == null) - { - return; - } - - if (queueFree && _item is Node node) - { - node.QueueFree(); - } - - _item = null; - UpdateAllDisplay(); - } public override void _DropData(Vector2 atPosition, Variant data) { @@ -202,7 +161,7 @@ public partial class ItemSlotNode : MarginContainer if (packsack.ItemContainer != null && _item != null) { packsack.ItemContainer.AddItem(_item); - ClearItem(false); + // ClearItem(false); return; } } @@ -215,12 +174,12 @@ public partial class ItemSlotNode : MarginContainer } customPacksack.ItemContainer.AddItem(sourceItem); - itemSlotNode.ClearItem(false); + // itemSlotNode.ClearItem(false); return; } - AddItem(sourceItem); - itemSlotNode.ClearItem(false); + // AddItem(sourceItem); + // itemSlotNode.ClearItem(false); } /// @@ -251,24 +210,6 @@ public partial class ItemSlotNode : MarginContainer public TextureRect? BackgroundTextureRect => _backgroundTextureRect; - /// - /// Whether the item in this node is empty - /// 此节点内的物品是否为空的 - /// - /// - ///Return true if the number of items is 0 or the item object does not exist - ///当物品数量为0或物品对象不存在时,返回true - /// - public bool IsEmpty() - { - if (_item == null || _item.Quantity == 0) - { - return true; - } - - return false; - } - /// /// Update all displays of this slot @@ -386,53 +327,19 @@ public partial class ItemSlotNode : MarginContainer return true; } - /// - /// Remove items from the item slot - /// 从物品槽内移除物品 - /// - /// - ///number(Less than 0, remove all items) - ///物品数量(小于0,则移除全部物品) - /// - /// - ///How many items were actually removed - ///实际移除了多少个物品 - /// - public int RemoveItem(int number) + + public void Update(IItem? item) { - if (_item == null) - { - return 0; - } - - //The number of actual removals - //实际移除的数量 - var removeNumber = number < 0 ? _item.Quantity : number; - _item.Quantity -= removeNumber; - if (_item.Quantity <= 0) - { - ClearItem(); - } - - return removeNumber; + UpdateAllDisplay(); } - public bool AddItem(IItem item) + public void ShowSelf() { - if (_item == null) - { - Item = item; - return true; - } + Show(); + } - var newQuantity = item.Quantity + _item.Quantity; - _item.Quantity = Math.Min(newQuantity, _item.MaxQuantity); - if (item is Node2D node2D) - { - node2D.QueueFree(); - } - - UpdateQuantityLabel(); - return true; + public void HideSelf() + { + Hide(); } } \ No newline at end of file diff --git a/scripts/inventory/UniversalItemContainer.cs b/scripts/inventory/UniversalItemContainer.cs index 2395f57..fc1a2cb 100644 --- a/scripts/inventory/UniversalItemContainer.cs +++ b/scripts/inventory/UniversalItemContainer.cs @@ -280,10 +280,12 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer var oldItem = _itemList[oldIndex]; oldItem.IsSelect = false; - var newItem= _itemList[newIndex]; + var newItem = _itemList[newIndex]; newItem.IsSelect = true; SelectedItemChangeEvent?.Invoke(new SelectedItemChangeEvent { + NewIndex = newIndex, + OldIndex = oldIndex, NewItem = newItem, OldItem = oldItem }); diff --git a/scripts/map/events/SelectedItemChangeEvent.cs b/scripts/map/events/SelectedItemChangeEvent.cs index df83753..be2acbb 100644 --- a/scripts/map/events/SelectedItemChangeEvent.cs +++ b/scripts/map/events/SelectedItemChangeEvent.cs @@ -8,6 +8,10 @@ namespace ColdMint.scripts.map.events; /// public class SelectedItemChangeEvent { + public int NewIndex { get; set; } + + public int OldIndex { get; set; } + /// /// Newly selected item /// 新选中的物品 @@ -18,7 +22,5 @@ public class SelectedItemChangeEvent /// Lost the selected item /// 失去选中的物品 /// - // ReSharper disable UnusedAutoPropertyAccessor.Global public IItem? OldItem { get; set; } - // ReSharper restore UnusedAutoPropertyAccessor.Global } \ No newline at end of file