Improve the efficiency of backpack UI toggle visibility. Prepare for the upcoming workbench UI.

提升背包UI切换可见度时的效率。为即将到来的工作台UI做准备。
This commit is contained in:
Cold-Mint 2024-09-14 23:38:57 +08:00
parent ba11bf06da
commit c25d985f87
Signed by: Cold-Mint
GPG Key ID: C5A9BF8A98E0CE99
9 changed files with 151 additions and 45 deletions

View File

@ -79,5 +79,4 @@ texture = ExtResource("5_4pssd")
[node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")] [node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")]
position = Vector2(149, 109) position = Vector2(149, 109)
collision_layer = 256
collision_mask = 0 collision_mask = 0

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=8 format=3 uid="uid://bnftvkj2cido7"] [gd_scene load_steps=9 format=3 uid="uid://bnftvkj2cido7"]
[ext_resource type="Script" path="res://scripts/loader/sceneLoader/GameSceneLoader.cs" id="1_mqdgt"] [ext_resource type="Script" path="res://scripts/loader/sceneLoader/GameSceneLoader.cs" id="1_mqdgt"]
[ext_resource type="Texture2D" uid="uid://cs6e0af876ss5" path="res://sprites/ui/HeartEmpty.png" id="2_n1yht"] [ext_resource type="Texture2D" uid="uid://cs6e0af876ss5" path="res://sprites/ui/HeartEmpty.png" id="2_n1yht"]
@ -7,6 +7,7 @@
[ext_resource type="Script" path="res://scripts/FpsLabel.cs" id="5_dis4v"] [ext_resource type="Script" path="res://scripts/FpsLabel.cs" id="5_dis4v"]
[ext_resource type="PackedScene" uid="uid://c74180dtf7j7a" path="res://scenes/mapContainer.tscn" id="6_ljdj4"] [ext_resource type="PackedScene" uid="uid://c74180dtf7j7a" path="res://scenes/mapContainer.tscn" id="6_ljdj4"]
[ext_resource type="PackedScene" uid="uid://bb188382q7btp" path="res://scenes/gameOverMenu.tscn" id="6_yjmrv"] [ext_resource type="PackedScene" uid="uid://bb188382q7btp" path="res://scenes/gameOverMenu.tscn" id="6_yjmrv"]
[ext_resource type="Script" path="res://scripts/utils/UiGroup.cs" id="7_p0u6a"]
[node name="Game" type="Node2D"] [node name="Game" type="Node2D"]
script = ExtResource("1_mqdgt") script = ExtResource("1_mqdgt")
@ -103,6 +104,7 @@ anchor_bottom = 1.0
grow_horizontal = 2 grow_horizontal = 2
grow_vertical = 2 grow_vertical = 2
mouse_filter = 2 mouse_filter = 2
script = ExtResource("7_p0u6a")
[node name="GameOverMenu" parent="CanvasLayer" instance=ExtResource("6_yjmrv")] [node name="GameOverMenu" parent="CanvasLayer" instance=ExtResource("6_yjmrv")]
visible = false visible = false

View File

@ -1,6 +1,5 @@
using ColdMint.scripts.character; using ColdMint.scripts.character;
using ColdMint.scripts.inventory; using ColdMint.scripts.inventory;
using ColdMint.scripts.loader.uiLoader;
using ColdMint.scripts.map.miniMap; using ColdMint.scripts.map.miniMap;
using ColdMint.scripts.utils; using ColdMint.scripts.utils;
using Godot; using Godot;
@ -101,35 +100,5 @@ public static class GameSceneDepend
///<para>The knapsack Ui container houses the container of the knapsack ui node. When a user uses a backpack, the node to which his backpack is attached is displayed from within the backpack ui container.</para> ///<para>The knapsack Ui container houses the container of the knapsack ui node. When a user uses a backpack, the node to which his backpack is attached is displayed from within the backpack ui container.</para>
///<para>背包Ui容器内存放的是背包ui节点的容器。当用户使用背包时会从背包ui容器内将其背包对于的节点展示出来。</para> ///<para>背包Ui容器内存放的是背包ui节点的容器。当用户使用背包时会从背包ui容器内将其背包对于的节点展示出来。</para>
/// </remarks> /// </remarks>
public static Control? BackpackUiContainer { get; set; } public static UiGroup? BackpackUiContainer { get; set; }
/// <summary>
/// <para>Hide the knapsack node in the knapsack Ui if the knapsack UI is displayed</para>
/// <para>如果背包Ui处于显示状态那么隐藏背包UI内的背包节点</para>
/// </summary>
public static void HideBackpackUiContainerIfVisible()
{
if (BackpackUiContainer == null)
{
return;
}
if (!BackpackUiContainer.Visible)
{
return;
}
NodeUtils.ForEachNode<PacksackUi>(BackpackUiContainer, node =>
{
//If the child node is not visible, the traversal continues.
//如果子节点不可见,则继续遍历。
if (!node.Visible)
return false;
//Until you find a visible node, hide it, and return true, ending the loop.
//直到找到可见的节点隐藏该节点然后返回true结束遍历。
node.Hide();
return true;
});
}
} }

View File

@ -626,7 +626,7 @@ public partial class CharacterTemplate : CharacterBody2D
{ {
if (_additionalForce != Vector2.Zero) if (_additionalForce != Vector2.Zero)
{ {
throw new InvalidOperationException("AddForce called more than once"); return;
} }
_additionalForce = force; _additionalForce = force;

View File

@ -89,7 +89,7 @@ public partial class Player : CharacterTemplate
private void SelectedItemSlotChangeEvent(SelectedItemSlotChangeEvent selectedItemSlotChangeEvent) private void SelectedItemSlotChangeEvent(SelectedItemSlotChangeEvent selectedItemSlotChangeEvent)
{ {
var item = selectedItemSlotChangeEvent.NewItemSlotNode?.GetItem(); var item = selectedItemSlotChangeEvent.NewItemSlotNode?.GetItem();
GameSceneDepend.HideBackpackUiContainerIfVisible(); GameSceneDepend.BackpackUiContainer?.HideAllControl();
if (item is Node2D node2D) if (item is Node2D node2D)
{ {
CurrentItem = node2D; CurrentItem = node2D;
@ -303,7 +303,7 @@ public partial class Player : CharacterTemplate
} }
ThrowItem(ItemContainer.GetSelectIndex(), 1, GetThrowVelocity()); ThrowItem(ItemContainer.GetSelectIndex(), 1, GetThrowVelocity());
GameSceneDepend.HideBackpackUiContainerIfVisible(); GameSceneDepend.BackpackUiContainer?.HideAllControl();
CurrentItem = null; CurrentItem = null;
} }
} }

View File

@ -23,7 +23,8 @@ public partial class Packsack : PickAbleTemplate
///<para>Can a new backpack be placed in the slot of the backpack?</para> ///<para>Can a new backpack be placed in the slot of the backpack?</para>
///<para>即此背包的槽位内是否可以再放置新的背包?</para> ///<para>即此背包的槽位内是否可以再放置新的背包?</para>
/// </remarks> /// </remarks>
[Export] public bool BackpackAllowed { get; set; } [Export]
public bool BackpackAllowed { get; set; }
public override bool CanPutInPack => false; public override bool CanPutInPack => false;
@ -40,14 +41,26 @@ public partial class Packsack : PickAbleTemplate
_packsackUi = NodeUtils.InstantiatePackedScene<PacksackUi>(_packedScene); _packsackUi = NodeUtils.InstantiatePackedScene<PacksackUi>(_packedScene);
if (_packsackUi != null) if (_packsackUi != null)
{ {
NodeUtils.CallDeferredAddChild(NodeUtils.FindContainerNode(_packsackUi, this), _packsackUi); var containerNode = NodeUtils.FindContainerNode(_packsackUi, this);
if (containerNode is UiGroup uiGroup)
{
uiGroup.RegisterControl(_packsackUi);
}
else
{
NodeUtils.CallDeferredAddChild(containerNode, _packsackUi);
}
_packsackUi.Title = Name; _packsackUi.Title = Name;
_packsackUi.ItemContainer = ItemContainer; _packsackUi.ItemContainer = ItemContainer;
_packsackUi.Hide();
} }
} }
GameSceneDepend.BackpackUiContainer?.Show(); if (_packsackUi != null)
_packsackUi?.Show(); {
GameSceneDepend.BackpackUiContainer?.ShowControl(_packsackUi);
}
} }
public IItemContainer? ItemContainer { get; private set; } public IItemContainer? ItemContainer { get; private set; }

View File

@ -31,7 +31,7 @@ public partial class GameSceneLoader : SceneLoaderTemplate
GameSceneDepend.HotBar = hotBar; GameSceneDepend.HotBar = hotBar;
//Backpack Ui container //Backpack Ui container
//背包Ui容器 //背包Ui容器
var backpackUiContainer = GetNode<Control>("CanvasLayer/BackpackUIContainer"); var backpackUiContainer = GetNode<UiGroup>("CanvasLayer/BackpackUIContainer");
GameSceneDepend.BackpackUiContainer = backpackUiContainer; GameSceneDepend.BackpackUiContainer = backpackUiContainer;
//Load operation prompt //Load operation prompt
//加载操作提示 //加载操作提示

View File

@ -107,8 +107,7 @@ public partial class PacksackUi : UiLoaderTemplate
{ {
_exitButton.Pressed += () => _exitButton.Pressed += () =>
{ {
GameSceneDepend.BackpackUiContainer?.Hide(); GameSceneDepend.BackpackUiContainer?.HideControl(this);
Hide();
}; };
} }
} }

124
scripts/utils/UiGroup.cs Normal file
View File

@ -0,0 +1,124 @@
using System.Collections.Generic;
using Godot;
namespace ColdMint.scripts.utils;
/// <summary>
/// <para>UI Group</para>
/// <para>UI组</para>
/// </summary>
public partial class UiGroup : Control
{
private readonly HashSet<Control> _visibleControls = [];
private readonly HashSet<Control> _allControls = [];
/// <summary>
/// <para>How many nodes are visible</para>
/// <para>有多少个节点处于可见状态</para>
/// </summary>
public int VisibleControlsCount => _visibleControls.Count;
/// <summary>
/// <para>Register nodes in the UI group. For registered nodes, do not use <see cref="Godot.CanvasItem.Show"/> or <see cref="Godot.CanvasItem.Hide"/> to change the visible state. Call the <see cref="ShowControl"/> and <see cref="HideControl"/> methods instead.</para>
/// <para>注册节点到UI组内对于已注册的节点不要直接使用<see cref="Godot.CanvasItem.Show"/>或<see cref="Godot.CanvasItem.Hide"/>方法来改变可见状态,请调用<see cref="ShowControl"/>和<see cref="HideControl"/>方法来替代他们。</para>
/// </summary>
/// <param name="control"></param>
public void RegisterControl(Control control)
{
control.TreeExited += () => { OnTreeExited(control); };
NodeUtils.CallDeferredAddChild(this, control);
_allControls.Add(control);
}
/// <summary>
/// <para>Hide all nodes</para>
/// <para>隐藏全部节点</para>
/// </summary>
public void HideAllControl()
{
if (_visibleControls.Count == 0)
{
return;
}
foreach (var visibleControl in _visibleControls)
{
visibleControl.Hide();
}
_visibleControls.Clear();
Hide();
}
/// <summary>
/// <para>Hide a node</para>
/// <para>隐藏某个节点</para>
/// </summary>
/// <param name="control"></param>
/// <returns></returns>
public bool HideControl(Control control)
{
if (!control.IsVisible())
{
return false;
}
if (!_allControls.Contains(control))
{
return false;
}
control.Hide();
_visibleControls.Remove(control);
ChangeSelfVisibility();
return true;
}
/// <summary>
/// <para>Show node</para>
/// <para>显示某个节点</para>
/// </summary>
/// <param name="control"></param>
/// <returns></returns>
public bool ShowControl(Control control)
{
if (control.IsVisible())
{
return false;
}
if (!_allControls.Contains(control))
{
return false;
}
control.Show();
_visibleControls.Add(control);
ChangeSelfVisibility();
return true;
}
/// <summary>
/// <para>ChangeSelfVisibility</para>
/// <para>改变自身的可见度</para>
/// </summary>
private void ChangeSelfVisibility()
{
if (_visibleControls.Count == 0)
{
Hide();
}
else
{
Show();
}
}
private void OnTreeExited(Control control)
{
//The Hide method is not called when a node exits from the tree, so remove the node here to prevent empty references.
//当节点从节点树内退出时并不会调用Hide方法所以在这里移除节点防止产生空引用。
_visibleControls.Remove(control);
_allControls.Remove(control);
}
}