diff --git a/DungeonShooting_Godot/excel/ActivityBase.xlsx b/DungeonShooting_Godot/excel/ActivityBase.xlsx index 312c49f9..0609aa9d 100644 Binary files a/DungeonShooting_Godot/excel/ActivityBase.xlsx and b/DungeonShooting_Godot/excel/ActivityBase.xlsx differ diff --git a/DungeonShooting_Godot/excel/EditorObject.xlsx b/DungeonShooting_Godot/excel/EditorObject.xlsx index 6341a4e1..cb2871cd 100644 Binary files a/DungeonShooting_Godot/excel/EditorObject.xlsx and b/DungeonShooting_Godot/excel/EditorObject.xlsx differ diff --git a/DungeonShooting_Godot/prefab/dungeonitem/Dungenitem0002.tscn b/DungeonShooting_Godot/prefab/dungeonitem/Dungenitem0002.tscn new file mode 100644 index 00000000..63cfe46d --- /dev/null +++ b/DungeonShooting_Godot/prefab/dungeonitem/Dungenitem0002.tscn @@ -0,0 +1,33 @@ +[gd_scene load_steps=5 format=3 uid="uid://c4ds87128cvpy"] + +[ext_resource type="Texture2D" uid="uid://bkc3fxmnxe7nh" path="res://resource/sprite/item/Items.png" id="1_dgsm7"] + +[sub_resource type="AtlasTexture" id="AtlasTexture_6ikro"] +atlas = ExtResource("1_dgsm7") +region = Rect2(336, 209, 42, 64) + +[sub_resource type="SpriteFrames" id="SpriteFrames_bq02g"] +animations = [{ +"frames": [{ +"duration": 1.0, +"texture": SubResource("AtlasTexture_6ikro") +}], +"loop": true, +"name": &"default", +"speed": 5.0 +}] + +[sub_resource type="RectangleShape2D" id="RectangleShape2D_8wvh6"] +size = Vector2(20, 14) + +[node name="Dungenitem0002" type="CharacterBody2D"] +collision_layer = 512 +collision_mask = 0 + +[node name="AnimatedSprite2D" type="AnimatedSprite2D" parent="."] +position = Vector2(6, -24) +sprite_frames = SubResource("SpriteFrames_bq02g") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="."] +position = Vector2(-1, 0) +shape = SubResource("RectangleShape2D_8wvh6") diff --git a/DungeonShooting_Godot/prefab/item/Item0021.tscn b/DungeonShooting_Godot/prefab/item/Item0021.tscn index 4b153fbc..cb0ef137 100644 --- a/DungeonShooting_Godot/prefab/item/Item0021.tscn +++ b/DungeonShooting_Godot/prefab/item/Item0021.tscn @@ -4,7 +4,6 @@ [ext_resource type="Shader" path="res://resource/shader/Blend.gdshader" id="2_0claj"] [ext_resource type="Texture2D" uid="uid://bt3rvgedbniwq" path="res://resource/sprite/item/hall_a/Slice_22.png" id="3_os210"] - [sub_resource type="ShaderMaterial" id="ShaderMaterial_wh4b7"] resource_local_to_scene = true shader = ExtResource("2_0claj") diff --git a/DungeonShooting_Godot/prefab/test/MoveComponent.tscn b/DungeonShooting_Godot/prefab/test/MoveComponent.tscn deleted file mode 100644 index c812259a..00000000 --- a/DungeonShooting_Godot/prefab/test/MoveComponent.tscn +++ /dev/null @@ -1,8 +0,0 @@ -[gd_scene load_steps=2 format=2] - -[sub_resource type="RectangleShape2D" id=1] - -[node name="MoveComponent" type="CharacterBody2D"] - -[node name="Collision" type="CollisionShape2D" parent="."] -shape = SubResource( 1 ) diff --git a/DungeonShooting_Godot/prefab/ui/MapEditor.tscn b/DungeonShooting_Godot/prefab/ui/MapEditor.tscn index 7af93472..600e4cc3 100644 --- a/DungeonShooting_Godot/prefab/ui/MapEditor.tscn +++ b/DungeonShooting_Godot/prefab/ui/MapEditor.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=16 format=3 uid="uid://csbxfkdupsckv"] +[gd_scene load_steps=18 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/commonIcon/Back.png" id="2_gkcw7"] @@ -8,10 +8,12 @@ [ext_resource type="Script" path="res://src/game/ui/mapEditor/tileView/EditorTileMap.cs" id="4_mhy1a"] [ext_resource type="Texture2D" uid="uid://bpbfjyj6258da" path="res://resource/sprite/ui/commonIcon/Setting.png" id="5_ubl8b"] [ext_resource type="PackedScene" uid="uid://b4u66mxndxbrg" path="res://prefab/ui/MapEditorTools.tscn" id="6_7pvgu"] +[ext_resource type="PackedScene" uid="uid://ckurrh15w3yrt" path="res://prefab/ui/MapEditorConfigObject.tscn" id="7_42mx1"] [ext_resource type="PackedScene" uid="uid://bb2ekkpxifd7g" path="res://prefab/ui/MapEditorMapLayer.tscn" id="7_ychtn"] [ext_resource type="PackedScene" uid="uid://peo0n8bl15y5" path="res://prefab/ui/MapEditorMapMark.tscn" id="8_8tgeu"] [ext_resource type="NavigationPolygon" uid="uid://brpcle7mygiml" path="res://resource/navigation/NavigationPolygon.tres" id="8_t7nq5"] [ext_resource type="PackedScene" uid="uid://tjbfj67t5akm" path="res://prefab/ui/MapEditorMapTile.tscn" id="10_4fu5v"] +[ext_resource type="PackedScene" uid="uid://6a4l0o8pmegw" path="res://prefab/ui/MapEditorObject.tscn" id="12_vpk4h"] [sub_resource type="Animation" id="Animation_o3btm"] length = 0.001 @@ -184,10 +186,10 @@ layout_mode = 2 [node name="MapEditorMapLayer" parent="Bg/VBoxContainer/HSplitContainer/HSplitContainer2/HBoxContainer/LayerPanel" instance=ExtResource("7_ychtn")] layout_mode = 1 -offset_left = 2.0 -offset_top = 2.0 -offset_right = -2.0 -offset_bottom = -2.0 + +[node name="MapEditorConfigObject" parent="Bg/VBoxContainer/HSplitContainer/HSplitContainer2/HBoxContainer/LayerPanel" instance=ExtResource("7_42mx1")] +visible = false +layout_mode = 1 [node name="Left" type="Panel" parent="Bg/VBoxContainer/HSplitContainer/HSplitContainer2/HBoxContainer"] custom_minimum_size = Vector2(300, 0) @@ -283,6 +285,14 @@ theme_override_constants/margin_top = 10 [node name="MapEditorMapTile" parent="Bg/VBoxContainer/HSplitContainer/HSplitContainer2/Right/MarginContainer/TabContainer/MapTile" instance=ExtResource("10_4fu5v")] layout_mode = 2 +[node name="MapObject" type="MarginContainer" parent="Bg/VBoxContainer/HSplitContainer/HSplitContainer2/Right/MarginContainer/TabContainer"] +visible = false +layout_mode = 2 +theme_override_constants/margin_top = 10 + +[node name="MapEditorObject" parent="Bg/VBoxContainer/HSplitContainer/HSplitContainer2/Right/MarginContainer/TabContainer/MapObject" instance=ExtResource("12_vpk4h")] +layout_mode = 2 + [node name="MapMark" type="MarginContainer" parent="Bg/VBoxContainer/HSplitContainer/HSplitContainer2/Right/MarginContainer/TabContainer"] visible = false layout_mode = 2 diff --git a/DungeonShooting_Godot/prefab/ui/MapEditorConfigObject.tscn b/DungeonShooting_Godot/prefab/ui/MapEditorConfigObject.tscn new file mode 100644 index 00000000..8efc4a0c --- /dev/null +++ b/DungeonShooting_Godot/prefab/ui/MapEditorConfigObject.tscn @@ -0,0 +1,93 @@ +[gd_scene load_steps=4 format=3 uid="uid://1kdlshgpe3q2"] + +[ext_resource type="Script" path="res://src/game/ui/mapEditorConfigObject/MapEditorConfigObjectPanel.cs" id="1_qm00b"] +[ext_resource type="Texture2D" uid="uid://blfvsup876agh" path="res://resource/sprite/ui/commonIcon/Search.png" id="2_rkdcy"] +[ext_resource type="Texture2D" uid="uid://bn47bmilcw4x0" path="res://resource/sprite/ui/commonIcon/Select2.png" id="3_65sjj"] + +[node name="MapEditorConfigObject" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_qm00b") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 2.0 +offset_top = 2.0 +offset_right = -2.0 +offset_bottom = -2.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 45) +layout_mode = 2 + +[node name="SearchInput" type="LineEdit" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "搜索" + +[node name="SearchButton" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +icon = ExtResource("2_rkdcy") + +[node name="ScrollContainer" type="ScrollContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="CellButton" type="Button" parent="VBoxContainer/ScrollContainer"] +custom_minimum_size = Vector2(112, 162) +layout_mode = 2 + +[node name="PreviewImage" type="TextureRect" parent="VBoxContainer/ScrollContainer/CellButton"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 2.0 +offset_top = 2.0 +offset_right = -2.0 +offset_bottom = -52.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +expand_mode = 2 +stretch_mode = 5 + +[node name="CellName" type="Label" parent="VBoxContainer/ScrollContainer/CellButton"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -52.0 +grow_horizontal = 2 +grow_vertical = 0 +theme_override_font_sizes/font_size = 16 +text = "名称" +horizontal_alignment = 1 +vertical_alignment = 1 +autowrap_mode = 2 +clip_text = true +text_overrun_behavior = 2 + +[node name="SelectTexture" type="NinePatchRect" parent="VBoxContainer/ScrollContainer/CellButton"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("3_65sjj") +region_rect = Rect2(0, 0, 36, 36) +patch_margin_left = 4 +patch_margin_top = 4 +patch_margin_right = 4 +patch_margin_bottom = 4 diff --git a/DungeonShooting_Godot/prefab/ui/MapEditorObject.tscn b/DungeonShooting_Godot/prefab/ui/MapEditorObject.tscn new file mode 100644 index 00000000..6cba6ccc --- /dev/null +++ b/DungeonShooting_Godot/prefab/ui/MapEditorObject.tscn @@ -0,0 +1,119 @@ +[gd_scene load_steps=8 format=3 uid="uid://6a4l0o8pmegw"] + +[ext_resource type="Script" path="res://src/game/ui/mapEditorObject/MapEditorObjectPanel.cs" id="1_yphyn"] +[ext_resource type="Texture2D" uid="uid://blfvsup876agh" path="res://resource/sprite/ui/commonIcon/Search.png" id="2_e3a41"] +[ext_resource type="Texture2D" uid="uid://btetxb0hqoifk" path="res://resource/sprite/ui/commonIcon/MarkCell_placeholder.png" id="3_s35vd"] +[ext_resource type="Shader" path="res://resource/shader/Blend.gdshader" id="4_by2nt"] +[ext_resource type="Texture2D" uid="uid://bn47bmilcw4x0" path="res://resource/sprite/ui/commonIcon/Select2.png" id="5_caspl"] +[ext_resource type="Texture2D" uid="uid://c5778ntk2rdon" path="res://resource/sprite/ui/commonIcon/Delete.png" id="7_8ld0o"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_wkboy"] +resource_local_to_scene = true +shader = ExtResource("4_by2nt") +shader_parameter/blend = Color(1, 1, 1, 1) +shader_parameter/schedule = 0.0 +shader_parameter/modulate = Color(1, 1, 1, 1) +shader_parameter/show_outline = true +shader_parameter/outline_color = Color(1, 1, 1, 1) +shader_parameter/outline_rainbow = false +shader_parameter/outline_use_blend = false +shader_parameter/grey = 0.0 + +[node name="MapEditorObject" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_yphyn") + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +custom_minimum_size = Vector2(0, 45) +layout_mode = 2 + +[node name="SearchInput" type="LineEdit" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +placeholder_text = "搜索" + +[node name="SearchButton" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +icon = ExtResource("2_e3a41") + +[node name="HBoxContainer2" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Label" type="Label" parent="VBoxContainer/HBoxContainer2"] +custom_minimum_size = Vector2(200, 0) +layout_mode = 2 +text = "物体层级:" + +[node name="LayerOption" type="OptionButton" parent="VBoxContainer/HBoxContainer2"] +layout_mode = 2 +size_flags_horizontal = 3 +item_count = 2 +selected = 0 +popup/item_0/text = "Normal" +popup/item_0/id = 0 +popup/item_1/text = "YSort" +popup/item_1/id = 1 + +[node name="ItemRoot" type="ScrollContainer" parent="VBoxContainer"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="Item" type="HBoxContainer" parent="VBoxContainer/ItemRoot"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="ItemButton" type="Button" parent="VBoxContainer/ItemRoot/Item"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "名称" +icon = ExtResource("3_s35vd") +alignment = 0 +text_overrun_behavior = 3 + +[node name="Icon" type="TextureRect" parent="VBoxContainer/ItemRoot/Item/ItemButton"] +material = SubResource("ShaderMaterial_wkboy") +custom_minimum_size = Vector2(64, 64) +layout_mode = 1 +anchors_preset = 4 +anchor_top = 0.5 +anchor_bottom = 0.5 +offset_left = 2.0 +offset_top = -32.0 +offset_right = 66.0 +offset_bottom = 32.0 +grow_vertical = 2 +expand_mode = 2 +stretch_mode = 5 + +[node name="Select" type="NinePatchRect" parent="VBoxContainer/ItemRoot/Item/ItemButton"] +visible = false +layout_mode = 2 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("5_caspl") +patch_margin_left = 4 +patch_margin_top = 4 +patch_margin_right = 4 +patch_margin_bottom = 4 + +[node name="DynamicDeleteButton" type="Button" parent="."] +visible = false +layout_mode = 2 +offset_right = 44.0 +offset_bottom = 40.0 +icon = ExtResource("7_8ld0o") diff --git a/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn b/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn index ff372202..8c3b14ed 100644 --- a/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn +++ b/DungeonShooting_Godot/prefab/ui/MapEditorTools.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=12 format=3 uid="uid://b4u66mxndxbrg"] +[gd_scene load_steps=14 format=3 uid="uid://b4u66mxndxbrg"] [ext_resource type="Script" path="res://src/game/ui/mapEditorTools/MapEditorToolsPanel.cs" id="1_mqp1c"] [ext_resource type="Script" path="res://src/game/ui/mapEditorTools/DoorHoverArea.cs" id="2_6qfy3"] @@ -10,7 +10,7 @@ [ext_resource type="Texture2D" uid="uid://dnty1a2tcawos" path="res://resource/sprite/ui/commonIcon/Mark.png" id="6_n7h3g"] [ext_resource type="Script" path="res://src/game/ui/mapEditorTools/MarkTool.cs" id="7_ekxcj"] [ext_resource type="Texture2D" uid="uid://cuntr7hec044f" path="res://resource/sprite/ui/commonIcon/Select.png" id="7_mqmd6"] - +[ext_resource type="Script" path="res://src/game/ui/mapEditorTools/CustomObject.cs" id="9_mdsqu"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_wxp5t"] resource_local_to_scene = true @@ -24,6 +24,9 @@ shader_parameter/outline_rainbow = false shader_parameter/outline_use_blend = false shader_parameter/grey = 0.0 +[sub_resource type="RectangleShape2D" id="RectangleShape2D_0a2r0"] +size = Vector2(16, 16) + [node name="MapEditorTools" type="Control"] layout_mode = 3 anchors_preset = 15 @@ -175,6 +178,21 @@ expand_mode = 2 stretch_mode = 5 script = ExtResource("7_ekxcj") +[node name="ObjectTemplate" type="Area2D" parent="."] +collision_layer = 8192 +collision_mask = 0 +monitoring = false +monitorable = false +script = ExtResource("9_mdsqu") + +[node name="CollisionShape2D" type="CollisionShape2D" parent="ObjectTemplate"] +shape = SubResource("RectangleShape2D_0a2r0") + +[node name="Bar" type="Node2D" parent="ObjectTemplate"] + +[node name="RectBrush" type="Node2D" parent="ObjectTemplate"] +z_index = 15 + [node name="HBoxContainer" type="HBoxContainer" parent="."] layout_mode = 1 anchors_preset = 1 diff --git a/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn b/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn index 44a597c4..2dbdc14f 100644 --- a/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn +++ b/DungeonShooting_Godot/prefab/ui/TileSetEditorCombination.tscn @@ -8,7 +8,7 @@ [ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/leftTop/TileEditCombination.cs" id="6_bb3jf"] [ext_resource type="Texture2D" uid="uid://bn47bmilcw4x0" path="res://resource/sprite/ui/commonIcon/Select2.png" id="6_g5ey6"] [ext_resource type="Script" path="res://src/game/ui/tileSetEditorCombination/right/TileSelected.cs" id="6_gql80"] -[ext_resource type="Script" path="res://src/game/common/ui/EditorMaskBrush.cs" id="7_k0dkc"] +[ext_resource type="Script" path="res://src/game/common/editor/EditorMaskBrush.cs" id="7_k0dkc"] [ext_resource type="Texture2D" uid="uid://d2wslibovwv7w" path="res://resource/sprite/ui/commonIcon/CenterTool.png" id="7_mbnpy"] [node name="TileSetEditorCombination" type="Control"] diff --git a/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn b/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn index 924a7c84..c3000745 100644 --- a/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn +++ b/DungeonShooting_Godot/prefab/ui/TileSetEditorTerrain.tscn @@ -3,7 +3,7 @@ [ext_resource type="Script" path="res://src/game/ui/tileSetEditorTerrain/TileSetEditorTerrainPanel.cs" id="1_6jjk7"] [ext_resource type="Texture2D" uid="uid://n4atvj5fkcpg" path="res://resource/sprite/ui/commonIcon/Add.png" id="2_ns54l"] [ext_resource type="Script" path="res://src/game/ui/tileSetEditorTerrain/down/TileEditArea.cs" id="2_ynf0r"] -[ext_resource type="Script" path="res://src/game/common/ui/EditorMaskBrush.cs" id="3_gydh0"] +[ext_resource type="Script" path="res://src/game/common/editor/EditorMaskBrush.cs" id="3_gydh0"] [ext_resource type="Texture2D" uid="uid://c5778ntk2rdon" path="res://resource/sprite/ui/commonIcon/Delete.png" id="3_jn1bd"] [ext_resource type="Texture2D" uid="uid://dggb6p4sdmfry" path="res://resource/sprite/ui/commonIcon/Edit.png" id="3_xmuhh"] [ext_resource type="Texture2D" uid="uid://bn47bmilcw4x0" path="res://resource/sprite/ui/commonIcon/Select2.png" id="4_ka47m"] diff --git a/DungeonShooting_Godot/resource/config/ActivityBase.json b/DungeonShooting_Godot/resource/config/ActivityBase.json index fd324d13..6351052f 100644 --- a/DungeonShooting_Godot/resource/config/ActivityBase.json +++ b/DungeonShooting_Godot/resource/config/ActivityBase.json @@ -939,7 +939,7 @@ }, { "Id": "item_0003", - "Name": "", + "Name": "\u6321\u677F", "Type": 99, "Quality": 0, "Price": 0, @@ -948,7 +948,7 @@ "IsStatic": true, "__Material": "", "Prefab": "res://prefab/item/Item0003.tscn", - "Icon": "", + "Icon": "res://resource/sprite/item/hall_b/item-32.png", "ShowInMapEditor": false }, { @@ -967,7 +967,7 @@ }, { "Id": "item_0005", - "Name": "", + "Name": "\u4FDD\u9669\u7BB1", "Type": 99, "Quality": 0, "Price": 0, @@ -976,7 +976,7 @@ "IsStatic": true, "__Material": "", "Prefab": "res://prefab/item/Item0005.tscn", - "Icon": "", + "Icon": "res://resource/sprite/item/hall_b/item-01.png", "ShowInMapEditor": false }, { @@ -1186,7 +1186,7 @@ "IsStatic": true, "__Material": "", "Prefab": "res://prefab/item/Item0020.tscn", - "Icon": "", + "Icon": "res://resource/sprite/item/hall_a/Slice_42.png", "ShowInMapEditor": false }, { @@ -1228,7 +1228,7 @@ "IsStatic": true, "__Material": "", "Prefab": "res://prefab/item/Item0023.tscn", - "Icon": "", + "Icon": "res://resource/sprite/item/hall_a/Slice_40.png", "ShowInMapEditor": false }, { diff --git a/DungeonShooting_Godot/resource/config/EditorObject.json b/DungeonShooting_Godot/resource/config/EditorObject.json index aaf4454c..842c6cf3 100644 --- a/DungeonShooting_Godot/resource/config/EditorObject.json +++ b/DungeonShooting_Godot/resource/config/EditorObject.json @@ -27,186 +27,11 @@ "Prefab": "item_0023", "Icon": "" }, - { - "Id": "0005", - "Name": "\u751F\u65E5\u86CB\u7CD5", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0001.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0001_ICON.png" - }, { "Id": "0006", "Name": "\u76F8\u673A", "Remark": "", "Prefab": "res://prefab/dungeonitem/Dungenitem0002.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0002_ICON.png" - }, - { - "Id": "0007", - "Name": "\u5893\u7891", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0003.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0003_ICON.png" - }, - { - "Id": "0008", - "Name": "\u74F6\u5B5001", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0004.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0004_ICON.png" - }, - { - "Id": "0009", - "Name": "\u9EC4\u7CD6\u68CD-\u5DE6", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0005.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0005_ICON.png" - }, - { - "Id": "0010", - "Name": "\u7EA2\u7CD6\u68CD-\u5DE6", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0006.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0006_ICON.png" - }, - { - "Id": "0011", - "Name": "\u9EC4\u7CD6\u68CD-\u53F3", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0007.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0007_ICON.png" - }, - { - "Id": "0012", - "Name": "\u7EA2\u7CD6\u68CD-\u53F3", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0008.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0008_ICON.png" - }, - { - "Id": "0013", - "Name": "\u7EA2\u68D2\u68D2\u7CD6", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0009.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0009_ICON.png" - }, - { - "Id": "0014", - "Name": "\u9EC4\u68D2\u68D2\u7CD6", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0010.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0010_ICON.png" - }, - { - "Id": "0015", - "Name": "\u751C\u751C\u5708", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0011.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0011_ICON.png" - }, - { - "Id": "0016", - "Name": "\u9999\u8549", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0012.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0012_ICON.png" - }, - { - "Id": "0017", - "Name": "\u68A8\u5B50", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0013.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0013_ICON.png" - }, - { - "Id": "0018", - "Name": "\u897F\u74DC", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0014.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0014_ICON.png" - }, - { - "Id": "0019", - "Name": "\u5C71\u7AF9", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0015.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0015_ICON.png" - }, - { - "Id": "0020", - "Name": "\u6A59\u5B50", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0016.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0016_ICON.png" - }, - { - "Id": "0021", - "Name": "\u7B3C\u5B50", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0017.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0017_ICON.png" - }, - { - "Id": "0022", - "Name": "\u6C99\u53D1", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0018.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0018_ICON.png" - }, - { - "Id": "0023", - "Name": "\u6905\u5B5001", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0019.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0019_ICON.png" - }, - { - "Id": "0024", - "Name": "\u996E\u6C34\u673A", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0020.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0020_ICON.png" - }, - { - "Id": "0025", - "Name": "\u6728\u7BB1", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0021.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0021_ICON.png" - }, - { - "Id": "0026", - "Name": "\u74F6\u5B5002", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0022.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0022_ICON.png" - }, - { - "Id": "0027", - "Name": "\u9152\u6876-\u5173", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0023.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0023_ICON.png" - }, - { - "Id": "0028", - "Name": "\u9152\u6876-\u5F00", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0024.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0024_ICON.png" - }, - { - "Id": "0029", - "Name": "\u5DE7\u514B\u529B\u5757", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0025.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0025_ICON.png" - }, - { - "Id": "0030", - "Name": "\u6728\u677F", - "Remark": "", - "Prefab": "res://prefab/dungeonitem/Dungenitem0026.tscn", - "Icon": "res://resource/DungeonitemICON/Dungeonitem0026_ICON.png" + "Icon": "res://resource/sprite/itemIcon/item0002_icon.png" } ] \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json b/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json index d175f222..ef1491fc 100644 --- a/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json +++ b/DungeonShooting_Godot/resource/map/tileMaps/GroupConfig.json @@ -47,6 +47,10 @@ { "ErrorType": 0, "Path": "resource/map/tileMaps/Test1/inlet/Start2" + }, + { + "ErrorType": 0, + "Path": "resource/map/tileMaps/Test1/inlet/StartTest" } ], "OutletList": [ diff --git a/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preinstall.json b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preinstall.json new file mode 100644 index 00000000..7f4ab09b --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preinstall.json @@ -0,0 +1 @@ +[{"Name":"Preinstall1","Weight":100,"Remark":"","AutoFill":true,"WaveList":[[{"Position":{"X":0,"Y":0},"Size":{"X":0,"Y":0},"SpecialMarkType":1,"DelayTime":0,"MarkList":[]}]]}] \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preview.png b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preview.png new file mode 100644 index 00000000..32aadb35 Binary files /dev/null and b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preview.png differ diff --git a/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preview.png.import b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preview.png.import new file mode 100644 index 00000000..5c42b21c --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/Preview.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://catkx4ioplk7r" +path="res://.godot/imported/Preview.png-28e265a85fcd3d3f19005e05f4081de2.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/map/tileMaps/Test1/inlet/StartTest/Preview.png" +dest_files=["res://.godot/imported/Preview.png-28e265a85fcd3d3f19005e05f4081de2.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/map/tileMaps/Test1/inlet/StartTest/RoomInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/RoomInfo.json new file mode 100644 index 00000000..2726f052 --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/RoomInfo.json @@ -0,0 +1 @@ +{"Position":{"X":-12,"Y":-11},"Size":{"X":20,"Y":19},"DoorAreaInfos":[],"GroupName":"Test1","RoomType":2,"RoomName":"StartTest","Weight":100,"Remark":""} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/TileInfo.json b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/TileInfo.json new file mode 100644 index 00000000..0c5fcb28 --- /dev/null +++ b/DungeonShooting_Godot/resource/map/tileMaps/Test1/inlet/StartTest/TileInfo.json @@ -0,0 +1 @@ +{"NavigationVertices":[{"X":90,"Y":106},{"X":-154,"Y":106},{"X":-154,"Y":-122},{"X":90,"Y":-122}],"NavigationPolygon":[[0,1,2,3]],"Floor":[-10,-8,0,3,-10,-7,0,3,-10,-6,0,3,-10,-5,0,3,-10,-4,0,3,-10,-3,0,3,-10,-2,0,3,-10,-1,0,3,-10,0,0,3,-10,1,0,3,-10,2,0,3,-10,3,0,3,-10,4,0,3,-10,5,0,3,-9,-8,0,3,-9,-7,0,3,-9,-6,0,3,-9,-5,0,3,-9,-4,0,3,-9,-3,0,3,-9,-2,0,3,-9,-1,0,3,-9,0,0,3,-9,1,0,3,-9,2,0,3,-9,3,0,3,-9,4,0,3,-9,5,0,3,-8,-8,0,3,-8,-7,0,3,-8,-6,0,3,-8,-5,0,3,-8,-4,0,3,-8,-3,0,3,-8,-2,0,3,-8,-1,0,3,-8,0,0,3,-8,1,0,3,-8,2,0,3,-8,3,0,3,-8,4,0,3,-8,5,0,3,-7,-8,0,3,-7,-7,0,3,-7,-6,0,3,-7,-5,0,3,-7,-4,0,3,-7,-3,0,3,-7,-2,0,3,-7,-1,0,3,-7,0,0,3,-7,1,0,3,-7,2,0,3,-7,3,0,3,-7,4,0,3,-7,5,0,3,-6,-8,0,3,-6,-7,0,3,-6,-6,0,3,-6,-5,0,3,-6,-4,0,3,-6,-3,0,3,-6,-2,0,3,-6,-1,0,3,-6,0,0,3,-6,1,0,3,-6,2,0,3,-6,3,0,3,-6,4,0,3,-6,5,0,3,-5,-8,0,3,-5,-7,0,3,-5,-6,0,3,-5,-5,0,3,-5,-4,0,3,-5,-3,0,3,-5,-2,0,3,-5,-1,0,3,-5,0,0,3,-5,1,0,3,-5,2,0,3,-5,3,0,3,-5,4,0,3,-5,5,0,3,-4,-8,0,3,-4,-7,0,3,-4,-6,0,3,-4,-5,0,3,-4,-4,0,3,-4,-3,0,3,-4,-2,0,3,-4,-1,0,3,-4,0,0,3,-4,1,0,3,-4,2,0,3,-4,3,0,3,-4,4,0,3,-4,5,0,3,-3,-8,0,3,-3,-7,0,3,-3,-6,0,3,-3,-5,0,3,-3,-4,0,3,-3,-3,0,3,-3,-2,0,3,-3,-1,0,3,-3,0,0,3,-3,1,0,3,-3,2,0,3,-3,3,0,3,-3,4,0,3,-3,5,0,3,-2,-8,0,3,-2,-7,0,3,-2,-6,0,3,-2,-5,0,3,-2,-4,0,3,-2,-3,0,3,-2,-2,0,3,-2,-1,0,3,-2,0,0,3,-2,1,0,3,-2,2,0,3,-2,3,0,3,-2,4,0,3,-2,5,0,3,-1,-8,0,3,-1,-7,0,3,-1,-6,0,3,-1,-5,0,3,-1,-4,0,3,-1,-3,0,3,-1,-2,0,3,-1,-1,0,3,-1,0,0,3,-1,1,0,3,-1,2,0,3,-1,3,0,3,-1,4,0,3,-1,5,0,3,0,-8,0,3,0,-7,0,3,0,-6,0,3,0,-5,0,3,0,-4,0,3,0,-3,0,3,0,-2,0,3,0,-1,0,3,0,0,0,3,0,1,0,3,0,2,0,3,0,3,0,3,0,4,0,3,0,5,0,3,1,-8,0,3,1,-7,0,3,1,-6,0,3,1,-5,0,3,1,-4,0,3,1,-3,0,3,1,-2,0,3,1,-1,0,3,1,0,0,3,1,1,0,3,1,2,0,3,1,3,0,3,1,4,0,3,1,5,0,3,2,-8,0,3,2,-7,0,3,2,-6,0,3,2,-5,0,3,2,-4,0,3,2,-3,0,3,2,-2,0,3,2,-1,0,3,2,0,0,3,2,1,0,3,2,2,0,3,2,3,0,3,2,4,0,3,2,5,0,3,3,-8,0,3,3,-7,0,3,3,-6,0,3,3,-5,0,3,3,-4,0,3,3,-3,0,3,3,-2,0,3,3,-1,0,3,3,0,0,3,3,1,0,3,3,2,0,3,3,3,0,3,3,4,0,3,3,5,0,3,4,-8,0,3,4,-7,0,3,4,-6,0,3,4,-5,0,3,4,-4,0,3,4,-3,0,3,4,-2,0,3,4,-1,0,3,4,0,0,3,4,1,0,3,4,2,0,3,4,3,0,3,4,4,0,3,4,5,0,3,5,-8,0,3,5,-7,0,3,5,-6,0,3,5,-5,0,3,5,-4,0,3,5,-3,0,3,5,-2,0,3,5,-1,0,3,5,0,0,3,5,1,0,3,5,2,0,3,5,3,0,3,5,4,0,3,5,5,0,3],"CustomFloor1":[],"CustomFloor2":[],"CustomFloor3":[],"CustomMiddle1":[],"CustomMiddle2":[],"CustomTop":[],"NormalLayerObjects":[],"YSortLayerObjects":[{"Id":"0006","X":-77,"Y":-38},{"Id":"0006","X":21,"Y":41}]} \ No newline at end of file diff --git a/DungeonShooting_Godot/resource/sprite/item/Items.png b/DungeonShooting_Godot/resource/sprite/item/Items.png new file mode 100644 index 00000000..69eb8b5d Binary files /dev/null and b/DungeonShooting_Godot/resource/sprite/item/Items.png differ diff --git a/DungeonShooting_Godot/resource/sprite/item/Items.png.import b/DungeonShooting_Godot/resource/sprite/item/Items.png.import new file mode 100644 index 00000000..cbd42e0d --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/item/Items.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bkc3fxmnxe7nh" +path="res://.godot/imported/Items.png-c7f11029206f49e1dc7f04d29807e764.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/item/Items.png" +dest_files=["res://.godot/imported/Items.png-c7f11029206f49e1dc7f04d29807e764.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/itemIcon/item0002_icon.png b/DungeonShooting_Godot/resource/sprite/itemIcon/item0002_icon.png new file mode 100644 index 00000000..007b31f8 Binary files /dev/null and b/DungeonShooting_Godot/resource/sprite/itemIcon/item0002_icon.png differ diff --git a/DungeonShooting_Godot/resource/sprite/itemIcon/item0002_icon.png.import b/DungeonShooting_Godot/resource/sprite/itemIcon/item0002_icon.png.import new file mode 100644 index 00000000..a431fcf5 --- /dev/null +++ b/DungeonShooting_Godot/resource/sprite/itemIcon/item0002_icon.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://vr2wbuxvn6e2" +path="res://.godot/imported/item0002_icon.png-0ef326b8a821685b6961de25b0df6160.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://resource/sprite/itemIcon/item0002_icon.png" +dest_files=["res://.godot/imported/item0002_icon.png-0ef326b8a821685b6961de25b0df6160.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/scene/Hall.tscn b/DungeonShooting_Godot/scene/Hall.tscn index 18ea82c2..da34be84 100644 --- a/DungeonShooting_Godot/scene/Hall.tscn +++ b/DungeonShooting_Godot/scene/Hall.tscn @@ -90,14 +90,13 @@ position = Vector2(502, 214) [node name="DungeonEntrance" type="Area2D" parent="." index="4"] z_index = 15 -position = Vector2(346, 179) +position = Vector2(483, 182) collision_layer = 0 collision_mask = 8 monitorable = false script = ExtResource("3_t3my6") [node name="CollisionShape2D" type="CollisionShape2D" parent="DungeonEntrance" index="0"] -position = Vector2(137.5, 2) shape = SubResource("RectangleShape2D_ru8u4") [node name="ItemRoot" type="Node2D" parent="." index="5"] diff --git a/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs b/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs index 8b75ae7c..bfb99e93 100644 --- a/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs +++ b/DungeonShooting_Godot/src/framework/activity/ActivityObject_Init.cs @@ -344,7 +344,7 @@ public partial class ActivityObject /// public const string Id_item_0002 = "item_0002"; /// - /// 名称:
+ /// 名称: 挡板
/// 简介: ///
public const string Id_item_0003 = "item_0003"; @@ -354,7 +354,7 @@ public partial class ActivityObject /// public const string Id_item_0004 = "item_0004"; /// - /// 名称:
+ /// 名称: 保险箱
/// 简介: ///
public const string Id_item_0005 = "item_0005"; diff --git a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs index 15ba72b0..98c3e1fd 100644 --- a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs +++ b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs @@ -347,9 +347,43 @@ public class UiGrid : IUiGrid where TUiCellNode : IUiCellNod } } + /// + /// 设置当前网格组件中的所有 Cell 数据, 性能较低 + /// + public void SetDataList(List array) + { + //取消选中 + SelectIndex = -1; + if (array.Count > _cellList.Count) + { + do + { + var cell = GetCellInstance(); + GridContainer.AddChild(cell.CellNode.GetUiInstance()); + } while (array.Count > _cellList.Count); + } + else if (array.Count < _cellList.Count) + { + do + { + var cell = _cellList[_cellList.Count - 1]; + _cellList.RemoveAt(_cellList.Count - 1); + ReclaimCellInstance(cell); + } while (array.Count < _cellList.Count); + } + + for (var i = 0; i < _cellList.Count; i++) + { + var data = array[i]; + _cellList[i].UpdateData(data); + } + } + /// /// 设置当前网格组件中的所有 Cell 数据, 该函数为协程函数,可用于分帧处理大量数据 /// + /// 数据集合 + /// public IEnumerator SetDataListCoroutine(ICollection array) { RemoveAll(); diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs index dd4469ad..c5aa90b4 100644 --- a/DungeonShooting_Godot/src/game/GameApplication.cs +++ b/DungeonShooting_Godot/src/game/GameApplication.cs @@ -121,7 +121,7 @@ public partial class GameApplication : Node2D, ICoroutine FirstDungeonConfig = GetDungeonConfig(DungeonGroupList[0], 1); //临时处理 - RoomConfig[DungeonGroupList[0]].BgColor = new Color("0a0a19"); + //RoomConfig[DungeonGroupList[0]].BgColor = new Color("0a0a19"); RoomConfig[DungeonGroupList[0]].SoundId = null; //"level1_bgm"; } diff --git a/DungeonShooting_Godot/src/game/common/ui/EditorGridBg.cs b/DungeonShooting_Godot/src/game/common/editor/EditorGridBg.cs similarity index 100% rename from DungeonShooting_Godot/src/game/common/ui/EditorGridBg.cs rename to DungeonShooting_Godot/src/game/common/editor/EditorGridBg.cs diff --git a/DungeonShooting_Godot/src/game/common/ui/EditorMaskBrush.cs b/DungeonShooting_Godot/src/game/common/editor/EditorMaskBrush.cs similarity index 100% rename from DungeonShooting_Godot/src/game/common/ui/EditorMaskBrush.cs rename to DungeonShooting_Godot/src/game/common/editor/EditorMaskBrush.cs diff --git a/DungeonShooting_Godot/src/game/common/editor/IEditorTab.cs b/DungeonShooting_Godot/src/game/common/editor/IEditorTab.cs new file mode 100644 index 00000000..f92a0141 --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/IEditorTab.cs @@ -0,0 +1,16 @@ + +/// +/// 编辑器页签 +/// +public interface IEditorTab +{ + /// + /// 选中页签 + /// + void OnSelectTab(); + + /// + /// 取消选中页签 + /// + void OnUnSelectTab(); +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorFocus.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorFocus.cs new file mode 100644 index 00000000..ed769b07 --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorFocus.cs @@ -0,0 +1,18 @@ + +using UI.MapEditor; + +/// +/// 聚焦按钮 +/// +public class EditorFocus : EditorToolBase +{ + public EditorFocus(EditorTileMap editorTileMap) : base( + ResourcePath.resource_sprite_ui_commonIcon_CenterTool_png, "聚焦", false, editorTileMap, EditorToolEnum.Focus) + { + } + + public override void OnClick() + { + EditorTileMap.OnFocusClick(); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorMarkTool.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorMarkTool.cs new file mode 100644 index 00000000..85fcd33b --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorMarkTool.cs @@ -0,0 +1,21 @@ + +using UI.MapEditor; + +/// +/// 编辑物体标记 +/// +public class EditorMarkTool : EditorToolBase +{ + public EditorMarkTool(EditorTileMap editorTileMap) : base( + ResourcePath.resource_sprite_ui_commonIcon_DoorTool_png, "编辑物体标记", true, editorTileMap, EditorToolEnum.MarkTool) + { + } + + public override void OnSetSelected(bool selected) + { + if (selected) + { + EditorTileMap.MapEditorPanel.S_MapEditorMapLayer.Instance.SetLayerVisible(MapLayer.MarkLayer, true); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorMove.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorMove.cs new file mode 100644 index 00000000..3fb06132 --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorMove.cs @@ -0,0 +1,34 @@ + +using Godot; +using UI.MapEditor; + +/// +/// 移动视角按钮 +/// +public class EditorMove : EditorToolBase +{ + private bool _isPressed; + + public EditorMove(EditorTileMap editorTileMap) : base( + ResourcePath.resource_sprite_ui_commonIcon_DragTool_png, "移动视角", true, editorTileMap, EditorToolEnum.Move) + { + } + + public override void OnMapInputEvent(InputEvent @event) + { + if (@event is InputEventMouseButton mouseButton) + { + if (mouseButton.ButtonIndex == MouseButton.Left || mouseButton.ButtonIndex == MouseButton.Right || mouseButton.ButtonIndex == MouseButton.Middle) + { + _isPressed = mouseButton.Pressed; + } + } + else if (@event is InputEventMouseMotion motion) + { + if (_isPressed) + { + EditorTileMap.SetMapPosition(EditorTileMap.Position + motion.Relative); + } + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorObjectPen.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorObjectPen.cs new file mode 100644 index 00000000..c11c09ed --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorObjectPen.cs @@ -0,0 +1,49 @@ + +using Godot; +using UI.MapEditor; + +public class EditorObjectPen : EditorToolBase +{ + private bool _isPressed; + + public EditorObjectPen(EditorTileMap editorTileMap) : base( + ResourcePath.resource_sprite_ui_commonIcon_PenTool_png, "绘制物体", true, editorTileMap, EditorToolEnum.ObjectPen) + { + } + + public override void OnMapInputEvent(InputEvent @event) + { + if (@event is InputEventMouseButton mouseButton) + { + if (mouseButton.ButtonIndex == MouseButton.Left) + { + _isPressed = mouseButton.Pressed; + if (_isPressed) + { + DoPutObject(); + } + } + } + } + + private void DoPutObject() + { + var config = EditorTileMap.MapEditorPanel.S_MapEditorConfigObject.Instance.GetSelectConfig(); + if (config != null) + { + var pos = EditorTileMap.GetLocalMousePosition().AsVector2I(); + EventManager.EmitEvent(EventEnum.OnPutObject, new RoomObjectInfo() + { + Id = config.Id, + X = pos.X, + Y = pos.Y + }); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); + } + else + { + EditorWindowManager.ShowTips("提示", "请先在左侧面板选择一个物体!"); + } + } + +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorObjectTool.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorObjectTool.cs new file mode 100644 index 00000000..cc77f57f --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorObjectTool.cs @@ -0,0 +1,111 @@ + +using System.Collections.Generic; +using Godot; +using UI.MapEditor; +using UI.MapEditorObject; +using UI.MapEditorTools; + +public class EditorObjectTool : EditorToolBase +{ + private bool _isPressed; + private int _flag = 0; + //private Vector2 _offset; + + private UiGrid _objectGrid; + private Dictionary _customObjecMapping; + + + public EditorObjectTool(EditorTileMap editorTileMap) : base( + ResourcePath.resource_sprite_ui_commonIcon_DoorTool_png, "编辑物体", true, editorTileMap, EditorToolEnum.ObjectTool) + { + } + + public override void OnSetSelected(bool selected) + { + _objectGrid = EditorTileMap.MapEditorPanel.S_MapEditorObject.Instance.ObjectGrid; + _customObjecMapping = EditorTileMap.MapEditorToolsPanel.CustomObjecMapping; + } + + public override void OnMapInputEvent(InputEvent @event) + { + if (@event is InputEventMouseButton mouseButton) + { + if (mouseButton.ButtonIndex == MouseButton.Left) + { + _isPressed = mouseButton.Pressed; + if (_isPressed) + { + DoSelectObject(); + } + else + { + _flag = 0; + } + } + } + else if (_isPressed && _flag > 0 && _objectGrid.SelectData != null && @event is InputEventMouseMotion) + { + DoMoveObject(); + } + } + + private void DoSelectObject() + { + var result = DoCollision(); + if (result != null) + { + if (_objectGrid.SelectData != result.Info) + { + //_offset = result.Position - EditorTileMap.GetLocalMousePosition(); + EventManager.EmitEvent(EventEnum.OnSelectObject, result.Info); + } + else + { + _flag++; + } + } + else + { + _flag = 0; + } + } + + private void DoMoveObject() + { + if (_objectGrid.SelectData != null && _customObjecMapping.TryGetValue(_objectGrid.SelectData, out var objectData)) + { + var position = EditorTileMap.GetLocalMousePosition();// - _offset; + var nodeInstance = objectData.Node.Instance; + nodeInstance.Position = position; + nodeInstance.Info.X = (int)position.X; + nodeInstance.Info.Y = (int)position.Y; + + EventManager.EmitEvent(EventEnum.OnTileMapDirty); + } + } + + private CustomObject DoCollision() + { + var param = new PhysicsPointQueryParameters2D(); + param.Position = EditorTileMap.GetGlobalMousePosition(); + param.CollisionMask = PhysicsLayer.UiMouse; + param.CollideWithAreas = true; + var result = EditorTileMap.GetWorld2D().DirectSpaceState.IntersectPoint(param); + + if (result.Count > 0) + { + foreach (var dictionary in result) + { + if (dictionary.TryGetValue("collider", out var collider)) + { + if ((Node2D)collider is CustomObject customObject) + { + return customObject; + } + } + } + } + + return null; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorTileAreaPen.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorTileAreaPen.cs new file mode 100644 index 00000000..6933c0ae --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorTileAreaPen.cs @@ -0,0 +1,138 @@ + +using Godot; +using UI.MapEditor; + +/// +/// 瓷砖区域画笔 +/// +public class EditorTileAreaPen : EditorToolBase +{ + private bool _isPressed; + private MouseButton _buttonIndex; + + private Vector2 _mousePosition; + private Vector2I _mouseCellPosition; + + //绘制填充区域 + private bool _drawFullRect = false; + private Vector2I _mouseStartCellPosition; + + public EditorTileAreaPen(EditorTileMap editorTileMap) : base( + ResourcePath.resource_sprite_ui_commonIcon_AreaTool_png, "绘制区域瓷砖", true, editorTileMap, EditorToolEnum.TileAreaPen) + { + } + + public override void Process(float delta) + { + var mousePosition = EditorTileMap.GetLocalMousePosition(); + _mouseCellPosition = EditorTileMap.LocalToMap(mousePosition); + _mousePosition = _mouseCellPosition * GameConfig.TileCellSize; + } + + public override void OnMapInputEvent(InputEvent @event) + { + if (@event is InputEventMouseButton mouseButton) + { + _buttonIndex = mouseButton.ButtonIndex; + if (mouseButton.ButtonIndex == MouseButton.Left || mouseButton.ButtonIndex == MouseButton.Right) + { + _isPressed = mouseButton.Pressed; + if (_isPressed) //开始按下 + { + _mouseStartCellPosition = EditorTileMap.LocalToMap(EditorTileMap.GetLocalMousePosition()); + _drawFullRect = true; + } + else if (!_isPressed && _drawFullRect) //松手提交 + { + _drawFullRect = false; + if (_buttonIndex == MouseButton.Left) //绘制 + { + DoDrawCell(); + } + else //擦除 + { + DoEraseCell(); + } + } + } + } + } + + private void DoDrawCell() + { + EditorTileMap.SetRectCell(_mouseStartCellPosition, _mouseCellPosition); + } + + private void DoEraseCell() + { + EditorTileMap.EraseRectCell(_mouseStartCellPosition, _mouseCellPosition); + } + + public override void OnMapDrawTool(CanvasItem brush) + { + if (_drawFullRect) + { + var canvasItem = brush; + var size = EditorTileMap.TileSet.TileSize; + var cellPos = _mouseStartCellPosition; + var temp = size; + if (_mouseStartCellPosition.X > _mouseCellPosition.X) + { + cellPos.X += 1; + temp.X -= size.X; + } + + if (_mouseStartCellPosition.Y > _mouseCellPosition.Y) + { + cellPos.Y += 1; + temp.Y -= size.Y; + } + + var p = cellPos * size; + var s = _mousePosition.AsVector2I() - p + temp; + + if (s.X < 0) + { + p.X += s.X; + s.X *= -1; + } + + if (s.Y < 0) + { + p.Y += s.Y; + s.Y *= -1; + } + + //绘制边框 + canvasItem.DrawRect(new Rect2(p, s), Colors.White, false, 2f / EditorTileMap.Scale.X); + + if (EditorTileMap.CurrLayer.Layer != MapLayer.AutoFloorLayer && + (EditorTileMap.CurrBrushType == EditorTileMap.TileMapDrawMode.Free || + EditorTileMap.CurrBrushType == EditorTileMap.TileMapDrawMode.Combination)) //自由绘制 或者 绘制组合 + { + if (_isPressed && _buttonIndex == MouseButton.Left && EditorTileMap.BrushWidth > 0 && EditorTileMap.BrushHeight > 0) //左键绘制 + { + var w = s.X / GameConfig.TileCellSize; + var h = s.Y / GameConfig.TileCellSize; + for (var i = 0; i < w; i++) + { + for (var j = 0; j < h; j++) + { + var x = i % EditorTileMap.BrushWidth + EditorTileMap.BrushStartX; + var y = j % EditorTileMap.BrushHeight + EditorTileMap.BrushStartY; + if (EditorTileMap.CurrBrush.TryGetValue(new Vector2I(x, y), out var v)) + { + var rect = new Rect2(p + (new Vector2I(i, j)) * GameConfig.TileCellSize, + GameConfig.TileCellSize, GameConfig.TileCellSize); + var srcRect = new Rect2(v * GameConfig.TileCellSize, GameConfig.TileCellSize, + GameConfig.TileCellSize); + canvasItem.DrawTextureRectRegion(EditorTileMap.CurrBrushTexture, rect, srcRect, + new Color(1, 1, 1, 0.3f)); + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorTilePen.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorTilePen.cs new file mode 100644 index 00000000..63b1751f --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorTilePen.cs @@ -0,0 +1,169 @@ + +using Godot; +using UI.MapEditor; + +/// +/// 瓷砖画笔 +/// +public class EditorTilePen : EditorToolBase +{ + private bool _isPressed; + private MouseButton _buttonIndex; + + //单次绘制是否改变过tile数据 + private bool _changeFlag = false; + + private Vector2 _mousePosition; + private Vector2I _mouseCellPosition; + + //上一帧鼠标所在的cell坐标 + private Vector2I _prevMouseCellPosition = new Vector2I(-99999, -99999); + + public EditorTilePen(EditorTileMap editorTileMap) : base( + ResourcePath.resource_sprite_ui_commonIcon_PenTool_png, "绘制瓷砖", true, editorTileMap, EditorToolEnum.TilePen) + { + } + + public override void Process(float delta) + { + var mousePosition = EditorTileMap.GetLocalMousePosition(); + //绘制2x2地形 + if ((!_isPressed || _buttonIndex != MouseButton.Right) && + EditorTileMap.CurrBrushType == EditorTileMap.TileMapDrawMode.Terrain && + EditorTileMap.CurrTerrain != null && + EditorTileMap.CurrTerrain.TerrainInfo.TerrainType == 1) + { + mousePosition -= new Vector2(GameConfig.TileCellSize / 2f, GameConfig.TileCellSize / 2f); + } + + _mouseCellPosition = EditorTileMap.LocalToMap(mousePosition); + _mousePosition = _mouseCellPosition * GameConfig.TileCellSize; + } + + public override void OnMapInputEvent(InputEvent @event) + { + if (@event is InputEventMouseButton mouseButton) + { + _buttonIndex = mouseButton.ButtonIndex; + if (mouseButton.ButtonIndex == MouseButton.Left || mouseButton.ButtonIndex == MouseButton.Right) + { + _isPressed = mouseButton.Pressed; + if (!_isPressed) + { + _changeFlag = false; + } + else if (_buttonIndex == MouseButton.Left) //绘制 + { + DoDrawCell(); + } + else if (_buttonIndex == MouseButton.Right) //擦除 + { + DoEraseCell(); + } + } + } + else if (@event is InputEventMouseMotion && _isPressed) + { + if (_buttonIndex == MouseButton.Left) //绘制 + { + DoDrawCell(); + } + else if (_buttonIndex == MouseButton.Right) //擦除 + { + DoEraseCell(); + } + } + } + + private void DoDrawCell() + { + if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过 + { + _changeFlag = true; + _prevMouseCellPosition = _mouseCellPosition; + //绘制图块 + EditorTileMap.SetSingleCell(_mouseCellPosition); + } + } + + private void DoEraseCell() + { + var position = EditorTileMap.GetLocalMousePosition(); + var mouseCellPosition = EditorTileMap.LocalToMap(position); + if (_prevMouseCellPosition != mouseCellPosition || !_changeFlag) //鼠标位置变过 + { + _changeFlag = true; + _prevMouseCellPosition = mouseCellPosition; + //绘制图块 + EditorTileMap.EraseSingleCell(mouseCellPosition); + } + } + + public override void OnMapDrawTool(CanvasItem brush) + { + var canvasItem = brush; + if (EditorTileMap.CurrLayer.Layer == MapLayer.AutoFloorLayer) //选择自动地板层 + { + DrawCellOutline(canvasItem); + } + else //自定义层 + { + if (EditorTileMap.CurrBrushType == EditorTileMap.TileMapDrawMode.Free || + EditorTileMap.CurrBrushType == EditorTileMap.TileMapDrawMode.Combination) //自由绘制 或者 绘制组合 + { + if (_isPressed && _buttonIndex == MouseButton.Right) //按下了左键擦除 + { + DrawCellOutline(canvasItem); + } + else //正常绘制 + { + foreach (var item in EditorTileMap.CurrBrush) + { + var rect = new Rect2( + _mousePosition + (item.Key + EditorTileMap.BrushOffset) * GameConfig.TileCellSize, + GameConfig.TileCellSize, GameConfig.TileCellSize); + var srcRect = new Rect2(item.Value * GameConfig.TileCellSize, GameConfig.TileCellSize, + GameConfig.TileCellSize); + canvasItem.DrawTextureRectRegion(EditorTileMap.CurrBrushTexture, rect, srcRect, + new Color(1, 1, 1, 0.3f)); + } + } + } + else if (EditorTileMap.CurrBrushType == EditorTileMap.TileMapDrawMode.Terrain) //绘制地形 + { + if (EditorTileMap.CurrTerrain == null) //未选择地形 + { + DrawCellOutline(canvasItem); + } + else if (EditorTileMap.CurrTerrain.TerrainInfo.TerrainType == 0) //3x3 + { + DrawCellOutline(canvasItem); + } + else //2x2 + { + DrawCellOutline(canvasItem); + if (!_isPressed || _buttonIndex != MouseButton.Right) //没按下左键擦除 + { + DrawCellOutline(canvasItem, new Vector2I(GameConfig.TileCellSize, 0)); + DrawCellOutline(canvasItem, new Vector2I(0, GameConfig.TileCellSize)); + DrawCellOutline(canvasItem, + new Vector2I(GameConfig.TileCellSize, GameConfig.TileCellSize)); + } + } + } + } + } + + private void DrawCellOutline(CanvasItem canvasItem) + { + canvasItem.DrawRect(new Rect2(_mousePosition, EditorTileMap.TileSet.TileSize), + Colors.White, false, 2f / EditorTileMap.Scale.X); + } + + private void DrawCellOutline(CanvasItem canvasItem, Vector2I offset) + { + canvasItem.DrawRect( + new Rect2(_mousePosition + offset, EditorTileMap.TileSet.TileSize), + Colors.White, false, 2f / EditorTileMap.Scale.X); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorToolBase.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorToolBase.cs new file mode 100644 index 00000000..c8fcc43b --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorToolBase.cs @@ -0,0 +1,79 @@ + +using Godot; +using UI.MapEditor; + +/// +/// 地图编辑器工具栏图标逻辑基类 +/// +public abstract class EditorToolBase +{ + /// + /// 工具图标 + /// + public string Icon { get; } + + /// + /// 工具提示名称 + /// + public string TipText { get; } + + /// + /// 是否可以选中 + /// + public bool CanSelect { get; } + + /// + /// 绑定的 TileMap + /// + public EditorTileMap EditorTileMap { get; } + + /// + /// 工具枚举类型 + /// + public EditorToolEnum EditorToolType { get; } + + public EditorToolBase(string icon, string tipText, bool canSelect, EditorTileMap editorTileMap, EditorToolEnum editorToolType) + { + Icon = icon; + CanSelect = canSelect; + EditorTileMap = editorTileMap; + EditorToolType = editorToolType; + TipText = tipText; + } + + /// + /// 点击时回调 + /// + public virtual void OnClick() + { + } + + /// + /// 改变选中状态时回调 + /// + public virtual void OnSetSelected(bool selected) + { + } + + /// + /// 选中后每帧调用 + /// + public virtual void Process(float delta) + { + } + + /// + /// 选中后处理的 TileMap 输入事件, 仅在选中时才会调用 + /// + public virtual void OnMapInputEvent(InputEvent @event) + { + } + + /// + /// 绘制工具, 仅在选中时才会调用 + /// + public virtual void OnMapDrawTool(CanvasItem brush) + { + + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorToolEnum.cs b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorToolEnum.cs new file mode 100644 index 00000000..198b2d78 --- /dev/null +++ b/DungeonShooting_Godot/src/game/common/editor/toolBtn/EditorToolEnum.cs @@ -0,0 +1,36 @@ + +public enum EditorToolEnum +{ + /// + /// 未选择 + /// + None, + /// + /// 切换移动模式 + /// + Move, + /// + /// 瓷砖画笔 + /// + TilePen, + /// + /// 瓷砖区域画笔 + /// + TileAreaPen, + /// + /// 物体画笔 + /// + ObjectPen, + /// + /// 物体编辑工具 + /// + ObjectTool, + /// + /// 标记工具 + /// + MarkTool, + /// + /// 聚焦 + /// + Focus +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs b/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs index cf6f7f81..fb4bdfc3 100644 --- a/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs +++ b/DungeonShooting_Godot/src/game/data/property/PhysicsLayer.cs @@ -51,4 +51,9 @@ public class PhysicsLayer /// 可被子弹击中的区域 /// public const uint HurtArea = 0b10000000000; + + /// + /// 鼠标检测的Ui + /// + public const uint UiMouse = 0b10000000000000; } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/event/EventEnum.cs b/DungeonShooting_Godot/src/game/event/EventEnum.cs index da71afbf..c920e4e6 100644 --- a/DungeonShooting_Godot/src/game/event/EventEnum.cs +++ b/DungeonShooting_Godot/src/game/event/EventEnum.cs @@ -217,4 +217,32 @@ public enum EventEnum /// 修改组合名称, 参数为 /// OnUpdateCombination, + /// + /// 当地牢编辑器选中对象配置时调用, 参数为 + /// + OnSelectObjectConfig, + /// + /// 放置对象, 参数为 + /// + OnPutObject, + /// + /// 移除对象, 参数为 + /// + OnRemoveObject, + /// + /// 更新对象位置, 参数为 + /// + OnUpdateObject, + /// + /// 选中对象, 参数为 + /// + OnSelectObject, + /// + /// 地图编辑器保存预览图片开始, 无参数 + /// + OnSavePreviewImageBegin, + /// + /// 地图编辑器保存预览图片完成, 无参数 + /// + OnSavePreviewImageFinish, } diff --git a/DungeonShooting_Godot/src/game/manager/ResourceManager.cs b/DungeonShooting_Godot/src/game/manager/ResourceManager.cs index 6df02486..88781185 100644 --- a/DungeonShooting_Godot/src/game/manager/ResourceManager.cs +++ b/DungeonShooting_Godot/src/game/manager/ResourceManager.cs @@ -240,4 +240,28 @@ public static class ResourceManager return name; } + + /// + /// 加载地牢编辑器中自定义对象, 返回的节点已经被禁用了所有逻辑 + /// + public static Node2D LoadEditorObject(ExcelConfig.EditorObject config) + { + Node2D node; + if (config.IsActivity()) + { + var activityBase = ExcelConfig.ActivityBase_Map[config.Prefab]; + node = LoadAndInstantiate(activityBase.Prefab); + } + else + { + node = LoadAndInstantiate(config.Prefab); + } + node.SetProcess(false); + node.SetPhysicsProcess(false); + node.SetProcessInput(false); + node.SetPhysicsProcessInternal(false); + node.SetProcessInput(false); + node.ProcessMode = Node.ProcessModeEnum.WhenPaused; + return node; + } } \ 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 221ab703..d39c1135 100644 --- a/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs +++ b/DungeonShooting_Godot/src/game/manager/UiManager_Methods.cs @@ -22,9 +22,11 @@ public static partial class UiManager public const string BottomTips = "BottomTips"; public const string EditorTileImage = "EditorTileImage"; public const string EditorDungeonGroup = "EditorDungeonGroup"; + public const string MapEditorConfigObject = "MapEditorConfigObject"; public const string EditorForm = "EditorForm"; public const string Setting = "Setting"; public const string Loading = "Loading"; + public const string MapEditorObject = "MapEditorObject"; public const string WeaponRoulette = "WeaponRoulette"; public const string MapEditorTools = "MapEditorTools"; public const string TileSetEditor = "TileSetEditor"; @@ -861,6 +863,54 @@ public static partial class UiManager return GetUiInstance(nameof(UI.EditorDungeonGroup.EditorDungeonGroup)); } + /// + /// 创建 MapEditorConfigObject, 并返回UI实例, 该函数不会打开 Ui + /// + public static UI.MapEditorConfigObject.MapEditorConfigObjectPanel Create_MapEditorConfigObject() + { + return CreateUi(UiNames.MapEditorConfigObject); + } + + /// + /// 打开 MapEditorConfigObject, 并返回UI实例 + /// + public static UI.MapEditorConfigObject.MapEditorConfigObjectPanel Open_MapEditorConfigObject() + { + return OpenUi(UiNames.MapEditorConfigObject); + } + + /// + /// 隐藏 MapEditorConfigObject 的所有实例 + /// + public static void Hide_MapEditorConfigObject() + { + var uiInstance = Get_MapEditorConfigObject_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.HideUi(); + } + } + + /// + /// 销毁 MapEditorConfigObject 的所有实例 + /// + public static void Destroy_MapEditorConfigObject() + { + var uiInstance = Get_MapEditorConfigObject_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.Destroy(); + } + } + + /// + /// 获取所有 MapEditorConfigObject 的实例, 如果没有实例, 则返回一个空数组 + /// + public static UI.MapEditorConfigObject.MapEditorConfigObjectPanel[] Get_MapEditorConfigObject_Instance() + { + return GetUiInstance(nameof(UI.MapEditorConfigObject.MapEditorConfigObject)); + } + /// /// 创建 EditorForm, 并返回UI实例, 该函数不会打开 Ui /// @@ -1005,6 +1055,54 @@ public static partial class UiManager return GetUiInstance(nameof(UI.Loading.Loading)); } + /// + /// 创建 MapEditorObject, 并返回UI实例, 该函数不会打开 Ui + /// + public static UI.MapEditorObject.MapEditorObjectPanel Create_MapEditorObject() + { + return CreateUi(UiNames.MapEditorObject); + } + + /// + /// 打开 MapEditorObject, 并返回UI实例 + /// + public static UI.MapEditorObject.MapEditorObjectPanel Open_MapEditorObject() + { + return OpenUi(UiNames.MapEditorObject); + } + + /// + /// 隐藏 MapEditorObject 的所有实例 + /// + public static void Hide_MapEditorObject() + { + var uiInstance = Get_MapEditorObject_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.HideUi(); + } + } + + /// + /// 销毁 MapEditorObject 的所有实例 + /// + public static void Destroy_MapEditorObject() + { + var uiInstance = Get_MapEditorObject_Instance(); + foreach (var uiPanel in uiInstance) + { + uiPanel.Destroy(); + } + } + + /// + /// 获取所有 MapEditorObject 的实例, 如果没有实例, 则返回一个空数组 + /// + public static UI.MapEditorObject.MapEditorObjectPanel[] Get_MapEditorObject_Instance() + { + return GetUiInstance(nameof(UI.MapEditorObject.MapEditorObject)); + } + /// /// 创建 WeaponRoulette, 并返回UI实例, 该函数不会打开 Ui /// diff --git a/DungeonShooting_Godot/src/game/room/Dungeon.cs b/DungeonShooting_Godot/src/game/room/Dungeon.cs index cd8e6f22..cc43d6ff 100644 --- a/DungeonShooting_Godot/src/game/room/Dungeon.cs +++ b/DungeonShooting_Godot/src/game/room/Dungeon.cs @@ -18,8 +18,8 @@ public partial class Dungeon : World public override void _Ready() { base._Ready(); - //Color = Colors.Black; - Debug.Log("[临时处理]: 这里设置房间迷雾"); + Color = Colors.Black; + //Debug.Log("[临时处理]: 这里设置房间迷雾"); } /// diff --git a/DungeonShooting_Godot/src/game/room/DungeonManager.cs b/DungeonShooting_Godot/src/game/room/DungeonManager.cs index 1713f614..929a0ae3 100644 --- a/DungeonShooting_Godot/src/game/room/DungeonManager.cs +++ b/DungeonShooting_Godot/src/game/room/DungeonManager.cs @@ -487,8 +487,8 @@ public partial class DungeonManager : Node2D //初始化所有房间 yield return _dungeonGenerator.EachRoomCoroutine(InitRoom); - Debug.Log("[临时处理]: 关闭房间迷雾"); - CurrWorld.FogMaskRoot.Visible = false; + //Debug.Log("[临时处理]: 关闭房间迷雾"); + //CurrWorld.FogMaskRoot.Visible = false; //房间背景颜色 RenderingServer.SetDefaultClearColor(_dungeonGenerator.RoomGroup.BgColor); diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs index 08735891..4a9c4fc0 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditor.cs @@ -32,20 +32,30 @@ public abstract partial class MapEditor : UiBase inst1.L_MapEditorMapLayer.Instance.OnCreateUi(); inst1.L_MapEditorMapLayer.Instance.OnInitNestedUi(); - var inst2 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_HBoxContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_CanvasLayer; - RecordNestedUi(inst2.L_MapEditorTools.Instance, inst2, UiManager.RecordType.Open); - inst2.L_MapEditorTools.Instance.OnCreateUi(); - inst2.L_MapEditorTools.Instance.OnInitNestedUi(); + var inst2 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_HBoxContainer.L_LayerPanel; + RecordNestedUi(inst2.L_MapEditorConfigObject.Instance, inst2, UiManager.RecordType.Open); + inst2.L_MapEditorConfigObject.Instance.OnCreateUi(); + inst2.L_MapEditorConfigObject.Instance.OnInitNestedUi(); - var inst3 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapTile; - RecordNestedUi(inst3.L_MapEditorMapTile.Instance, inst3, UiManager.RecordType.Open); - inst3.L_MapEditorMapTile.Instance.OnCreateUi(); - inst3.L_MapEditorMapTile.Instance.OnInitNestedUi(); + var inst3 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_HBoxContainer.L_Left.L_MarginContainer.L_MapView.L_SubViewport.L_CanvasLayer; + RecordNestedUi(inst3.L_MapEditorTools.Instance, inst3, UiManager.RecordType.Open); + inst3.L_MapEditorTools.Instance.OnCreateUi(); + inst3.L_MapEditorTools.Instance.OnInitNestedUi(); - var inst4 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapMark; - RecordNestedUi(inst4.L_MapEditorMapMark.Instance, inst4, UiManager.RecordType.Open); - inst4.L_MapEditorMapMark.Instance.OnCreateUi(); - inst4.L_MapEditorMapMark.Instance.OnInitNestedUi(); + var inst4 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapTile; + RecordNestedUi(inst4.L_MapEditorMapTile.Instance, inst4, UiManager.RecordType.Open); + inst4.L_MapEditorMapTile.Instance.OnCreateUi(); + inst4.L_MapEditorMapTile.Instance.OnInitNestedUi(); + + var inst5 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapObject; + RecordNestedUi(inst5.L_MapEditorObject.Instance, inst5, UiManager.RecordType.Open); + inst5.L_MapEditorObject.Instance.OnCreateUi(); + inst5.L_MapEditorObject.Instance.OnInitNestedUi(); + + var inst6 = L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapMark; + RecordNestedUi(inst6.L_MapEditorMapMark.Instance, inst6, UiManager.RecordType.Open); + inst6.L_MapEditorMapMark.Instance.OnCreateUi(); + inst6.L_MapEditorMapMark.Instance.OnInitNestedUi(); } @@ -184,6 +194,22 @@ public abstract partial class MapEditor : UiBase } } + /// + /// 类型: , 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.HBoxContainer.LayerPanel.MapEditorConfigObject + /// + public class MapEditorConfigObject : UiNode + { + public MapEditorConfigObject(MapEditorPanel uiPanel, UI.MapEditorConfigObject.MapEditorConfigObjectPanel node) : base(uiPanel, node) { } + public override MapEditorConfigObject Clone() + { + var uiNode = new MapEditorConfigObject(UiPanel, (UI.MapEditorConfigObject.MapEditorConfigObjectPanel)Instance.Duplicate()); + UiPanel.RecordNestedUi(uiNode.Instance, this, UiManager.RecordType.Open); + uiNode.Instance.OnCreateUi(); + uiNode.Instance.OnInitNestedUi(); + return uiNode; + } + } + /// /// 类型: , 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.HBoxContainer.LayerPanel /// @@ -202,6 +228,19 @@ public abstract partial class MapEditor : UiBase } private MapEditorMapLayer _L_MapEditorMapLayer; + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.HBoxContainer.MapEditorConfigObject + /// + public MapEditorConfigObject L_MapEditorConfigObject + { + get + { + if (_L_MapEditorConfigObject == null) _L_MapEditorConfigObject = new MapEditorConfigObject(UiPanel, Instance.GetNode("MapEditorConfigObject")); + return _L_MapEditorConfigObject; + } + } + private MapEditorConfigObject _L_MapEditorConfigObject; + public LayerPanel(MapEditorPanel uiPanel, Godot.Panel node) : base(uiPanel, node) { } public override LayerPanel Clone() => new (UiPanel, (Godot.Panel)Instance.Duplicate()); } @@ -537,6 +576,44 @@ public abstract partial class MapEditor : UiBase public override MapTile Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate()); } + /// + /// 类型: , 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.TabContainer.MapObject.MapEditorObject + /// + public class MapEditorObject : UiNode + { + public MapEditorObject(MapEditorPanel uiPanel, UI.MapEditorObject.MapEditorObjectPanel node) : base(uiPanel, node) { } + public override MapEditorObject Clone() + { + var uiNode = new MapEditorObject(UiPanel, (UI.MapEditorObject.MapEditorObjectPanel)Instance.Duplicate()); + UiPanel.RecordNestedUi(uiNode.Instance, this, UiManager.RecordType.Open); + uiNode.Instance.OnCreateUi(); + uiNode.Instance.OnInitNestedUi(); + return uiNode; + } + } + + /// + /// 类型: , 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.TabContainer.MapObject + /// + public class MapObject : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.TabContainer.MapEditorObject + /// + public MapEditorObject L_MapEditorObject + { + get + { + if (_L_MapEditorObject == null) _L_MapEditorObject = new MapEditorObject(UiPanel, Instance.GetNode("MapEditorObject")); + return _L_MapEditorObject; + } + } + private MapEditorObject _L_MapEditorObject; + + public MapObject(MapEditorPanel uiPanel, Godot.MarginContainer node) : base(uiPanel, node) { } + public override MapObject Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate()); + } + /// /// 类型: , 路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.TabContainer.MapMark.MapEditorMapMark /// @@ -593,6 +670,19 @@ public abstract partial class MapEditor : UiBase } private MapTile _L_MapTile; + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.MapObject + /// + public MapObject L_MapObject + { + get + { + if (_L_MapObject == null) _L_MapObject = new MapObject(UiPanel, Instance.GetNode("MapObject")); + return _L_MapObject; + } + } + private MapObject _L_MapObject; + /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.MapMark /// @@ -804,6 +894,11 @@ public abstract partial class MapEditor : UiBase /// public MapEditorMapLayer S_MapEditorMapLayer => L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_HBoxContainer.L_LayerPanel.L_MapEditorMapLayer; + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.HBoxContainer.LayerPanel.MapEditorConfigObject + /// + public MapEditorConfigObject S_MapEditorConfigObject => L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_HBoxContainer.L_LayerPanel.L_MapEditorConfigObject; + /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.HBoxContainer.LayerPanel /// @@ -879,6 +974,16 @@ public abstract partial class MapEditor : UiBase /// public MapTile S_MapTile => L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapTile; + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.TabContainer.MapObject.MapEditorObject + /// + public MapEditorObject S_MapEditorObject => L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapObject.L_MapEditorObject; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.TabContainer.MapObject + /// + public MapObject S_MapObject => L_Bg.L_VBoxContainer.L_HSplitContainer.L_HSplitContainer2.L_Right.L_MarginContainer.L_TabContainer.L_MapObject; + /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditor.Bg.VBoxContainer.HSplitContainer.HSplitContainer2.Right.MarginContainer.TabContainer.MapMark.MapEditorMapMark /// diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs index d54856e4..451931e3 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorPanel.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Linq; using Godot; @@ -22,27 +23,92 @@ public partial class MapEditorPanel : MapEditor ErrorType = errorType; } } + + /// + /// 当前选中的页签 + /// + public MapEditorTab TabType + { + get + { + switch (S_TabContainer.Instance.CurrentTab) + { + case 0: return MapEditorTab.MapTile; + case 1: return MapEditorTab.MapObject; + case 2: return MapEditorTab.MapMark; + } + + return MapEditorTab.Unknown; + } + } private string _title; - + + private long _currTab = -1; + private Dictionary _cacheToolType = new Dictionary(); + //暂未用到, 后面补逻辑 + private List _tabs = new List(); + private int _prevTabIndex = -1; + public override void OnCreateUi() { - S_TabContainer.Instance.SetTabTitle(0, "图块"); - S_TabContainer.Instance.SetTabTitle(1, "对象"); - S_TabContainer.Instance.TabChanged += OnTabChanged; + var tabContainer = S_TabContainer.Instance; + tabContainer.SetTabTitle(0, "图块"); + tabContainer.SetTabTitle(1, "对象"); + tabContainer.SetTabTitle(2, "预设"); + tabContainer.TabChanged += OnTabChanged; //S_MapLayer.Instance.Init(S_MapLayer); S_Left.Instance.Resized += OnMapViewResized; S_Back.Instance.Pressed += OnBackClick; S_Save.Instance.Pressed += OnSave; S_Play.Instance.Pressed += OnPlay; - OnTabChanged(0); + //初始化页签 + var childCount = tabContainer.GetChildCount(); + for (var i = 0; i < childCount; i++) + { + var tabChild = tabContainer.GetChild(i); + if (tabChild.GetChildCount() > 0) + { + var temp = tabChild.GetChild(0); + _tabs.Add((IEditorTab)temp); + } + } + + //默认选中第一个 + this.CallDelay(0, () => { OnTabChanged(0); }); } //切换页签 private void OnTabChanged(long tab) { - S_LayerPanel.Instance.Visible = tab == 0; + var toolsPanel = S_MapEditorTools.Instance; + _cacheToolType[_currTab] = toolsPanel.ActiveToolType; + + if (_prevTabIndex >= 0) + { + _tabs[_prevTabIndex].OnUnSelectTab(); + } + _tabs[(int)tab].OnSelectTab(); + _prevTabIndex = (int)tab; + + //还原所选工具 + if (_cacheToolType.TryGetValue(tab, out var toolType)) + { + if (toolType == EditorToolEnum.None) + { + toolsPanel.SetActiviteTool(EditorToolEnum.Move); + } + else + { + toolsPanel.SetActiviteTool(toolType); + } + } + else if (toolType == EditorToolEnum.None) + { + toolsPanel.SetActiviteTool(EditorToolEnum.Move); + } + _currTab = tab; } public override void OnShowUi() @@ -105,6 +171,9 @@ public partial class MapEditorPanel : MapEditor //加载Tile var loadMap = S_TileMap.Instance.Load(roomSplit, tileSetSplit); + //刷新物体页签 + S_MapEditorObject.Instance.InitData(); + //刷新预设页签 S_MapEditorMapMark.Instance.RefreshPreinstallSelect(); return loadMap; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorTab.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorTab.cs new file mode 100644 index 00000000..c4448849 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/MapEditorTab.cs @@ -0,0 +1,21 @@ +namespace UI.MapEditor; + +public enum MapEditorTab +{ + /// + /// 未知 + /// + Unknown, + /// + /// 图块 + /// + MapTile, + /// + /// 对象 + /// + MapObject, + /// + /// 预设 + /// + MapMark +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs index 47f8b722..7d5581c0 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs @@ -10,30 +10,6 @@ namespace UI.MapEditor; public partial class EditorTileMap : TileMap, IUiNodeScript { - public enum MouseButtonType - { - /// - /// 无状态 - /// - None, - /// - /// 拖拽模式 - /// - Drag, - /// - /// 笔 - /// - Pen, - /// - /// 绘制区域模式 - /// - Area, - /// - /// 编辑工具模式 - /// - Edit, - } - public enum TileMapDrawMode { /// @@ -53,6 +29,16 @@ public partial class EditorTileMap : TileMap, IUiNodeScript /// Combination } + + /// + /// 输入事件 + /// + public event Action MapInputEvent; + + /// + /// 绘制工具事件 + /// + public event Action MapDrawToolEvent; /// /// 所属地图编辑器UI @@ -63,31 +49,16 @@ public partial class EditorTileMap : TileMap, IUiNodeScript /// 编辑器工具UI /// public MapEditorToolsPanel MapEditorToolsPanel { get; set; } - + /// - /// 左键功能 + /// 当前选中的工具 /// - public MouseButtonType MouseType { get; private set; } = MouseButtonType.Pen; + public EditorToolEnum ActiveToolType => MapEditorToolsPanel.ActiveToolType; - //鼠标坐标 - private Vector2 _mousePosition; - //鼠标所在的cell坐标 - private Vector2I _mouseCellPosition; - //上一帧鼠标所在的cell坐标 - private Vector2I _prevMouseCellPosition = new Vector2I(-99999, -99999); - //单次绘制是否改变过tile数据 - private bool _changeFlag = false; - //左键开始按下时鼠标所在的坐标 - private Vector2I _mouseStartCellPosition; //鼠标中建是否按下 private bool _isMiddlePressed = false; private Vector2 _moveOffset; - //左键是否按下 - private bool _isLeftPressed = false; - //右键是否按下 - private bool _isRightPressed = false; - //绘制填充区域 - private bool _drawFullRect = false; + //负责存储自动图块数据 private InfiniteGrid _autoCellLayerGrid = new InfiniteGrid(); //停止绘制多久后开始执行生成操作 @@ -165,14 +136,26 @@ public partial class EditorTileMap : TileMap, IUiNodeScript /// public Texture2D CurrBrushTexture { get; private set; } - private int _brushStartX = 0; - private int _brushStartY = 0; - //笔刷宽度, 单位: 格 - private int _brushWidth = 0; - //笔刷高度, 单位: 格 - private int _brushHeight = 0; - //笔刷偏移, 单位: 格 - private Vector2I _brushOffset = Vector2I.Zero; + /// + /// 笔刷起始x坐标, 单位: 格 + /// + public int BrushStartX { get; private set; } = 0; + /// + /// 笔刷起始y坐标, 单位: 格 + /// + public int BrushStartY { get; private set; } = 0; + /// + /// 笔刷宽度, 单位: 格 + /// + public int BrushWidth { get; private set; } = 0; + /// + /// 笔刷高度, 单位: 格 + /// + public int BrushHeight { get; private set; } = 0; + /// + /// 笔刷偏移, 单位: 格 + /// + public Vector2I BrushOffset { get; private set; } = Vector2I.Zero; //淡化其它层级 private bool _desaltOtherLayer = false; @@ -209,11 +192,6 @@ public partial class EditorTileMap : TileMap, IUiNodeScript _editorTileMap.L_Brush.Instance.Draw += DrawGuides; _eventFactory = EventManager.CreateEventFactory(); - _eventFactory.AddEventListener(EventEnum.OnSelectDragTool, OnSelectHandTool); - _eventFactory.AddEventListener(EventEnum.OnSelectPenTool, OnSelectPenTool); - _eventFactory.AddEventListener(EventEnum.OnSelectRectTool, OnSelectRectTool); - _eventFactory.AddEventListener(EventEnum.OnSelectEditTool, OnSelectEditTool); - _eventFactory.AddEventListener(EventEnum.OnClickCenterTool, OnClickCenterTool); _eventFactory.AddEventListener(EventEnum.OnTileMapDirty, OnEditorDirty); RenderingServer.FramePostDraw += OnFramePostDraw; @@ -239,64 +217,10 @@ public partial class EditorTileMap : TileMap, IUiNodeScript _editorTileMap.L_Brush.Instance.QueueRedraw(); var newDelta = (float)delta; - _drawFullRect = false; - var position = GetLocalMousePosition(); - //绘制2x2地形 - if (CurrBrushType == TileMapDrawMode.Terrain && CurrTerrain != null && CurrTerrain.TerrainInfo.TerrainType == 1 && !_isRightPressed) - { - position -= new Vector2(GameConfig.TileCellSize / 2f, GameConfig.TileCellSize / 2f); - } - _mouseCellPosition = LocalToMap(position); - _mousePosition = new Vector2( - _mouseCellPosition.X * GameConfig.TileCellSize, - _mouseCellPosition.Y * GameConfig.TileCellSize - ); - + if (!MapEditorToolsPanel.S_HBoxContainer.Instance.IsMouseInRect()) //不在Ui节点上 { - //左键绘制 - if (_isLeftPressed) - { - if (MouseType == MouseButtonType.Pen) //绘制单格 - { - if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过 - { - _changeFlag = true; - _prevMouseCellPosition = _mouseCellPosition; - //绘制图块 - SetSingleCell(_mouseCellPosition); - } - } - else if (MouseType == MouseButtonType.Area) //绘制区域 - { - _drawFullRect = true; - } - else if (MouseType == MouseButtonType.Drag) //拖拽 - { - SetMapPosition(GetGlobalMousePosition() + _moveOffset); - } - } - else if (_isRightPressed) //右键擦除 - { - if (MouseType == MouseButtonType.Pen) //绘制单格 - { - if (_prevMouseCellPosition != _mouseCellPosition || !_changeFlag) //鼠标位置变过 - { - _changeFlag = true; - _prevMouseCellPosition = _mouseCellPosition; - EraseSingleCell(_mouseCellPosition); - } - } - else if (MouseType == MouseButtonType.Area) //绘制区域 - { - _drawFullRect = true; - } - else if (MouseType == MouseButtonType.Drag) //拖拽 - { - SetMapPosition(GetGlobalMousePosition() + _moveOffset); - } - } - else if (_isMiddlePressed) //中键移动 + if (_isMiddlePressed) //中键移动 { SetMapPosition(GetGlobalMousePosition() + _moveOffset); } @@ -352,169 +276,17 @@ public partial class EditorTileMap : TileMap, IUiNodeScript } } - //绘制笔刷 - if (MouseType == MouseButtonType.Pen || MouseType == MouseButtonType.Area) + if (MapDrawToolEvent != null) { - if (_drawFullRect) //绘制填充矩形 - { - var size = TileSet.TileSize; - var cellPos = _mouseStartCellPosition; - var temp = size; - if (_mouseStartCellPosition.X > _mouseCellPosition.X) - { - cellPos.X += 1; - temp.X -= size.X; - } - if (_mouseStartCellPosition.Y > _mouseCellPosition.Y) - { - cellPos.Y += 1; - temp.Y -= size.Y; - } - - var p = cellPos * size; - var s = _mousePosition.AsVector2I() - p + temp; - - if (s.X < 0) - { - p.X += s.X; - s.X *= -1; - } - - if (s.Y < 0) - { - p.Y += s.Y; - s.Y *= -1; - } - - //绘制边框 - canvasItem.DrawRect(new Rect2(p, s), Colors.White, false, 2f / Scale.X); - - if (CurrLayer.Layer != MapLayer.AutoFloorLayer && (CurrBrushType == TileMapDrawMode.Free || CurrBrushType == TileMapDrawMode.Combination)) //自由绘制 或者 绘制组合 - { - if (_isLeftPressed && _brushWidth > 0 && _brushHeight > 0) //左键绘制 - { - var w = s.X / GameConfig.TileCellSize; - var h = s.Y / GameConfig.TileCellSize; - for (var i = 0; i < w; i++) - { - for (var j = 0; j < h; j++) - { - var x = i % _brushWidth + _brushStartX; - var y = j % _brushHeight + _brushStartY; - if (CurrBrush.TryGetValue(new Vector2I(x, y), out var v)) - { - var rect = new Rect2(p + (new Vector2I(i, j)) * GameConfig.TileCellSize, GameConfig.TileCellSize, GameConfig.TileCellSize); - var srcRect = new Rect2(v * GameConfig.TileCellSize, GameConfig.TileCellSize, GameConfig.TileCellSize); - canvasItem.DrawTextureRectRegion(CurrBrushTexture, rect, srcRect, new Color(1, 1, 1, 0.3f)); - } - } - } - } - } - } - else //绘制单格 - { - if (CurrLayer.Layer == MapLayer.AutoFloorLayer) //选择自动地板层 - { - DrawCellOutline(canvasItem); - } - else //自定义层 - { - if (CurrBrushType == TileMapDrawMode.Free || CurrBrushType == TileMapDrawMode.Combination) //自由绘制 或者 绘制组合 - { - if (_isRightPressed) //按下了左键擦除 - { - DrawCellOutline(canvasItem); - } - else //正常绘制 - { - foreach (var item in CurrBrush) - { - var rect = new Rect2(_mousePosition + (item.Key + _brushOffset) * GameConfig.TileCellSize, GameConfig.TileCellSize, GameConfig.TileCellSize); - var srcRect = new Rect2(item.Value * GameConfig.TileCellSize, GameConfig.TileCellSize, GameConfig.TileCellSize); - canvasItem.DrawTextureRectRegion(CurrBrushTexture, rect, srcRect, new Color(1, 1, 1, 0.3f)); - } - } - } - else if (CurrBrushType == TileMapDrawMode.Terrain) //绘制地形 - { - if (CurrTerrain == null) //未选择地形 - { - DrawCellOutline(canvasItem); - } - else if (CurrTerrain.TerrainInfo.TerrainType == 0) //3x3 - { - DrawCellOutline(canvasItem); - } - else //2x2 - { - DrawCellOutline(canvasItem); - if (!_isRightPressed) //没按下左键擦除 - { - DrawCellOutline(canvasItem, new Vector2I(GameConfig.TileCellSize, 0)); - DrawCellOutline(canvasItem, new Vector2I(0, GameConfig.TileCellSize)); - DrawCellOutline(canvasItem, new Vector2I(GameConfig.TileCellSize, GameConfig.TileCellSize)); - } - } - } - } - } + MapDrawToolEvent(canvasItem); } } - private void DrawCellOutline(CanvasItem canvasItem) - { - canvasItem.DrawRect(new Rect2(_mousePosition, TileSet.TileSize), Colors.White, false, 2f / Scale.X); - } - - private void DrawCellOutline(CanvasItem canvasItem, Vector2I offset) - { - canvasItem.DrawRect(new Rect2(_mousePosition + offset, TileSet.TileSize), Colors.White, false, 2f / Scale.X); - } - public override void _Input(InputEvent @event) { if (@event is InputEventMouseButton mouseButton) { - if (mouseButton.ButtonIndex == MouseButton.Left) //左键 - { - if (mouseButton.Pressed) //按下 - { - _moveOffset = Position - GetGlobalMousePosition(); - _mouseStartCellPosition = LocalToMap(GetLocalMousePosition()); - } - else - { - _changeFlag = false; - if (_drawFullRect) //松开, 提交绘制的矩形区域 - { - SetRectCell(_mouseStartCellPosition, _mouseCellPosition); - _drawFullRect = false; - } - } - - _isLeftPressed = mouseButton.Pressed; - } - else if (mouseButton.ButtonIndex == MouseButton.Right) //右键 - { - if (mouseButton.Pressed) //按下 - { - _moveOffset = Position - GetGlobalMousePosition(); - _mouseStartCellPosition = LocalToMap(GetLocalMousePosition()); - } - else - { - _changeFlag = false; - if (_drawFullRect) //松开, 提交擦除的矩形区域 - { - EraseRectCell(_mouseStartCellPosition, _mouseCellPosition); - _drawFullRect = false; - } - } - - _isRightPressed = mouseButton.Pressed; - } - else if (mouseButton.ButtonIndex == MouseButton.WheelDown) + if (mouseButton.ButtonIndex == MouseButton.WheelDown) { //缩小 Shrink(); @@ -533,6 +305,11 @@ public partial class EditorTileMap : TileMap, IUiNodeScript } } } + + if (MapInputEvent != null && !MapEditorToolsPanel.S_HBoxContainer.Instance.IsMouseInRect()) + { + MapInputEvent(@event); + } } /// @@ -592,11 +369,11 @@ public partial class EditorTileMap : TileMap, IUiNodeScript yEnd = Mathf.Max(cell.Y, yEnd); } - _brushStartX = xStart; - _brushStartY = yStart; - _brushWidth = xEnd - xStart + 1; - _brushHeight = yEnd - yStart + 1; - _brushOffset = new Vector2I(-(xStart + (xEnd - xStart) / 2), -(yStart + (yEnd - yStart) / 2)); + BrushStartX = xStart; + BrushStartY = yStart; + BrushWidth = xEnd - xStart + 1; + BrushHeight = yEnd - yStart + 1; + BrushOffset = new Vector2I(-(xStart + (xEnd - xStart) / 2), -(yStart + (yEnd - yStart) / 2)); } } @@ -812,7 +589,7 @@ public partial class EditorTileMap : TileMap, IUiNodeScript RunCheckHandler(); //聚焦 (需要延时一帧调用) - this.CallDelayInNode(0, () => OnClickCenterTool(null)); + this.CallDelayInNode(0, OnFocusClick); return true; } @@ -869,8 +646,10 @@ public partial class EditorTileMap : TileMap, IUiNodeScript } } - //绘制单个贴图 - private void SetSingleCell(Vector2I position) + /// + /// 绘制单个贴图 + /// + public void SetSingleCell(Vector2I position) { if (CurrLayer.Layer == MapLayer.AutoFloorLayer) //选择自动地板层, 那么不管笔刷类型, 通通使用 Main Source 中的 Main Terrain { @@ -889,7 +668,7 @@ public partial class EditorTileMap : TileMap, IUiNodeScript { foreach (var item in CurrBrush) { - SetCell(CurrLayer.Layer, position + item.Key + _brushOffset, CurrSourceIndex, item.Value); + SetCell(CurrLayer.Layer, position + item.Key + BrushOffset, CurrSourceIndex, item.Value); dirty = true; } } @@ -928,8 +707,10 @@ public partial class EditorTileMap : TileMap, IUiNodeScript } } - //绘制区域贴图 - private void SetRectCell(Vector2I start, Vector2I end) + /// + /// 绘制区域贴图 + /// + public void SetRectCell(Vector2I start, Vector2I end) { if (start.X > end.X) { @@ -966,13 +747,18 @@ public partial class EditorTileMap : TileMap, IUiNodeScript var dirty = false; if (CurrBrushType == TileMapDrawMode.Free || CurrBrushType == TileMapDrawMode.Combination) //自由绘制 或者 组合 { + if (BrushWidth == 0 || BrushHeight == 0) + { + return; + } + dirty = CurrBrush.Count > 0; for (var i = 0; i < width; i++) { for (var j = 0; j < height; j++) { - var x = i % _brushWidth + _brushStartX; - var y = j % _brushHeight + _brushStartY; + var x = i % BrushWidth + BrushStartX; + var y = j % BrushHeight + BrushStartY; if (CurrBrush.TryGetValue(new Vector2I(x, y), out var v)) { SetCell(CurrLayer.Layer, new Vector2I(start.X + i, start.Y + j), CurrSourceIndex, v); @@ -1015,8 +801,10 @@ public partial class EditorTileMap : TileMap, IUiNodeScript } } - //擦除单个图块 - private void EraseSingleCell(Vector2I position) + /// + /// 擦除单个图块 + /// + public void EraseSingleCell(Vector2I position) { if (CurrLayer.Layer == MapLayer.AutoFloorLayer) //选择自动地板层, 那么不管笔刷类型, 通通使用 Main Source 中的 Main Terrain { @@ -1100,8 +888,10 @@ public partial class EditorTileMap : TileMap, IUiNodeScript } } - //擦除一个区域内的贴图 - private void EraseRectCell(Vector2I start, Vector2I end) + /// + /// 擦除一个区域内的贴图 + /// + public void EraseRectCell(Vector2I start, Vector2I end) { if (start.X > end.X) { @@ -1230,42 +1020,10 @@ public partial class EditorTileMap : TileMap, IUiNodeScript MapEditorPanel.S_ErrorCellAnimationPlayer.Instance.Stop(); } - /// - /// 选中拖拽功能 - /// - private void OnSelectHandTool(object arg) - { - MouseType = MouseButtonType.Drag; - } - - /// - /// 选中画笔攻击 - /// - private void OnSelectPenTool(object arg) - { - MouseType = MouseButtonType.Pen; - } - - /// - /// 选中绘制区域功能 - /// - private void OnSelectRectTool(object arg) - { - MouseType = MouseButtonType.Area; - } - - /// - /// 选择编辑门区域 - /// - private void OnSelectEditTool(object arg) - { - MouseType = MouseButtonType.Edit; - } - /// /// 聚焦 /// - private void OnClickCenterTool(object arg) + public void OnFocusClick() { var pos = MapEditorPanel.S_SubViewport.Instance.Size / 2; if (CurrRoomSize.X == 0 && CurrRoomSize.Y == 0) //聚焦原点 @@ -1427,6 +1185,10 @@ public partial class EditorTileMap : TileMap, IUiNodeScript PushLayerDataToList(MapLayer.CustomMiddleLayer2, tileInfo.CustomMiddle2); PushLayerDataToList(MapLayer.CustomTopLayer, tileInfo.CustomTop); + //--------------------------------------- + + MapEditorPanel.S_MapEditorObject.Instance.OnSaveData(tileInfo); + MapProjectManager.SaveRoomTileInfo(CurrRoomSplit); } @@ -1568,6 +1330,8 @@ public partial class EditorTileMap : TileMap, IUiNodeScript SetLayerModulate(MapLayer.CustomMiddleLayer2, Colors.White); SetLayerModulate(MapLayer.AutoTopLayer, Colors.White); SetLayerModulate(MapLayer.CustomTopLayer, Colors.White); + + EventManager.EmitEvent(EventEnum.OnSavePreviewImageBegin); } private void OnFramePostDraw() @@ -1614,6 +1378,8 @@ public partial class EditorTileMap : TileMap, IUiNodeScript _previewFinish(); _hasPreviewImage = false; + + EventManager.EmitEvent(EventEnum.OnSavePreviewImageFinish); } } } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/ItemCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/ItemCell.cs new file mode 100644 index 00000000..d30b965e --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/ItemCell.cs @@ -0,0 +1,29 @@ +using System.Collections; +using Config; + +namespace UI.MapEditorConfigObject; + +public class ItemCell : UiCell +{ + public override void OnInit() + { + CellNode.L_SelectTexture.Instance.Visible = false; + } + + public override IEnumerator OnSetDataCoroutine(ExcelConfig.EditorObject data) + { + CellNode.L_CellName.Instance.Text = data.GetRealName(); + CellNode.L_PreviewImage.Instance.Texture = data.GetIcon(); + yield return null; + } + + public override void OnSelect() + { + CellNode.L_SelectTexture.Instance.Visible = true; + } + + public override void OnUnSelect() + { + CellNode.L_SelectTexture.Instance.Visible = false; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/MapEditorConfigObject.cs b/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/MapEditorConfigObject.cs new file mode 100644 index 00000000..2a28d978 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/MapEditorConfigObject.cs @@ -0,0 +1,262 @@ +namespace UI.MapEditorConfigObject; + +/// +/// Ui代码, 该类是根据ui场景自动生成的, 请不要手动编辑该类, 以免造成代码丢失 +/// +public abstract partial class MapEditorConfigObject : UiBase +{ + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer + /// + public VBoxContainer L_VBoxContainer + { + get + { + if (_L_VBoxContainer == null) _L_VBoxContainer = new VBoxContainer((MapEditorConfigObjectPanel)this, GetNode("VBoxContainer")); + return _L_VBoxContainer; + } + } + private VBoxContainer _L_VBoxContainer; + + + public MapEditorConfigObject() : base(nameof(MapEditorConfigObject)) + { + } + + public sealed override void OnInitNestedUi() + { + + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.HBoxContainer.SearchInput + /// + public class SearchInput : UiNode + { + public SearchInput(MapEditorConfigObjectPanel uiPanel, Godot.LineEdit node) : base(uiPanel, node) { } + public override SearchInput Clone() => new (UiPanel, (Godot.LineEdit)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.HBoxContainer.SearchButton + /// + public class SearchButton : UiNode + { + public SearchButton(MapEditorConfigObjectPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override SearchButton Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.HBoxContainer + /// + public class HBoxContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.SearchInput + /// + public SearchInput L_SearchInput + { + get + { + if (_L_SearchInput == null) _L_SearchInput = new SearchInput(UiPanel, Instance.GetNode("SearchInput")); + return _L_SearchInput; + } + } + private SearchInput _L_SearchInput; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.SearchButton + /// + public SearchButton L_SearchButton + { + get + { + if (_L_SearchButton == null) _L_SearchButton = new SearchButton(UiPanel, Instance.GetNode("SearchButton")); + return _L_SearchButton; + } + } + private SearchButton _L_SearchButton; + + public HBoxContainer(MapEditorConfigObjectPanel uiPanel, Godot.HBoxContainer node) : base(uiPanel, node) { } + public override HBoxContainer Clone() => new (UiPanel, (Godot.HBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton.PreviewImage + /// + public class PreviewImage : UiNode + { + public PreviewImage(MapEditorConfigObjectPanel uiPanel, Godot.TextureRect node) : base(uiPanel, node) { } + public override PreviewImage Clone() => new (UiPanel, (Godot.TextureRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton.CellName + /// + public class CellName : UiNode + { + public CellName(MapEditorConfigObjectPanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override CellName Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton.SelectTexture + /// + public class SelectTexture : UiNode + { + public SelectTexture(MapEditorConfigObjectPanel uiPanel, Godot.NinePatchRect node) : base(uiPanel, node) { } + public override SelectTexture Clone() => new (UiPanel, (Godot.NinePatchRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton + /// + public class CellButton : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.PreviewImage + /// + public PreviewImage L_PreviewImage + { + get + { + if (_L_PreviewImage == null) _L_PreviewImage = new PreviewImage(UiPanel, Instance.GetNode("PreviewImage")); + return _L_PreviewImage; + } + } + private PreviewImage _L_PreviewImage; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellName + /// + public CellName L_CellName + { + get + { + if (_L_CellName == null) _L_CellName = new CellName(UiPanel, Instance.GetNode("CellName")); + return _L_CellName; + } + } + private CellName _L_CellName; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.SelectTexture + /// + public SelectTexture L_SelectTexture + { + get + { + if (_L_SelectTexture == null) _L_SelectTexture = new SelectTexture(UiPanel, Instance.GetNode("SelectTexture")); + return _L_SelectTexture; + } + } + private SelectTexture _L_SelectTexture; + + public CellButton(MapEditorConfigObjectPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override CellButton Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer.ScrollContainer + /// + public class ScrollContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.CellButton + /// + public CellButton L_CellButton + { + get + { + if (_L_CellButton == null) _L_CellButton = new CellButton(UiPanel, Instance.GetNode("CellButton")); + return _L_CellButton; + } + } + private CellButton _L_CellButton; + + public ScrollContainer(MapEditorConfigObjectPanel uiPanel, Godot.ScrollContainer node) : base(uiPanel, node) { } + public override ScrollContainer Clone() => new (UiPanel, (Godot.ScrollContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorConfigObject.VBoxContainer + /// + public class VBoxContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.HBoxContainer + /// + public HBoxContainer L_HBoxContainer + { + get + { + if (_L_HBoxContainer == null) _L_HBoxContainer = new HBoxContainer(UiPanel, Instance.GetNode("HBoxContainer")); + return _L_HBoxContainer; + } + } + private HBoxContainer _L_HBoxContainer; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorConfigObject.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 VBoxContainer(MapEditorConfigObjectPanel uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) { } + public override VBoxContainer Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate()); + } + + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.HBoxContainer.SearchInput + /// + public SearchInput S_SearchInput => L_VBoxContainer.L_HBoxContainer.L_SearchInput; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.HBoxContainer.SearchButton + /// + public SearchButton S_SearchButton => L_VBoxContainer.L_HBoxContainer.L_SearchButton; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.HBoxContainer + /// + public HBoxContainer S_HBoxContainer => L_VBoxContainer.L_HBoxContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton.PreviewImage + /// + public PreviewImage S_PreviewImage => L_VBoxContainer.L_ScrollContainer.L_CellButton.L_PreviewImage; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton.CellName + /// + public CellName S_CellName => L_VBoxContainer.L_ScrollContainer.L_CellButton.L_CellName; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton.SelectTexture + /// + public SelectTexture S_SelectTexture => L_VBoxContainer.L_ScrollContainer.L_CellButton.L_SelectTexture; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer.CellButton + /// + public CellButton S_CellButton => L_VBoxContainer.L_ScrollContainer.L_CellButton; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer.ScrollContainer + /// + public ScrollContainer S_ScrollContainer => L_VBoxContainer.L_ScrollContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorConfigObject.VBoxContainer + /// + public VBoxContainer S_VBoxContainer => L_VBoxContainer; + +} diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/MapEditorConfigObjectPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/MapEditorConfigObjectPanel.cs new file mode 100644 index 00000000..c9976f44 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorConfigObject/MapEditorConfigObjectPanel.cs @@ -0,0 +1,65 @@ +using System.Linq; +using Config; +using Godot; + +namespace UI.MapEditorConfigObject; + +public partial class MapEditorConfigObjectPanel : MapEditorConfigObject +{ + private UiGrid _grid; + private bool _initData = false; + private long _gridCoroutineId = -1; + + public override void OnCreateUi() + { + _grid = CreateUiGrid(S_CellButton); + _grid.SetAutoColumns(true); + _grid.SetHorizontalExpand(true); + + //搜索按钮 + S_SearchButton.Instance.Pressed += OnSearchButtonClicked; + } + + public override void OnShowUi() + { + if (!_initData) + { + _initData = true; + OnSearchButtonClicked(); + } + } + + public override void OnDestroyUi() + { + + } + + /// + /// 获取选中的配置 + /// + public ExcelConfig.EditorObject GetSelectConfig() + { + return _grid.SelectData; + } + + //搜索按钮点击 + private void OnSearchButtonClicked() + { + if (_gridCoroutineId != -1) + { + StopCoroutine(_gridCoroutineId); + } + + var text = S_SearchInput.Instance.Text; + if (string.IsNullOrEmpty(text)) + { + _gridCoroutineId = StartCoroutine(_grid.SetDataListCoroutine(ExcelConfig.EditorObject_List)); + } + else + { + var enumerable = ExcelConfig.EditorObject_List.Where(item => item.GetRealName().Contains(text)); + _gridCoroutineId = StartCoroutine(_grid.SetDataListCoroutine(enumerable.ToArray())); + } + } + +} diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs index 9c59d27e..f57a16dc 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs @@ -4,7 +4,7 @@ using UI.MapEditor; namespace UI.MapEditorMapMark; -public partial class MapEditorMapMarkPanel : MapEditorMapMark +public partial class MapEditorMapMarkPanel : MapEditorMapMark, IEditorTab { public enum SelectToolType { @@ -495,4 +495,17 @@ public partial class MapEditorMapMarkPanel : MapEditorMapMark } S_AutoFillTip.Instance.Visible = false; } + + public void OnSelectTab() + { + var panel = EditorTileMap.MapEditorPanel; + panel.S_LayerPanel.Instance.Visible = false; + + panel.S_MapEditorTools.Instance.SetToolButton(EditorToolEnum.Move, EditorToolEnum.MarkTool, EditorToolEnum.Focus); + } + + public void OnUnSelectTab() + { + + } } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapTile/MapEditorMapTilePanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapTile/MapEditorMapTilePanel.cs index e82ff5fd..4afcfe94 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorMapTile/MapEditorMapTilePanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapTile/MapEditorMapTilePanel.cs @@ -3,7 +3,7 @@ using UI.MapEditor; namespace UI.MapEditorMapTile; -public partial class MapEditorMapTilePanel : MapEditorMapTile +public partial class MapEditorMapTilePanel : MapEditorMapTile, IEditorTab { /// /// 使用的TileSet数据 @@ -129,4 +129,19 @@ public partial class MapEditorMapTilePanel : MapEditorMapTile S_Tab2.Instance.Visible = v2; S_Tab3.Instance.Visible = v3; } + + public void OnSelectTab() + { + var panel = EditorTileMap.MapEditorPanel; + panel.S_LayerPanel.Instance.Visible = true; + panel.S_LayerPanel.L_MapEditorMapLayer.Instance.ShowUi(); + panel.S_LayerPanel.L_MapEditorConfigObject.Instance.HideUi(); + + panel.S_MapEditorTools.Instance.SetToolButton(EditorToolEnum.Move, EditorToolEnum.TilePen, EditorToolEnum.TileAreaPen, EditorToolEnum.Focus); + } + + public void OnUnSelectTab() + { + + } } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorObject/ItemCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorObject/ItemCell.cs new file mode 100644 index 00000000..fb1c2d56 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorObject/ItemCell.cs @@ -0,0 +1,36 @@ +using System.Collections; +using Config; + +namespace UI.MapEditorObject; + +public class ItemCell : UiCell +{ + public override void OnInit() + { + CellNode.L_ItemButton.L_Select.Instance.Visible = false; + CellNode.L_ItemButton.Instance.Pressed += Click; + } + + public override void OnSetData(RoomObjectInfo data) + { + var config = ExcelConfig.EditorObject_Map[data.Id]; + CellNode.L_ItemButton.Instance.Text = config.GetRealName(); + CellNode.L_ItemButton.L_Icon.Instance.Texture = config.GetIcon(); + } + + public override void OnSelect() + { + CellNode.L_ItemButton.L_Select.Instance.Visible = true; + EventManager.EmitEvent(EventEnum.OnSelectObject, Data); + } + + public override void OnUnSelect() + { + CellNode.L_ItemButton.L_Select.Instance.Visible = false; + } + + public override void OnDoubleClick() + { + CellNode.UiPanel.FoceSelectObject(Data); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorObject/MapEditorObject.cs b/DungeonShooting_Godot/src/game/ui/mapEditorObject/MapEditorObject.cs new file mode 100644 index 00000000..0c00715b --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorObject/MapEditorObject.cs @@ -0,0 +1,370 @@ +namespace UI.MapEditorObject; + +/// +/// Ui代码, 该类是根据ui场景自动生成的, 请不要手动编辑该类, 以免造成代码丢失 +/// +public abstract partial class MapEditorObject : UiBase +{ + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer + /// + public VBoxContainer L_VBoxContainer + { + get + { + if (_L_VBoxContainer == null) _L_VBoxContainer = new VBoxContainer((MapEditorObjectPanel)this, GetNode("VBoxContainer")); + return _L_VBoxContainer; + } + } + private VBoxContainer _L_VBoxContainer; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.DynamicDeleteButton + /// + public DynamicDeleteButton L_DynamicDeleteButton + { + get + { + if (_L_DynamicDeleteButton == null) _L_DynamicDeleteButton = new DynamicDeleteButton((MapEditorObjectPanel)this, GetNode("DynamicDeleteButton")); + return _L_DynamicDeleteButton; + } + } + private DynamicDeleteButton _L_DynamicDeleteButton; + + + public MapEditorObject() : base(nameof(MapEditorObject)) + { + } + + public sealed override void OnInitNestedUi() + { + + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.HBoxContainer.SearchInput + /// + public class SearchInput : UiNode + { + public SearchInput(MapEditorObjectPanel uiPanel, Godot.LineEdit node) : base(uiPanel, node) { } + public override SearchInput Clone() => new (UiPanel, (Godot.LineEdit)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.HBoxContainer.SearchButton + /// + public class SearchButton : UiNode + { + public SearchButton(MapEditorObjectPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override SearchButton Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.HBoxContainer + /// + public class HBoxContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.SearchInput + /// + public SearchInput L_SearchInput + { + get + { + if (_L_SearchInput == null) _L_SearchInput = new SearchInput(UiPanel, Instance.GetNode("SearchInput")); + return _L_SearchInput; + } + } + private SearchInput _L_SearchInput; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.SearchButton + /// + public SearchButton L_SearchButton + { + get + { + if (_L_SearchButton == null) _L_SearchButton = new SearchButton(UiPanel, Instance.GetNode("SearchButton")); + return _L_SearchButton; + } + } + private SearchButton _L_SearchButton; + + public HBoxContainer(MapEditorObjectPanel uiPanel, Godot.HBoxContainer node) : base(uiPanel, node) { } + public override HBoxContainer Clone() => new (UiPanel, (Godot.HBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.HBoxContainer2.Label + /// + public class Label : UiNode + { + public Label(MapEditorObjectPanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override Label Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.HBoxContainer2.LayerOption + /// + public class LayerOption : UiNode + { + public LayerOption(MapEditorObjectPanel uiPanel, Godot.OptionButton node) : base(uiPanel, node) { } + public override LayerOption Clone() => new (UiPanel, (Godot.OptionButton)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.HBoxContainer2 + /// + public class HBoxContainer2 : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.Label + /// + public Label L_Label + { + get + { + if (_L_Label == null) _L_Label = new Label(UiPanel, Instance.GetNode("Label")); + return _L_Label; + } + } + private Label _L_Label; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.LayerOption + /// + public LayerOption L_LayerOption + { + get + { + if (_L_LayerOption == null) _L_LayerOption = new LayerOption(UiPanel, Instance.GetNode("LayerOption")); + return _L_LayerOption; + } + } + private LayerOption _L_LayerOption; + + public HBoxContainer2(MapEditorObjectPanel uiPanel, Godot.HBoxContainer node) : base(uiPanel, node) { } + public override HBoxContainer2 Clone() => new (UiPanel, (Godot.HBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.ItemRoot.Item.ItemButton.Icon + /// + public class Icon : UiNode + { + public Icon(MapEditorObjectPanel uiPanel, Godot.TextureRect node) : base(uiPanel, node) { } + public override Icon Clone() => new (UiPanel, (Godot.TextureRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.ItemRoot.Item.ItemButton.Select + /// + public class Select : UiNode + { + public Select(MapEditorObjectPanel uiPanel, Godot.NinePatchRect node) : base(uiPanel, node) { } + public override Select Clone() => new (UiPanel, (Godot.NinePatchRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.ItemRoot.Item.ItemButton + /// + public class ItemButton : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot.Item.Icon + /// + public Icon L_Icon + { + get + { + if (_L_Icon == null) _L_Icon = new Icon(UiPanel, Instance.GetNode("Icon")); + return _L_Icon; + } + } + private Icon _L_Icon; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot.Item.Select + /// + public Select L_Select + { + get + { + if (_L_Select == null) _L_Select = new Select(UiPanel, Instance.GetNode("Select")); + return _L_Select; + } + } + private Select _L_Select; + + public ItemButton(MapEditorObjectPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override ItemButton Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.ItemRoot.Item + /// + public class Item : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot.ItemButton + /// + public ItemButton L_ItemButton + { + get + { + if (_L_ItemButton == null) _L_ItemButton = new ItemButton(UiPanel, Instance.GetNode("ItemButton")); + return _L_ItemButton; + } + } + private ItemButton _L_ItemButton; + + public Item(MapEditorObjectPanel uiPanel, Godot.HBoxContainer node) : base(uiPanel, node) { } + public override Item Clone() => new (UiPanel, (Godot.HBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer.ItemRoot + /// + public class ItemRoot : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.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 ItemRoot(MapEditorObjectPanel uiPanel, Godot.ScrollContainer node) : base(uiPanel, node) { } + public override ItemRoot Clone() => new (UiPanel, (Godot.ScrollContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.VBoxContainer + /// + public class VBoxContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.HBoxContainer + /// + public HBoxContainer L_HBoxContainer + { + get + { + if (_L_HBoxContainer == null) _L_HBoxContainer = new HBoxContainer(UiPanel, Instance.GetNode("HBoxContainer")); + return _L_HBoxContainer; + } + } + private HBoxContainer _L_HBoxContainer; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.HBoxContainer2 + /// + public HBoxContainer2 L_HBoxContainer2 + { + get + { + if (_L_HBoxContainer2 == null) _L_HBoxContainer2 = new HBoxContainer2(UiPanel, Instance.GetNode("HBoxContainer2")); + return _L_HBoxContainer2; + } + } + private HBoxContainer2 _L_HBoxContainer2; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorObject.ItemRoot + /// + public ItemRoot L_ItemRoot + { + get + { + if (_L_ItemRoot == null) _L_ItemRoot = new ItemRoot(UiPanel, Instance.GetNode("ItemRoot")); + return _L_ItemRoot; + } + } + private ItemRoot _L_ItemRoot; + + public VBoxContainer(MapEditorObjectPanel uiPanel, Godot.VBoxContainer node) : base(uiPanel, node) { } + public override VBoxContainer Clone() => new (UiPanel, (Godot.VBoxContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorObject.DynamicDeleteButton + /// + public class DynamicDeleteButton : UiNode + { + public DynamicDeleteButton(MapEditorObjectPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override DynamicDeleteButton Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.HBoxContainer.SearchInput + /// + public SearchInput S_SearchInput => L_VBoxContainer.L_HBoxContainer.L_SearchInput; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.HBoxContainer.SearchButton + /// + public SearchButton S_SearchButton => L_VBoxContainer.L_HBoxContainer.L_SearchButton; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.HBoxContainer + /// + public HBoxContainer S_HBoxContainer => L_VBoxContainer.L_HBoxContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.HBoxContainer2.Label + /// + public Label S_Label => L_VBoxContainer.L_HBoxContainer2.L_Label; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.HBoxContainer2.LayerOption + /// + public LayerOption S_LayerOption => L_VBoxContainer.L_HBoxContainer2.L_LayerOption; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.HBoxContainer2 + /// + public HBoxContainer2 S_HBoxContainer2 => L_VBoxContainer.L_HBoxContainer2; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot.Item.ItemButton.Icon + /// + public Icon S_Icon => L_VBoxContainer.L_ItemRoot.L_Item.L_ItemButton.L_Icon; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot.Item.ItemButton.Select + /// + public Select S_Select => L_VBoxContainer.L_ItemRoot.L_Item.L_ItemButton.L_Select; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot.Item.ItemButton + /// + public ItemButton S_ItemButton => L_VBoxContainer.L_ItemRoot.L_Item.L_ItemButton; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot.Item + /// + public Item S_Item => L_VBoxContainer.L_ItemRoot.L_Item; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer.ItemRoot + /// + public ItemRoot S_ItemRoot => L_VBoxContainer.L_ItemRoot; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.VBoxContainer + /// + public VBoxContainer S_VBoxContainer => L_VBoxContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorObject.DynamicDeleteButton + /// + public DynamicDeleteButton S_DynamicDeleteButton => L_DynamicDeleteButton; + +} diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorObject/MapEditorObjectPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorObject/MapEditorObjectPanel.cs new file mode 100644 index 00000000..0914bb5e --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorObject/MapEditorObjectPanel.cs @@ -0,0 +1,260 @@ +using System.Collections.Generic; +using System.Linq; +using Config; +using Godot; +using UI.MapEditor; + +namespace UI.MapEditorObject; + +public partial class MapEditorObjectPanel : MapEditorObject, IEditorTab +{ + /// + /// 编辑器Tile对象 + /// + public EditorTileMap EditorTileMap { get; private set; } + + /// + /// 临时存储普通层自定义物体数据 + /// + public readonly List NormalLayerObjects = new List(); + + /// + /// 临时存储Y排序层自定义物体数据 + /// + public readonly List YSortLayerObjects = new List(); + + /// + /// 当前页签是否选中 + /// + public bool IsActiveTab { get; private set; } + + /// + /// 物体网格 + /// + public UiGrid ObjectGrid { get; private set; } + + public override void OnCreateUi() + { + var editorPanel = (MapEditorPanel)ParentUi; + EditorTileMap = editorPanel.S_TileMap.Instance; + + ObjectGrid = CreateUiGrid(S_Item); + ObjectGrid.SetHorizontalExpand(true); + ObjectGrid.SelectEvent += OnSelectEvent; + + AddEventListener(EventEnum.OnPutObject, OnPutObject); + AddEventListener(EventEnum.OnSelectObject, OnSelectObject); + + S_SearchButton.Instance.Pressed += OnSearchClick; + S_LayerOption.Instance.ItemSelected += (index) => + { + OnChangeObjectLayer(index); + OnSearchClick(); + }; + + S_DynamicDeleteButton.Instance.Pressed += OnDelete; + } + + public override void OnDestroyUi() + { + + } + + /// + /// 初始化面板数据 + /// + public void InitData() + { + var tileInfo = EditorTileMap.CurrRoomSplit.TileInfo; + if (tileInfo.NormalLayerObjects != null) + { + foreach (var temp in tileInfo.NormalLayerObjects) + { + if (ExcelConfig.EditorObject_Map.ContainsKey(temp.Id)) + { + NormalLayerObjects.Add(temp.Clone()); + } + } + } + + if (tileInfo.YSortLayerObjects != null) + { + foreach (var temp in tileInfo.YSortLayerObjects) + { + if (ExcelConfig.EditorObject_Map.ContainsKey(temp.Id)) + { + YSortLayerObjects.Add(temp.Clone()); + } + } + } + + EditorTileMap.MapEditorPanel.S_MapEditorTools.Instance.InitCustomObjectData(); + //刷新数据 + OnSearchClick(); + } + + /// + /// 保存配置数据 + /// + public void OnSaveData(DungeonTileInfo tileInfo) + { + tileInfo.NormalLayerObjects.Clear(); + foreach (var normalLayerObject in NormalLayerObjects) + { + tileInfo.NormalLayerObjects.Add(normalLayerObject.Clone()); + } + tileInfo.YSortLayerObjects.Clear(); + foreach (var ySortLayerObject in YSortLayerObjects) + { + tileInfo.YSortLayerObjects.Add(ySortLayerObject.Clone()); + } + } + + /// + /// 聚焦物体 + /// + public void FoceSelectObject(RoomObjectInfo info) + { + EditorTileMap.SetLookPosition(new Vector2(info.X, info.Y)); + } + + /// + /// 获取当前选中的物体层 + /// + public List GetCurrentObjectLayer() + { + return S_LayerOption.Instance.Selected == 0 ? NormalLayerObjects : YSortLayerObjects; + } + + /// + /// 获取当前选中的物体层 + /// + public RoomLayerEnum GetCurrentObjectLayerEnum() + { + return S_LayerOption.Instance.Selected == 0 ? RoomLayerEnum.NormalLayer : RoomLayerEnum.YSortLayer; + } + + private void OnChangeObjectLayer(long index) + { + var editorToolsPanel = EditorTileMap.MapEditorPanel.S_MapEditorTools.Instance; + var toolsPanel = editorToolsPanel; + + if (index == 0) + { + toolsPanel.CustomNormalRoot.Modulate = Colors.White; + toolsPanel.CustomYSortRoot.Modulate = new Color(1, 1, 1, 0.5f); + } + else + { + toolsPanel.CustomNormalRoot.Modulate = new Color(1, 1, 1, 0.5f); + toolsPanel.CustomYSortRoot.Modulate = Colors.White; + } + + //启用当前层的Area2D物体监视 + foreach (var custonObjectData in editorToolsPanel.CustomObjecMapping) + { + var objectData = custonObjectData.Value; + objectData.Node.Instance.Monitorable = (long)objectData.Layer == index; + } + } + + //搜索 + public void OnSearchClick() + { + var dataList = GetCurrentObjectLayer(); + var text = S_SearchInput.Instance.Text; + if (string.IsNullOrEmpty(text)) + { + ObjectGrid.SetDataList(dataList); + } + else + { + var result = dataList.Where(data => ExcelConfig.EditorObject_Map[data.Id].Name.Contains(text)).ToArray(); + ObjectGrid.SetDataList(result); + } + } + + //创建自定义物体 + private void OnPutObject(object obj) + { + var temp = (RoomObjectInfo)obj; + var layer = GetCurrentObjectLayer(); + layer.Add(temp); + OnSearchClick(); + } + + private void OnSelectEvent(int index) + { + if (index < 0) + { + S_DynamicDeleteButton.Instance.Visible = false; + S_DynamicDeleteButton.Reparent(this); + } + else + { + S_DynamicDeleteButton.Instance.Visible = true; + S_DynamicDeleteButton.Reparent(ObjectGrid.GetCell(index).CellNode.Instance); + } + } + + //删除 + private void OnDelete() + { + if (ObjectGrid.SelectIndex < 0) + { + return; + } + + EditorWindowManager.ShowConfirm("提示", "确定删除该物体吗?", b => + { + if (b) + { + var layer = GetCurrentObjectLayer(); + var temp = layer[ObjectGrid.SelectIndex]; + layer.RemoveAt(ObjectGrid.SelectIndex); + + //派发删除事件 + EventManager.EmitEvent(EventEnum.OnRemoveObject, temp); + + OnSearchClick(); + + //标记数据脏了 + EventManager.EmitEvent(EventEnum.OnTileMapDirty); + } + }); + } + + public void OnSelectTab() + { + IsActiveTab = true; + var panel = EditorTileMap.MapEditorPanel; + + panel.S_LayerPanel.Instance.Visible = true; + panel.S_LayerPanel.L_MapEditorMapLayer.Instance.HideUi(); + panel.S_LayerPanel.L_MapEditorConfigObject.Instance.ShowUi(); + + panel.S_MapEditorTools.Instance.SetToolButton(EditorToolEnum.Move, EditorToolEnum.ObjectPen, EditorToolEnum.ObjectTool, EditorToolEnum.Focus); + OnChangeObjectLayer(S_LayerOption.Instance.Selected); + } + + public void OnUnSelectTab() + { + var panel = EditorTileMap.MapEditorPanel; + panel.S_MapEditorTools.Instance.CustomNormalRoot.Modulate = Colors.White; + panel.S_MapEditorTools.Instance.CustomYSortRoot.Modulate = Colors.White; + IsActiveTab = false; + } + + private void OnSelectObject(object obj) + { + var data = (RoomObjectInfo)obj; + if (ObjectGrid.SelectData != data) + { + var uiCell = ObjectGrid.Find(item => item.Data == data); + if (uiCell != null) + { + uiCell.Click(); + } + } + } +} diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/CustomObject.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/CustomObject.cs new file mode 100644 index 00000000..95b93a81 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/CustomObject.cs @@ -0,0 +1,55 @@ +using Godot; +using UI.MapEditorObject; + +namespace UI.MapEditorTools; + +public partial class CustomObject : Area2D, IUiNodeScript +{ + public RoomObjectInfo Info; + public Node2D Node; + + private MapEditorObjectPanel _objectPanel; + + private MapEditorTools.ObjectTemplate _uiNode; + private static Rect2 _rect = new Rect2(-GameConfig.TileCellSizeVector2I / 2, GameConfig.TileCellSizeVector2I); + + public void SetUiNode(IUiNode uiNode) + { + _uiNode = (MapEditorTools.ObjectTemplate) uiNode; + _uiNode.L_RectBrush.Instance.Draw += OnDraw; + _objectPanel = _uiNode.UiPanel.MapEditorPanel.S_MapEditorObject.Instance; + } + + public void OnDestroy() + { + + } + + public void Init(RoomObjectInfo info, Node2D node) + { + Info = info; + Node = node; + + _uiNode.L_Bar.AddChild(node); + } + + public override void _Process(double delta) + { + _uiNode.L_RectBrush.Instance.QueueRedraw(); + } + + private void OnDraw() + { + if (_objectPanel.IsActiveTab) //选中页签才能绘制 + { + if (_objectPanel.ObjectGrid.SelectData == Info) //判断是否选中 + { + _uiNode.L_RectBrush.Instance.DrawRect(_rect, Colors.Green, false, 1f); + } + else + { + _uiNode.L_RectBrush.Instance.DrawRect(_rect, Colors.White, false, 1f); + } + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs index 4dfff222..07cdacee 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs @@ -257,11 +257,11 @@ public partial class DoorDragArea : Control bool checkResult; if (DoorAreaInfo == null) { - checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(Direction, doorAreaRange.X, doorAreaRange.Y); + checkResult = MapEditorToolsPanel.EditorMap.CheckDoorArea(Direction, doorAreaRange.X, doorAreaRange.Y); } else { - checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(DoorAreaInfo, doorAreaRange.X, doorAreaRange.Y); + checkResult = MapEditorToolsPanel.EditorMap.CheckDoorArea(DoorAreaInfo, doorAreaRange.X, doorAreaRange.Y); } if (checkResult) { @@ -350,11 +350,11 @@ public partial class DoorDragArea : Control bool checkResult; if (DoorAreaInfo == null) { - checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(Direction, doorAreaRange.X, doorAreaRange.Y); + checkResult = MapEditorToolsPanel.EditorMap.CheckDoorArea(Direction, doorAreaRange.X, doorAreaRange.Y); } else { - checkResult = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(DoorAreaInfo, doorAreaRange.X, doorAreaRange.Y); + checkResult = MapEditorToolsPanel.EditorMap.CheckDoorArea(DoorAreaInfo, doorAreaRange.X, doorAreaRange.Y); } if (checkResult) { @@ -426,7 +426,7 @@ public partial class DoorDragArea : Control private void OnMouseEntered() { - if (MapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) + if (MapEditorToolsPanel.EditorMap.ActiveToolType != EditorToolEnum.MarkTool) { return; } @@ -435,7 +435,7 @@ public partial class DoorDragArea : Control private void OnMouseExited() { - if (MapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) + if (MapEditorToolsPanel.EditorMap.ActiveToolType != EditorToolEnum.MarkTool) { return; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragButton.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragButton.cs index 6f816230..c0e00d7c 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragButton.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragButton.cs @@ -65,7 +65,7 @@ public partial class DoorDragButton : TextureButton private void OnButtonDown() { - if (_mapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) + if (_mapEditorToolsPanel.EditorMap.ActiveToolType != EditorToolEnum.MarkTool) { return; } @@ -85,7 +85,7 @@ public partial class DoorDragButton : TextureButton private void OnButtonUp() { - if (_mapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) + if (_mapEditorToolsPanel.EditorMap.ActiveToolType != EditorToolEnum.MarkTool) { return; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs index 32da2d8c..a03035ee 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs @@ -48,7 +48,7 @@ public partial class DoorHoverArea : ColorRect var previewRoot = MapEditorToolsPanel.S_HoverPreviewRoot.Instance; //检测是否会与其他门发生碰撞 - var canCreateDragArea = MapEditorToolsPanel.EditorMap.Instance.CheckDoorArea(Direction, start, start); + var canCreateDragArea = MapEditorToolsPanel.EditorMap.CheckDoorArea(Direction, start, start); if (canCreateDragArea) { previewRoot.Visible = true; @@ -74,7 +74,7 @@ public partial class DoorHoverArea : ColorRect { IsDrag = false; Debug.Log("提交创建: " + direction + ", " + start + ", " + end); - _currToolTemplate.Instance.DoorAreaInfo = MapEditorToolsPanel.EditorMap.Instance.CreateDoorArea(direction, start, end); + _currToolTemplate.Instance.DoorAreaInfo = MapEditorToolsPanel.EditorMap.CreateDoorArea(direction, start, end); //派发修改数据修改事件 EventManager.EmitEvent(EventEnum.OnTileMapDirty); } @@ -88,13 +88,13 @@ public partial class DoorHoverArea : ColorRect private void OnMouseEnter() { - if (MapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) + if (MapEditorToolsPanel.EditorMap.ActiveToolType != EditorToolEnum.MarkTool) { return; } if (MapEditorToolsPanel.ActiveHoverArea == null || !IsDrag) { - var roomSize = MapEditorToolsPanel.EditorMap.Instance.CurrRoomSize; + var roomSize = MapEditorToolsPanel.EditorMap.CurrRoomSize; //房间大小为0, 不能放置门区域 if (roomSize.X == 0 && roomSize.Y == 0) { @@ -113,7 +113,7 @@ public partial class DoorHoverArea : ColorRect private void OnMouseExit() { - if (MapEditorToolsPanel.EditorMap.Instance.MouseType != EditorTileMap.MouseButtonType.Edit) + if (MapEditorToolsPanel.EditorMap.ActiveToolType != EditorToolEnum.MarkTool) { return; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs index 9c0c8428..49cd221d 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorTools.cs @@ -18,6 +18,19 @@ public abstract partial class MapEditorTools : UiBase } private ToolRoot _L_ToolRoot; + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.ObjectTemplate + /// + public ObjectTemplate L_ObjectTemplate + { + get + { + if (_L_ObjectTemplate == null) _L_ObjectTemplate = new ObjectTemplate((MapEditorToolsPanel)this, GetNode("ObjectTemplate")); + return _L_ObjectTemplate; + } + } + private ObjectTemplate _L_ObjectTemplate; + /// /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.HBoxContainer /// @@ -39,6 +52,7 @@ public abstract partial class MapEditorTools : UiBase public sealed override void OnInitNestedUi() { _ = L_ToolRoot.L_MarkTemplate; + _ = L_ObjectTemplate; } @@ -381,6 +395,81 @@ public abstract partial class MapEditorTools : UiBase public override ToolRoot Clone() => new (UiPanel, (Godot.Control)Instance.Duplicate()); } + /// + /// 类型: , 路径: MapEditorTools.ObjectTemplate.CollisionShape2D + /// + public class CollisionShape2D : UiNode + { + public CollisionShape2D(MapEditorToolsPanel uiPanel, Godot.CollisionShape2D node) : base(uiPanel, node) { } + public override CollisionShape2D Clone() => new (UiPanel, (Godot.CollisionShape2D)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorTools.ObjectTemplate.Bar + /// + public class Bar : UiNode + { + public Bar(MapEditorToolsPanel uiPanel, Godot.Node2D node) : base(uiPanel, node) { } + public override Bar Clone() => new (UiPanel, (Godot.Node2D)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorTools.ObjectTemplate.RectBrush + /// + public class RectBrush : UiNode + { + public RectBrush(MapEditorToolsPanel uiPanel, Godot.Node2D node) : base(uiPanel, node) { } + public override RectBrush Clone() => new (UiPanel, (Godot.Node2D)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: MapEditorTools.ObjectTemplate + /// + public class ObjectTemplate : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.CollisionShape2D + /// + public CollisionShape2D L_CollisionShape2D + { + get + { + if (_L_CollisionShape2D == null) _L_CollisionShape2D = new CollisionShape2D(UiPanel, Instance.GetNode("CollisionShape2D")); + return _L_CollisionShape2D; + } + } + private CollisionShape2D _L_CollisionShape2D; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.Bar + /// + public Bar L_Bar + { + get + { + if (_L_Bar == null) _L_Bar = new Bar(UiPanel, Instance.GetNode("Bar")); + return _L_Bar; + } + } + private Bar _L_Bar; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: MapEditorTools.RectBrush + /// + public RectBrush L_RectBrush + { + get + { + if (_L_RectBrush == null) _L_RectBrush = new RectBrush(UiPanel, Instance.GetNode("RectBrush")); + return _L_RectBrush; + } + } + private RectBrush _L_RectBrush; + + public ObjectTemplate(MapEditorToolsPanel uiPanel, UI.MapEditorTools.CustomObject node) : base(uiPanel, node) { } + public override ObjectTemplate Clone() => new (UiPanel, (UI.MapEditorTools.CustomObject)Instance.Duplicate()); + } + /// /// 类型: , 路径: MapEditorTools.HBoxContainer.ToolButton.Select /// @@ -515,6 +604,26 @@ public abstract partial class MapEditorTools : UiBase /// public ToolRoot S_ToolRoot => L_ToolRoot; + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.ObjectTemplate.CollisionShape2D + /// + public CollisionShape2D S_CollisionShape2D => L_ObjectTemplate.L_CollisionShape2D; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.ObjectTemplate.Bar + /// + public Bar S_Bar => L_ObjectTemplate.L_Bar; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.ObjectTemplate.RectBrush + /// + public RectBrush S_RectBrush => L_ObjectTemplate.L_RectBrush; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.ObjectTemplate + /// + public ObjectTemplate S_ObjectTemplate => L_ObjectTemplate; + /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: MapEditorTools.HBoxContainer.ToolButton.Select /// diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs index c85cf822..ad7e5804 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Config; using Godot; using UI.MapEditor; @@ -7,20 +8,17 @@ namespace UI.MapEditorTools; public partial class MapEditorToolsPanel : MapEditorTools { - public class ToolBtnData + public class CustonObjectData { - //是否可以选中 - public bool CanSelect = false; - //工具图标 - public string Icon; - //点击时回调 - public Action OnClick; + public RoomObjectInfo RoomObjectInfo; + public ObjectTemplate Node; + public RoomLayerEnum Layer; - public ToolBtnData(bool canSelect, string icon, Action onClick) + public CustonObjectData(RoomObjectInfo roomObjectInfo, ObjectTemplate node, RoomLayerEnum layer) { - CanSelect = canSelect; - Icon = icon; - OnClick = onClick; + RoomObjectInfo = roomObjectInfo; + Node = node; + Layer = layer; } } @@ -37,24 +35,52 @@ public partial class MapEditorToolsPanel : MapEditorTools /// /// 所属编辑器Tile对象 /// - public MapEditor.MapEditor.TileMap EditorMap { get; private set; } + public EditorTileMap EditorMap { get; private set; } + + /// + /// 所属编辑器面板对象 + /// + public MapEditorPanel MapEditorPanel { get; private set; } /// /// 是否打开弹窗 /// public bool IsOpenPopUps { get; private set; } + + /// + /// 当前选中的工具 + /// + public EditorToolEnum ActiveToolType => _toolGrid != null && _toolGrid.SelectData != null ? _toolGrid.SelectData.EditorToolType : EditorToolEnum.None; + + /// + /// 自定义对象普通层根节点 + /// + public Node2D CustomNormalRoot { get; private set; } + /// + /// 自定义对象YSort层根节点 + /// + public Node2D CustomYSortRoot { get; private set; } + + /// + /// 自定义物体映射字典, 负责存储所有自定义物体 + /// + public Dictionary CustomObjecMapping { get; } = new Dictionary(); private List _doorTools = new List(); - private UiGrid _toolGrid; + private Dictionary _toolMapping = new Dictionary(); + private UiGrid _toolGrid; //当前预设的所有标记 private Dictionary _currMarkToolsMap = new Dictionary(); - private EventFactory _eventFactory; - private int _editToolIndex; + + //丢失的物体id + private HashSet _missingSet = new HashSet(); + + private Color _tempColor1, _tempColor2; public override void OnCreateUi() { - var mapEditorPanel = (MapEditorPanel)ParentUi; - EditorMap = mapEditorPanel.S_TileMap; + MapEditorPanel = (MapEditorPanel)ParentUi; + EditorMap = MapEditorPanel.S_TileMap.Instance; S_N_HoverArea.Instance.Init(this, DoorDirection.N); S_S_HoverArea.Instance.Init(this, DoorDirection.S); @@ -63,59 +89,87 @@ public partial class MapEditorToolsPanel : MapEditorTools S_ToolRoot.Instance.RemoveChild(S_DoorToolTemplate.Instance); S_MarkTemplate.Instance.Visible = false; - _toolGrid = new UiGrid(S_ToolButton, typeof(ToolButtonCell)); - _toolGrid.SetColumns(10); - //拖拽按钮 - _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_DragTool_png, () => - { - EventManager.EmitEvent(EventEnum.OnSelectDragTool); - })); - //画笔按钮 - _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_PenTool_png, () => - { - EventManager.EmitEvent(EventEnum.OnSelectPenTool); - })); - //绘制区域按钮 - _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_AreaTool_png, () => - { - EventManager.EmitEvent(EventEnum.OnSelectRectTool); - })); - //编辑工具按钮 - _toolGrid.Add(new ToolBtnData(true, ResourcePath.resource_sprite_ui_commonIcon_DoorTool_png, () => - { - EventManager.EmitEvent(EventEnum.OnSelectEditTool); - mapEditorPanel.S_MapEditorMapLayer.Instance.SetLayerVisible(MapLayer.MarkLayer, true); - })); - _editToolIndex = _toolGrid.Count - 1; - //聚焦按钮 - _toolGrid.Add(new ToolBtnData(false, ResourcePath.resource_sprite_ui_commonIcon_CenterTool_png, () => - { - EventManager.EmitEvent(EventEnum.OnClickCenterTool); - })); - _toolGrid.SelectIndex = 1; + S_ObjectTemplate.Instance.Visible = false; + + //工具栏 + AddToolMapping(new EditorMove(EditorMap)); + AddToolMapping(new EditorTilePen(EditorMap)); + AddToolMapping(new EditorTileAreaPen(EditorMap)); + AddToolMapping(new EditorMarkTool(EditorMap)); + AddToolMapping(new EditorFocus(EditorMap)); + AddToolMapping(new EditorObjectPen(EditorMap)); + AddToolMapping(new EditorObjectTool(EditorMap)); - _eventFactory = EventManager.CreateEventFactory(); - _eventFactory.AddEventListener(EventEnum.OnSelectWave, OnSelectWaveTool); - _eventFactory.AddEventListener(EventEnum.OnCreateMark, OnCreateMarkTool); - _eventFactory.AddEventListener(EventEnum.OnSelectMark, OnSelectMarkTool); - _eventFactory.AddEventListener(EventEnum.OnDeleteMark, OnDeleteMarkTool); - _eventFactory.AddEventListener(EventEnum.OnSetMarkVisible, OnSetMarkVisible); - _eventFactory.AddEventListener(EventEnum.OnEditMark, OnEditMarkTool); - _eventFactory.AddEventListener(EventEnum.OnSelectPreinstall, RefreshMark); + //工具栏网格 + _toolGrid = new UiGrid(S_ToolButton, typeof(ToolButtonCell)); + _toolGrid.SetColumns(15); + + CustomNormalRoot = new Node2D(); + CustomNormalRoot.ZIndex = -1; + EditorMap.AddChild(CustomNormalRoot); + CustomYSortRoot = new Node2D(); + EditorMap.AddChild(CustomYSortRoot); + + //标记相关 + AddEventListener(EventEnum.OnSelectWave, OnSelectWaveTool); + AddEventListener(EventEnum.OnCreateMark, OnCreateMarkTool); + AddEventListener(EventEnum.OnSelectMark, OnSelectMarkTool); + AddEventListener(EventEnum.OnDeleteMark, OnDeleteMarkTool); + AddEventListener(EventEnum.OnSetMarkVisible, OnSetMarkVisible); + AddEventListener(EventEnum.OnEditMark, OnEditMarkTool); + AddEventListener(EventEnum.OnSelectPreinstall, RefreshMark); + + //自定义物体相关 + AddEventListener(EventEnum.OnPutObject, OnPutObject); + AddEventListener(EventEnum.OnRemoveObject, OnRemoveObject); + AddEventListener(EventEnum.OnSelectObject, OnSelectObject); + + //保存预览图相关 + AddEventListener(EventEnum.OnSavePreviewImageBegin, OnSavePreviewImageBegin); + AddEventListener(EventEnum.OnSavePreviewImageFinish, OnSavePreviewImageFinish); } public override void OnDestroyUi() { - _eventFactory.RemoveAllEventListener(); - _eventFactory = null; S_DoorToolTemplate.Instance.QueueFree(); _toolGrid.Destroy(); } + /// + /// 初始化面板数据 + /// + public void InitCustomObjectData() + { + var objectPanel = MapEditorPanel.S_MapEditorObject.Instance; + foreach (var objectInfo in objectPanel.NormalLayerObjects) + { + OnCreateObject(objectInfo, RoomLayerEnum.NormalLayer); + } + + foreach (var objectInfo in objectPanel.YSortLayerObjects) + { + OnCreateObject(objectInfo, RoomLayerEnum.YSortLayer); + } + + if (_missingSet.Count > 0) + { + var str = ""; + foreach (var item in _missingSet) + { + if (str.Length > 0) + { + str += ","; + } + str += item; + } + EditorWindowManager.ShowTips("警告", $"发现存在丢失的自定义物体,id为:{str}"); + } + } + public override void Process(float delta) { S_HoverPreviewRoot.Instance.Visible = ActiveHoverArea != null && !DoorHoverArea.IsDrag; - if (EditorMap.Instance.MouseType == EditorTileMap.MouseButtonType.Edit) + if (EditorMap.ActiveToolType == EditorToolEnum.MarkTool) { S_ToolRoot.Instance.Modulate = new Color(1, 1, 1, 1); } @@ -127,6 +181,134 @@ public partial class MapEditorToolsPanel : MapEditorTools IsOpenPopUps = UiManager.GetUiInstanceCount(UiManager.UiNames.EditorWindow) > 0; } + private void AddToolMapping(EditorToolBase toolBase) + { + _toolMapping.Add(toolBase.EditorToolType, toolBase); + } + + /// + /// 设置当前选择的工具 + /// + public void SetActiviteTool(EditorToolEnum toolEnum) + { + if (IsDestroyed) + { + return; + } + + if (_toolGrid == null) + { + this.CallDelay(0, () => { _SetActiviteTool(toolEnum); }); + } + else + { + _SetActiviteTool(toolEnum); + } + } + + private void _SetActiviteTool(EditorToolEnum toolEnum) + { + var uiCell = _toolGrid.Find(tool => tool.Data.EditorToolType == toolEnum); + if (uiCell != null) + { + uiCell.Click(); + } + } + + /// + /// 设置工具栏按钮 + /// + public void SetToolButton(params EditorToolEnum[] toolEnum) + { + if (IsDestroyed) + { + return; + } + + if (_toolGrid == null) + { + this.CallDelay(0, () => { _SetToolButton(toolEnum); }); + } + else + { + _SetToolButton(toolEnum); + } + } + + public void _SetToolButton(params EditorToolEnum[] toolEnum) + { + _toolGrid.RemoveAll(); + foreach (var editorToolEnum in toolEnum) + { + if (_toolMapping.TryGetValue(editorToolEnum, out var tool)) + { + _toolGrid.Add(tool); + } + } + } + + + //放置自定义物体 + private void OnPutObject(object obj) + { + var info = (RoomObjectInfo)obj; + var layerType = MapEditorPanel.S_MapEditorObject.Instance.GetCurrentObjectLayerEnum(); + OnCreateObject(info, layerType); + } + + /// + /// 移除物体 + /// + private void OnRemoveObject(object obj) + { + var info = (RoomObjectInfo)obj; + if (CustomObjecMapping.TryGetValue(info, out var data)) + { + CustomObjecMapping.Remove(info); + data.Node.QueueFree(); + } + } + + /// + /// 选择物体 + /// + private void OnSelectObject(object obj) + { + SetActiviteTool(EditorToolEnum.ObjectTool); + } + + //创建自定义物体 + private void OnCreateObject(RoomObjectInfo info, RoomLayerEnum layerType) + { + if (ExcelConfig.EditorObject_Map.TryGetValue(info.Id, out var config)) + { + var node = ResourceManager.LoadEditorObject(config); + + var template = S_ObjectTemplate.Clone(); + template.Instance.Visible = true; + template.Instance.Position = new Vector2(info.X, info.Y); + template.Instance.Init(info, node); + template.Instance.Monitorable = (int)layerType == MapEditorPanel.S_MapEditorObject.Instance.S_LayerOption.Instance.Selected; + + switch (layerType) + { + case RoomLayerEnum.NormalLayer: + CustomNormalRoot.AddChild(template.Instance); + CustomObjecMapping.Add(info, new CustonObjectData(info, template, RoomLayerEnum.NormalLayer)); + break; + case RoomLayerEnum.YSortLayer: + CustomYSortRoot.AddChild(template.Instance); + CustomObjecMapping.Add(info, new CustonObjectData(info, template, RoomLayerEnum.YSortLayer)); + break; + } + } + else + { + Debug.LogError($"创建CustomObject没有找到物体配置: {info.Id}!"); + _missingSet.Add(info.Id); + } + } + //刷新标记 private void RefreshMark(object arg) { @@ -155,11 +337,8 @@ public partial class MapEditorToolsPanel : MapEditorTools private void OnSelectWaveTool(object arg) { //选中编辑工具 - if (_toolGrid.SelectIndex != _editToolIndex) - { - _toolGrid.Click(_editToolIndex); - } - + SetActiviteTool(EditorToolEnum.MarkTool); + var selectIndex = EditorTileMapManager.SelectWaveIndex; var waveList = EditorTileMapManager.SelectPreinstall.WaveList; for (var i = 0; i < waveList.Count; i++) @@ -202,10 +381,7 @@ public partial class MapEditorToolsPanel : MapEditorTools private void OnSelectMarkTool(object arg) { //选中编辑工具 - if (_toolGrid.SelectIndex != _editToolIndex) - { - _toolGrid.Click(_editToolIndex); - } + SetActiviteTool(EditorToolEnum.MarkTool); if (arg is MarkInfo markInfo) { @@ -378,7 +554,7 @@ public partial class MapEditorToolsPanel : MapEditorTools _doorTools.Remove(toolInstance); if (toolInstance.Instance.DoorAreaInfo != null) { - EditorMap.Instance.RemoveDoorArea(toolInstance.Instance.DoorAreaInfo); + EditorMap.RemoveDoorArea(toolInstance.Instance.DoorAreaInfo); } toolInstance.Instance.QueueFree(); //派发修改数据修改事件 @@ -537,4 +713,29 @@ public partial class MapEditorToolsPanel : MapEditorTools _doorTools.Add(doorTool); return doorTool; } + + private void OnSavePreviewImageBegin(object obj) + { + foreach (var custonObjectData in CustomObjecMapping) + { + custonObjectData.Value.Node.L_RectBrush.Instance.Visible = false; + } + + _tempColor1 = CustomNormalRoot.Modulate; + _tempColor2 = CustomYSortRoot.Modulate; + + CustomNormalRoot.Modulate = Colors.White; + CustomYSortRoot.Modulate = Colors.White; + } + + private void OnSavePreviewImageFinish(object obj) + { + foreach (var custonObjectData in CustomObjecMapping) + { + custonObjectData.Value.Node.L_RectBrush.Instance.Visible = true; + } + + CustomNormalRoot.Modulate = _tempColor1; + CustomYSortRoot.Modulate = _tempColor2; + } } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs index 877db035..9eb73605 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs @@ -158,7 +158,7 @@ public partial class MarkAreaTool : Node2D var flag = false; //必须要选中 - if (_toolRoot.UiPanel.EditorMap.Instance.MouseType == EditorTileMap.MouseButtonType.Edit) + if (_toolRoot.UiPanel.EditorMap.ActiveToolType == EditorToolEnum.MarkTool) { var mousePosition = GetLocalMousePosition(); //判断鼠标是否在点上 diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs index 5090139d..f90d7a81 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs @@ -71,7 +71,7 @@ public partial class MarkTool : TextureRect, IUiNodeScript var activeMark = _toolNode.UiPanel.ActiveMark; if ((activeMark == null || (!activeMark.IsDrag && !activeMark.MarkAreaTool.IsDrag)) && !MarkAreaTool.IsDrag && Input.IsMouseButtonPressed(MouseButton.Left) && - _toolNode.UiPanel.EditorMap.Instance.MouseType == EditorTileMap.MouseButtonType.Edit) + _toolNode.UiPanel.EditorMap.ActiveToolType == EditorToolEnum.MarkTool) { _isDown = true; if (_toolNode.UiPanel.ActiveMark != this) diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/ToolButtonCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/ToolButtonCell.cs index 6d84a6fc..f1007b58 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/ToolButtonCell.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/ToolButtonCell.cs @@ -1,15 +1,24 @@ namespace UI.MapEditorTools; -public class ToolButtonCell : UiCell +public class ToolButtonCell : UiCell { public override void OnInit() { CellNode.L_Select.Instance.Visible = false; } - public override void OnSetData(MapEditorToolsPanel.ToolBtnData data) + public override void OnSetData(EditorToolBase data) { CellNode.Instance.TextureNormal = ResourceManager.LoadTexture2D(data.Icon); + CellNode.Instance.TooltipText = data.TipText; + } + + public override void Process(float delta) + { + if (Grid.SelectIndex == Index) + { + Data.Process(delta); + } } public override bool CanSelect() @@ -20,11 +29,17 @@ public class ToolButtonCell : UiCell