diff --git a/DungeonShooting_Godot/prefab/ui/TileSetEditorSegment.tscn b/DungeonShooting_Godot/prefab/ui/TileSetEditorSegment.tscn index b438f78..1928861 100644 --- a/DungeonShooting_Godot/prefab/ui/TileSetEditorSegment.tscn +++ b/DungeonShooting_Godot/prefab/ui/TileSetEditorSegment.tscn @@ -1,10 +1,12 @@ -[gd_scene load_steps=7 format=3 uid="uid://daias2tkvj20c"] +[gd_scene load_steps=9 format=3 uid="uid://daias2tkvj20c"] [ext_resource type="Script" path="res://src/game/ui/tileSetEditorSegment/TileSetEditorSegmentPanel.cs" id="1_to1lc"] [ext_resource type="Script" path="res://src/game/ui/tileSetEditorSegment/TileEditArea.cs" id="2_h43yx"] [ext_resource type="Shader" path="res://resource/material/Grid.gdshader" id="2_t1p2n"] [ext_resource type="Texture2D" uid="uid://uhhfgdhpk7i4" path="res://icon.png" id="2_wr143"] [ext_resource type="Script" path="res://src/game/ui/tileSetEditorSegment/MaskBrush.cs" id="4_ytys0"] +[ext_resource type="Script" path="res://src/game/ui/tileSetEditorSegment/TileSelectedCell.cs" id="6_ebs5u"] +[ext_resource type="Texture2D" uid="uid://bn47bmilcw4x0" path="res://resource/sprite/ui/commonIcon/Select2.png" id="6_g5ey6"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_u3xqn"] shader = ExtResource("2_t1p2n") @@ -34,7 +36,7 @@ [node name="Left" type="Panel" parent="HSplitContainer"] layout_mode = 2 size_flags_horizontal = 3 -size_flags_stretch_ratio = 70.0 +size_flags_stretch_ratio = 68.0 [node name="MarginContainer" type="MarginContainer" parent="HSplitContainer/Left"] layout_mode = 1 @@ -110,7 +112,7 @@ [node name="Right" type="Panel" parent="HSplitContainer"] layout_mode = 2 size_flags_horizontal = 3 -size_flags_stretch_ratio = 30.0 +size_flags_stretch_ratio = 31.0 [node name="MarginContainer" type="MarginContainer" parent="HSplitContainer/Right"] layout_mode = 1 @@ -123,3 +125,64 @@ theme_override_constants/margin_top = 2 theme_override_constants/margin_right = 2 theme_override_constants/margin_bottom = 2 + +[node name="RightBg" type="VBoxContainer" parent="HSplitContainer/Right/MarginContainer"] +layout_mode = 2 +script = ExtResource("6_ebs5u") + +[node name="Label" type="Label" parent="HSplitContainer/Right/MarginContainer/RightBg"] +layout_mode = 2 +text = "已经导入的图块(右键移除):" + +[node name="ScrollContainer" type="ScrollContainer" parent="HSplitContainer/Right/MarginContainer/RightBg"] +layout_mode = 2 +size_flags_vertical = 3 + +[node name="CellButton" type="Button" parent="HSplitContainer/Right/MarginContainer/RightBg/ScrollContainer"] +custom_minimum_size = Vector2(120, 145) +layout_mode = 2 + +[node name="PreviewImage" type="TextureRect" parent="HSplitContainer/Right/MarginContainer/RightBg/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 = -27.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +stretch_mode = 5 + +[node name="CellId" type="Label" parent="HSplitContainer/Right/MarginContainer/RightBg/ScrollContainer/CellButton"] +layout_mode = 1 +anchors_preset = 12 +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_top = -27.0 +offset_bottom = -3.0 +grow_horizontal = 2 +grow_vertical = 0 +theme_override_font_sizes/font_size = 16 +text = "(0,0)" +horizontal_alignment = 1 +vertical_alignment = 1 +clip_text = true +text_overrun_behavior = 1 + +[node name="SelectTexture" type="NinePatchRect" parent="HSplitContainer/Right/MarginContainer/RightBg/ScrollContainer/CellButton"] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +texture = ExtResource("6_g5ey6") +region_rect = Rect2(0, 0, 36, 36) +patch_margin_left = 3 +patch_margin_top = 3 +patch_margin_right = 3 +patch_margin_bottom = 3 diff --git a/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs b/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs index 643a556..48f1b01 100644 --- a/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs +++ b/DungeonShooting_Godot/src/framework/map/DungeonTileMap.cs @@ -416,8 +416,8 @@ /// /// 给TileMap添加轮廓, 该函数为协程函数 /// - /// 描轮廓的Tile - public IEnumerator AddOutlineTile(TileCellInfo tileCellInfo) + /// 描轮廓的Tile + public IEnumerator AddOutlineTile(TileCellData tileCellData) { var c = 0; var rect = _tileRoot.GetUsedRect(); @@ -436,7 +436,7 @@ var flag1 = _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, pos) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, pos) != -1 || _tileRoot.GetCellSourceId(GameConfig.AisleFloorMapLayer, pos) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) != tileCellInfo.AutoTileCoord); + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, pos) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, pos) != tileCellData.AutoTileCoord); if (!flag1) //空地 { var posDown = new Vector2I(pos.X, pos.Y + 1); @@ -451,39 +451,39 @@ var flag2 = _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posDown) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posDown) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posDown) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posDown) != tileCellInfo.AutoTileCoord) || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posDown) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posDown) != tileCellData.AutoTileCoord) || _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posTop) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posTop) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posTop) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posTop) != tileCellInfo.AutoTileCoord) || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posTop) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posTop) != tileCellData.AutoTileCoord) || _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLeft) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLeft) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLeft) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLeft) != tileCellInfo.AutoTileCoord) || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLeft) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLeft) != tileCellData.AutoTileCoord) || _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRight) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRight) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRight) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRight) != tileCellInfo.AutoTileCoord) || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRight) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRight) != tileCellData.AutoTileCoord) || // _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLD) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLD) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLD) != tileCellInfo.AutoTileCoord) || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLD) != tileCellData.AutoTileCoord) || _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posLT) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posLT) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLT) != tileCellInfo.AutoTileCoord) || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posLT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posLT) != tileCellData.AutoTileCoord) || _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRD) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRD) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRD) != tileCellInfo.AutoTileCoord) || + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRD) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRD) != tileCellData.AutoTileCoord) || _tileRoot.GetCellSourceId(GameConfig.FloorMapLayer, posRT) != -1 || _tileRoot.GetCellSourceId(GameConfig.MiddleMapLayer, posRT) != -1 || - (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRT) != tileCellInfo.AutoTileCoord); + (_tileRoot.GetCellSourceId(GameConfig.TopMapLayer, posRT) != -1 && _tileRoot.GetCellAtlasCoords(GameConfig.TopMapLayer, posRT) != tileCellData.AutoTileCoord); if (flag2) //非空地, 那么说明这个点需要填充 WALL_BLOCK { - _tileRoot.SetCell(GameConfig.TopMapLayer, pos, tileCellInfo.Id, tileCellInfo.AutoTileCoord); + _tileRoot.SetCell(GameConfig.TopMapLayer, pos, tileCellData.Id, tileCellData.AutoTileCoord); } } } @@ -491,7 +491,7 @@ } //填充tile区域 - private void FillRect(int layer, TileCellInfo info, Vector2 pos, Vector2 size) + private void FillRect(int layer, TileCellData data, Vector2 pos, Vector2 size) { for (int i = 0; i < size.X; i++) { @@ -502,7 +502,7 @@ { _tempAisleFloorGrid.Set(p, true); } - _tileRoot.SetCell(layer, p, 0, info.AutoTileCoord); + _tileRoot.SetCell(layer, p, 0, data.AutoTileCoord); } } } diff --git a/DungeonShooting_Godot/src/framework/map/TileCellData.cs b/DungeonShooting_Godot/src/framework/map/TileCellData.cs new file mode 100644 index 0000000..8a6f991 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/map/TileCellData.cs @@ -0,0 +1,24 @@ + +using Godot; + +/// +/// 地图cell属性信息 +/// +public class TileCellData +{ + public TileCellData(int id, Vector2I autoTileCoord) + { + Id = id; + AutoTileCoord = autoTileCoord; + } + + /// + /// 在TileSet中的图块id, 也就是sourceId + /// + public int Id; + + /// + /// 如果是图块集, 该属性就表示在图块集的位置 + /// + public Vector2I AutoTileCoord; +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs b/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs deleted file mode 100644 index bd120a6..0000000 --- a/DungeonShooting_Godot/src/framework/map/TileCellInfo.cs +++ /dev/null @@ -1,24 +0,0 @@ - -using Godot; - -/// -/// 地图cell属性信息 -/// -public class TileCellInfo -{ - public TileCellInfo(int id, Vector2I autoTileCoord) - { - Id = id; - AutoTileCoord = autoTileCoord; - } - - /// - /// 在TileSet中的图块id, 也就是sourceId - /// - public int Id; - - /// - /// 如果是图块集, 该属性就表示在图块集的位置 - /// - public Vector2I AutoTileCoord; -} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs index bc51bd0..047bae6 100644 --- a/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs +++ b/DungeonShooting_Godot/src/framework/ui/grid/UiGrid.cs @@ -240,6 +240,22 @@ return _cellList[index]; } + + /// + /// 根据自定义回调查询数据 + /// + public UiCell Find(Func, bool> func) + { + foreach (var uiCell in _cellList) + { + if (func(uiCell)) + { + return uiCell; + } + } + + return null; + } /// /// 设置当前网格组件中的所有 Cell 数据, 性能较低 diff --git a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs index c35d34a..f20e1ee 100644 --- a/DungeonShooting_Godot/src/game/manager/ResourcePath.cs +++ b/DungeonShooting_Godot/src/game/manager/ResourcePath.cs @@ -115,6 +115,7 @@ public const string resource_font_VonwaonBitmap16px_ttf = "res://resource/font/VonwaonBitmap-16px.ttf"; public const string resource_material_Blend_gdshader = "res://resource/material/Blend.gdshader"; public const string resource_material_Blend_tres = "res://resource/material/Blend.tres"; + public const string resource_material_Grid_gdshader = "res://resource/material/Grid.gdshader"; public const string resource_material_Mask_gdshader = "res://resource/material/Mask.gdshader"; public const string resource_material_OffsetVertex_gdshader = "res://resource/material/OffsetVertex.gdshader"; public const string resource_material_Outline_gdshader = "res://resource/material/Outline.gdshader"; diff --git a/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs b/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs index 968d8f3..64b8469 100644 --- a/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs +++ b/DungeonShooting_Godot/src/game/room/AutoTileConfig.cs @@ -7,22 +7,22 @@ /// public class AutoTileConfig { - public TileCellInfo IN_LT = new TileCellInfo(0, new Vector2I(3, 3)); - public TileCellInfo IN_LB = new TileCellInfo(0, new Vector2I(11, 2)); - public TileCellInfo IN_RT = new TileCellInfo(0, new Vector2I(1, 3)); - public TileCellInfo IN_RB = new TileCellInfo(0, new Vector2I(13, 2)); - public TileCellInfo R = new TileCellInfo(0, new Vector2I(1, 3)); - public TileCellInfo L = new TileCellInfo(0, new Vector2I(3, 3)); - public TileCellInfo T = new TileCellInfo(0, new Vector2I(2, 7)); - public TileCellInfo B = new TileCellInfo(0, new Vector2I(2, 2)); - public TileCellInfo Floor = new TileCellInfo(0, new Vector2I(0, 8)); + public TileCellData IN_LT = new TileCellData(0, new Vector2I(3, 3)); + public TileCellData IN_LB = new TileCellData(0, new Vector2I(11, 2)); + public TileCellData IN_RT = new TileCellData(0, new Vector2I(1, 3)); + public TileCellData IN_RB = new TileCellData(0, new Vector2I(13, 2)); + public TileCellData R = new TileCellData(0, new Vector2I(1, 3)); + public TileCellData L = new TileCellData(0, new Vector2I(3, 3)); + public TileCellData T = new TileCellData(0, new Vector2I(2, 7)); + public TileCellData B = new TileCellData(0, new Vector2I(2, 2)); + public TileCellData Floor = new TileCellData(0, new Vector2I(0, 8)); - public TileCellInfo OUT_LT = new TileCellInfo(0, new Vector2I(1, 2)); - public TileCellInfo OUT_LB = new TileCellInfo(0, new Vector2I(1, 7)); - public TileCellInfo OUT_RT = new TileCellInfo(0, new Vector2I(3, 2)); - public TileCellInfo OUT_RB = new TileCellInfo(0, new Vector2I(3, 7)); + public TileCellData OUT_LT = new TileCellData(0, new Vector2I(1, 2)); + public TileCellData OUT_LB = new TileCellData(0, new Vector2I(1, 7)); + public TileCellData OUT_RT = new TileCellData(0, new Vector2I(3, 2)); + public TileCellData OUT_RB = new TileCellData(0, new Vector2I(3, 7)); - public TileCellInfo WALL_BLOCK = new TileCellInfo(0, new Vector2I(2, 3)); + public TileCellData WALL_BLOCK = new TileCellData(0, new Vector2I(2, 3)); private List _middleLayerAtlasCoords = new List() { diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs index 3a5f751..7c25b8e 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs @@ -4,20 +4,35 @@ public partial class TileSetEditorPanel : TileSetEditor { - /// - /// 纹理路径 - /// - public string TexturePath; + // /// + // /// 纹理路径 + // /// + // public string TexturePath { get; private set; } /// /// 纹理 /// - public Texture2D Texture; + public Texture2D Texture { get; private set; } + + /// + /// 纹理的Image对象 + /// + public Image TextureImage { get; private set; } /// /// 背景颜色 /// - public Color BgColor; + public Color BgColor { get; private set; } + + /// + /// Cell 横轴数量 + /// + public int CellHorizontal { get; private set; } + + /// + /// Cell 纵轴数量 + /// + public int CellVertical { get; private set; } /// /// 页签对象 @@ -52,18 +67,54 @@ public override void OnDestroyUi() { TabGrid.Destroy(); + if (TextureImage != null) + { + TextureImage.Dispose(); + } } + /// + /// 初始化数据 + /// public void InitData(TileSetInfo tileSetInfo) { S_Title.Instance.Text = "正在编辑:" + tileSetInfo.Name; - TexturePath = "icon.png"; - Texture = ImageTexture.CreateFromImage(Image.LoadFromFile(TexturePath)); - + SetTexture(ImageTexture.CreateFromImage(Image.LoadFromFile("resource/tileSprite/map1/16x16 dungeon ii wall reconfig v04 spritesheet.png"))); TabGrid.SelectIndex = 0; } + /// + /// 设置纹理 + /// + public void SetTexture(Texture2D texture) + { + Texture = texture; + if (TextureImage != null) + { + TextureImage.Dispose(); + } + TextureImage = texture.GetImage(); + CellHorizontal = texture.GetWidth() / GameConfig.TileCellSize; + CellVertical = texture.GetHeight() / GameConfig.TileCellSize; + } + + /// + /// 设置背景颜色 + /// + public void SetBgColor(Color color) + { + BgColor = color; + } + + /// + /// 将二维位置转换为索引的函数 + /// + public int CellPositionToIndex(Vector2I pos) + { + return pos.Y * CellHorizontal + pos.X; + } + //返回上一级按钮点击 private void OnBackClick() { diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs index 732f083..71def9a 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs @@ -15,7 +15,7 @@ public override void OnCreateUi() { _tileSetEditor = (TileSetEditor.TileSetEditorPanel)ParentUi; - _tileSetEditor.BgColor = S_ImportPreviewBg.Instance.Color; + _tileSetEditor.SetBgColor(S_ImportPreviewBg.Instance.Color); _dragBinder = DragUiManager.BindDrag(S_ImportPreviewBg.Instance, OnDragCallback); @@ -109,7 +109,7 @@ color => { S_ImportPreviewBg.Instance.Color = color; - _tileSetEditor.BgColor = color; + _tileSetEditor.SetBgColor(color); }, //关闭窗口 () => { _isOpenColorPicker = false; } @@ -156,8 +156,7 @@ { Debug.Log("导入文件: " + file); var imageTexture = ImageTexture.CreateFromImage(Image.LoadFromFile(file)); - _tileSetEditor.TexturePath = file; - _tileSetEditor.Texture = imageTexture; + _tileSetEditor.SetTexture(imageTexture); SetTexture(imageTexture); } diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/MaskRectCell.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/MaskRectCell.cs index f842a80..9336e91 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/MaskRectCell.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/MaskRectCell.cs @@ -4,8 +4,31 @@ public class MaskRectCell : UiCell { + public override void OnInit() + { + CellNode.Instance.Draw += OnDraw; + } + public override void OnSetData(bool data) { - CellNode.Instance.Color = data ? new Color(0, 0, 0, 0) : new Color(0, 0, 0, 0.5882353F); + //选择当前cell时显示透明颜色 + CellNode.Instance.Color = data ? new Color(0, 0, 0, 0) : new Color(0, 0, 0, 0.7f); + } + + public override void Process(float delta) + { + CellNode.Instance.QueueRedraw(); + } + + private void OnDraw() + { + if (Data) + { + //选中时绘制轮廓 + CellNode.Instance.DrawRect( + new Rect2(Vector2.Zero, CellNode.Instance.Size), + new Color(0, 1, 1), false, 2 / CellNode.UiPanel.S_TileTexture.Instance.Scale.X + ); + } } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileCell.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileCell.cs new file mode 100644 index 0000000..0ae00ce --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileCell.cs @@ -0,0 +1,50 @@ +using Godot; + +namespace UI.TileSetEditorSegment; + +public class TileCell : UiCell +{ + private Image _image; + private ImageTexture _previewTexture; + + public override void OnInit() + { + CellNode.L_SelectTexture.Instance.Visible = false; + _image = Image.Create(GameConfig.TileCellSize, GameConfig.TileCellSize, false, Image.Format.Rgba8); + _previewTexture = ImageTexture.CreateFromImage(_image); + CellNode.L_PreviewImage.Instance.Texture = _previewTexture; + } + + + public override void OnSetData(Vector2I data) + { + var image = CellNode.UiPanel.EditorPanel.TextureImage; + _image.BlitRect(image, new Rect2I(data * GameConfig.TileCellSizeVector2I, GameConfig.TileCellSizeVector2I), Vector2I.Zero); + _previewTexture.Update(_image); + CellNode.L_CellId.Instance.Text = data.ToString(); + } + + public override void OnDestroy() + { + _previewTexture.Dispose(); + } + + public override void OnSelect() + { + CellNode.L_SelectTexture.Instance.Visible = true; + } + + public override void OnUnSelect() + { + CellNode.L_SelectTexture.Instance.Visible = false; + } + + public override int OnSort(UiCell other) + { + if (Data.Y != other.Data.Y) + { + return Data.Y - other.Data.Y; + } + return Data.X - other.Data.X; + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileEditArea.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileEditArea.cs index 1a2c12c..aedabac 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileEditArea.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileEditArea.cs @@ -7,15 +7,6 @@ private TileSetEditorSegment.LeftBg _leftBg; private DragBinder _dragBinder; private UiGrid _maskGrid; - - /// - /// 网格横轴数量 - /// - public int CellHorizontal { get; private set; } - /// - /// 网格纵轴数量 - /// - public int CellVertical { get; private set; } public void SetUiNode(IUiNode uiNode) { @@ -34,6 +25,7 @@ public void OnDestroy() { _dragBinder.UnBind(); + _maskGrid.Destroy(); } private void OnDrag(DragState state, Vector2 pos) @@ -73,18 +65,52 @@ public override void _Process(double delta) { - if (Input.IsMouseButtonPressed(MouseButton.Left)) + if (Input.IsMouseButtonPressed(MouseButton.Left)) //左键导入 { if (IsMouseInTexture()) { - var cellPos = GetMouseCellPosition(); - var index = CellPositionToIndex(cellPos); - Debug.Log($"cellPos: {cellPos}, index: {index}"); - _maskGrid.UpdateByIndex(index, true); + ImportCell(GetMouseCellPosition()); + } + } + else if (Input.IsMouseButtonPressed(MouseButton.Right)) //右键移除 + { + if (IsMouseInTexture()) + { + RemoveCell(GetMouseCellPosition()); } } } + /// + /// 导入选中的Cell图块 + /// + /// cell位置, 从图块左上角开始 + public void ImportCell(Vector2I cell) + { + var cellIndex = _leftBg.UiPanel.EditorPanel.CellPositionToIndex(cell); + var uiCell = _maskGrid.GetCell(cellIndex); + if (!uiCell.Data) + { + uiCell.SetData(true); + _leftBg.UiPanel.S_RightBg.Instance.ImportCell(cell); + } + } + + /// + /// 移除选中的Cell图块 + /// + /// cell位置, 从图块左上角开始 + public void RemoveCell(Vector2I cell) + { + var cellIndex = _leftBg.UiPanel.EditorPanel.CellPositionToIndex(cell); + var uiCell = _maskGrid.GetCell(cellIndex); + if (uiCell.Data) + { + uiCell.SetData(false); + _leftBg.UiPanel.S_RightBg.Instance.RemoveCell(cell); + } + } + //缩小 private void Shrink() { @@ -144,8 +170,8 @@ //改变TileSet纹理 private void OnChangeTileSetTexture(Texture2D texture) { - var width = texture.GetWidth() / GameConfig.TileCellSize; - var height = texture.GetHeight() / GameConfig.TileCellSize; + var width = _leftBg.UiPanel.EditorPanel.CellHorizontal; + var height = _leftBg.UiPanel.EditorPanel.CellVertical; _maskGrid.RemoveAll(); _maskGrid.SetColumns(width); for (int i = 0; i < width; i++) @@ -190,13 +216,4 @@ var pos = textureRect.GetLocalMousePosition() / GameConfig.TileCellSize; return pos.AsVector2I(); } - - /// - /// 将二维位置转换为索引的函数 - /// - public int CellPositionToIndex(Vector2I pos) - { - var gridWidth = _maskGrid.GetColumns(); - return pos.Y * gridWidth + pos.X; - } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileSelectedCell.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileSelectedCell.cs new file mode 100644 index 0000000..9bd9914 --- /dev/null +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileSelectedCell.cs @@ -0,0 +1,39 @@ +using Godot; + +namespace UI.TileSetEditorSegment; + +public partial class TileSelectedCell : VBoxContainer, IUiNodeScript +{ + private TileSetEditorSegment.RightBg _rightBg; + private UiGrid _grid; + + public void SetUiNode(IUiNode uiNode) + { + _rightBg = (TileSetEditorSegment.RightBg)uiNode; + + _grid = new UiGrid(_rightBg.L_ScrollContainer.L_CellButton, typeof(TileCell)); + _grid.SetCellOffset(new Vector2I(5, 5)); + _grid.SetAutoColumns(true); + _grid.SetHorizontalExpand(true); + } + + public void OnDestroy() + { + _grid.Destroy(); + } + + public void ImportCell(Vector2I cell) + { + _grid.Add(cell); + _grid.Sort(); + } + + public void RemoveCell(Vector2I cell) + { + var uiCell = _grid.Find(c => c.Data == cell); + if (uiCell != null) + { + _grid.RemoveByIndex(uiCell.Index); + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileSetEditorSegment.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileSetEditorSegment.cs index 7b4aa50..561db83 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileSetEditorSegment.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorSegment/TileSetEditorSegment.cs @@ -26,6 +26,7 @@ public sealed override void OnInitNestedUi() { _ = L_HSplitContainer.L_Left.L_MarginContainer.L_LeftBg; + _ = L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg; } @@ -193,10 +194,164 @@ } /// + /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.Label + /// + public class Label : UiNode + { + public Label(TileSetEditorSegmentPanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override Label Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton.PreviewImage + /// + public class PreviewImage : UiNode + { + public PreviewImage(TileSetEditorSegmentPanel uiPanel, Godot.TextureRect node) : base(uiPanel, node) { } + public override PreviewImage Clone() => new (UiPanel, (Godot.TextureRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton.CellId + /// + public class CellId : UiNode + { + public CellId(TileSetEditorSegmentPanel uiPanel, Godot.Label node) : base(uiPanel, node) { } + public override CellId Clone() => new (UiPanel, (Godot.Label)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton.SelectTexture + /// + public class SelectTexture : UiNode + { + public SelectTexture(TileSetEditorSegmentPanel uiPanel, Godot.NinePatchRect node) : base(uiPanel, node) { } + public override SelectTexture Clone() => new (UiPanel, (Godot.NinePatchRect)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton + /// + public class CellButton : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.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 属性获取当前节点实例对象, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellId + /// + public CellId L_CellId + { + get + { + if (_L_CellId == null) _L_CellId = new CellId(UiPanel, Instance.GetNode("CellId")); + return _L_CellId; + } + } + private CellId _L_CellId; + + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.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(TileSetEditorSegmentPanel uiPanel, Godot.Button node) : base(uiPanel, node) { } + public override CellButton Clone() => new (UiPanel, (Godot.Button)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer + /// + public class ScrollContainer : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.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(TileSetEditorSegmentPanel uiPanel, Godot.ScrollContainer node) : base(uiPanel, node) { } + public override ScrollContainer Clone() => new (UiPanel, (Godot.ScrollContainer)Instance.Duplicate()); + } + + /// + /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg + /// + public class RightBg : UiNode + { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.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 属性获取当前节点实例对象, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.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 RightBg(TileSetEditorSegmentPanel uiPanel, UI.TileSetEditorSegment.TileSelectedCell node) : base(uiPanel, node) { } + public override RightBg Clone() => new (UiPanel, (UI.TileSetEditorSegment.TileSelectedCell)Instance.Duplicate()); + } + + /// /// 类型: , 路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer /// public class MarginContainer_1 : UiNode { + /// + /// 使用 Instance 属性获取当前节点实例对象, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.RightBg + /// + public RightBg L_RightBg + { + get + { + if (_L_RightBg == null) _L_RightBg = new RightBg(UiPanel, Instance.GetNode("RightBg")); + return _L_RightBg; + } + } + private RightBg _L_RightBg; + public MarginContainer_1(TileSetEditorSegmentPanel uiPanel, Godot.MarginContainer node) : base(uiPanel, node) { } public override MarginContainer_1 Clone() => new (UiPanel, (Godot.MarginContainer)Instance.Duplicate()); } @@ -295,6 +450,41 @@ public Left S_Left => L_HSplitContainer.L_Left; /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.Label + /// + public Label S_Label => L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg.L_Label; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton.PreviewImage + /// + public PreviewImage S_PreviewImage => L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg.L_ScrollContainer.L_CellButton.L_PreviewImage; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton.CellId + /// + public CellId S_CellId => L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg.L_ScrollContainer.L_CellButton.L_CellId; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton.SelectTexture + /// + public SelectTexture S_SelectTexture => L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg.L_ScrollContainer.L_CellButton.L_SelectTexture; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer.CellButton + /// + public CellButton S_CellButton => L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg.L_ScrollContainer.L_CellButton; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg.ScrollContainer + /// + public ScrollContainer S_ScrollContainer => L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg.L_ScrollContainer; + + /// + /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right.MarginContainer.RightBg + /// + public RightBg S_RightBg => L_HSplitContainer.L_Right.L_MarginContainer.L_RightBg; + + /// /// 场景中唯一名称的节点, 节点类型: , 节点路径: TileSetEditorSegment.HSplitContainer.Right /// public Right S_Right => L_HSplitContainer.L_Right;