diff --git "a/DungeonShooting_Godot/resource/map/tileSet/\346\265\213\350\257\225\346\225\260\346\215\256/TileSet.json" "b/DungeonShooting_Godot/resource/map/tileSet/\346\265\213\350\257\225\346\225\260\346\215\256/TileSet.json" new file mode 100644 index 0000000..7ebecf0 --- /dev/null +++ "b/DungeonShooting_Godot/resource/map/tileSet/\346\265\213\350\257\225\346\225\260\346\215\256/TileSet.json" @@ -0,0 +1,58 @@ +{ + "Name": "\u6D4B\u8BD5\u6570\u636E", + "Sources": [ + { + "Name": "Test", + "SourcePath": null, + "Terrain": { + "_000_010_010": null, + "_010_010_010": null, + "_010_010_000": null, + "_000_010_000": null, + "_000_011_010": null, + "_010_011_010": null, + "_010_011_000": null, + "_000_011_000": null, + "_000_111_010": null, + "_010_111_010": null, + "_010_111_000": null, + "_000_111_000": null, + "_000_110_010": null, + "_010_110_010": null, + "_010_110_000": null, + "_000_110_000": null, + "_110_111_010": null, + "_010_011_011": null, + "_011_011_010": null, + "_010_111_110": null, + "_000_111_011": null, + "_011_111_111": null, + "_111_111_011": null, + "_011_111_000": null, + "_000_111_110": null, + "_110_111_111": null, + "_111_111_110": null, + "_110_111_000": null, + "_011_111_010": null, + "_010_110_110": null, + "_110_110_010": null, + "_010_111_011": null, + "_000_011_011": null, + "_011_011_011": null, + "_011_111_011": null, + "_011_011_000": null, + "_010_111_111": null, + "_110_111_011": null, + "_111_111_111": null, + "_111_111_000": null, + "_000_111_111": null, + "_011_111_110": null, + "_111_111_010": null, + "_000_110_110": null, + "_110_111_110": null, + "_110_110_110": null, + "_110_110_000": null + } + } + ] +} \ No newline at end of file diff --git "a/DungeonShooting_Godot/resource/map/tileSet/\346\265\213\350\257\225\346\225\260\346\215\256/test.png" "b/DungeonShooting_Godot/resource/map/tileSet/\346\265\213\350\257\225\346\225\260\346\215\256/test.png" new file mode 100644 index 0000000..cb64efb --- /dev/null +++ "b/DungeonShooting_Godot/resource/map/tileSet/\346\265\213\350\257\225\346\225\260\346\215\256/test.png" Binary files differ diff --git a/DungeonShooting_Godot/src/framework/map/serialize/tileSet/TileSetSourceInfo.cs b/DungeonShooting_Godot/src/framework/map/serialize/tileSet/TileSetSourceInfo.cs index 2fbd026..5873d44 100644 --- a/DungeonShooting_Godot/src/framework/map/serialize/tileSet/TileSetSourceInfo.cs +++ b/DungeonShooting_Godot/src/framework/map/serialize/tileSet/TileSetSourceInfo.cs @@ -1,5 +1,6 @@ using System.Text.Json.Serialization; +using Godot; /// /// 图集资源数据 @@ -11,18 +12,68 @@ /// [JsonInclude] public string Name; + + /// + /// 资源路径 + /// + [JsonInclude] + public string SourcePath; + + /// + /// 地形配置数据 + /// + [JsonInclude] + public TileSetTerrainInfo Terrain; + [JsonIgnore] + private Image _sourceImage; + [JsonIgnore] + private bool _overWriteImage; + /// /// 初始化默认数据 /// public void InitData() { + Terrain = new TileSetTerrainInfo(); + } + + /// + /// 是否重写过Image + /// + public bool IsOverWriteImage() + { + return _overWriteImage; } + /// + /// 获取资源图像数据 + /// + public Image GetSourceImage() + { + if (_sourceImage == null && string.IsNullOrEmpty(SourcePath)) + { + return null; + } + return _sourceImage ??= Image.LoadFromFile(SourcePath); + } + + /// + /// 设置图像资源 + /// + public void SetSourceImage(Image image) + { + _overWriteImage = true; + _sourceImage = image; + } + public TileSetSourceInfo Clone() { var tileSetSourceInfo = new TileSetSourceInfo(); tileSetSourceInfo.Name = Name; + tileSetSourceInfo.Terrain = Terrain; + tileSetSourceInfo.SourcePath = SourcePath; + tileSetSourceInfo._sourceImage = _sourceImage; return tileSetSourceInfo; } } \ No newline at end of file diff --git a/DungeonShooting_Godot/src/framework/map/serialize/tileSet/TileSetTerrainInfo.cs b/DungeonShooting_Godot/src/framework/map/serialize/tileSet/TileSetTerrainInfo.cs new file mode 100644 index 0000000..8c4b704 --- /dev/null +++ b/DungeonShooting_Godot/src/framework/map/serialize/tileSet/TileSetTerrainInfo.cs @@ -0,0 +1,96 @@ + +using System.Text.Json.Serialization; +using Godot; + +/// +/// 地形配置数据 +/// +public class TileSetTerrainInfo +{ + //第一列 + [JsonInclude] public int[] _000_010_010; + [JsonInclude] public int[] _010_010_010; + [JsonInclude] public int[] _010_010_000; + + [JsonInclude] public int[] _000_010_000; + + //第二列 + [JsonInclude] public int[] _000_011_010; + [JsonInclude] public int[] _010_011_010; + [JsonInclude] public int[] _010_011_000; + + [JsonInclude] public int[] _000_011_000; + + //第三列 + [JsonInclude] public int[] _000_111_010; + [JsonInclude] public int[] _010_111_010; + [JsonInclude] public int[] _010_111_000; + + [JsonInclude] public int[] _000_111_000; + + //第四列 + [JsonInclude] public int[] _000_110_010; + [JsonInclude] public int[] _010_110_010; + [JsonInclude] public int[] _010_110_000; + + [JsonInclude] public int[] _000_110_000; + + //第五列 + [JsonInclude] public int[] _110_111_010; + [JsonInclude] public int[] _010_011_011; + [JsonInclude] public int[] _011_011_010; + + [JsonInclude] public int[] _010_111_110; + + //第六列 + [JsonInclude] public int[] _000_111_011; + [JsonInclude] public int[] _011_111_111; + [JsonInclude] public int[] _111_111_011; + + [JsonInclude] public int[] _011_111_000; + + //第七列 + [JsonInclude] public int[] _000_111_110; + [JsonInclude] public int[] _110_111_111; + [JsonInclude] public int[] _111_111_110; + + [JsonInclude] public int[] _110_111_000; + + //第八列 + [JsonInclude] public int[] _011_111_010; + [JsonInclude] public int[] _010_110_110; + [JsonInclude] public int[] _110_110_010; + + [JsonInclude] public int[] _010_111_011; + + //第九列 + [JsonInclude] public int[] _000_011_011; + [JsonInclude] public int[] _011_011_011; + [JsonInclude] public int[] _011_111_011; + + [JsonInclude] public int[] _011_011_000; + + //第十列 + [JsonInclude] public int[] _010_111_111; + [JsonInclude] public int[] _110_111_011; + [JsonInclude] public int[] _111_111_111; + + [JsonInclude] public int[] _111_111_000; + + //第十一列 + [JsonInclude] public int[] _000_111_111; + [JsonInclude] public int[] _011_111_110; + + [JsonInclude] public int[] _111_111_010; + + //第十二列 + [JsonInclude] public int[] _000_110_110; + [JsonInclude] public int[] _110_111_110; + [JsonInclude] public int[] _110_110_110; + [JsonInclude] public int[] _110_110_000; + + public Vector2I GetPosition(int[] ints) + { + return new Vector2I(ints[0], ints[1]); + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/GameApplication.cs b/DungeonShooting_Godot/src/game/GameApplication.cs index a7229fe..9eda44b 100644 --- a/DungeonShooting_Godot/src/game/GameApplication.cs +++ b/DungeonShooting_Godot/src/game/GameApplication.cs @@ -132,6 +132,7 @@ SceneRoot.AddChild(DungeonManager); MapProjectManager.Init(); + EditorTileSetManager.Init(); BottomTipsPanel.Init(); //打开主菜单Ui UiManager.Open_Main(); diff --git a/DungeonShooting_Godot/src/game/GameConfig.cs b/DungeonShooting_Godot/src/game/GameConfig.cs index 9db0ec4..990b710 100644 --- a/DungeonShooting_Godot/src/game/GameConfig.cs +++ b/DungeonShooting_Godot/src/game/GameConfig.cs @@ -39,6 +39,10 @@ /// public const string RoomTileDir = "resource/map/tileMaps/"; /// + /// 房间TileSet路径 + /// + public const string RoomTileSetDir = "resource/map/tileSet/"; + /// /// 房间组配置文件名称 /// public const string RoomGroupConfigFile = "GroupConfig.json"; diff --git a/DungeonShooting_Godot/src/game/event/EventEnum.cs b/DungeonShooting_Godot/src/game/event/EventEnum.cs index 3b51809..30ca385 100644 --- a/DungeonShooting_Godot/src/game/event/EventEnum.cs +++ b/DungeonShooting_Godot/src/game/event/EventEnum.cs @@ -86,11 +86,11 @@ /// /// 标记房间数据脏了, 也就是数据有修改 /// - OnEditorDirty, + OnTileMapDirty, /// /// 编辑器触发保存, 参数为> /// - OnEditorSave, + OnTileMapSave, /// /// 选中拖拽工具 /// @@ -149,6 +149,14 @@ OnSetMarkVisible, /// + /// 保存TileSet, 参数为 + /// + OnTileSetSave, + /// + /// 标记TileSet脏了, 参数为 + /// + OnTileSetDirty, + /// /// 创建TileSet资源, 参数为 /// OnCreateTileSetSource, diff --git a/DungeonShooting_Godot/src/game/manager/EditorTileSetManager.cs b/DungeonShooting_Godot/src/game/manager/EditorTileSetManager.cs new file mode 100644 index 0000000..7376fdc --- /dev/null +++ b/DungeonShooting_Godot/src/game/manager/EditorTileSetManager.cs @@ -0,0 +1,65 @@ + +using System.IO; +using System.Text.Json; +using Godot; + +public static class EditorTileSetManager +{ + + /// + /// 扫描路径 + /// + public static string CustomMapPath { get; private set; } + + private static bool _init; + + public static void Init() + { + if (_init) + { + return; + } + + _init = true; +#if TOOLS + CustomMapPath = GameConfig.RoomTileSetDir; +#else + CustomMapPath = GameConfig.RoomTileSetDir; +#endif + EventManager.AddEventListener(EventEnum.OnTileSetSave, OnTileSetSave); + } + + //保存图块集 + private static void OnTileSetSave(object o) + { + if (o is TileSetInfo tileSetInfo) + { + var dir = CustomMapPath + tileSetInfo.Name; + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + + var path = dir + "/TileSet.json"; + + //保存json + var options = new JsonSerializerOptions(); + options.WriteIndented = true; + var jsonText = JsonSerializer.Serialize(tileSetInfo, options); + File.WriteAllText(path, jsonText); + + //保存资源 + if (tileSetInfo.Sources != null) + { + foreach (var sourceInfo in tileSetInfo.Sources) + { + if (sourceInfo.IsOverWriteImage()) + { + var image = sourceInfo.GetSourceImage(); + image.SavePng(dir + "/" + sourceInfo.Name + ".png"); + } + } + } + } + } +} \ No newline at end of file diff --git a/DungeonShooting_Godot/src/game/manager/MapProjectManager.cs b/DungeonShooting_Godot/src/game/manager/MapProjectManager.cs index 40d59dd..5dfcc65 100644 --- a/DungeonShooting_Godot/src/game/manager/MapProjectManager.cs +++ b/DungeonShooting_Godot/src/game/manager/MapProjectManager.cs @@ -33,7 +33,7 @@ CustomMapPath = GameConfig.RoomTileDir; //CustomMapPath = ""; #endif - EventManager.AddEventListener(EventEnum.OnEditorSave, OnRoomSave); + EventManager.AddEventListener(EventEnum.OnTileMapSave, OnRoomSave); } //房间保存时回调 diff --git a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs index ae0918b..9d92dae 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditor/tileView/EditorTileMap.cs @@ -178,7 +178,7 @@ _eventFactory.AddEventListener(EventEnum.OnSelectRectTool, OnSelectRectTool); _eventFactory.AddEventListener(EventEnum.OnSelectEditTool, OnSelectEditTool); _eventFactory.AddEventListener(EventEnum.OnClickCenterTool, OnClickCenterTool); - _eventFactory.AddEventListener(EventEnum.OnEditorDirty, OnEditorDirty); + _eventFactory.AddEventListener(EventEnum.OnTileMapDirty, OnEditorDirty); RenderingServer.FramePostDraw += OnFramePostDraw; var navigationRegion = _editorTileMap.L_NavigationRegion.Instance; @@ -478,7 +478,7 @@ IsDirty = false; MapEditorPanel.SetTitleDirty(false); //派发保存事件 - EventManager.EmitEvent(EventEnum.OnEditorSave); + EventManager.EmitEvent(EventEnum.OnTileMapSave); if (finish != null) { finish(); @@ -690,7 +690,7 @@ ClearLayer(AutoMiddleLayer); CloseErrorCell(); //标记有修改数据 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } //重新计算房间区域 diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs index c441c4b..898eccd 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/EditorWaveCell.cs @@ -90,7 +90,7 @@ EventManager.EmitEvent(EventEnum.OnSetMarkVisible, new MarkInfoVisibleData(markInfo, false)); } //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } /// diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs index 9cab651..39554ab 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorMapMark/MapEditorMapMarkPanel.cs @@ -274,7 +274,7 @@ roomSplitPreinstall.Add(preinstall); RefreshPreinstallSelect(roomSplitPreinstall.Count - 1); //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); }); } @@ -292,7 +292,7 @@ var optionButton = S_PreinstallOption.Instance; optionButton.SetItemText(optionButton.Selected, $"{preinstall.Name} ({preinstall.Weight})"); //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); }); } @@ -318,7 +318,7 @@ //刷新选项 RefreshPreinstallSelect(EditorTileMapManager.SelectRoom.Preinstall.Count - 1); //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } }); } @@ -346,7 +346,7 @@ item.WaveList.Add(wave); _grid.Add(wave); //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } //工具节点编辑按钮点击 @@ -407,7 +407,7 @@ _grid.RemoveByIndex(index); EditorTileMapManager.SetSelectWaveIndex(-1); //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } }); } @@ -431,7 +431,7 @@ markCell.Grid.Sort(); EventManager.EmitEvent(EventEnum.OnEditMark, dataMarkInfo); //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); }); } } @@ -470,7 +470,7 @@ waveCell.MarkGrid.RemoveByIndex(markCellIndex); waveCell.Data.Remove(markInfo); //派发数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } }); } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs index 34b2d6f..4dfff22 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorDragArea.cs @@ -420,7 +420,7 @@ DoorAreaInfo.End = doorAreaRange.Y; Debug.Log("提交修改: " + doorAreaRange); //派发修改数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs index 2fcfe26..32da2d8 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/DoorHoverArea.cs @@ -76,7 +76,7 @@ Debug.Log("提交创建: " + direction + ", " + start + ", " + end); _currToolTemplate.Instance.DoorAreaInfo = MapEditorToolsPanel.EditorMap.Instance.CreateDoorArea(direction, start, end); //派发修改数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } //取消提交 diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs index 40d595e..341d0b5 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MapEditorToolsPanel.cs @@ -380,7 +380,7 @@ } toolInstance.Instance.QueueFree(); //派发修改数据修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } /// diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs index b52324f..877db03 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkAreaTool.cs @@ -70,7 +70,7 @@ _startWidth = _markInfo.Size.X; _startHeight = _markInfo.Size.Y; //派发修改事件 - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } IsDrag = false; } diff --git a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs index bb6f72c..5090139 100644 --- a/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs +++ b/DungeonShooting_Godot/src/game/ui/mapEditorTools/MarkTool.cs @@ -61,7 +61,7 @@ if (_startPos != pos) { _startPos = pos; - EventManager.EmitEvent(EventEnum.OnEditorDirty); + EventManager.EmitEvent(EventEnum.OnTileMapDirty); } } } diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs index 5e2a4c2..a87628a 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditor/TileSetEditorPanel.cs @@ -9,9 +9,17 @@ /// 编辑使用的 tileSetInfo 数据 /// public TileSetInfo TileSetInfo { get; private set; } + /// + /// 原始 tileSetInfo 数据 + /// public TileSetInfo OriginTileSetInfo { get; private set; } /// + /// 当前正在使用的 TileSetSourceInfo 数据 + /// + public TileSetSourceInfo TileSetSourceInfo { get; private set; } + + /// /// 是否初始化过纹理 /// public bool InitTexture { get; private set; } @@ -75,6 +83,7 @@ S_DeleteButton.Instance.Pressed += OnDeleteSourceClick; S_AddButton.Instance.Pressed += OnAddSourceClick; S_OptionButton.Instance.ItemSelected += OnOptionChange; + S_Save.Instance.Pressed += OnSaveClick; } public override void OnDestroyUi() @@ -99,9 +108,6 @@ OriginTileSetInfo = tileSetInfo; TileSetInfo = tileSetInfo.Clone(); S_Title.Instance.Text = "正在编辑:" + TileSetInfo.Name; - - //SetTextureData(Image.LoadFromFile("resource/tileSprite/map1/16x16 dungeon ii wall reconfig v04 spritesheet.png")); - //TabGrid.SelectIndex = 0; } /// @@ -109,6 +115,11 @@ /// public void SetTextureData(Image image) { + if (TileSetSourceInfo == null) + { + return; + } + InitTexture = true; Texture.SetImage(image); if (TextureImage != null) @@ -224,12 +235,20 @@ { TabGrid.Visible = true; TabGrid.SelectIndex = 0; + TileSetSourceInfo = TileSetInfo.Sources[(int)index]; } else { TabGrid.Visible = false; TabGrid.SelectIndex = -1; + TileSetSourceInfo = null; } EventManager.EmitEvent(EventEnum.OnSelectTileSetSource); } + + //保存 + private void OnSaveClick() + { + EventManager.EmitEvent(EventEnum.OnTileSetSave, TileSetInfo); + } } diff --git a/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs b/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs index 231aab2..5c9163c 100644 --- a/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs +++ b/DungeonShooting_Godot/src/game/ui/tileSetEditorImport/TileSetEditorImportPanel.cs @@ -175,7 +175,14 @@ /// 纹理路径 private void SetImportTexture(string file) { + if (_tileSetEditor.TileSetSourceInfo == null) + { + return; + } + Debug.Log("导入文件: " + file); - _tileSetEditor.SetTextureData(Image.LoadFromFile(file)); + var image = Image.LoadFromFile(file); + _tileSetEditor.TileSetSourceInfo.SetSourceImage(image); + _tileSetEditor.SetTextureData(image); } }