Bind the item container to the item container display.
将物品容器和物品容器显示器绑定。
This commit is contained in:
parent
32299877c6
commit
234241b74a
|
@ -10,13 +10,15 @@ namespace ColdMint.scripts.inventory;
|
||||||
public partial class HotBar : HBoxContainer
|
public partial class HotBar : HBoxContainer
|
||||||
{
|
{
|
||||||
private IItemContainer? _itemContainer;
|
private IItemContainer? _itemContainer;
|
||||||
|
private IItemContainerDisplay? _itemContainerDisplay;
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
base._Ready();
|
base._Ready();
|
||||||
_itemContainer = new UniversalItemContainer(Config.HotBarSize);
|
_itemContainer = new UniversalItemContainer(Config.HotBarSize);
|
||||||
_itemContainer.SupportSelect = true;
|
_itemContainer.SupportSelect = true;
|
||||||
|
_itemContainerDisplay = new ItemSlotContainerDisplay(this);
|
||||||
|
_itemContainerDisplay.BindItemContainer(_itemContainer);
|
||||||
NodeUtils.DeleteAllChild(this);
|
NodeUtils.DeleteAllChild(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
13
scripts/inventory/IItemContainerDisplay.cs
Normal file
13
scripts/inventory/IItemContainerDisplay.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace ColdMint.scripts.inventory;
|
||||||
|
|
||||||
|
public interface IItemContainerDisplay : IEnumerable<IItemDisplay>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Bind an item container to the item container display</para>
|
||||||
|
/// <para>为物品容器显示器绑定物品容器</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemContainer"></param>
|
||||||
|
void BindItemContainer(IItemContainer itemContainer);
|
||||||
|
}
|
34
scripts/inventory/IItemDisplay.cs
Normal file
34
scripts/inventory/IItemDisplay.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
namespace ColdMint.scripts.inventory;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>IItemDisplay</para>
|
||||||
|
/// <para>物品显示器</para>
|
||||||
|
/// </summary>
|
||||||
|
public interface IItemDisplay
|
||||||
|
{
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Call this method to refresh the display when the item's information changes</para>
|
||||||
|
/// <para>物品的信息发生变更时,调用此方法刷新显示器</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<param name="item">
|
||||||
|
///<para>New data for items after changes</para>
|
||||||
|
///<para>发生改变后的物品新数据</para>
|
||||||
|
/// </param>
|
||||||
|
/// </remarks>
|
||||||
|
void Update(IItem? item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Show item Display</para>
|
||||||
|
/// <para>显示物品显示器</para>
|
||||||
|
/// </summary>
|
||||||
|
void ShowSelf();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Hide item Display</para>
|
||||||
|
/// <para>隐藏物品显示器</para>
|
||||||
|
/// </summary>
|
||||||
|
void HideSelf();
|
||||||
|
|
||||||
|
}
|
127
scripts/inventory/ItemContainerDisplayTemplate.cs
Normal file
127
scripts/inventory/ItemContainerDisplayTemplate.cs
Normal file
|
@ -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<IItemDisplay> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Update data</para>
|
||||||
|
/// <para>更新数据</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
///<para>Used to batch update the Item data in itemContainer to the display.</para>
|
||||||
|
///<para>用于将itemContainer内的Item数据批量更新到显示器内。</para>
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="itemContainer">
|
||||||
|
///<para>Item container data</para>
|
||||||
|
///<para>物品容器数据</para>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="endIndex">
|
||||||
|
///<para>endIndex</para>
|
||||||
|
///<para>结束位置</para>
|
||||||
|
/// </param>
|
||||||
|
/// <param name="startIndex">
|
||||||
|
///<para>startIndex</para>
|
||||||
|
///<para>起始位置</para>
|
||||||
|
/// </param>
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Update data for a single location</para>
|
||||||
|
/// <para>更新单个位置的数据</para>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="itemContainer"></param>
|
||||||
|
/// <param name="index"></param>
|
||||||
|
/// <param name="usedCapacity"></param>
|
||||||
|
private void UpdateDataForSingleLocation(IItemContainer itemContainer, int index, int usedCapacity)
|
||||||
|
{
|
||||||
|
var itemDisplay = ItemDisplayList[index];
|
||||||
|
itemDisplay.Update(index < usedCapacity ? itemContainer.GetItem(index) : null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <para>Add item display</para>
|
||||||
|
/// <para>添加物品显示器</para>
|
||||||
|
/// </summary>
|
||||||
|
protected abstract void AddItemDisplay();
|
||||||
|
|
||||||
|
public IEnumerator<IItemDisplay> GetEnumerator()
|
||||||
|
{
|
||||||
|
return ItemDisplayList.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
}
|
26
scripts/inventory/ItemSlotContainerDisplay.cs
Normal file
26
scripts/inventory/ItemSlotContainerDisplay.cs
Normal file
|
@ -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<PackedScene>("res://prefab/ui/ItemSlot.tscn");
|
||||||
|
|
||||||
|
protected override void AddItemDisplay()
|
||||||
|
{
|
||||||
|
if (_packedScene == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var itemSlotNode = NodeUtils.InstantiatePackedScene<ItemSlotNode>(_packedScene);
|
||||||
|
if (itemSlotNode == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemDisplayList.Add(itemSlotNode);
|
||||||
|
NodeUtils.CallDeferredAddChild(rootNode, itemSlotNode);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ namespace ColdMint.scripts.inventory;
|
||||||
/// <para>A slot in the inventory</para>
|
/// <para>A slot in the inventory</para>
|
||||||
/// <para>物品栏内的一个插槽</para>
|
/// <para>物品栏内的一个插槽</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class ItemSlotNode : MarginContainer
|
public partial class ItemSlotNode : MarginContainer, IItemDisplay
|
||||||
{
|
{
|
||||||
private TextureRect? _backgroundTextureRect;
|
private TextureRect? _backgroundTextureRect;
|
||||||
private TextureRect? _iconTextureRect;
|
private TextureRect? _iconTextureRect;
|
||||||
|
@ -21,17 +21,6 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
private Texture2D? _backgroundTextureWhenSelect;
|
private Texture2D? _backgroundTextureWhenSelect;
|
||||||
private IItem? _item;
|
private IItem? _item;
|
||||||
|
|
||||||
public IItem? Item
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
//Set item
|
|
||||||
//设置物品
|
|
||||||
_item = value;
|
|
||||||
UpdateAllDisplay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void _Ready()
|
public override void _Ready()
|
||||||
{
|
{
|
||||||
_backgroundTexture = GD.Load<Texture2D>("res://sprites/ui/ItemBarEmpty.png");
|
_backgroundTexture = GD.Load<Texture2D>("res://sprites/ui/ItemBarEmpty.png");
|
||||||
|
@ -49,8 +38,6 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
{
|
{
|
||||||
if (_isSelect || _iconTextureRect == null)
|
if (_isSelect || _iconTextureRect == null)
|
||||||
{
|
{
|
||||||
//Drag is not allowed if there is no icon or no pile of items.
|
|
||||||
//如果没有图标或者没有物品堆,那么不允许拖动。
|
|
||||||
return new Variant();
|
return new Variant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,34 +130,6 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Clean out the items in the item slot</para>
|
|
||||||
/// <para>清理物品槽内的物品</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="queueFree">
|
|
||||||
///<para>Whether to release a node</para>
|
|
||||||
///<para>是否释放节点</para>
|
|
||||||
/// </param>
|
|
||||||
/// <remarks>
|
|
||||||
///<para>Clean up item object references in item slots.</para>
|
|
||||||
///<para>清理物品槽内的物品对象引用。</para>
|
|
||||||
/// </remarks>
|
|
||||||
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)
|
public override void _DropData(Vector2 atPosition, Variant data)
|
||||||
{
|
{
|
||||||
if (_iconTextureRect == null)
|
if (_iconTextureRect == null)
|
||||||
|
@ -202,7 +161,7 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
if (packsack.ItemContainer != null && _item != null)
|
if (packsack.ItemContainer != null && _item != null)
|
||||||
{
|
{
|
||||||
packsack.ItemContainer.AddItem(_item);
|
packsack.ItemContainer.AddItem(_item);
|
||||||
ClearItem(false);
|
// ClearItem(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,12 +174,12 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
}
|
}
|
||||||
|
|
||||||
customPacksack.ItemContainer.AddItem(sourceItem);
|
customPacksack.ItemContainer.AddItem(sourceItem);
|
||||||
itemSlotNode.ClearItem(false);
|
// itemSlotNode.ClearItem(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddItem(sourceItem);
|
// AddItem(sourceItem);
|
||||||
itemSlotNode.ClearItem(false);
|
// itemSlotNode.ClearItem(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -251,24 +210,6 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
|
|
||||||
public TextureRect? BackgroundTextureRect => _backgroundTextureRect;
|
public TextureRect? BackgroundTextureRect => _backgroundTextureRect;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Whether the item in this node is empty</para>
|
|
||||||
/// <para>此节点内的物品是否为空的</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <returns>
|
|
||||||
///<para>Return true if the number of items is 0 or the item object does not exist</para>
|
|
||||||
///<para>当物品数量为0或物品对象不存在时,返回true</para>
|
|
||||||
/// </returns>
|
|
||||||
public bool IsEmpty()
|
|
||||||
{
|
|
||||||
if (_item == null || _item.Quantity == 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Update all displays of this slot</para>
|
/// <para>Update all displays of this slot</para>
|
||||||
|
@ -386,53 +327,19 @@ public partial class ItemSlotNode : MarginContainer
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// <para>Remove items from the item slot</para>
|
public void Update(IItem? item)
|
||||||
/// <para>从物品槽内移除物品</para>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="number">
|
|
||||||
///<para>number(Less than 0, remove all items)</para>
|
|
||||||
///<para>物品数量(小于0,则移除全部物品)</para>
|
|
||||||
/// </param>
|
|
||||||
/// <returns>
|
|
||||||
///<para>How many items were actually removed</para>
|
|
||||||
///<para>实际移除了多少个物品</para>
|
|
||||||
/// </returns>
|
|
||||||
public int RemoveItem(int number)
|
|
||||||
{
|
{
|
||||||
if (_item == null)
|
UpdateAllDisplay();
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//The number of actual removals
|
public void ShowSelf()
|
||||||
//实际移除的数量
|
|
||||||
var removeNumber = number < 0 ? _item.Quantity : number;
|
|
||||||
_item.Quantity -= removeNumber;
|
|
||||||
if (_item.Quantity <= 0)
|
|
||||||
{
|
{
|
||||||
ClearItem();
|
Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
return removeNumber;
|
public void HideSelf()
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddItem(IItem item)
|
|
||||||
{
|
{
|
||||||
if (_item == null)
|
Hide();
|
||||||
{
|
|
||||||
Item = item;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var newQuantity = item.Quantity + _item.Quantity;
|
|
||||||
_item.Quantity = Math.Min(newQuantity, _item.MaxQuantity);
|
|
||||||
if (item is Node2D node2D)
|
|
||||||
{
|
|
||||||
node2D.QueueFree();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateQuantityLabel();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -280,10 +280,12 @@ public class UniversalItemContainer(int totalCapacity) : IItemContainer
|
||||||
|
|
||||||
var oldItem = _itemList[oldIndex];
|
var oldItem = _itemList[oldIndex];
|
||||||
oldItem.IsSelect = false;
|
oldItem.IsSelect = false;
|
||||||
var newItem= _itemList[newIndex];
|
var newItem = _itemList[newIndex];
|
||||||
newItem.IsSelect = true;
|
newItem.IsSelect = true;
|
||||||
SelectedItemChangeEvent?.Invoke(new SelectedItemChangeEvent
|
SelectedItemChangeEvent?.Invoke(new SelectedItemChangeEvent
|
||||||
{
|
{
|
||||||
|
NewIndex = newIndex,
|
||||||
|
OldIndex = oldIndex,
|
||||||
NewItem = newItem,
|
NewItem = newItem,
|
||||||
OldItem = oldItem
|
OldItem = oldItem
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,6 +8,10 @@ namespace ColdMint.scripts.map.events;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SelectedItemChangeEvent
|
public class SelectedItemChangeEvent
|
||||||
{
|
{
|
||||||
|
public int NewIndex { get; set; }
|
||||||
|
|
||||||
|
public int OldIndex { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// <para>Newly selected item</para>
|
/// <para>Newly selected item</para>
|
||||||
/// <para>新选中的物品</para>
|
/// <para>新选中的物品</para>
|
||||||
|
@ -18,7 +22,5 @@ public class SelectedItemChangeEvent
|
||||||
/// <para>Lost the selected item</para>
|
/// <para>Lost the selected item</para>
|
||||||
/// <para>失去选中的物品</para>
|
/// <para>失去选中的物品</para>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
// ReSharper disable UnusedAutoPropertyAccessor.Global
|
|
||||||
public IItem? OldItem { get; set; }
|
public IItem? OldItem { get; set; }
|
||||||
// ReSharper restore UnusedAutoPropertyAccessor.Global
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user