diff --git a/prefab/roomTemplates/dungeon/initialRoom.tscn b/prefab/roomTemplates/dungeon/initialRoom.tscn
index 5387b44..6767cd1 100644
--- a/prefab/roomTemplates/dungeon/initialRoom.tscn
+++ b/prefab/roomTemplates/dungeon/initialRoom.tscn
@@ -79,5 +79,4 @@ texture = ExtResource("5_4pssd")
[node name="RigidBody2D" parent="." instance=ExtResource("5_7c8bh")]
position = Vector2(149, 109)
-collision_layer = 256
collision_mask = 0
diff --git a/scenes/game.tscn b/scenes/game.tscn
index bba6d90..115c3b5 100644
--- a/scenes/game.tscn
+++ b/scenes/game.tscn
@@ -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="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="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="Script" path="res://scripts/utils/UiGroup.cs" id="7_p0u6a"]
[node name="Game" type="Node2D"]
script = ExtResource("1_mqdgt")
@@ -103,6 +104,7 @@ anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
mouse_filter = 2
+script = ExtResource("7_p0u6a")
[node name="GameOverMenu" parent="CanvasLayer" instance=ExtResource("6_yjmrv")]
visible = false
diff --git a/scripts/GameSceneDepend.cs b/scripts/GameSceneDepend.cs
index 2b1b4dc..5b5d5d9 100644
--- a/scripts/GameSceneDepend.cs
+++ b/scripts/GameSceneDepend.cs
@@ -1,6 +1,5 @@
using ColdMint.scripts.character;
using ColdMint.scripts.inventory;
-using ColdMint.scripts.loader.uiLoader;
using ColdMint.scripts.map.miniMap;
using ColdMint.scripts.utils;
using Godot;
@@ -101,35 +100,5 @@ public static class GameSceneDepend
///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.
///背包Ui容器内存放的是背包ui节点的容器。当用户使用背包时,会从背包ui容器内将其背包对于的节点展示出来。
///
- public static Control? BackpackUiContainer { get; set; }
-
-
- ///
- /// Hide the knapsack node in the knapsack Ui if the knapsack UI is displayed
- /// 如果背包Ui处于显示状态,那么隐藏背包UI内的背包节点
- ///
- public static void HideBackpackUiContainerIfVisible()
- {
- if (BackpackUiContainer == null)
- {
- return;
- }
-
- if (!BackpackUiContainer.Visible)
- {
- return;
- }
-
- NodeUtils.ForEachNode(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;
- });
- }
+ public static UiGroup? BackpackUiContainer { get; set; }
}
\ No newline at end of file
diff --git a/scripts/character/CharacterTemplate.cs b/scripts/character/CharacterTemplate.cs
index 5966795..553430d 100644
--- a/scripts/character/CharacterTemplate.cs
+++ b/scripts/character/CharacterTemplate.cs
@@ -626,7 +626,7 @@ public partial class CharacterTemplate : CharacterBody2D
{
if (_additionalForce != Vector2.Zero)
{
- throw new InvalidOperationException("AddForce called more than once");
+ return;
}
_additionalForce = force;
diff --git a/scripts/character/Player.cs b/scripts/character/Player.cs
index 5bead97..6b5897b 100644
--- a/scripts/character/Player.cs
+++ b/scripts/character/Player.cs
@@ -89,7 +89,7 @@ public partial class Player : CharacterTemplate
private void SelectedItemSlotChangeEvent(SelectedItemSlotChangeEvent selectedItemSlotChangeEvent)
{
var item = selectedItemSlotChangeEvent.NewItemSlotNode?.GetItem();
- GameSceneDepend.HideBackpackUiContainerIfVisible();
+ GameSceneDepend.BackpackUiContainer?.HideAllControl();
if (item is Node2D node2D)
{
CurrentItem = node2D;
@@ -303,7 +303,7 @@ public partial class Player : CharacterTemplate
}
ThrowItem(ItemContainer.GetSelectIndex(), 1, GetThrowVelocity());
- GameSceneDepend.HideBackpackUiContainerIfVisible();
+ GameSceneDepend.BackpackUiContainer?.HideAllControl();
CurrentItem = null;
}
}
diff --git a/scripts/inventory/Packsack.cs b/scripts/inventory/Packsack.cs
index 1a36e31..1245dd7 100644
--- a/scripts/inventory/Packsack.cs
+++ b/scripts/inventory/Packsack.cs
@@ -14,7 +14,7 @@ public partial class Packsack : PickAbleTemplate
private PackedScene? _packedScene;
private PacksackUi? _packsackUi;
[Export] public int NumberSlots { get; set; }
-
+
///
/// Whether to allow backpacks
/// 是否允许放置背包
@@ -23,7 +23,8 @@ public partial class Packsack : PickAbleTemplate
///Can a new backpack be placed in the slot of the backpack?
///即此背包的槽位内是否可以再放置新的背包?
///
- [Export] public bool BackpackAllowed { get; set; }
+ [Export]
+ public bool BackpackAllowed { get; set; }
public override bool CanPutInPack => false;
@@ -40,14 +41,26 @@ public partial class Packsack : PickAbleTemplate
_packsackUi = NodeUtils.InstantiatePackedScene(_packedScene);
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.ItemContainer = ItemContainer;
+ _packsackUi.Hide();
}
}
- GameSceneDepend.BackpackUiContainer?.Show();
- _packsackUi?.Show();
+ if (_packsackUi != null)
+ {
+ GameSceneDepend.BackpackUiContainer?.ShowControl(_packsackUi);
+ }
}
public IItemContainer? ItemContainer { get; private set; }
diff --git a/scripts/loader/sceneLoader/GameSceneLoader.cs b/scripts/loader/sceneLoader/GameSceneLoader.cs
index 2db575f..551e0c7 100644
--- a/scripts/loader/sceneLoader/GameSceneLoader.cs
+++ b/scripts/loader/sceneLoader/GameSceneLoader.cs
@@ -31,7 +31,7 @@ public partial class GameSceneLoader : SceneLoaderTemplate
GameSceneDepend.HotBar = hotBar;
//Backpack Ui container
//背包Ui容器
- var backpackUiContainer = GetNode("CanvasLayer/BackpackUIContainer");
+ var backpackUiContainer = GetNode("CanvasLayer/BackpackUIContainer");
GameSceneDepend.BackpackUiContainer = backpackUiContainer;
//Load operation prompt
//加载操作提示
diff --git a/scripts/loader/uiLoader/PacksackUi.cs b/scripts/loader/uiLoader/PacksackUi.cs
index ab1b998..4ad9470 100644
--- a/scripts/loader/uiLoader/PacksackUi.cs
+++ b/scripts/loader/uiLoader/PacksackUi.cs
@@ -107,8 +107,7 @@ public partial class PacksackUi : UiLoaderTemplate
{
_exitButton.Pressed += () =>
{
- GameSceneDepend.BackpackUiContainer?.Hide();
- Hide();
+ GameSceneDepend.BackpackUiContainer?.HideControl(this);
};
}
}
diff --git a/scripts/utils/UiGroup.cs b/scripts/utils/UiGroup.cs
new file mode 100644
index 0000000..6bd7d1a
--- /dev/null
+++ b/scripts/utils/UiGroup.cs
@@ -0,0 +1,124 @@
+using System.Collections.Generic;
+using Godot;
+
+namespace ColdMint.scripts.utils;
+
+///
+/// UI Group
+/// UI组
+///
+public partial class UiGroup : Control
+{
+ private readonly HashSet _visibleControls = [];
+ private readonly HashSet _allControls = [];
+
+ ///
+ /// How many nodes are visible
+ /// 有多少个节点处于可见状态
+ ///
+ public int VisibleControlsCount => _visibleControls.Count;
+
+ ///
+ /// Register nodes in the UI group. For registered nodes, do not use or to change the visible state. Call the and methods instead.
+ /// 注册节点到UI组内,对于已注册的节点,不要直接使用或方法来改变可见状态,请调用和方法来替代他们。
+ ///
+ ///
+ public void RegisterControl(Control control)
+ {
+ control.TreeExited += () => { OnTreeExited(control); };
+ NodeUtils.CallDeferredAddChild(this, control);
+ _allControls.Add(control);
+ }
+
+ ///
+ /// Hide all nodes
+ /// 隐藏全部节点
+ ///
+ public void HideAllControl()
+ {
+ if (_visibleControls.Count == 0)
+ {
+ return;
+ }
+
+ foreach (var visibleControl in _visibleControls)
+ {
+ visibleControl.Hide();
+ }
+
+ _visibleControls.Clear();
+ Hide();
+ }
+
+ ///
+ /// Hide a node
+ /// 隐藏某个节点
+ ///
+ ///
+ ///
+ public bool HideControl(Control control)
+ {
+ if (!control.IsVisible())
+ {
+ return false;
+ }
+
+ if (!_allControls.Contains(control))
+ {
+ return false;
+ }
+
+ control.Hide();
+ _visibleControls.Remove(control);
+ ChangeSelfVisibility();
+ return true;
+ }
+
+ ///
+ /// Show node
+ /// 显示某个节点
+ ///
+ ///
+ ///
+ public bool ShowControl(Control control)
+ {
+ if (control.IsVisible())
+ {
+ return false;
+ }
+
+ if (!_allControls.Contains(control))
+ {
+ return false;
+ }
+
+ control.Show();
+ _visibleControls.Add(control);
+ ChangeSelfVisibility();
+ return true;
+ }
+
+ ///
+ /// ChangeSelfVisibility
+ /// 改变自身的可见度
+ ///
+ 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);
+ }
+}
\ No newline at end of file