From c41b84142ae598dbcf91365342636b8346f5642a Mon Sep 17 00:00:00 2001 From: DazedAnon Date: Sun, 26 Jul 2026 13:18:18 -0500 Subject: [PATCH] Context aware skills for TL Images Skill --- data/help/05-other-tabs.md | 3 ++- data/skills/image_translation.md | 31 +++++++++++++++------------- docs/image-manager-engine-plan.md | 3 +++ gui/rpgmaker_image_manager.py | 4 ++++ gui/skills_tab.py | 4 ++-- modules/rpgmakermvmz.py | 18 ++++++++-------- tests/test_image_manager.py | 2 ++ tests/test_rpgmaker_image_manager.py | 23 +++++++++++++++++++++ util/image_manager.py | 15 ++++++++++++++ 9 files changed, 77 insertions(+), 26 deletions(-) diff --git a/data/help/05-other-tabs.md b/data/help/05-other-tabs.md index 9c4e727..8081f9e 100644 --- a/data/help/05-other-tabs.md +++ b/data/help/05-other-tabs.md @@ -26,7 +26,8 @@ folder containing loose PNGs. 1. Use **Decrypt** for RPG Maker assets or **Make editable** for ordinary PNGs. Editable copies mirror their game-relative paths under `.dazedtl/images/`. 2. Click **Copy skill** and paste the scoped bitmap-localization instructions into your coding - agent. + agent. The shared workflow automatically receives RPG Maker or Generic-specific guidance from + the active image profile. 3. Review the edited PNGs here. 4. Patch highlighted images, or clear highlights to patch every editable PNG. diff --git a/data/skills/image_translation.md b/data/skills/image_translation.md index 74373b1..90201ad 100644 --- a/data/skills/image_translation.md +++ b/data/skills/image_translation.md @@ -1,16 +1,20 @@ # Localize Editable Bitmap UI -Translate player-visible source-language text embedded in the editable RPG Maker bitmap UI -assets under this folder, recursively: +Translate player-visible source-language text embedded in the editable bitmap UI assets for the +{{ENGINE_NAME}} image profile under this folder, recursively: `{{EDITABLE_IMAGES_FOLDER}}` -Use this game project as read-only context for vocabulary, image usages, event data, plugins, -scripts, runtime coordinates, scaling, opacity, and dynamic values: +Use this game or project folder as read-only context for vocabulary, image usages, scripts, data, +runtime coordinates, scaling, opacity, and dynamic values: `{{GAME_ROOT}}` +Apply this engine-profile guidance: + +{{ENGINE_CONTEXT}} + Use this file as the authoritative glossary for every translation: `{{VOCAB_FILE}}` @@ -26,10 +30,10 @@ backups and temporary candidates outside the editable image folder so they canno patchable assets. Work through all editable PNGs without asking for confirmation unless a hard safety rule below requires review. -Runtime assets may be read, decoded, or decrypted in memory or into an isolated temporary -directory when needed to reconstruct an editable image. This does not authorize modifying those -runtime assets. Prefer the project's own clean source layers over attempting to recover artwork -from a flattened text-bearing PNG. +Runtime assets may be read or decoded in memory or into an isolated temporary directory when +needed to reconstruct an editable image, when permitted by the engine-profile guidance. This does +not authorize modifying those runtime assets. Prefer the project's own clean source layers over +attempting to recover artwork from a flattened text-bearing PNG. Translate embedded bitmap text by reconstructing the smallest safe UI regions and rendering @@ -110,9 +114,8 @@ clean version of every covered visual element. Check: - Runtime images with matching prefixes, encounter numbers, abbreviations, or character names. - Enemy battlers, recollections, cut-ins, gallery images, portraits, and layered battle sprites. - Alternate pages or variants that reveal how the same composition is assembled. -- Event and script references that map an editable filename to a runtime encounter or asset. -- RPG Maker encrypted image files. Read the project encryption key and decode a copy in memory - or a temporary directory when required; never alter the encrypted original. +- Code, data, scene, or script references that map an editable filename to a runtime use. +- Additional runtime variants or source layers made accessible by the engine-profile guidance. Build an explicit mapping from each editable variant to its clean source art. Preserve semantic and progression differences: for example, use the enemy icon on introductory pages and the @@ -125,8 +128,8 @@ clone over, or cover the flattened artwork first. ### 5. Inspect runtime drawing logic -Search the read-only game project for every image filename and the code or event data that -displays it. Determine: +Search the read-only game or project folder for every image filename and any code, data, scene, +or script definition that displays it. Determine: - Image position, scale, and runtime opacity. - Runtime-drawn counters, percentages, names, or other values. @@ -248,7 +251,7 @@ effect stack and visual prominence. ### 11. Protect dynamic values -Reserve the exact runtime-drawn areas discovered from source code or event data. Test likely +Reserve the exact runtime-drawn areas discovered from available project or runtime data. Test likely maximum values such as `0`, `99`, `100`, `999`, and any known project-specific maximum. Ensure translated labels and suffixes cannot collide with right-aligned or centered runtime values. diff --git a/docs/image-manager-engine-plan.md b/docs/image-manager-engine-plan.md index 3dcd431..d66ed52 100644 --- a/docs/image-manager-engine-plan.md +++ b/docs/image-manager-engine-plan.md @@ -37,6 +37,7 @@ An image profile exposes: 5. Creation of editable copies. 6. Runtime-file generation for patching. 7. Capabilities and actionable unsupported-operation errors. +8. A concise context block injected into the shared bitmap-localization skill. Patch delivery is separate from engine encoding. The initial Git/GameUpdate backend publishes engine-built files at their game-relative paths and adds exact @@ -62,6 +63,8 @@ later apply-only and export-folder backends. - Generic mode exposes an image-folder selector constrained to the game root. - Action wording follows capability: RPG Maker uses Decrypt for encrypted assets; generic assets use Make editable. +- Copy skill injects the active engine name and profile guidance into one shared, + engine-neutral bitmap-localization workflow. - The first release keeps the existing All/Editable filters. Baseline metadata provides the foundation for later Modified/Conflict filters without making every ordinary filter operation hash thousands of images on the UI thread. diff --git a/gui/rpgmaker_image_manager.py b/gui/rpgmaker_image_manager.py index 5176da2..d3b00f8 100644 --- a/gui/rpgmaker_image_manager.py +++ b/gui/rpgmaker_image_manager.py @@ -45,6 +45,7 @@ from util.image_manager import ( detect_image_engine, editable_workspace_root, ensure_editable_workspace, + get_image_profile, make_profile_assets_editable, normalize_generic_image_root, prepare_profile_assets_for_patch, @@ -1025,7 +1026,10 @@ class ImageManager(QWidget): if self.game_root is None: raise ValueError("Select a game folder first.") game_root = Path(self.game_root).expanduser().resolve() + profile = get_image_profile(self.engine_id) replacements = { + "{{ENGINE_NAME}}": profile.label, + "{{ENGINE_CONTEXT}}": profile.translation_skill_context, "{{GAME_ROOT}}": str(game_root), "{{EDITABLE_IMAGES_FOLDER}}": str(self._editable_image_root().resolve()), "{{VOCAB_FILE}}": str(game_root / "vocab.txt"), diff --git a/gui/skills_tab.py b/gui/skills_tab.py index d177630..964ca78 100644 --- a/gui/skills_tab.py +++ b/gui/skills_tab.py @@ -124,8 +124,8 @@ class SkillsTab(QWidget): path=SKILLS_DIR / "image_translation.md", hint=( "Clipboard skill copied from the Image Manager for deterministic bitmap UI " - "localisation. Keep the {{GAME_ROOT}}, {{EDITABLE_IMAGES_FOLDER}}, and " - "{{VOCAB_FILE}} placeholders." + "localisation. Keep the {{ENGINE_NAME}}, {{ENGINE_CONTEXT}}, {{GAME_ROOT}}, " + "{{EDITABLE_IMAGES_FOLDER}}, and {{VOCAB_FILE}} placeholders." ), is_json=False, ) diff --git a/modules/rpgmakermvmz.py b/modules/rpgmakermvmz.py index a8c6239..7325b9e 100644 --- a/modules/rpgmakermvmz.py +++ b/modules/rpgmakermvmz.py @@ -148,13 +148,13 @@ TLSYSTEMSWITCHES = False JOIN408 = False # Dialogue / Scroll / Choices (Main Codes) -CODE101 = True -CODE401 = True -CODE405 = True -CODE102 = True +CODE101 = False +CODE401 = False +CODE405 = False +CODE102 = False # Optional -CODE408 = True +CODE408 = False # Variables CODE122 = False @@ -162,14 +162,14 @@ CODE122_VAR_MIN = 0 CODE122_VAR_MAX = 2000 # Plugins / Scripts -CODE355655 = False -CODE357 = False +CODE355655 = True +CODE357 = True CODE657 = False CODE356 = False CODE320 = False CODE324 = False CODE325 = False -CODE111 = False +CODE111 = True CODE108 = False # ─── Plugin Manager ────────────────────────────────────────────────────────── @@ -201,7 +201,7 @@ HEADER_MAPPINGS_357 = { "SceneGlossary": (["category"], None), } # Subset of HEADER_MAPPINGS_357 keys that should be processed (empty = none). -ENABLED_PLUGINS_357: set = {"DTextPicture"} +ENABLED_PLUGINS_357: set = {"BattleLogOutput"} # All known code-355/655 script patterns. Enable entries via ENABLED_PATTERNS_355655. PATTERNS_355655 = { diff --git a/tests/test_image_manager.py b/tests/test_image_manager.py index 844e1dc..1daeaaf 100644 --- a/tests/test_image_manager.py +++ b/tests/test_image_manager.py @@ -169,6 +169,8 @@ class ImageEngineDetectionTests(unittest.TestCase): self.assertTrue(profiles[PROFILE_RPGMAKER_MVMZ].supports_encryption) self.assertFalse(profiles[PROFILE_GENERIC].supports_encryption) self.assertTrue(profiles[PROFILE_GENERIC].configurable_image_root) + self.assertIn("RPG Maker MV/MZ", profiles[PROFILE_RPGMAKER_MVMZ].translation_skill_context) + self.assertNotIn("RPG Maker", profiles[PROFILE_GENERIC].translation_skill_context) def test_detects_rpgmaker_from_system_json_and_img(self): with tempfile.TemporaryDirectory() as raw: diff --git a/tests/test_rpgmaker_image_manager.py b/tests/test_rpgmaker_image_manager.py index 3c02fd7..f2e4d1e 100644 --- a/tests/test_rpgmaker_image_manager.py +++ b/tests/test_rpgmaker_image_manager.py @@ -317,6 +317,9 @@ class RPGMakerImageManagerSelectionTests(unittest.TestCase): self.assertIn(str(self.game_root), prompt) self.assertIn(str(self.game_root / ".dazedtl" / "images" / "img"), prompt) self.assertIn(str(self.game_root / "vocab.txt"), prompt) + self.assertIn("RPG Maker MV/MZ image profile", prompt) + self.assertIn("This is an RPG Maker MV/MZ project", prompt) + self.assertIn("`.rpgmvp` or `.png_`", prompt) self.assertIn("authoritative glossary for every translation", prompt) self.assertIn("deterministic raster backend", prompt) self.assertIn("runtime value locations as protected keepout regions", prompt) @@ -329,6 +332,8 @@ class RPGMakerImageManagerSelectionTests(unittest.TestCase): self.assertNotIn("{{GAME_ROOT}}", prompt) self.assertNotIn("{{EDITABLE_IMAGES_FOLDER}}", prompt) self.assertNotIn("{{VOCAB_FILE}}", prompt) + self.assertNotIn("{{ENGINE_NAME}}", prompt) + self.assertNotIn("{{ENGINE_CONTEXT}}", prompt) self.assertIn( "Copied image translation skill for 1 editable PNG", self.manager.status_label.text(), @@ -440,6 +445,24 @@ class GenericImageManagerUITests(unittest.TestCase): self.assertEqual(manager.image_list.count(), 1) self.assertEqual(manager.assets[0].asset_id, "assets/images/ui/menu.png") self.assertFalse((game_root / ".dazedtl").exists()) + + asset = manager.assets[0] + asset.plain_path.parent.mkdir(parents=True) + asset.plain_path.write_bytes(asset.runtime_plain_path.read_bytes()) + manager._start_scan() + manager._scan_worker.wait(5000) + self.app.processEvents() + QApplication.clipboard().clear() + manager.copy_translation_button.click() + prompt = QApplication.clipboard().text() + + self.assertIn("Generic / Loose Images image profile", prompt) + self.assertIn("manages loose PNG assets", prompt) + self.assertIn("without assuming a particular game engine", prompt) + self.assertNotIn("RPG Maker", prompt) + self.assertNotIn(".rpgmvp", prompt) + self.assertNotIn("{{ENGINE_NAME}}", prompt) + self.assertNotIn("{{ENGINE_CONTEXT}}", prompt) finally: for worker in list(manager._thumbnail_workers): worker.wait(5000) diff --git a/util/image_manager.py b/util/image_manager.py index 6ead55c..2b8067e 100644 --- a/util/image_manager.py +++ b/util/image_manager.py @@ -84,6 +84,7 @@ class ImageEngineProfile: label: str configurable_image_root: bool supports_encryption: bool + translation_skill_context: str supported_extensions: tuple[str, ...] = SUPPORTED_PLAIN_EXTENSIONS @@ -93,12 +94,26 @@ IMAGE_ENGINE_PROFILES = ( "RPG Maker MV/MZ", configurable_image_root=False, supports_encryption=True, + translation_skill_context=( + "This is an RPG Maker MV/MZ project. Runtime images normally live under `img/` or " + "`www/img/`. Inspect event commands, plugins, and scripts for image placement, " + "scaling, opacity, dynamic values, and filename-dependent behavior. Encrypted " + "`.rpgmvp` or `.png_` assets may be decoded read-only with the encryption key from " + "`System.json`; never modify an encrypted runtime original." + ), ), ImageEngineProfile( PROFILE_GENERIC, "Generic / Loose Images", configurable_image_root=True, supports_encryption=False, + translation_skill_context=( + "This profile manages loose PNG assets without assuming a particular game engine. " + "Search available code, data, scenes, and asset references for runtime usage when " + "they exist. If placement, scaling, opacity, or dynamic-value behavior cannot be " + "established, preserve suspicious blank regions and report the uncertainty. Do not " + "attempt archive extraction, bundle rebuilding, or format conversion." + ), ), )