Compare commits
3
Commits
eadc7a1157
...
v1.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eaf58c0d38 | ||
|
|
fcdd2a041b | ||
|
|
d50af2e910 |
No files matched your search
@@ -19,7 +19,7 @@ tools/rpg_editor/redo = Redo
|
|||||||
tools/rpg_editor/redo_tip = Redo (Ctrl+Y)
|
tools/rpg_editor/redo_tip = Redo (Ctrl+Y)
|
||||||
tools/rpg_editor/play = Play
|
tools/rpg_editor/play = Play
|
||||||
tools/rpg_editor/play_tip = Save and walk the map from its spawn in the running game
|
tools/rpg_editor/play_tip = Save and walk the map from its spawn in the running game
|
||||||
tools/rpg_editor/play_no_scene = Scene "{0}" is not loaded yet: reload the mods (Ctrl+Shift+R) after creating a map.
|
tools/rpg_editor/play_no_scene = The game does not know scene "{0}": check scenes/{0}.json in the map's mod.
|
||||||
tools/rpg_editor/scene_created = scene {0} created
|
tools/rpg_editor/scene_created = scene {0} created
|
||||||
tools/rpg_editor/section_palette = Palette
|
tools/rpg_editor/section_palette = Palette
|
||||||
tools/rpg_editor/section_map = Map
|
tools/rpg_editor/section_map = Map
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ tools/rpg_editor/redo = Вернуть
|
|||||||
tools/rpg_editor/redo_tip = Вернуть отменённое (Ctrl+Y)
|
tools/rpg_editor/redo_tip = Вернуть отменённое (Ctrl+Y)
|
||||||
tools/rpg_editor/play = Играть
|
tools/rpg_editor/play = Играть
|
||||||
tools/rpg_editor/play_tip = Сохранить и пройтись по карте от точки появления в запущенной игре
|
tools/rpg_editor/play_tip = Сохранить и пройтись по карте от точки появления в запущенной игре
|
||||||
tools/rpg_editor/play_no_scene = Сцена «{0}» ещё не загружена: после создания карты перезагрузите моды (Ctrl+Shift+R).
|
tools/rpg_editor/play_no_scene = Игра не знает сцену «{0}»: проверьте файл scenes/{0}.json в моде карты.
|
||||||
tools/rpg_editor/scene_created = создана сцена {0}
|
tools/rpg_editor/scene_created = создана сцена {0}
|
||||||
tools/rpg_editor/section_palette = Палитра
|
tools/rpg_editor/section_palette = Палитра
|
||||||
tools/rpg_editor/section_map = Карта
|
tools/rpg_editor/section_map = Карта
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ namespace Cthangover.Tools.RpgEditor
|
|||||||
/// (Ctrl+Z / Ctrl+Y); Ctrl+S saves. A new file becomes a map filled with the
|
/// (Ctrl+Z / Ctrl+Y); Ctrl+S saves. A new file becomes a map filled with the
|
||||||
/// first tile of the first tileset, and the first save also writes
|
/// first tile of the first tileset, and the first save also writes
|
||||||
/// <c>scenes/<id>.json</c> when the mod has no such scene, because the
|
/// <c>scenes/<id>.json</c> when the mod has no such scene, because the
|
||||||
/// map id is the scene name.
|
/// map id is the scene name; the game re-reads its scenes right away
|
||||||
|
/// (<see cref="SceneManager.ReloadContent"/>), so "Play" works on a new map
|
||||||
|
/// without a mod reload.
|
||||||
/// <para/>
|
/// <para/>
|
||||||
/// After a save the map is put into the running game's map cache, and a
|
/// After a save the map is put into the running game's map cache, and a
|
||||||
/// world showing it is remounted, so the edit is visible at once; "Play"
|
/// world showing it is remounted, so the edit is visible at once; "Play"
|
||||||
@@ -36,7 +38,6 @@ namespace Cthangover.Tools.RpgEditor
|
|||||||
public partial class RpgMapEditorWindow : ToolWindow
|
public partial class RpgMapEditorWindow : ToolWindow
|
||||||
{
|
{
|
||||||
private const string MapDir = "maps";
|
private const string MapDir = "maps";
|
||||||
private const string SceneDir = "scenes";
|
|
||||||
|
|
||||||
private readonly RpgTextures textures = new();
|
private readonly RpgTextures textures = new();
|
||||||
private readonly Dictionary<RpgEditLayer, Button> layerButtons = new();
|
private readonly Dictionary<RpgEditLayer, Button> layerButtons = new();
|
||||||
@@ -254,6 +255,8 @@ namespace Cthangover.Tools.RpgEditor
|
|||||||
}
|
}
|
||||||
|
|
||||||
var sceneNote = isNew ? EnsureScene() : null;
|
var sceneNote = isNew ? EnsureScene() : null;
|
||||||
|
if (sceneNote != null)
|
||||||
|
SceneManager.ReloadContent();
|
||||||
isNew = false;
|
isNew = false;
|
||||||
MarkClean();
|
MarkClean();
|
||||||
PublishToGame(json);
|
PublishToGame(json);
|
||||||
@@ -264,12 +267,11 @@ namespace Cthangover.Tools.RpgEditor
|
|||||||
/// <summary>Writes <c>scenes/<id>.json</c> for a new map when the mod has none; returns a status suffix.</summary>
|
/// <summary>Writes <c>scenes/<id>.json</c> for a new map when the mod has none; returns a status suffix.</summary>
|
||||||
private string EnsureScene()
|
private string EnsureScene()
|
||||||
{
|
{
|
||||||
var scenePath = SceneDir + "/" + document.Map.ID + ".json";
|
var scene = new SceneFileEntry { ModId = modId, Name = document.Map.ID, RelativePath = SceneFileEntry.PathFor(document.Map.ID) };
|
||||||
if (!string.IsNullOrEmpty(ModFileService.ReadText(modId, scenePath)))
|
if (!string.IsNullOrEmpty(ModFileService.ReadText(modId, scene.RelativePath)))
|
||||||
return null;
|
return null;
|
||||||
var json = "{\n \"name\": \"" + document.Map.ID + "\",\n \"defaultAmbient\": \"\"\n}\n";
|
return SceneFileService.Write(scene)
|
||||||
return ModFileService.WriteText(modId, scenePath, json)
|
? " · " + string.Format(ToolUi.Tr("tools/rpg_editor/scene_created"), scene.RelativePath)
|
||||||
? " · " + string.Format(ToolUi.Tr("tools/rpg_editor/scene_created"), scenePath)
|
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,14 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Cthangover.Core.Bootstrap;
|
using Cthangover.Core.Bootstrap;
|
||||||
|
using Cthangover.Core.Scenes;
|
||||||
using Cthangover.Core.Utils;
|
using Cthangover.Core.Utils;
|
||||||
using Cthangover.Mods.Interface.Tool;
|
using Cthangover.Mods.Interface.Tool;
|
||||||
using Cthangover.Mods.Rpg;
|
using Cthangover.Mods.Rpg;
|
||||||
|
using Cthangover.Tools.Common;
|
||||||
|
using Cthangover.Tools.Services;
|
||||||
|
using Cthangover.Mods.Interface.View;
|
||||||
using Godot;
|
using Godot;
|
||||||
|
|
||||||
namespace Cthangover.Tools.RpgEditor.Tests
|
namespace Cthangover.Tools.RpgEditor.Tests
|
||||||
@@ -11,8 +16,10 @@ namespace Cthangover.Tools.RpgEditor.Tests
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Drives the RPG map editor through its controls like an author: layer
|
/// Drives the RPG map editor through its controls like an author: layer
|
||||||
/// buttons are pressed, the palette and the canvas get mouse events through
|
/// buttons are pressed, the palette and the canvas get mouse events through
|
||||||
/// their <c>gui_input</c> signal, Ctrl+Z goes into the window. The window is
|
/// their <c>gui_input</c> signal, Ctrl+Z goes into the window. That window is
|
||||||
/// freed at the end without saving, so the demo maps never change.
|
/// freed without saving, so the demo maps never change. A second window then
|
||||||
|
/// creates a new map through the file selector's "+" and saves it: the game must
|
||||||
|
/// know the map's scene at once (no mod reload); its files are deleted again.
|
||||||
/// Result line: <c>[TEST_RESULT] name=rpg_editor_edit passed=N failed=M</c>.
|
/// Result line: <c>[TEST_RESULT] name=rpg_editor_edit passed=N failed=M</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class RpgEditorTestDriver : Node
|
public partial class RpgEditorTestDriver : Node
|
||||||
@@ -20,6 +27,7 @@ namespace Cthangover.Tools.RpgEditor.Tests
|
|||||||
private const float TickSeconds = 0.15f;
|
private const float TickSeconds = 0.15f;
|
||||||
private const float TimeoutSeconds = 60f;
|
private const float TimeoutSeconds = 60f;
|
||||||
private const int RockTile = 11;
|
private const int RockTile = 11;
|
||||||
|
private const string NewMap = "zz_editor_test_map";
|
||||||
|
|
||||||
private static readonly Vector2I PaintCell = new(3, 5);
|
private static readonly Vector2I PaintCell = new(3, 5);
|
||||||
private static readonly Vector2I EventCell = new(2, 6);
|
private static readonly Vector2I EventCell = new(2, 6);
|
||||||
@@ -32,6 +40,7 @@ namespace Cthangover.Tools.RpgEditor.Tests
|
|||||||
private RpgMapEditorWindow window;
|
private RpgMapEditorWindow window;
|
||||||
private RpgMapEditorCanvas canvas;
|
private RpgMapEditorCanvas canvas;
|
||||||
private int eventsBefore;
|
private int eventsBefore;
|
||||||
|
private string newMapMod;
|
||||||
|
|
||||||
/// <summary>Creates the driver; <paramref name="shotsDir"/> null disables screenshots.</summary>
|
/// <summary>Creates the driver; <paramref name="shotsDir"/> null disables screenshots.</summary>
|
||||||
public RpgEditorTestDriver(string shotsDir)
|
public RpgEditorTestDriver(string shotsDir)
|
||||||
@@ -115,11 +124,58 @@ namespace Cthangover.Tools.RpgEditor.Tests
|
|||||||
case 4:
|
case 4:
|
||||||
Shot("collision");
|
Shot("collision");
|
||||||
window.QueueFree();
|
window.QueueFree();
|
||||||
|
window = ToolWindow.Open<RpgMapEditorWindow>();
|
||||||
|
step++;
|
||||||
|
return;
|
||||||
|
case 5:
|
||||||
|
canvas = window.FindChildren("*", "", true, false).OfType<RpgMapEditorCanvas>().FirstOrDefault();
|
||||||
|
if (canvas?.Document == null)
|
||||||
|
return;
|
||||||
|
newMapMod = Selector().CurrentMod;
|
||||||
|
DeleteNewMapFiles();
|
||||||
|
Selector().FindChildren("*", "", true, false).OfType<Button>().First(b => b.Text == "+").EmitSignal(BaseButton.SignalName.Pressed);
|
||||||
|
step++;
|
||||||
|
return;
|
||||||
|
case 6:
|
||||||
|
var dialog = window.FindChildren("*", "", true, false).OfType<ConfirmationDialog>().FirstOrDefault();
|
||||||
|
if (dialog == null)
|
||||||
|
return;
|
||||||
|
dialog.FindChildren("*", "", true, false).OfType<LineEdit>().First().Text = NewMap;
|
||||||
|
dialog.EmitSignal(AcceptDialog.SignalName.Confirmed);
|
||||||
|
step++;
|
||||||
|
return;
|
||||||
|
case 7:
|
||||||
|
if (canvas.Document?.Map?.ID != NewMap)
|
||||||
|
return;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Press("tools/common/save");
|
||||||
|
Check(File.Exists(ModFileService.GetWritablePath(newMapMod, "scenes/" + NewMap + ".json")), "the first save of a new map writes its scene");
|
||||||
|
Check(GetTree().Root.GetNodeOrNull<SceneManager>("SceneManager")?.HasScene(NewMap) == true, "the game knows the new map's scene without a mod reload");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
window.QueueFree();
|
||||||
|
DeleteNewMapFiles();
|
||||||
|
SceneManager.ReloadContent();
|
||||||
|
}
|
||||||
Finish();
|
Finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ModFileSelector Selector() => window.FindChildren("*", "", true, false).OfType<ModFileSelector>().First();
|
||||||
|
|
||||||
|
private void DeleteNewMapFiles()
|
||||||
|
{
|
||||||
|
foreach (var file in new[] { "maps/" + NewMap + ".json", "scenes/" + NewMap + ".json" })
|
||||||
|
{
|
||||||
|
var path = ModFileService.GetWritablePath(newMapMod, file);
|
||||||
|
if (path != null && File.Exists(path))
|
||||||
|
File.Delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Press(string key)
|
private void Press(string key)
|
||||||
{
|
{
|
||||||
var text = TranslationServer.Translate(key);
|
var text = TranslationServer.Translate(key);
|
||||||
@@ -173,7 +229,7 @@ namespace Cthangover.Tools.RpgEditor.Tests
|
|||||||
if (string.IsNullOrEmpty(shotsDir) || DisplayServer.GetName() == "headless")
|
if (string.IsNullOrEmpty(shotsDir) || DisplayServer.GetName() == "headless")
|
||||||
return;
|
return;
|
||||||
DirAccess.MakeDirRecursiveAbsolute(shotsDir);
|
DirAccess.MakeDirRecursiveAbsolute(shotsDir);
|
||||||
GetViewport().GetTexture().GetImage()?.SavePng(shotsDir.TrimEnd('/') + "/rpg_editor_" + name + ".png");
|
ViewportCapture.SavePng(GetViewport(), shotsDir.TrimEnd('/') + "/rpg_editor_" + name + ".png");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Finish()
|
private void Finish()
|
||||||
|
|||||||
Reference in new issue
Block a user