diff --git a/DungeonShooting_Godot/prefab/ui/MapEditor.tscn b/DungeonShooting_Godot/prefab/ui/MapEditor.tscn index 9c78399..cd8e817 100644 --- a/DungeonShooting_Godot/prefab/ui/MapEditor.tscn +++ b/DungeonShooting_Godot/prefab/ui/MapEditor.tscn @@ -1,10 +1,11 @@ -[gd_scene load_steps=9 format=3 uid="uid://csbxfkdupsckv"] +[gd_scene load_steps=10 format=3 uid="uid://csbxfkdupsckv"] [ext_resource type="Script" path="res://src/game/ui/mapEditor/MapEditorPanel.cs" id="1_5s7a0"] [ext_resource type="Texture2D" uid="uid://cajcnlimvoxk" path="res://resource/sprite/ui/mapEditorProject/Back.png" id="2_s2w5x"] [ext_resource type="TileSet" uid="uid://b00g22o1cqhe8" path="res://resource/map/tileSet/TileSet1.tres" id="2_vrg60"] [ext_resource type="Script" path="res://src/game/ui/mapEditor/TileView/EditorTileMap.cs" id="2_waq8f"] [ext_resource type="Texture2D" uid="uid://0878uloew5jo" path="res://resource/sprite/ui/mapEditor/ErrorCell.png" id="4_465u2"] +[ext_resource type="PackedScene" uid="uid://b4u66mxndxbrg" path="res://prefab/ui/MapEditorTools.tscn" id="6_7pvgu"] [sub_resource type="Animation" id="Animation_o3btm"] length = 0.001 @@ -164,6 +165,8 @@ [node name="CanvasLayer" type="CanvasLayer" parent="Bg/VBoxContainer/HSplitContainer/Left/MarginContainer/MapView/SubViewport"] layer = 2 +[node name="MapEditorTools" parent="Bg/VBoxContainer/HSplitContainer/Left/MarginContainer/MapView/SubViewport/CanvasLayer" instance=ExtResource("6_7pvgu")] + [node name="Right" type="Panel" parent="Bg/VBoxContainer/HSplitContainer"] custom_minimum_size = Vector2(300, 0) layout_mode = 2 diff --git a/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn b/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn index fc98fe2..ffdf975 100644 --- a/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn +++ b/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn @@ -1,7 +1,11 @@ -[gd_scene load_steps=3 format=3 uid="uid://b4u66mxndxbrg"] +[gd_scene load_steps=7 format=3 uid="uid://b4u66mxndxbrg"] [ext_resource type="Script" path="res://src/game/ui/mapEditorTools/MapEditorToolsPanel.cs" id="1_mqp1c"] [ext_resource type="Texture2D" uid="uid://uhhfgdhpk7i4" path="res://icon.png" id="2_rwvbg"] +[ext_resource type="Script" path="res://src/game/ui/mapEditorTools/DoorDragArea.cs" id="3_3w0w6"] +[ext_resource type="Script" path="res://src/game/ui/mapEditorTools/DoorDragButton.cs" id="3_45muq"] +[ext_resource type="Texture2D" uid="uid://4wupcp53rrpi" path="res://resource/sprite/ui/mapEditorTools/DoorDragButton.png" id="3_trbb5"] +[ext_resource type="Texture2D" uid="uid://dcq8xinoyvo85" path="res://resource/sprite/ui/mapEditorTools/DoorDragButton_down.png" id="4_12cej"] [node name="MapEditorTools" type="Control"] layout_mode = 3 @@ -47,3 +51,49 @@ texture_normal = ExtResource("2_rwvbg") texture_pressed = ExtResource("2_rwvbg") texture_hover = ExtResource("2_rwvbg") + +[node name="DoorToolTemplate" type="Control" parent="."] +anchors_preset = 0 +script = ExtResource("3_3w0w6") + +[node name="DoorArea" type="ColorRect" parent="DoorToolTemplate"] +layout_mode = 1 +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_top = -32.0 +offset_right = 64.0 +grow_vertical = 0 +color = Color(0.184314, 1, 0.0392157, 0.188235) + +[node name="StartBtn" type="TextureButton" parent="DoorToolTemplate"] +layout_mode = 1 +anchors_preset = 3 +anchor_left = 1.0 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = -2.0 +offset_top = -36.0 +grow_horizontal = 0 +grow_vertical = 0 +texture_normal = ExtResource("3_trbb5") +texture_pressed = ExtResource("4_12cej") +texture_hover = ExtResource("4_12cej") +stretch_mode = 0 +script = ExtResource("3_45muq") + +[node name="EndBtn" type="TextureButton" parent="DoorToolTemplate"] +layout_mode = 1 +anchors_preset = 2 +anchor_top = 1.0 +anchor_bottom = 1.0 +offset_left = 64.0 +offset_top = -36.0 +offset_right = 66.0 +grow_vertical = 0 +texture_normal = ExtResource("3_trbb5") +texture_pressed = ExtResource("4_12cej") +texture_hover = ExtResource("4_12cej") +stretch_mode = 0 +script = ExtResource("3_45muq") diff --git a/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton.png b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton.png new file mode 100644 index 0000000..b2efd10 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton.png.import b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton.png.import new file mode 100644 index 0000000..0588993 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://4wupcp53rrpi" +path="res://.godot/imported/DoorDragButton.png-4094a4aa3ca627538a0de7f7993208bd.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/ui/mapEditorTools/DoorDragButton.png" +dest_files=["res://.godot/imported/DoorDragButton.png-4094a4aa3ca627538a0de7f7993208bd.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_down.png b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_down.png new file mode 100644 index 0000000..f5413ce --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_down.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_down.png.import b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_down.png.import new file mode 100644 index 0000000..43fa59c --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_down.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dcq8xinoyvo85" +path="res://.godot/imported/DoorDragButton_down.png-34213115cda413530ae9d1c4111ca91a.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/ui/mapEditorTools/DoorDragButton_down.png" +dest_files=["res://.godot/imported/DoorDragButton_down.png-34213115cda413530ae9d1c4111ca91a.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_hover.png b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_hover.png new file mode 100644 index 0000000..5723ea8 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_hover.png Binary files differ diff --git a/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_hover.png.import b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_hover.png.import new file mode 100644 index 0000000..bbd2937 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/ui/mapEditorTools/DoorDragButton_hover.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://cc6nakbhepy2" +path="res://.godot/imported/DoorDragButton_hover.png-ad7c38cb89f44b039fe7fcca449c978b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/ui/mapEditorTools/DoorDragButton_hover.png" +dest_files=["res://.godot/imported/DoorDragButton_hover.png-ad7c38cb89f44b039fe7fcca449c978b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/DungeonShooting_Godot/src/framework/common/Utils.cs b/DungeonShooting_Godot/src/framework/common/Utils.cs index 7aa9760..99ce138 100644 --- a/DungeonShooting_Godot/src/framework/common/Utils.cs +++ b/DungeonShooting_Godot/src/framework/common/Utils.cs @@ -80,6 +80,52 @@ return angle; } + + /// + /// 根据步长吸附值 + /// + /// 原数值 + /// 吸附步长 + public static float Adsorption(float value, float step) + { + var f = Mathf.Round(value / step); + return f * step; + } + + /// + /// 根据步长吸附值 + /// + /// 原数值 + /// 吸附步长 + public static int Adsorption(float value, int step) + { + var f = Mathf.RoundToInt(value / step); + return f * step; + } + + /// + /// 根据步长吸附值 + /// + /// 原数值 + /// 吸附步长 + public static Vector2 Adsorption(Vector2 value, Vector2 step) + { + var x = Mathf.Round(value.X / step.X); + var y = Mathf.Round(value.Y / step.Y); + return new Vector2(x * step.X, y * step.Y); + } + + /// + /// 根据步长吸附值 + /// + /// 原数值 + /// 吸附步长 + public static Vector2I Adsorption(Vector2 value, Vector2I step) + { + var x = Mathf.RoundToInt(value.X / step.X); + var y = Mathf.RoundToInt(value.Y / step.Y); + return new Vector2I(x * step.X, y * step.Y); + } /// /// 字符串首字母小写 diff --git a/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs b/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs index 0cfe656..a298096 100644 --- a/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs +++ b/DungeonShooting_Godot/src/framework/generator/UiGenerator.cs @@ -14,6 +14,7 @@ public static class UiGenerator { private static Dictionary _nodeNameMap = new Dictionary(); + private static int _nestedIndex = 1; /// /// 根据名称在编辑器中创建Ui, open 表示创建完成后是否在编辑器中打开这个ui @@ -98,6 +99,7 @@ public static void GenerateUiCode(Node control, string path) { _nodeNameMap.Clear(); + _nestedIndex = 1; var uiNode = EachNodeFromEditor(control.Name, control); var code = GenerateClassCode(uiNode); File.WriteAllText(path, code); @@ -111,7 +113,8 @@ try { _nodeNameMap.Clear(); - + _nestedIndex = 1; + var uiName = control.Name.ToString(); var path = GameConfig.UiCodeDir + uiName.FirstToLower() + "/" + uiName + ".cs"; GD.Print("重新生成ui代码: " + path); @@ -169,9 +172,11 @@ 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"; + var uiInst = "inst" + _nestedIndex++; + str += retraction + $" var {uiInst} = {layer}Instance;\n"; + str += retraction + $" RecordNestedUi({uiInst}, UiManager.RecordType.Open);\n"; + str += retraction + $" {uiInst}.OnCreateUi();\n"; + str += retraction + $" {uiInst}.OnInitNestedUi();\n\n"; } else { diff --git a/DungeonShooting_Godot/src/game/data/DragState.cs b/DungeonShooting_Godot/src/game/data/DragState.cs new file mode 100644 index 0000000..04f4fb0 --- /dev/null +++ b/DungeonShooting_Godot/src/game/data/DragState.cs @@ -0,0 +1,19 @@ + +/// +/// 拖拽状态 +/// +public enum DragState +{ + /// + /// 拖拽开始 + /// + DragStart, + /// + /// 拖拽中 + /// + DragMove, + /// + /// 拖拽结束 + /// + DragEnd +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs index 4a0c58f..0cfd5e5 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs @@ -23,6 +23,15 @@ { } + public sealed override void OnInitNestedUi() + { + var inst1 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_CanvasLayer.L_MapEditorTools.Instance; + RecordNestedUi(inst1, UiManager.RecordType.Open); + inst1.OnCreateUi(); + inst1.OnInitNestedUi(); + + } + /// /// 类型: , 路径: MapEditor.Bg.VBoxContainer.Head.Back /// @@ -130,10 +139,39 @@ } /// + /// 类型: , 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.CanvasLayer.MapEditorTools + /// + public class MapEditorTools : UiNode + { + public MapEditorTools(MapEditor uiPanel, UI.MapEditorTools.MapEditorToolsPanel node) : base(uiPanel, node) { } + public override MapEditorTools Clone() + { + var uiNode = new MapEditorTools(UiPanel, (UI.MapEditorTools.MapEditorToolsPanel)Instance.Duplicate()); + UiPanel.RecordNestedUi(uiNode.Instance, UiManager.RecordType.Open); + uiNode.Instance.OnCreateUi(); + uiNode.Instance.OnInitNestedUi(); + return uiNode; + } + } + + /// /// 类型: , 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.CanvasLayer /// public class CanvasLayer : UiNode { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.MapEditorTools + /// + public MapEditorTools L_MapEditorTools + { + get + { + if (_L_MapEditorTools == null) _L_MapEditorTools = new MapEditorTools(UiPanel, Instance.GetNodeOrNull("MapEditorTools")); + return _L_MapEditorTools; + } + } + private MapEditorTools _L_MapEditorTools; + public CanvasLayer(MapEditor uiPanel, Godot.CanvasLayer node) : base(uiPanel, node) { } public override CanvasLayer Clone() => new (UiPanel, (Godot.CanvasLayer)Instance.Duplicate()); } @@ -372,6 +410,11 @@ public TileMap S_TileMap => L_Bg.L_VBoxContainer.L_HSplitContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_TileMap; /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.CanvasLayer.MapEditorTools + /// + public MapEditorTools S_MapEditorTools => L_Bg.L_VBoxContainer.L_HSplitContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_CanvasLayer.L_MapEditorTools; + + /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.Left.MarginContainer.MapView.SubViewport.CanvasLayer /// public CanvasLayer S_CanvasLayer => L_Bg.L_VBoxContainer.L_HSplitContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_CanvasLayer; diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs index 8294611..4c7e5e0 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs @@ -5,19 +5,11 @@ public partial class MapEditorPanel : MapEditor { - /// - /// 左上角工具面板 - /// - public MapEditorToolsPanel ToolsPanel { get; private set; } - private EditorTileMapBar _editorTileMapBar; public override void OnCreateUi() { _editorTileMapBar = new EditorTileMapBar(this, S_TileMap); - ToolsPanel = S_CanvasLayer.OpenNestedUi(UiManager.UiName.MapEditorTools); - - //S_HSplitContainer.Instance.AnchorLeft } public override void OnShowUi() diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMap.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMap.cs index 34cc2cc..b67d76f 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMap.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMap.cs @@ -5,6 +5,7 @@ using System.Text.Json; using Godot; using Godot.Collections; +using UI.MapEditorTools; namespace UI.MapEditor; @@ -40,6 +41,11 @@ /// public MapEditorPanel MapEditorPanel { get; set; } + /// + /// 编辑器工具UI + /// + public MapEditorToolsPanel MapEditorToolsPanel { get; set; } + //鼠标坐标 private Vector2 _mousePosition; //鼠标所在的cell坐标 @@ -106,11 +112,11 @@ _mouseCellPosition.X * GameConfig.TileCellSize, _mouseCellPosition.Y * GameConfig.TileCellSize ); - - if (!MapEditorPanel.ToolsPanel.S_HBoxContainer.Instance.IsPositionOver(GetGlobalMousePosition())) //不在Ui节点上 + + if (!MapEditorToolsPanel.S_HBoxContainer.Instance.IsPositionOver(GetGlobalMousePosition())) //不在Ui节点上 { //左键绘制 - if (_isLeftPressed) + if (_isLeftPressed && false) { if (Input.IsKeyPressed(Key.Shift)) //按住shift绘制矩形 { @@ -124,7 +130,7 @@ SetSingleAutoCell(_mouseCellPosition); } } - else if (_isRightPressed) //右键擦除 + else if (_isRightPressed && false) //右键擦除 { if (Input.IsKeyPressed(Key.Shift)) //按住shift擦除矩形 { @@ -137,10 +143,10 @@ EraseSingleAutoCell(_mouseCellPosition); } } - else if (_isMiddlePressed) //中建移动 + else if (_isMiddlePressed) //中键移动 { //GD.Print("移动..."); - Position = GetGlobalMousePosition() + _moveOffset; + SetMapPosition(GetGlobalMousePosition() + _moveOffset); } } @@ -393,7 +399,7 @@ if (scale.LengthSquared() >= 0.5f) { Scale = scale; - Position += pos * 0.1f * scale; + SetMapPosition(Position + pos * 0.1f * scale); } else { @@ -409,7 +415,7 @@ if (scale.LengthSquared() <= 2000) { Scale = scale; - Position -= pos * 0.1f * prevScale; + SetMapPosition(Position - pos * 0.1f * prevScale); } else { @@ -691,11 +697,11 @@ var pos = MapEditorPanel.S_SubViewport.Instance.Size / 2; if (_roomSize.X == 0 && _roomSize.Y == 0) //聚焦原点 { - Position = pos; + SetMapPosition(pos); } else //聚焦地图中心点 { - Position = pos - (_roomPosition + _roomSize / 2) * TileSet.TileSize * Scale; + SetMapPosition(pos - (_roomPosition + _roomSize / 2) * TileSet.TileSize * Scale); } } @@ -746,4 +752,11 @@ var jsonStr = JsonSerializer.Serialize(tileInfo); File.WriteAllText(path, jsonStr); } + + //设置地图坐标 + private void SetMapPosition(Vector2 pos) + { + Position = pos; + MapEditorToolsPanel.SetDoorToolTransform(pos, Scale); + } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMapBar.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMapBar.cs index 11590a2..0c8a697 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMapBar.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/TileView/EditorTileMapBar.cs @@ -12,24 +12,27 @@ _editorTileMap = editorTileMap; _editorPanel = editorPanel; _editorTileMap.Instance.MapEditorPanel = editorPanel; + _editorTileMap.Instance.MapEditorToolsPanel = editorPanel.S_MapEditorTools.Instance; } public void OnShow() { _editorTileMap.L_Brush.Instance.Draw += OnDrawGuides; - _editorPanel.ToolsPanel.S_HandTool.Instance.Pressed += _editorTileMap.Instance.OnSelectHandTool; - _editorPanel.ToolsPanel.S_PenTool.Instance.Pressed += _editorTileMap.Instance.OnSelectPenTool; - _editorPanel.ToolsPanel.S_RectTool.Instance.Pressed += _editorTileMap.Instance.OnSelectRectTool; - _editorPanel.ToolsPanel.S_CenterTool.Instance.Pressed += _editorTileMap.Instance.OnClickCenterTool; + var mapEditorToolsPanel = _editorPanel.S_MapEditorTools.Instance; + mapEditorToolsPanel.S_HandTool.Instance.Pressed += _editorTileMap.Instance.OnSelectHandTool; + mapEditorToolsPanel.S_PenTool.Instance.Pressed += _editorTileMap.Instance.OnSelectPenTool; + mapEditorToolsPanel.S_RectTool.Instance.Pressed += _editorTileMap.Instance.OnSelectRectTool; + mapEditorToolsPanel.S_CenterTool.Instance.Pressed += _editorTileMap.Instance.OnClickCenterTool; } public void OnHide() { _editorTileMap.L_Brush.Instance.Draw -= OnDrawGuides; - _editorPanel.ToolsPanel.S_HandTool.Instance.Pressed -= _editorTileMap.Instance.OnSelectHandTool; - _editorPanel.ToolsPanel.S_PenTool.Instance.Pressed -= _editorTileMap.Instance.OnSelectPenTool; - _editorPanel.ToolsPanel.S_RectTool.Instance.Pressed -= _editorTileMap.Instance.OnSelectRectTool; - _editorPanel.ToolsPanel.S_CenterTool.Instance.Pressed -= _editorTileMap.Instance.OnClickCenterTool; + var mapEditorToolsPanel = _editorPanel.S_MapEditorTools.Instance; + mapEditorToolsPanel.S_HandTool.Instance.Pressed -= _editorTileMap.Instance.OnSelectHandTool; + mapEditorToolsPanel.S_PenTool.Instance.Pressed -= _editorTileMap.Instance.OnSelectPenTool; + mapEditorToolsPanel.S_RectTool.Instance.Pressed -= _editorTileMap.Instance.OnSelectRectTool; + mapEditorToolsPanel.S_CenterTool.Instance.Pressed -= _editorTileMap.Instance.OnClickCenterTool; } public void Process(float delta) diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs new file mode 100644 index 0000000..8838d90 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs @@ -0,0 +1,91 @@ +using Godot; + +namespace UI.MapEditorTools; + +public partial class DoorDragArea : Control +{ + /// + /// 当前区域所占大小 + /// + public Vector2 AreaSize => new Vector2(_areaSize, GameConfig.TileCellSize * 2); + + private MapEditorTools.DoorToolTemplate _node; + private Vector2 _startTempPos; + private Vector2 _endTempPos; + //区域大小 + private float _areaSize; + + public void SetDoorDragAreaNode(MapEditorTools.DoorToolTemplate node) + { + _node = node; + _areaSize = node.L_DoorArea.Instance.Size.X; + _node.L_StartBtn.Instance.DragEvent += OnStartAreaDrag; + _node.L_EndBtn.Instance.DragEvent += OnEndAreaDrag; + } + + public void SetDoorAreaTransform(Vector2 pos, Vector2 scale) + { + Position = pos; + Scale = scale; + } + + /// + /// 设置区域大小 + /// + public void SetDoorAreaSize(float value) + { + if (_areaSize != value) + { + _areaSize = value; + RefreshArea(); + } + } + + //刷新区域位置 + private void RefreshArea() + { + var colorRect = _node.L_DoorArea.Instance; + var position = colorRect.Position; + position.X = _node.L_StartBtn.Instance.Position.X; + colorRect.Position = position; + colorRect.Size = AreaSize; + + var position2 = _node.L_EndBtn.Instance.Position; + position2.X = position.X + AreaSize.X; + _node.L_EndBtn.Instance.Position = position2; + } + + private void OnStartAreaDrag(DragState dragState, Vector2 offset) + { + if (dragState == DragState.DragStart) + { + _startTempPos = _node.L_StartBtn.Instance.Position; + } + else if (dragState == DragState.DragMove) + { + var position = _startTempPos; + position.X = position.X += offset.X; + _node.L_StartBtn.Instance.Position = position; + + //刷新区域位置 + SetDoorAreaSize(_node.L_EndBtn.Instance.Position.X - position.X); + } + } + + private void OnEndAreaDrag(DragState dragState, Vector2 offset) + { + if (dragState == DragState.DragStart) + { + _endTempPos = _node.L_EndBtn.Instance.Position; + } + else if (dragState == DragState.DragMove) + { + var position = _endTempPos; + position.X = position.X += offset.X; + //_node.L_EndBtn.Instance.Position = position; + + //刷新区域位置 + SetDoorAreaSize(position.X - _node.L_StartBtn.Instance.Position.X); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragButton.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragButton.cs new file mode 100644 index 0000000..84e18e5 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragButton.cs @@ -0,0 +1,64 @@ +using System; +using Godot; + +namespace UI.MapEditorTools; + +public partial class DoorDragButton : TextureButton +{ + private static Vector2 _stepValue = new Vector2(GameConfig.TileCellSize, GameConfig.TileCellSize); + + /// + /// 拖拽当前物体的回调函数, 第一个参数为拖拽状态, 第二个参数为相对于初始点的拖拽偏移坐标 + /// + public event Action DragEvent; + + private DoorDragArea _parent; + private bool _down; + private Vector2 _startPos; + private Vector2 _prevPos; + + public override void _Ready() + { + _parent = GetParent(); + ButtonDown += OnButtonDown; + ButtonUp += OnButtonUp; + } + + public override void _Process(double delta) + { + if (_down) + { + if (DragEvent != null) + { + var offset = Utils.Adsorption((GetGlobalMousePosition() - _startPos) / _parent.Scale, _stepValue); + if (offset != _prevPos) + { + _prevPos = offset; + DragEvent(DragState.DragMove, offset); + } + } + } + } + + private void OnButtonDown() + { + _down = true; + _startPos = GetGlobalMousePosition(); + _prevPos = Vector2.Zero; + if (DragEvent != null) + { + DragEvent(DragState.DragStart, Vector2.Zero); + } + } + + private void OnButtonUp() + { + _down = false; + if (DragEvent != null) + { + var offset = Utils.Adsorption((GetGlobalMousePosition() - _startPos) / _parent.Scale, _stepValue); + _prevPos = offset; + DragEvent(DragState.DragEnd, offset); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs index 0cac553..ce76bfd 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs @@ -8,142 +8,254 @@ /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.HBoxContainer /// - public MapEditorTools_HBoxContainer L_HBoxContainer + public HBoxContainer L_HBoxContainer { get { - if (_L_HBoxContainer == null) _L_HBoxContainer = new MapEditorTools_HBoxContainer(this, GetNodeOrNull("HBoxContainer")); + if (_L_HBoxContainer == null) _L_HBoxContainer = new HBoxContainer(this, GetNodeOrNull("HBoxContainer")); return _L_HBoxContainer; } } - private MapEditorTools_HBoxContainer _L_HBoxContainer; + private HBoxContainer _L_HBoxContainer; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.DoorToolTemplate + /// + public DoorToolTemplate L_DoorToolTemplate + { + get + { + if (_L_DoorToolTemplate == null) _L_DoorToolTemplate = new DoorToolTemplate(this, GetNodeOrNull("DoorToolTemplate")); + return _L_DoorToolTemplate; + } + } + private DoorToolTemplate _L_DoorToolTemplate; public MapEditorTools() : base(nameof(MapEditorTools)) { } + public sealed override void OnInitNestedUi() + { + } + /// /// 类型: , 路径: MapEditorTools.HBoxContainer.HandTool /// - public class MapEditorTools_HandTool : UiNode + public class HandTool : UiNode { - public MapEditorTools_HandTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } - public override MapEditorTools_HandTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); + public HandTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } + public override HandTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); } /// /// 类型: , 路径: MapEditorTools.HBoxContainer.PenTool /// - public class MapEditorTools_PenTool : UiNode + public class PenTool : UiNode { - public MapEditorTools_PenTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } - public override MapEditorTools_PenTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); + public PenTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } + public override PenTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); } /// /// 类型: , 路径: MapEditorTools.HBoxContainer.RectTool /// - public class MapEditorTools_RectTool : UiNode + public class RectTool : UiNode { - public MapEditorTools_RectTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } - public override MapEditorTools_RectTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); + public RectTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } + public override RectTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); } /// /// 类型: , 路径: MapEditorTools.HBoxContainer.CenterTool /// - public class MapEditorTools_CenterTool : UiNode + public class CenterTool : UiNode { - public MapEditorTools_CenterTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } - public override MapEditorTools_CenterTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); + public CenterTool(MapEditorTools uiPanel, Godot.TextureButton node) : base(uiPanel, node) { } + public override CenterTool Clone() => new (UiPanel, (Godot.TextureButton)Instance.Duplicate()); } /// /// 类型: , 路径: MapEditorTools.HBoxContainer /// - public class MapEditorTools_HBoxContainer : UiNode + public class HBoxContainer : UiNode { /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.HandTool /// - public MapEditorTools_HandTool L_HandTool + public HandTool L_HandTool { get { - if (_L_HandTool == null) _L_HandTool = new MapEditorTools_HandTool(UiPanel, Instance.GetNodeOrNull("HandTool")); + if (_L_HandTool == null) _L_HandTool = new HandTool(UiPanel, Instance.GetNodeOrNull("HandTool")); return _L_HandTool; } } - private MapEditorTools_HandTool _L_HandTool; + private HandTool _L_HandTool; /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.PenTool /// - public MapEditorTools_PenTool L_PenTool + public PenTool L_PenTool { get { - if (_L_PenTool == null) _L_PenTool = new MapEditorTools_PenTool(UiPanel, Instance.GetNodeOrNull("PenTool")); + if (_L_PenTool == null) _L_PenTool = new PenTool(UiPanel, Instance.GetNodeOrNull("PenTool")); return _L_PenTool; } } - private MapEditorTools_PenTool _L_PenTool; + private PenTool _L_PenTool; /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.RectTool /// - public MapEditorTools_RectTool L_RectTool + public RectTool L_RectTool { get { - if (_L_RectTool == null) _L_RectTool = new MapEditorTools_RectTool(UiPanel, Instance.GetNodeOrNull("RectTool")); + if (_L_RectTool == null) _L_RectTool = new RectTool(UiPanel, Instance.GetNodeOrNull("RectTool")); return _L_RectTool; } } - private MapEditorTools_RectTool _L_RectTool; + private RectTool _L_RectTool; /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.CenterTool /// - public MapEditorTools_CenterTool L_CenterTool + public CenterTool L_CenterTool { get { - if (_L_CenterTool == null) _L_CenterTool = new MapEditorTools_CenterTool(UiPanel, Instance.GetNodeOrNull("CenterTool")); + if (_L_CenterTool == null) _L_CenterTool = new CenterTool(UiPanel, Instance.GetNodeOrNull("CenterTool")); return _L_CenterTool; } } - private MapEditorTools_CenterTool _L_CenterTool; + private CenterTool _L_CenterTool; - public MapEditorTools_HBoxContainer(MapEditorTools uiPanel, Godot.HBoxContainer node) : base(uiPanel, node) { } - public override MapEditorTools_HBoxContainer Clone() => new (UiPanel, (Godot.HBoxContainer)Instance.Duplicate()); + public HBoxContainer(MapEditorTools uiPanel, Godot.HBoxContainer node) : base(uiPanel, node) { } + public override HBoxContainer Clone() => new (UiPanel, (Godot.HBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorTools.DoorToolTemplate.DoorArea + /// + public class DoorArea : UiNode + { + public DoorArea(MapEditorTools uiPanel, Godot.ColorRect node) : base(uiPanel, node) { } + public override DoorArea Clone() => new (UiPanel, (Godot.ColorRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorTools.DoorToolTemplate.StartBtn + /// + public class StartBtn : UiNode + { + public StartBtn(MapEditorTools uiPanel, UI.MapEditorTools.DoorDragButton node) : base(uiPanel, node) { } + public override StartBtn Clone() => new (UiPanel, (UI.MapEditorTools.DoorDragButton)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorTools.DoorToolTemplate.EndBtn + /// + public class EndBtn : UiNode + { + public EndBtn(MapEditorTools uiPanel, UI.MapEditorTools.DoorDragButton node) : base(uiPanel, node) { } + public override EndBtn Clone() => new (UiPanel, (UI.MapEditorTools.DoorDragButton)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorTools.DoorToolTemplate + /// + public class DoorToolTemplate : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.DoorArea + /// + public DoorArea L_DoorArea + { + get + { + if (_L_DoorArea == null) _L_DoorArea = new DoorArea(UiPanel, Instance.GetNodeOrNull("DoorArea")); + return _L_DoorArea; + } + } + private DoorArea _L_DoorArea; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.StartBtn + /// + public StartBtn L_StartBtn + { + get + { + if (_L_StartBtn == null) _L_StartBtn = new StartBtn(UiPanel, Instance.GetNodeOrNull("StartBtn")); + return _L_StartBtn; + } + } + private StartBtn _L_StartBtn; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.EndBtn + /// + public EndBtn L_EndBtn + { + get + { + if (_L_EndBtn == null) _L_EndBtn = new EndBtn(UiPanel, Instance.GetNodeOrNull("EndBtn")); + return _L_EndBtn; + } + } + private EndBtn _L_EndBtn; + + public DoorToolTemplate(MapEditorTools uiPanel, UI.MapEditorTools.DoorDragArea node) : base(uiPanel, node) { } + public override DoorToolTemplate Clone() => new (UiPanel, (UI.MapEditorTools.DoorDragArea)Instance.Duplicate()); } /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.HBoxContainer.HandTool /// - public MapEditorTools_HandTool S_HandTool => L_HBoxContainer.L_HandTool; + public HandTool S_HandTool => L_HBoxContainer.L_HandTool; /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.HBoxContainer.PenTool /// - public MapEditorTools_PenTool S_PenTool => L_HBoxContainer.L_PenTool; + public PenTool S_PenTool => L_HBoxContainer.L_PenTool; /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.HBoxContainer.RectTool /// - public MapEditorTools_RectTool S_RectTool => L_HBoxContainer.L_RectTool; + public RectTool S_RectTool => L_HBoxContainer.L_RectTool; /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.HBoxContainer.CenterTool /// - public MapEditorTools_CenterTool S_CenterTool => L_HBoxContainer.L_CenterTool; + public CenterTool S_CenterTool => L_HBoxContainer.L_CenterTool; /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.HBoxContainer /// - public MapEditorTools_HBoxContainer S_HBoxContainer => L_HBoxContainer; + public HBoxContainer S_HBoxContainer => L_HBoxContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.DoorToolTemplate.DoorArea + /// + public DoorArea S_DoorArea => L_DoorToolTemplate.L_DoorArea; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.DoorToolTemplate.StartBtn + /// + public StartBtn S_StartBtn => L_DoorToolTemplate.L_StartBtn; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.DoorToolTemplate.EndBtn + /// + public EndBtn S_EndBtn => L_DoorToolTemplate.L_EndBtn; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.DoorToolTemplate + /// + public DoorToolTemplate S_DoorToolTemplate => L_DoorToolTemplate; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs index 71a65c0..366923d 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs @@ -4,6 +4,10 @@ public partial class MapEditorToolsPanel : MapEditorTools { + public override void OnCreateUi() + { + S_DoorToolTemplate.Instance.SetDoorDragAreaNode(S_DoorToolTemplate); + } public override void OnShowUi() { @@ -15,4 +19,9 @@ } + public void SetDoorToolTransform(Vector2 pos, Vector2 scale) + { + S_DoorToolTemplate.Instance.SetDoorAreaTransform(pos, scale); + } + }