diff --git a/DungeonShooting_Godot/prefab/ui/EditorForm.tscn b/DungeonShooting_Godot/prefab/ui/EditorForm.tscn new file mode 100644 index 0000000..295dd77 --- /dev/null +++ b/DungeonShooting_Godot/prefab/ui/EditorForm.tscn @@ -0,0 +1,41 @@ +[gd_scene load_steps=2 format=3 uid="uid://djfbqfqkjoquj"] + +[ext_resource type="Script" path="res://src/game/ui/editorForm/EditorFormPanel.cs" id="1_oq0ff"] + +[node name="EditorForm" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +script = ExtResource("1_oq0ff") + +[node name="MarginContainer" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 50 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 + +[node name="ScrollContainer" type="ScrollContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer/ScrollContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +theme_override_constants/separation = 20 + +[node name="Item" type="HBoxContainer" parent="MarginContainer/ScrollContainer/VBoxContainer"] +layout_mode = 2 + +[node name="NameLabel" type="Label" parent="MarginContainer/ScrollContainer/VBoxContainer/Item"] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_stretch_ratio = 20.0 +text = "名称:" +horizontal_alignment = 2 +vertical_alignment = 1 diff --git a/DungeonShooting_Godot/resource/map/tileSet/TileSet2/TileSet.json b/DungeonShooting_Godot/resource/map/tileSet/TileSet2/TileSet.json index e4ac01c..4a8fc8a 100644 --- a/DungeonShooting_Godot/resource/map/tileSet/TileSet2/TileSet.json +++ b/DungeonShooting_Godot/resource/map/tileSet/TileSet2/TileSet.json @@ -94,6 +94,54 @@ ] }, "TerrainType": 0 + }, + { + "Name": "Test", + "F": {}, + "M": {}, + "T": { + "16": [ + 0, + 128 + ], + "48": [ + 16, + 128 + ], + "56": [ + 32, + 128 + ] + }, + "TerrainType": 0 + }, + { + "Name": "Test2", + "F": {}, + "M": {}, + "T": { + "341": [ + 176, + 48 + ], + "80": [ + 48, + 32 + ], + "272": [ + 16, + 32 + ], + "336": [ + 32, + 32 + ], + "276": [ + 16, + 48 + ] + }, + "TerrainType": 1 } ], "Combination": [ diff --git a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs index bb13117..2e3fb0d 100644 --- a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs +++ b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs @@ -52,10 +52,11 @@ { var uiCell = _cellList[newIndex]; uiCell.OnSelect(); - if (SelectEvent != null) - { - SelectEvent(newIndex); - } + } + + if (SelectEvent != null) + { + SelectEvent(newIndex); } } } @@ -343,15 +344,17 @@ } /// - /// 添加单条 Cell 数据 + /// 添加单条 Cell 数据, select 为是否立即选中 /// - public void Add(TData data) + public void Add(TData data, bool select = false) { - //取消选中 - SelectIndex = -1; var cell = GetCellInstance(); GridContainer.AddChild(cell.CellNode.GetUiInstance()); cell.SetData(data); + if (select) + { + SelectIndex = Count - 1; + } } /// diff --git a/DungeonShooting_Godot/src/game/data/FormItemData.cs b/DungeonShooting_Godot/src/game/data/FormItemData.cs new file mode 100644 index 0000000..f6fa43e --- /dev/null +++ b/DungeonShooting_Godot/src/game/data/FormItemData.cs @@ -0,0 +1,20 @@ + +using Godot; + +public class FormItemData where T : Control +{ + /// + /// 显示文本 + /// + public string Label; + /// + /// 挂载的节点 + /// + public T UiNode; + + public FormItemData(string label, T uiNode) + { + Label = label; + UiNode = uiNode; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs b/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs index 0b9e948..de043ba 100644 --- a/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs +++ b/DungeonShooting_Godot/src/game/manager/EditorWindowManager.cs @@ -5,6 +5,7 @@ using Config; using Godot; using UI.EditorColorPicker; +using UI.EditorForm; using UI.EditorImportCombination; using UI.EditorInfo; using UI.EditorInput; @@ -226,7 +227,7 @@ //检查名称是否合规 if (string.IsNullOrEmpty(groupName)) { - ShowTips("错误", "组名称不能为空!"); + ShowTips("错误", "组名称不能为空!"); return; } @@ -235,7 +236,7 @@ var dir = new DirectoryInfo(path); if (dir.Exists && dir.GetDirectories().Length > 0) { - ShowTips("错误", $"已经有相同路径的房间了!"); + ShowTips("错误", $"已经有相同路径的房间了!"); return; } @@ -586,7 +587,7 @@ //检查名称是否合规 if (string.IsNullOrEmpty(name)) { - ShowTips("错误", "名称不能为空!"); + ShowTips("错误", "名称不能为空!"); return; } @@ -595,7 +596,7 @@ var dir = new DirectoryInfo(path); if (dir.Exists && dir.GetFiles().Length > 0) { - ShowTips("错误", $"已经有相同名称的TileSet了!"); + ShowTips("错误", $"已经有相同名称的TileSet了!"); return; } @@ -641,6 +642,116 @@ }) ); } + + /// + /// 显示创建地形的面板 + /// + /// 创建地形时所在的TileSource + /// 创建完成回调 + /// 所属父级Ui + public static void ShowCreateTerrain(TileSetSourceInfo sourceInfo, Action onCreate, UiBase parentUi = null) + { + var window = CreateWindowInstance(parentUi); + window.SetWindowTitle("创建Terrain"); + window.SetWindowSize(new Vector2I(600, 350)); + var body = window.OpenBody(UiManager.UiNames.EditorForm); + + //第一项 + var item1 = new FormItemData("地形名称", new LineEdit() + { + PlaceholderText = "请输入名称" + }); + //第二项 + var option = new OptionButton(); + option.AddItem("3x3掩码(47格)"); + option.AddItem("2x2掩码(13格)"); + option.Selected = 0; + var item2 = new FormItemData("掩码类型", option); + + body.AddItem(item1); + body.AddItem(item2); + window.SetButtonList( + new EditorWindowPanel.ButtonData("确定", () => + { + var text = item1.UiNode.Text; + if (string.IsNullOrEmpty(text)) + { + ShowTips("错误", $"名称不允许为空!"); + return; + } + + if (sourceInfo.Terrain.FindIndex(info => info.Name == text) >= 0) + { + ShowTips("错误", $"已经有相同名称的Terrain了!"); + return; + } + + var terrainInfo = new TileSetTerrainInfo(); + terrainInfo.InitData(); + terrainInfo.Name = text; + terrainInfo.TerrainType = (byte)option.Selected; + + window.CloseWindow(); + onCreate(terrainInfo); + }), + new EditorWindowPanel.ButtonData("取消", () => + { + window.CloseWindow(); + }) + ); + } + + /// + /// 显示编辑地形的MainBu + /// + /// 创建地形时所在的TileSource + /// 创建完成回调 + /// 所属父级Ui + public static void ShowEditTerrain(TileSetSourceInfo sourceInfo, Action onCreate, UiBase parentUi = null) + { + var window = CreateWindowInstance(parentUi); + window.SetWindowTitle("创建Terrain"); + window.SetWindowSize(new Vector2I(600, 350)); + var body = window.OpenBody(UiManager.UiNames.EditorForm); + + //第一项 + var item1 = new FormItemData("地形名称", new LineEdit() + { + PlaceholderText = "请输入名称" + }); + //第二项 + var option = new OptionButton(); + option.AddItem("3x3掩码(47格)"); + option.AddItem("2x2掩码(13格)"); + option.Selected = 0; + var item2 = new FormItemData("掩码类型", option); + + body.AddItem(item1); + body.AddItem(item2); + window.SetButtonList( + new EditorWindowPanel.ButtonData("确定", () => + { + var text = item1.UiNode.Text; + if (sourceInfo.Terrain.FindIndex(info => info.Name == text) >= 0) + { + ShowTips("错误", $"已经有相同名称的Terrain了!"); + return; + } + + var terrainInfo = new TileSetTerrainInfo(); + terrainInfo.InitData(); + terrainInfo.Name = text; + terrainInfo.TerrainType = (byte)option.Selected; + + window.CloseWindow(); + onCreate(terrainInfo); + }), + new EditorWindowPanel.ButtonData("取消", () => + { + window.CloseWindow(); + }) + ); + } private static EditorWindowPanel CreateWindowInstance(UiBase parentUi = null) { diff --git a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs index 0e3e43f..f361dc8 100644 --- a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs +++ b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs @@ -70,7 +70,9 @@ public const string prefab_ui_BottomTips_tscn = "res://prefab/ui/BottomTips.tscn"; public const string prefab_ui_Debugger_tscn = "res://prefab/ui/Debugger.tscn"; public const string prefab_ui_EditorColorPicker_tscn = "res://prefab/ui/EditorColorPicker.tscn"; + public const string prefab_ui_EditorForm_tscn = "res://prefab/ui/EditorForm.tscn"; public const string prefab_ui_EditorImportCombination_tscn = "res://prefab/ui/EditorImportCombination.tscn"; + public const string prefab_ui_EditorInfo_tscn = "res://prefab/ui/EditorInfo.tscn"; public const string prefab_ui_EditorInput_tscn = "res://prefab/ui/EditorInput.tscn"; public const string prefab_ui_EditorTips_tscn = "res://prefab/ui/EditorTips.tscn"; public const string prefab_ui_EditorTools_tscn = "res://prefab/ui/EditorTools.tscn"; @@ -78,7 +80,6 @@ public const string prefab_ui_Loading_tscn = "res://prefab/ui/Loading.tscn"; public const string prefab_ui_Main_tscn = "res://prefab/ui/Main.tscn"; public const string prefab_ui_MapEditor_tscn = "res://prefab/ui/MapEditor.tscn"; - public const string prefab_ui_MapEditorCreateGroup_tscn = "res://prefab/ui/MapEditorCreateGroup.tscn"; public const string prefab_ui_MapEditorCreateMark_tscn = "res://prefab/ui/MapEditorCreateMark.tscn"; public const string prefab_ui_MapEditorCreatePreinstall_tscn = "res://prefab/ui/MapEditorCreatePreinstall.tscn"; public const string prefab_ui_MapEditorCreateRoom_tscn = "res://prefab/ui/MapEditorCreateRoom.tscn"; @@ -121,6 +122,12 @@ public const string resource_font_DinkieBitmap9pxItalicDemo_ttf = "res://resource/font/DinkieBitmap-9pxItalicDemo.ttf"; public const string resource_font_VonwaonBitmap12px_ttf = "res://resource/font/VonwaonBitmap-12px.ttf"; public const string resource_font_VonwaonBitmap16px_ttf = "res://resource/font/VonwaonBitmap-16px.ttf"; + public const string resource_map_tileSet_TileSetConfig_json = "res://resource/map/tileSet/TileSetConfig.json"; + public const string resource_map_tileSet_TileSet1_Main_png = "res://resource/map/tileSet/TileSet1/Main.png"; + public const string resource_map_tileSet_TileSet1_TileSet_json = "res://resource/map/tileSet/TileSet1/TileSet.json"; + public const string resource_map_tileSet_TileSet2_Main_png = "res://resource/map/tileSet/TileSet2/Main.png"; + public const string resource_map_tileSet_TileSet2_Test2_png = "res://resource/map/tileSet/TileSet2/Test2.png"; + public const string resource_map_tileSet_TileSet2_TileSet_json = "res://resource/map/tileSet/TileSet2/TileSet.json"; public const string resource_material_Blend_gdshader = "res://resource/material/Blend.gdshader"; public const string resource_material_Blend_tres = "res://resource/material/Blend.tres"; public const string resource_material_GodRays_gdshader = "res://resource/material/GodRays.gdshader"; @@ -228,6 +235,7 @@ public const string resource_sprite_map_TerrainMask_png = "res://resource/sprite/map/TerrainMask.png"; public const string resource_sprite_map_TerrainMask2_png = "res://resource/sprite/map/TerrainMask2.png"; public const string resource_sprite_map_TerrainMask3_png = "res://resource/sprite/map/TerrainMask3.png"; + public const string resource_sprite_map_TerrainMask4_png = "res://resource/sprite/map/TerrainMask4.png"; public const string resource_sprite_map_WallTransition1_png = "res://resource/sprite/map/WallTransition1.png"; public const string resource_sprite_map_WallTransition2_png = "res://resource/sprite/map/WallTransition2.png"; public const string resource_sprite_map_WallTransition3_png = "res://resource/sprite/map/WallTransition3.png"; @@ -332,6 +340,7 @@ public const string resource_sprite_ui_commonIcon_Select_png = "res://resource/sprite/ui/commonIcon/Select.png"; public const string resource_sprite_ui_commonIcon_Select2_png = "res://resource/sprite/ui/commonIcon/Select2.png"; public const string resource_sprite_ui_commonIcon_Setting_png = "res://resource/sprite/ui/commonIcon/Setting.png"; + public const string resource_sprite_ui_commonIcon_Success_mini_png = "res://resource/sprite/ui/commonIcon/Success_mini.png"; public const string resource_sprite_ui_commonIcon_Unknown_png = "res://resource/sprite/ui/commonIcon/Unknown.png"; public const string resource_sprite_ui_commonIcon_UnknownActivity_png = "res://resource/sprite/ui/commonIcon/UnknownActivity.png"; public const string resource_sprite_ui_commonIcon_Unlock_png = "res://resource/sprite/ui/commonIcon/Unlock.png"; @@ -444,6 +453,7 @@ public const string scene_test_TestCreateSector_tscn = "res://scene/test/TestCreateSector.tscn"; public const string scene_test_TestDrawSprite_tscn = "res://scene/test/TestDrawSprite.tscn"; public const string scene_test_TestGridData_tscn = "res://scene/test/TestGridData.tscn"; + public const string scene_test_TestLoadTileSetConfig_tscn = "res://scene/test/TestLoadTileSetConfig.tscn"; public const string scene_test_TestMask_tscn = "res://scene/test/TestMask.tscn"; public const string scene_test_TestMask2_tscn = "res://scene/test/TestMask2.tscn"; public const string scene_test_TestNavigation2_tscn = "res://scene/test/TestNavigation2.tscn"; @@ -455,5 +465,6 @@ public const string scene_test_TestPerfectPixel_tscn = "res://scene/test/TestPerfectPixel.tscn"; public const string scene_test_TestPerfectPixelScene_tscn = "res://scene/test/TestPerfectPixelScene.tscn"; public const string scene_test_TestRoomFog_tscn = "res://scene/test/TestRoomFog.tscn"; + public const string scene_test_TestTerrain2x2_tscn = "res://scene/test/TestTerrain2x2.tscn"; public const string scene_test_TestTileLayer_tscn = "res://scene/test/TestTileLayer.tscn"; } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs b/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs index cd4187a..3f4a528 100644 --- a/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs +++ b/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs @@ -8,6 +8,7 @@ public const string BottomTips = "BottomTips"; public const string Debugger = "Debugger"; public const string EditorColorPicker = "EditorColorPicker"; + public const string EditorForm = "EditorForm"; public const string EditorImportCombination = "EditorImportCombination"; public const string EditorInfo = "EditorInfo"; public const string EditorInput = "EditorInput"; @@ -182,6 +183,54 @@ } /// + /// 创建 EditorForm, 并返回UI实例, 该函数不会打开 Ui + /// + public static UI.EditorForm.EditorFormPanel Create_EditorForm() + { + return CreateUi(UiNames.EditorForm); + } + + /// + /// 打开 EditorForm, 并返回UI实例 + /// + public static UI.EditorForm.EditorFormPanel Open_EditorForm() + { + return OpenUi(UiNames.EditorForm); + } + + /// + /// 隐藏 EditorForm 的所有实例 + /// + public static void Hide_EditorForm() + { + var uiInstance = Get_EditorForm_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.HideUi(); + } + } + + /// + /// 销毁 EditorForm 的所有实例 + /// + public static void Destroy_EditorForm() + { + var uiInstance = Get_EditorForm_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.Destroy(); + } + } + + /// + /// 获取所有 EditorForm 的实例, 如果没有实例, 则返回一个空数组 + /// + public static UI.EditorForm.EditorFormPanel[] Get_EditorForm_Instance() + { + return GetUiInstance(nameof(UI.EditorForm.EditorForm)); + } + + /// /// 创建 EditorImportCombination, 并返回UI实例, 该函数不会打开 Ui /// public static UI.EditorImportCombination.EditorImportCombinationPanel Create_EditorImportCombination() diff --git a/DungeonShooting_Godot/src/game/ui/editorForm/EditorForm.cs b/DungeonShooting_Godot/src/game/ui/editorForm/EditorForm.cs new file mode 100644 index 0000000..59f6b34 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/editorForm/EditorForm.cs @@ -0,0 +1,154 @@ +namespace UI.EditorForm; + +/// +/// Ui代码, 该类是根据ui场景自动生成的, 请不要手动编辑该类, 以免造成代码丢失 +/// +public abstract partial class EditorForm : UiBase +{ + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: EditorForm.MarginContainer + /// + public MarginContainer L_MarginContainer + { + get + { + if (_L_MarginContainer == null) _L_MarginContainer = new MarginContainer((EditorFormPanel)this, GetNode("MarginContainer")); + return _L_MarginContainer; + } + } + private MarginContainer _L_MarginContainer; + + + public EditorForm() : base(nameof(EditorForm)) + { + } + + public sealed override void OnInitNestedUi() + { + + } + + /// + /// 类型: , 路径: EditorForm.MarginContainer.ScrollContainer.VBoxContainer.Item.NameLabel + /// + public class NameLabel : UiNode + { + public NameLabel(EditorFormPanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override NameLabel Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: EditorForm.MarginContainer.ScrollContainer.VBoxContainer.Item + /// + public class Item : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: EditorForm.MarginContainer.ScrollContainer.VBoxContainer.NameLabel + /// + public NameLabel L_NameLabel + { + get + { + if (_L_NameLabel == null) _L_NameLabel = new NameLabel(UiPanel, Instance.GetNode("NameLabel")); + return _L_NameLabel; + } + } + private NameLabel _L_NameLabel; + + public Item(EditorFormPanel uiPanel, Godot.HBoxContainer node) : base(uiPanel, node) { } + public override Item Clone() => new (UiPanel, (Godot.HBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: EditorForm.MarginContainer.ScrollContainer.VBoxContainer + /// + public class VBoxContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: EditorForm.MarginContainer.ScrollContainer.Item + /// + public Item L_Item + { + get + { + if (_L_Item == null) _L_Item = new Item(UiPanel, Instance.GetNode("Item")); + return _L_Item; + } + } + private Item _L_Item; + + public VBoxContainer(EditorFormPanel uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) { } + public override VBoxContainer Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: EditorForm.MarginContainer.ScrollContainer + /// + public class ScrollContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: EditorForm.MarginContainer.VBoxContainer + /// + public VBoxContainer L_VBoxContainer + { + get + { + if (_L_VBoxContainer == null) _L_VBoxContainer = new VBoxContainer(UiPanel, Instance.GetNode("VBoxContainer")); + return _L_VBoxContainer; + } + } + private VBoxContainer _L_VBoxContainer; + + public ScrollContainer(EditorFormPanel uiPanel, Godot.ScrollContainer node) : base(uiPanel, node) { } + public override ScrollContainer Clone() => new (UiPanel, (Godot.ScrollContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: EditorForm.MarginContainer + /// + public class MarginContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: EditorForm.ScrollContainer + /// + public ScrollContainer L_ScrollContainer + { + get + { + if (_L_ScrollContainer == null) _L_ScrollContainer = new ScrollContainer(UiPanel, Instance.GetNode("ScrollContainer")); + return _L_ScrollContainer; + } + } + private ScrollContainer _L_ScrollContainer; + + public MarginContainer(EditorFormPanel uiPanel, Godot.MarginContainer node) : base(uiPanel, node) { } + public override MarginContainer Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate()); + } + + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: EditorForm.MarginContainer.ScrollContainer.VBoxContainer.Item.NameLabel + /// + public NameLabel S_NameLabel => L_MarginContainer.L_ScrollContainer.L_VBoxContainer.L_Item.L_NameLabel; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: EditorForm.MarginContainer.ScrollContainer.VBoxContainer.Item + /// + public Item S_Item => L_MarginContainer.L_ScrollContainer.L_VBoxContainer.L_Item; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: EditorForm.MarginContainer.ScrollContainer.VBoxContainer + /// + public VBoxContainer S_VBoxContainer => L_MarginContainer.L_ScrollContainer.L_VBoxContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: EditorForm.MarginContainer.ScrollContainer + /// + public ScrollContainer S_ScrollContainer => L_MarginContainer.L_ScrollContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: EditorForm.MarginContainer + /// + public MarginContainer S_MarginContainer => L_MarginContainer; + +} diff --git a/DungeonShooting_Godot/src/game/ui/editorForm/EditorFormPanel.cs b/DungeonShooting_Godot/src/game/ui/editorForm/EditorFormPanel.cs new file mode 100644 index 0000000..b581d22 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/editorForm/EditorFormPanel.cs @@ -0,0 +1,27 @@ +using Godot; + +namespace UI.EditorForm; + +/// +/// 最基础的表单显示Ui +/// +public partial class EditorFormPanel : EditorForm +{ + public override void OnCreateUi() + { + S_Item.Instance.Visible = false; + } + + /// + /// 添加表单元素 + /// + public void AddItem(FormItemData item) where T : Control + { + var itemNode = S_Item.CloneAndPut(); + itemNode.Instance.Visible = true; + itemNode.L_NameLabel.Instance.Text = item.Label + ":"; + itemNode.AddChild(item.UiNode); + item.UiNode.SetHorizontalExpand(true); + item.UiNode.SizeFlagsStretchRatio = 80; + } +} diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorProject/TileSetEditorProjectPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorProject/TileSetEditorProjectPanel.cs index 535bda5..f5a62ef 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorProject/TileSetEditorProjectPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorProject/TileSetEditorProjectPanel.cs @@ -87,6 +87,11 @@ tileSetSourceInfo.InitData(); tileSetSourceInfo.Name = "Main"; tileSetInfo.Sources.Add(tileSetSourceInfo); + //默认创建一个Main Terrain, 该Terrain不可删除 + var tileSetTerrainInfo = new TileSetTerrainInfo(); + tileSetTerrainInfo.InitData(); + tileSetTerrainInfo.Name = "Main"; + tileSetSourceInfo.Terrain.Add(tileSetTerrainInfo); split.SetTileSetInfo(tileSetInfo); GameApplication.Instance.TileSetConfig.Add(name, split); diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TerrainTabCell.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TerrainTabCell.cs index 6e05c89..a8a4f46 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TerrainTabCell.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TerrainTabCell.cs @@ -9,7 +9,15 @@ public override void OnSetData(TileSetTerrainInfo data) { - CellNode.Instance.Text = data.Name; + RefreshData(); + } + + /// + /// 刷新数据 + /// + public void RefreshData() + { + CellNode.Instance.Text = Data.Name; } public override void OnSelect() diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs index dd75542..bc04723 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs @@ -13,7 +13,7 @@ /// /// 当前选中的地形索引 /// - public int CurrTerrainIndex { get; set; } = -1; + public int CurrTerrainIndex => TerrainTabGrid.SelectIndex; /// /// 当前选中的地形 @@ -71,11 +71,13 @@ TerrainGrid2x2 = InitTopGrid(S_TerrainRoot.L_TerrainTexture4.Instance, GameConfig.TerrainBit2x2, TileSetTerrainInfo.TerrainLayerType); TerrainGridMiddle = InitTopGrid(S_TerrainRoot.L_TerrainTexture2.Instance, GameConfig.TerrainBitMiddle, TileSetTerrainInfo.MiddleLayerType); TerrainGridFloor = InitTopGrid(S_TerrainRoot.L_TerrainTexture3.Instance, GameConfig.TerrainBitFloor, TileSetTerrainInfo.FloorLayerType); - + //删除地形按钮 S_DeleteButton.Instance.Pressed += OnDeleteTerrainClick; //添加地形按钮 S_AddButton.Instance.Pressed += OnAddTerrainClick; + //编辑地形 + S_EditButton.Instance.Pressed += OnEditTerrainClick; OnSetTileTexture(EditorPanel.Texture); OnChangeTileSetBgColor(EditorPanel.BgColor); @@ -99,18 +101,21 @@ _refreshGridConnect = false; var terrain = CurrTerrain; - if (terrain.TerrainType == 0) //选中47格Terrain + if (terrain != null) { - TerrainGrid3x3.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); - if (EditorPanel.TileSetSourceIndex == 0 && CurrTerrainIndex == 0) //选中Main Source + if (terrain.TerrainType == 0) //选中47格Terrain { - TerrainGridMiddle.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); - TerrainGridFloor.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); + TerrainGrid3x3.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); + if (EditorPanel.TileSetSourceIndex == 0 && CurrTerrainIndex == 0) //选中Main Source + { + TerrainGridMiddle.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); + TerrainGridFloor.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); + } } - } - else //选中13格Terrain - { - TerrainGrid2x2.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); + else //选中13格Terrain + { + TerrainGrid2x2.ForEach(cell => RefreshConnectTerrainCell(terrain, cell)); + } } } } @@ -185,7 +190,12 @@ /// public void OnDropCell(MaskCell maskCell) { - if (CurrTerrain.TerrainType == 0) //选中47个Terrain + var terrain = CurrTerrain; + if (terrain == null) + { + return; + } + if (terrain.TerrainType == 0) //选中47个Terrain { var flag = true; TerrainGrid3x3.ForEach((cell) => @@ -255,8 +265,6 @@ //切换选中的地形 private void OnChangeTerrain(int index) { - CurrTerrainIndex = index; - //清除所有绑定的Terrain if (index >= 0) { @@ -269,18 +277,21 @@ S_BottomBg.Instance.SetHoverCell(null); var terrain = CurrTerrain; - if (terrain.TerrainType == 0) //选中47个Terrain + if (terrain != null) { - TerrainGrid3x3.ForEach(cell => SetTerrainCellData(terrain, cell)); - if (EditorPanel.TileSetSourceIndex == 0 && CurrTerrainIndex == 0) //选中Main Source + if (terrain.TerrainType == 0) //选中47个Terrain { - TerrainGridMiddle.ForEach(cell => SetTerrainCellData(terrain, cell)); - TerrainGridFloor.ForEach(cell => SetTerrainCellData(terrain, cell)); + TerrainGrid3x3.ForEach(cell => SetTerrainCellData(terrain, cell)); + if (EditorPanel.TileSetSourceIndex == 0 && CurrTerrainIndex == 0) //选中Main Source + { + TerrainGridMiddle.ForEach(cell => SetTerrainCellData(terrain, cell)); + TerrainGridFloor.ForEach(cell => SetTerrainCellData(terrain, cell)); + } } - } - else //选中13格Terrain - { - TerrainGrid2x2.ForEach(cell => SetTerrainCellData(terrain, cell)); + else //选中13格Terrain + { + TerrainGrid2x2.ForEach(cell => SetTerrainCellData(terrain, cell)); + } } if (index >= 0) @@ -343,7 +354,7 @@ { if (EditorPanel.TileSetSourceIndex == 0 && CurrTerrainIndex == 0) //不能删除 Main Terrain { - EditorWindowManager.ShowTips("警告", "不允许删 Main Terrain!"); + EditorWindowManager.ShowTips("警告", "不允许删除 Main Terrain!"); return; } @@ -354,15 +365,75 @@ { if (v) { + var index = TerrainTabGrid.SelectIndex; //执行删除操作 + EditorPanel.TileSetSourceInfo.Terrain.Remove(terrain); + TerrainTabGrid.RemoveByIndex(index); + if (index == TerrainTabGrid.Count) + { + TerrainTabGrid.SelectIndex = TerrainTabGrid.Count - 1; + } + else + { + TerrainTabGrid.SelectIndex = index; + } + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } }); } + else + { + EditorWindowManager.ShowTips("提示", "清选择一个Terrain!"); + } } //创建地形 private void OnAddTerrainClick() { + EditorWindowManager.ShowCreateTerrain(EditorPanel.TileSetSourceInfo, terrainInfo => + { + //执行添加操作 + EditorPanel.TileSetSourceInfo.Terrain.Add(terrainInfo); + TerrainTabGrid.Add(terrainInfo, true); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); + }); + } + + //编辑地形(重命名) + private void OnEditTerrainClick() + { + if (EditorPanel.TileSetSourceIndex == 0 && CurrTerrainIndex == 0) //不能删除 Main Terrain + { + EditorWindowManager.ShowTips("警告", "不允许重命名 Main Terrain!"); + return; + } + var terrain = CurrTerrain; + if (terrain != null) + { + EditorWindowManager.ShowInput("提示", $"是否删除地形'{terrain.Name}'?", terrain.Name, (v, isClose) => + { + if (string.IsNullOrEmpty(v)) + { + EditorWindowManager.ShowTips("错误", $"名称不允许为空!"); + return false; + } + if (terrain.Name != v && EditorPanel.TileSetSourceInfo.Terrain.FindIndex(info => info.Name == v) >= 0) + { + EditorWindowManager.ShowTips("错误", $"已经有相同名称的Terrain了!"); + return false; + } + + terrain.Name = v; + //刷新页签 + ((TerrainTabCell)TerrainTabGrid.GetCell(CurrTerrainIndex)).RefreshData(); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); + return true; + }); + } + else + { + EditorWindowManager.ShowTips("提示", "清选择一个Terrain!"); + } } } diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TerrainCell.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TerrainCell.cs index 93a786d..e184418 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TerrainCell.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TerrainCell.cs @@ -121,11 +121,11 @@ { if (cellData == null) { - _panel.CurrTerrain.RemoveTerrainCell(Index, Data); + _panel.CurrTerrain?.RemoveTerrainCell(Index, Data); } else { - _panel.CurrTerrain.SetTerrainCell(Index, Data, cellData); + _panel.CurrTerrain?.SetTerrainCell(Index, Data, cellData); } EventManager.EmitEvent(EventEnum.OnTileSetDirty); diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TileEditTerrain.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TileEditTerrain.cs index 8075876..4009d20 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TileEditTerrain.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorTerrain/up/TileEditTerrain.cs @@ -36,9 +36,10 @@ { TerrainCell cell = null; var _panel = UiNode.UiPanel; - if (_panel.S_TopBg.Instance.IsMouseInRect()) + var terrain = _panel.CurrTerrain; + if (terrain != null && _panel.S_TopBg.Instance.IsMouseInRect()) { - if (_panel.CurrTerrain.TerrainType == 0) //选中47个Terrain + if (terrain.TerrainType == 0) //选中47个Terrain { cell = CalcMouseHoverCell(_panel.S_TerrainTexture1.Instance, _panel.TerrainGrid3x3); if (_panel.EditorPanel.TileSetSourceIndex == 0 && _panel.CurrTerrainIndex == 0) //选中Main Source @@ -113,14 +114,22 @@ { rootSize = UiNode.L_TerrainRoot.Instance.Size; } - else if (panel.CurrTerrain.TerrainType == 0) //选中 47 格 Terrain + else if (panel.CurrTerrain != null) { - rootSize = UiNode.L_TerrainRoot.L_TerrainTexture1.Instance.Size; + if (panel.CurrTerrain.TerrainType == 0) //选中 47 格 Terrain + { + rootSize = UiNode.L_TerrainRoot.L_TerrainTexture1.Instance.Size; + } + else //13 格 Terrain + { + rootSize = UiNode.L_TerrainRoot.L_TerrainTexture4.Instance.Size; + } } - else //13 格 Terrain + else { - rootSize = UiNode.L_TerrainRoot.L_TerrainTexture4.Instance.Size; + rootSize = Vector2.One; } + Utils.DoFocusNode(ContainerRoot, Size, rootSize); RefreshGridTrans(); }