diff --git a/DungeonShooting_Godot/prefab/ui/MapEditorCreateRoom.tscn b/DungeonShooting_Godot/prefab/ui/MapEditorCreateRoom.tscn index eb89af9..6012bae 100644 --- a/DungeonShooting_Godot/prefab/ui/MapEditorCreateRoom.tscn +++ b/DungeonShooting_Godot/prefab/ui/MapEditorCreateRoom.tscn @@ -7,5 +7,7 @@ anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 script = ExtResource("1_dep3f") Layer = 3 diff --git a/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs b/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs index 16960a6..0cfe656 100644 --- a/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs +++ b/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs @@ -98,7 +98,7 @@ public static void GenerateUiCode(Node control, string path) { _nodeNameMap.Clear(); - var uiNode = EachNode(control.Name, control); + var uiNode = EachNodeFromEditor(control.Name, control); var code = GenerateClassCode(uiNode); File.WriteAllText(path, code); } @@ -140,23 +140,53 @@ private static string GenerateClassCode(UiNodeInfo uiNodeInfo) { + var retraction = " "; return $"namespace UI.{uiNodeInfo.OriginName};\n\n" + $"/// \n" + $"/// Ui代码, 该类是根据ui场景自动生成的, 请不要手动编辑该类, 以免造成代码丢失\n" + $"/// \n" + $"public abstract partial class {uiNodeInfo.OriginName} : UiBase\n" + $"{{\n" + - GeneratePropertyListClassCode("", uiNodeInfo.OriginName + ".", uiNodeInfo, " ") + + GeneratePropertyListClassCode("", uiNodeInfo.OriginName + ".", uiNodeInfo, retraction) + $"\n" + $" public {uiNodeInfo.OriginName}() : base(nameof({uiNodeInfo.OriginName}))\n" + $" {{\n" + $" }}\n" + $"\n" + - GenerateAllChildrenClassCode(uiNodeInfo.OriginName + ".", uiNodeInfo, " ") + + $" public sealed override void OnInitNestedUi()\n" + + $" {{\n" + + GenerateInitNestedUi("", uiNodeInfo, retraction) + + $" }}\n" + $"\n" + - GenerateSoleLayerCode(uiNodeInfo, "", uiNodeInfo.OriginName, " ") + + GenerateAllChildrenClassCode(uiNodeInfo.OriginName + ".", uiNodeInfo, retraction) + + $"\n" + + GenerateSoleLayerCode(uiNodeInfo, "", uiNodeInfo.OriginName, retraction) + $"}}\n"; } + + private static string GenerateInitNestedUi(string layer, UiNodeInfo uiNodeInfo, string retraction) + { + var str = ""; + if (uiNodeInfo.IsRefUi) + { + str += retraction + $" RecordNestedUi({layer}Instance, UiManager.RecordType.Open);\n"; + str += retraction + $" {layer}Instance.OnCreateUi();\n"; + str += retraction + $" {layer}Instance.OnInitNestedUi();\n\n"; + } + else + { + if (uiNodeInfo.Children != null) + { + for (var i = 0; i < uiNodeInfo.Children.Count; i++) + { + var item = uiNodeInfo.Children[i]; + str += GenerateInitNestedUi(layer + item.Name + ".", item, retraction); + } + } + } + + return str; + } private static string GenerateAllChildrenClassCode(string parent, UiNodeInfo uiNodeInfo, string retraction) { @@ -176,6 +206,24 @@ private static string GenerateChildrenClassCode(string parent, UiNodeInfo uiNodeInfo, string retraction) { + string cloneCode; + + if (uiNodeInfo.IsRefUi) + { + cloneCode = retraction + $" public override {uiNodeInfo.ClassName} Clone()\n"; + cloneCode += retraction + $" {{\n"; + cloneCode += retraction + $" var uiNode = new {uiNodeInfo.ClassName}(UiPanel, ({uiNodeInfo.NodeTypeName})Instance.Duplicate());\n"; + cloneCode += retraction + $" UiPanel.RecordNestedUi(uiNode.Instance, UiManager.RecordType.Open);\n"; + cloneCode += retraction + $" uiNode.Instance.OnCreateUi();\n"; + cloneCode += retraction + $" uiNode.Instance.OnInitNestedUi();\n"; + cloneCode += retraction + $" return uiNode;\n"; + cloneCode += retraction + $" }}\n"; + } + else + { + cloneCode = retraction + $" public override {uiNodeInfo.ClassName} Clone() => new (UiPanel, ({uiNodeInfo.NodeTypeName})Instance.Duplicate());\n"; + } + return retraction + $"/// \n" + retraction + $"/// 类型: , 路径: {parent}{uiNodeInfo.OriginName}\n" + retraction + $"/// \n" + @@ -183,7 +231,7 @@ retraction + $"{{\n" + GeneratePropertyListClassCode("Instance.", parent, uiNodeInfo, retraction + " ") + retraction + $" public {uiNodeInfo.ClassName}({uiNodeInfo.UiRootName} uiPanel, {uiNodeInfo.NodeTypeName} node) : base(uiPanel, node) {{ }}\n" + - retraction + $" public override {uiNodeInfo.ClassName} Clone() => new (UiPanel, ({uiNodeInfo.NodeTypeName})Instance.Duplicate());\n" + + cloneCode + retraction + $"}}\n\n"; } @@ -265,49 +313,6 @@ return count <= 1; } - - /// - /// 递归解析节点, 并生成 UiNodeInfo 数据 - /// - private static UiNodeInfo EachNode(string uiRootName, Node node) - { - var originName = Regex.Replace(node.Name, "[^\\w]", ""); - //类定义该图层的类名 - string className; - if (_nodeNameMap.ContainsKey(originName)) //有同名图层, 为了防止类名冲突, 需要在 UiNode 后面加上索引 - { - var count = _nodeNameMap[originName]; - className = originName + "_" + count; - _nodeNameMap[originName] = count + 1; - } - else - { - className = originName; - _nodeNameMap.Add(originName, 1); - } - - var uiNode = new UiNodeInfo(uiRootName, "L_" + originName, originName, className, node.GetType().FullName); - - var childCount = node.GetChildCount(); - if (childCount > 0) - { - for (var i = 0; i < childCount; i++) - { - var children = node.GetChild(i); - if (children != null) - { - if (uiNode.Children == null) - { - uiNode.Children = new List(); - } - - uiNode.Children.Add(EachNode(uiRootName, children)); - } - } - } - - return uiNode; - } /// /// 在编辑器下递归解析节点, 由于编辑器下绑定用户脚本的节点无法直接判断节点类型, 那么就只能获取节点的脚本然后解析名称和命名空间 @@ -353,6 +358,22 @@ { uiNode = new UiNodeInfo(uiRootName, fieldName, originName, className, fileName); } + //检测是否是引用Ui + if (fileName.EndsWith("Panel")) + { + var childUiName = fileName.Substring(0, fileName.Length - 5); + if (childUiName != uiRootName && File.Exists(GameConfig.UiPrefabDir + childUiName + ".tscn")) + { + //是引用Ui + uiNode.IsRefUi = true; + } + } + } + + //如果是引用Ui, 就没有必要递归子节点了 + if (uiNode.IsRefUi) + { + return uiNode; } var childCount = node.GetChildCount(); @@ -402,6 +423,10 @@ /// Ui根节点名称 /// public string UiRootName; + /// + /// 是否是引用Ui + /// + public bool IsRefUi; public UiNodeInfo(string uiRootName, string name, string originName, string className, string nodeTypeName) { diff --git a/DungeonShooting_Godot/src/framework/ui/UiBase.cs b/DungeonShooting_Godot/src/framework/ui/UiBase.cs index 574abd6..32851ee 100644 --- a/DungeonShooting_Godot/src/framework/ui/UiBase.cs +++ b/DungeonShooting_Godot/src/framework/ui/UiBase.cs @@ -62,6 +62,13 @@ } /// + /// 用于初始化打开的子Ui, 在 OnCreateUi() 之后调用 + /// + public virtual void OnInitNestedUi() + { + } + + /// /// 创建当前ui时调用 /// public virtual void OnCreateUi() diff --git a/DungeonShooting_Godot/src/framework/ui/UiManager.cs b/DungeonShooting_Godot/src/framework/ui/UiManager.cs index 15c8aa5..bb14326 100644 --- a/DungeonShooting_Godot/src/framework/ui/UiManager.cs +++ b/DungeonShooting_Godot/src/framework/ui/UiManager.cs @@ -78,7 +78,7 @@ } /// - /// 记录ui的创建或者销毁 + /// 记录ui的创建或者销毁, 子 ui 通过 UiBase.RecordNestedUi() 来记录 /// public static void RecordUi(UiBase uiBase, RecordType type) { @@ -119,6 +119,7 @@ var canvasLayer = GetUiLayer(uiBase.Layer); canvasLayer.AddChild(uiBase); uiBase.OnCreateUi(); + uiBase.OnInitNestedUi(); return uiBase; } diff --git a/DungeonShooting_Godot/src/framework/ui/UiNode.cs b/DungeonShooting_Godot/src/framework/ui/UiNode.cs index 78bd116..1ed8c8b 100644 --- a/DungeonShooting_Godot/src/framework/ui/UiNode.cs +++ b/DungeonShooting_Godot/src/framework/ui/UiNode.cs @@ -51,6 +51,7 @@ UiPanel.RecordNestedUi(uiBase, UiManager.RecordType.Open); uiBase.OnCreateUi(); + uiBase.OnInitNestedUi(); if (UiPanel.IsOpen) { uiBase.ShowUi(); diff --git a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs index 4dfc545..6ccbe64 100644 --- a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs +++ b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs @@ -57,6 +57,7 @@ public const string prefab_ui_MapEditorTools_tscn = "res://prefab/ui/MapEditorTools.tscn"; public const string prefab_ui_RoomUI_tscn = "res://prefab/ui/RoomUI.tscn"; public const string prefab_ui_Settlement_tscn = "res://prefab/ui/Settlement.tscn"; + public const string prefab_ui_TestUi_tscn = "res://prefab/ui/TestUi.tscn"; public const string prefab_weapon_Weapon0001_tscn = "res://prefab/weapon/Weapon0001.tscn"; public const string prefab_weapon_Weapon0002_tscn = "res://prefab/weapon/Weapon0002.tscn"; public const string prefab_weapon_Weapon0003_tscn = "res://prefab/weapon/Weapon0003.tscn"; diff --git a/DungeonShooting_Godot/src/game/ui/loading/Loading.cs b/DungeonShooting_Godot/src/game/ui/loading/Loading.cs index 8ac9098..7f2fe7a 100644 --- a/DungeonShooting_Godot/src/game/ui/loading/Loading.cs +++ b/DungeonShooting_Godot/src/game/ui/loading/Loading.cs @@ -8,61 +8,65 @@ /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Loading.ColorRect /// - public Loading_ColorRect L_ColorRect + public ColorRect L_ColorRect { get { - if (_L_ColorRect == null) _L_ColorRect = new Loading_ColorRect(this, GetNodeOrNull("ColorRect")); + if (_L_ColorRect == null) _L_ColorRect = new ColorRect(this, GetNodeOrNull("ColorRect")); return _L_ColorRect; } } - private Loading_ColorRect _L_ColorRect; + private ColorRect _L_ColorRect; /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: Loading.Label /// - public Loading_Label L_Label + public Label L_Label { get { - if (_L_Label == null) _L_Label = new Loading_Label(this, GetNodeOrNull("Label")); + if (_L_Label == null) _L_Label = new Label(this, GetNodeOrNull("Label")); return _L_Label; } } - private Loading_Label _L_Label; + private Label _L_Label; public Loading() : base(nameof(Loading)) { } + public sealed override void OnInitNestedUi() + { + } + /// /// 类型: , 路径: Loading.ColorRect /// - public class Loading_ColorRect : UiNode + public class ColorRect : UiNode { - public Loading_ColorRect(Loading uiPanel, Godot.ColorRect node) : base(uiPanel, node) { } - public override Loading_ColorRect Clone() => new (UiPanel, (Godot.ColorRect)Instance.Duplicate()); + public ColorRect(Loading uiPanel, Godot.ColorRect node) : base(uiPanel, node) { } + public override ColorRect Clone() => new (UiPanel, (Godot.ColorRect)Instance.Duplicate()); } /// /// 类型: , 路径: Loading.Label /// - public class Loading_Label : UiNode + public class Label : UiNode { - public Loading_Label(Loading uiPanel, Godot.Label node) : base(uiPanel, node) { } - public override Loading_Label Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + public Label(Loading uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override Label Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); } /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: Loading.ColorRect /// - public Loading_ColorRect S_ColorRect => L_ColorRect; + public ColorRect S_ColorRect => L_ColorRect; /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: Loading.Label /// - public Loading_Label S_Label => L_Label; + public Label S_Label => L_Label; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorCreateRoom/MapEditorCreateRoom.cs b/DungeonShooting_Godot/src/game/ui/mapEditorCreateRoom/MapEditorCreateRoom.cs index ff99457..3290400 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorCreateRoom/MapEditorCreateRoom.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorCreateRoom/MapEditorCreateRoom.cs @@ -10,5 +10,9 @@ { } + public sealed override void OnInitNestedUi() + { + } + }