Update characters_editor implementation, assets and documentation
This commit is contained in:
1 parent
c975b5ae86
commit
d7250b26b2
28 files changed
+429
-73
No files matched your search
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "Character Editor Test",
|
||||
"description": "GUI test of the character editor in rpg_plus: opens rpg_demo_game's characters, shows the slime's localized name, adds a character with the New button, types its name, health and RPG charset into the form, saves; the game must know the character with its stats and name at once, and the RPG map editor's characters tab must offer it with its charset. The new file and the locale edits are removed again. Activated by --itest=characters_editor_edit with --game=rpg_plus --new (the prologue is clicked through first).",
|
||||
"description": "GUI test of the character editor in rpg_plus: opens rpg_plus_game's characters, shows the slime's localized name, adds a character with the New button, types its name, health and RPG charset into the form, saves; the game must know the character with its stats and name at once. The new file and the locale edits are removed again. Activated by --itest=characters_editor_edit with --game=rpg_plus --new (the prologue is clicked through first).",
|
||||
"sources": [
|
||||
"src/*.cs"
|
||||
],
|
||||
"depends": [
|
||||
"rpg_demo_game>=1",
|
||||
"rpg_plus_game>=1",
|
||||
"rpg_editor>=1"
|
||||
]
|
||||
}
|
||||
@@ -1,38 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Cthangover.Core.Bootstrap;
|
||||
using Cthangover.Core.Characters;
|
||||
using Cthangover.Core.Localization;
|
||||
using Cthangover.Core.Mods;
|
||||
using Cthangover.Core.Mods.Resolvers;
|
||||
using Cthangover.Core.Utils;
|
||||
using Cthangover.Mods.Interface.Tool;
|
||||
using Cthangover.Mods.Interface.View;
|
||||
using Cthangover.Mods.Rpg;
|
||||
using Cthangover.Tools.RpgEditor;
|
||||
using Cthangover.Tools.Services;
|
||||
using Godot;
|
||||
|
||||
namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Cthangover.Core.Bootstrap;
|
||||
using Cthangover.Core.Characters;
|
||||
using Cthangover.Core.Localization;
|
||||
using Cthangover.Core.Mods;
|
||||
using Cthangover.Core.Mods.Resolvers;
|
||||
using Cthangover.Core.Utils;
|
||||
using Cthangover.Mods.Interface.Tool;
|
||||
using Cthangover.Mods.Interface.View;
|
||||
using Cthangover.Tools.Services;
|
||||
using Cthangover.Mods.Rpg.Model;
|
||||
using Cthangover.Tools.RpgEditor;
|
||||
using Godot;
|
||||
|
||||
/// <summary>
|
||||
/// Drives the character editor like an author: the toolbar buttons and the
|
||||
/// form's fields (their change signals), Save. Then the game itself is asked:
|
||||
/// the entity cache must hold the new character with the typed health and its
|
||||
/// action, the translation server its typed name, and the RPG map editor's
|
||||
/// character list must offer it with the typed charset. The new characters
|
||||
/// action, and the translation server its typed name. The new characters
|
||||
/// file is deleted and the mod's locale files are restored afterwards, so
|
||||
/// rpg_demo_game stays as it was.
|
||||
/// rpg_plus_game stays as it was.
|
||||
/// Result line: <c>[TEST_RESULT] name=characters_editor_edit passed=N failed=M</c>.
|
||||
/// </summary>
|
||||
public partial class CharacterEditorTestDriver : Node
|
||||
{
|
||||
private const float TickSeconds = 0.15f;
|
||||
private const float TimeoutSeconds = 60f;
|
||||
private const string Mod = "rpg_demo_game";
|
||||
private const string NewFile = "characters/rpg_demo_game.json";
|
||||
private const string NewId = "rpg_demo_game_new_character";
|
||||
private const string Mod = "rpg_plus_game";
|
||||
private const string NewFile = "characters/rpg_plus_game.json";
|
||||
private const string NewId = "rpg_plus_game_new_character";
|
||||
private const string TypedName = "Тестовый гоблин";
|
||||
|
||||
private readonly List<string> failures = new();
|
||||
@@ -99,8 +98,17 @@ namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
var slime = window.Document.Find("rpg_slime");
|
||||
Check(slime != null, "the demo's characters are listed");
|
||||
window.Select(slime);
|
||||
Check(window.Document.GetText(language, "rpg_demo/character/slime") == TranslationServer.Translate("rpg_demo/character/slime").ToString(),
|
||||
Check(window.Document.GetText(language, "rpg_plus/character/slime") == TranslationServer.Translate("rpg_plus/character/slime").ToString(),
|
||||
$"the form shows the character's name in '{language}'");
|
||||
Check(Row("tools/characters_editor/health").OfType<SpinBox>().First().Editable, "a character without Stats: health is edited");
|
||||
var wolf = window.Document.Find("rpg_wolf");
|
||||
Check(wolf?.Data["Stats"] != null, "the demo's wolf has Stats (its health comes from them)");
|
||||
window.Select(wolf);
|
||||
Check(!Row("tools/characters_editor/health").OfType<SpinBox>().First().Editable
|
||||
&& !Row("tools/characters_editor/attack").OfType<SpinBox>().First().Editable
|
||||
&& !Row("tools/characters_editor/defence").OfType<SpinBox>().First().Editable,
|
||||
"a character with Stats: health, attack and defence are computed, not edited");
|
||||
window.Select(slime);
|
||||
|
||||
Press("tools/entity_editor/new");
|
||||
Check(window.SelectedId == NewId, $"New adds and selects {NewId} (got {window.SelectedId})");
|
||||
@@ -122,8 +130,21 @@ namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
Check(characters.TryGetValue(NewId, out var saved), "the game knows the new character right after saving");
|
||||
Check(saved?.Health == 33 && saved.Actions?.Contains("physics/attack") == true, "with the typed health and its action");
|
||||
Check(TranslationServer.Translate(saved?.Name ?? "-").ToString() == TypedName, $"and the typed name ({saved?.Name})");
|
||||
var offered = RpgCharacterCatalog.Load(new RpgTextures()).FirstOrDefault(e => e.Id == NewId);
|
||||
Check(offered?.Look == "village/slime" && offered.Name == TypedName, $"the RPG map editor offers it with its charset ({offered?.Look})");
|
||||
// plan 14.G7: "Joins the party" writes the join scenario at once; unticking removes it again.
|
||||
var join = window.FindChildren("JoinsParty", "", true, false).OfType<CheckBox>().FirstOrDefault();
|
||||
Check(join != null && !join.Disabled && !join.ButtonPressed, "a new character can join the party (its check box is free and off)");
|
||||
Check(!CompanionScenario.Exists(Mod, NewId), "no join scenario before the tick");
|
||||
join.ButtonPressed = true;
|
||||
var joinText = ModFileService.ReadText(Mod, CompanionScenario.Path(Mod, NewId)) ?? string.Empty;
|
||||
Check(joinText.Contains("flag " + NewId + "_joined 1") && joinText.Contains("action party.add id=" + NewId) && !joinText.Contains("\r"),
|
||||
"the tick writes the join scenario (flag, party.add, LF lines)");
|
||||
join.ButtonPressed = false;
|
||||
Check(!CompanionScenario.Exists(Mod, NewId), "the untick removes the join scenario");
|
||||
// phase 8 (claude_plan.md E4): the RPG map editor opens beside the characters and its actor palette has rows.
|
||||
// It does not list characters yet (plan 12.4 leaves that to a later step), so the new character is not checked there.
|
||||
var rpgEditor = ToolWindow.Open<RpgEditorWindow>();
|
||||
Check(rpgEditor.Palette.Count(RpgObjectForm.Actor) > 0, "the RPG map editor opens and its palette lists actors");
|
||||
rpgEditor.QueueFree();
|
||||
var written = ModFileService.ReadText(Mod, NewFile) ?? string.Empty;
|
||||
Check(written.Contains("\"Kind\": \"character\"") && !written.Contains("\r"), "the new file declares its kind and has LF lines");
|
||||
Check(characterFiles.All(f => ModFileService.ReadText(Mod, f.Key) == f.Value), "the demo's character files are untouched");
|
||||
@@ -166,6 +187,7 @@ namespace Cthangover.Tools.CharactersEditor.Tests
|
||||
var path = ModFileService.GetWritablePath(Mod, NewFile);
|
||||
if (path != null && File.Exists(path))
|
||||
File.Delete(path);
|
||||
CompanionScenario.Remove(Mod, NewId);
|
||||
foreach (var backup in backups)
|
||||
ModFileService.WriteText(Mod, backup.Key, backup.Value);
|
||||
ModManager.Instance.GetResolver<EntityResolver>()?.ClearCache();
|
||||
|
||||
Reference in new issue
Block a user