feat: report ATL problems only for used transforms; animate moving images
CI / frontend (push) Successful in 23s
CI / backend (push) Successful in 1m55s

- Unsupported ATL constructs in a transform now block the import only when the
  transform is used (at clause, another transform, even before its definition).
  Stock screens.rpy transforms for unused screens no longer fail games
- image blocks with one picture plus linear/ease/parallel/repeat keep their
  animation (image-level ATL); the renderer also starts it
- Python: skip @gui.variant/@renpy.variant functions (inactive variants), treat
  @renpy.pure as transparent, read renpy.store.x as x
- Accept renpy.transition, end_replay, block_rollback and music set_pause/set_pan
  as presentation-only no-ops, and implement them in the player (set_pause and
  set_pan were allowed by the converter but missing at runtime)
- Skip the 0x52-URM add-on directory (in-game console / save editor) when
  parsing scripts and media
- Tests for lazy ATL warnings, moving images and variants

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-25 12:20:39 +03:00
1 parent ff82d882c0
commit 4418da47eb
9 files changed
+133 -12

No files matched your search

+31
View File
@@ -164,3 +164,34 @@ def test_atl_frames_layeredimage_and_channels():
"img": {"ref": "eileen_face_happy"}}
assert layers[2]["img"] == {"file": "sad.png"}
assert d.channels["amb"] == {"mixer": "sfx", "loop": True}
def test_moving_image_keeps_its_animation():
d = parse('image spin:\n "mark.png"\n xalign 0.5\n linear 0 rotate 0\n linear 4 rotate -360\n repeat\n')
image = d.images["spin"]
assert image["file"] == "mark.png"
spec = image["at"][0]
assert spec["props"] == {"xalign": 0.5}
assert spec["atl"]["repeat"] is True and spec["atl"]["steps"][-1]["props"] == {"rotate": -360.0}
assert not d.blockers
def test_unused_transforms_with_unsupported_atl_do_not_block():
d = parse("transform spinner(delay, cycle):\n function renpy.display.layout.example\nlabel start:\n 'Hi'\n")
assert not d.blockers
def test_gui_variants_and_renpy_store_are_understood():
d = parse(
"init python:\n"
" @gui.variant\n"
" def small():\n"
" gui.text_size = 30\n"
" @renpy.pure\n"
" def twice(x):\n"
" return x * 2\n"
" renpy.store.seen.append(1)\n")
assert [s["op"] for s in d.init_code] == ["def", "eval"]
assert d.init_code[0]["decos"] == [] and d.init_code[0]["name"] == "twice"
assert d.init_code[1]["e"]["f"]["o"] == {"k": "name", "id": "seen"}
assert not d.blockers