feat: Ren'Py screens (screen/call screen/show screen) with actions and styles
Converter - screens.py parses the screen language: containers (fixed, frame, vbox, hbox, grid, vpgrid, viewport, button, has), widgets (text, textbutton, imagebutton, add, bar ...), if/for/use/transclude, default, python, key, timer, on, inline ATL, conditional properties, and decompiled forms (unparenthesised operators, glued property values, comma separated actions) - style statements, call/show/hide screen operators and Python-level renpy.show_screen are translated; only screens the game shows are audited, unused stock screens no longer block an import; undefined screens do - ATL values may be computed at run time and transforms take parameters (at blink(0.2, 0.3)); blur property Player - screens.ts builds the DOM from the IR and rebuilds it on state changes; buttons with idle/hover/selected/insensitive states, tooltips, sounds, modal screens, timers and keys that survive re-rendering, saved with the save file - Actions: Jump, Call, Return, SetVariable, Toggle*, SetScreenVariable, Show, Hide, ToggleScreen, Function, Play, Notify, If, Language, ShowMenu, OpenURL ... - Crop/LiveCrop/Solid/Frame/Transform/DynamicDisplayable values, crop property, globals(), renpy.variant/change_language/seen_image, transition stubs Tests: screen parser and runtime (linkedom DOM), screens fixture compiled from tests/fixtures/screens.rpy. Docs: docs/SCREENS.md. Twisted-Thoughts now passes the strict compatibility check. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
47fc121e7d
commit
62ece25902
24 files changed
+2997
-60
No files matched your search
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"screens":{"card":{"params":[{"n":"title","d":null,"kind":"p"}],"props":{},"defaults":[],"body":[{"w":"frame","args":[],"props":{},"body":[{"w":"vbox","args":[],"props":{},"body":[{"w":"text","args":[{"k":"name","id":"title"}],"props":{},"body":[]},{"c":"transclude"}]}]}]},"counter":{"params":[],"props":{},"defaults":[],"body":[{"w":"add","args":[{"k":"const","v":"#fff"}],"props":{"xysize":{"k":"tuple","v":[{"k":"const","v":10},{"k":"const","v":10}]}},"body":[]},{"w":"bar","args":[],"props":{"value":{"k":"call","f":{"k":"name","id":"VariableValue"},"a":[{"k":"const","v":"score"},{"k":"const","v":10}],"kw":{}},"xsize":{"k":"const","v":100},"vertical":{"k":"const","v":false}},"body":[]}]},"deck":{"params":[],"props":{},"defaults":[],"body":[{"c":"use","name":"card","args":[{"k":"const","v":"Deck"}],"kw":{},"body":[{"w":"text","args":[{"k":"bin","op":"+","l":{"k":"const","v":"child "},"r":{"k":"const","v":"one"}}],"props":{},"body":[]},{"w":"textbutton","args":[{"k":"const","v":"Pick"}],"props":{"action":{"k":"call","f":{"k":"name","id":"Return"},"a":[{"k":"const","v":1}],"kw":{}}},"body":[]}]},{"w":"add","args":[{"k":"const","v":"pic.png"}],"props":{"crop":{"k":"tuple","v":[{"k":"const","v":1},{"k":"const","v":2},{"k":"const","v":30},{"k":"const","v":40}]}},"body":[]},{"w":"add","args":[{"k":"const","v":"dot.png"}],"props":{"at":[{"props":{"alpha":0.0},"name":"blink","atl":"blink","args":[{"k":"const","v":0.02},{"k":"const","v":0.02}],"kw":{}}]},"body":[]},{"w":"add","args":[{"k":"const","v":"bg.png"}],"props":{"alpha":{"k":"const","v":0.0},"at":[{"props":{},"atl":{"steps":[{"op":"move","warp":"linear","t":0.1,"props":{"alpha":1.0}}],"repeat":null}}]},"body":[]},{"c":"on","event":"show","action":{"k":"call","f":{"k":"name","id":"SetVariable"},"a":[{"k":"const","v":"shown"},{"k":"const","v":true}],"kw":{}}},{"c":"on","event":"hide","action":{"k":"call","f":{"k":"name","id":"SetVariable"},"a":[{"k":"const","v":"hid"},{"k":"const","v":true}],"kw":{}}},{"w":"text","args":[{"k":"const","v":"x"}],"props":{"pos":{"k":"tuple","v":[{"k":"const","v":5},{"k":"const","v":6}]}},"body":[]},{"w":"vpgrid","args":[],"props":{"cols":{"k":"const","v":2}},"body":[{"w":"text","args":[{"k":"const","v":"a"}],"props":{},"body":[]},{"w":"text","args":[{"k":"const","v":"b"}],"props":{},"body":[]}]},{"w":"textbutton","args":[{"k":"const","v":"Language"}],"props":{"action":{"k":"list","v":[{"k":"call","f":{"k":"name","id":"Language"},"a":[{"k":"const","v":"ru"}],"kw":{}},{"k":"call","f":{"k":"name","id":"ToggleScreen"},"a":[{"k":"const","v":"counter"}],"kw":{}}]}},"body":[]},{"w":"add","args":[{"k":"call","f":{"k":"name","id":"Crop"},"a":[{"k":"tuple","v":[{"k":"const","v":0},{"k":"const","v":0},{"k":"const","v":8},{"k":"const","v":8}]},{"k":"const","v":"sprite.png"}],"kw":{}}],"props":{},"body":[]}]},"hud":{"params":[{"n":"day","d":{"k":"const","v":1},"kind":"p"}],"props":{"tag":{"k":"name","id":"hud"},"zorder":{"k":"const","v":5},"style_prefix":{"k":"const","v":"hud"}},"defaults":[["open",{"k":"const","v":false}]],"body":[{"w":"frame","args":[],"props":{"xalign":{"k":"const","v":0.0},"yalign":{"k":"const","v":0.0}},"body":[{"w":"vbox","args":[],"props":{"spacing":{"k":"const","v":6}},"body":[{"w":"text","args":[{"k":"const","v":"Day [day]"}],"props":{},"body":[]},{"c":"if","branches":[{"c":{"k":"cmp","l":{"k":"name","id":"money"},"ops":[">"],"r":[{"k":"const","v":10}]},"body":[{"w":"text","args":[{"k":"const","v":"Rich"}],"props":{},"body":[]}]},{"c":null,"body":[{"w":"text","args":[{"k":"const","v":"Poor"}],"props":{},"body":[]}]}]},{"c":"for","t":{"k":"name","id":"item"},"it":{"k":"name","id":"inventory"},"body":[{"w":"textbutton","args":[{"k":"name","id":"item"}],"props":{"action":{"k":"call","f":{"k":"name","id":"SetVariable"},"a":[{"k":"const","v":"held"},{"k":"name","id":"item"}],"kw":{}}},"body":[]}]},{"w":"textbutton","args":[{"k":"const","v":"Menu"}],"props":{"action":{"k":"call","f":{"k":"name","id":"ToggleScreenVariable"},"a":[{"k":"const","v":"open"}],"kw":{}},"selected":{"k":"name","id":"open"}},"body":[]},{"c":"if","branches":[{"c":{"k":"name","id":"open"},"body":[{"w":"text","args":[{"k":"const","v":"open!"}],"props":{},"body":[]}]}]},{"w":"textbutton","args":[{"k":"const","v":"Go"}],"props":{"action":{"k":"list","v":[{"k":"call","f":{"k":"name","id":"SetVariable"},"a":[{"k":"const","v":"went"},{"k":"const","v":true}],"kw":{}},{"k":"call","f":{"k":"name","id":"Jump"},"a":[{"k":"const","v":"elsewhere"}],"kw":{}}]}},"body":[]}]}]},{"c":"key","key":{"k":"const","v":"K_h"},"action":{"k":"call","f":{"k":"name","id":"SetVariable"},"a":[{"k":"const","v":"hotkey"},{"k":"const","v":true}],"kw":{}}},{"c":"timer","delay":{"k":"const","v":0.02},"action":{"k":"call","f":{"k":"name","id":"SetVariable"},"a":[{"k":"const","v":"ticked"},{"k":"const","v":true}],"kw":{}},"repeat":null}]},"mood":{"params":[],"props":{},"defaults":[],"body":[{"w":"imagebutton","args":[],"props":{"action":{"k":"tuple","v":[{"k":"call","f":{"k":"name","id":Line truncated
|
||||
Vendored
+94
@@ -0,0 +1,94 @@
|
||||
# Source of screens.json. Regenerate from backend/ with:
|
||||
# python -m tests.make_screens ../frontend/tests/fixtures/screens.rpy ../frontend/tests/fixtures/screens.json
|
||||
|
||||
style hud_text:
|
||||
size 30
|
||||
color "#abc"
|
||||
|
||||
style hud_button:
|
||||
background "#123"
|
||||
hover_background "#456"
|
||||
padding (10, 4)
|
||||
|
||||
transform fade_in:
|
||||
alpha 0.0
|
||||
linear 0.1 alpha 1.0
|
||||
|
||||
screen hud(day=1):
|
||||
tag hud
|
||||
zorder 5
|
||||
style_prefix "hud"
|
||||
default open = False
|
||||
frame:
|
||||
xalign 0.0
|
||||
yalign 0.0
|
||||
vbox:
|
||||
spacing 6
|
||||
text "Day [day]"
|
||||
if money > 10:
|
||||
text "Rich"
|
||||
else:
|
||||
text "Poor"
|
||||
for item in inventory:
|
||||
textbutton item action SetVariable("held", item)
|
||||
textbutton "Menu" action ToggleScreenVariable("open") selected open
|
||||
if open:
|
||||
text "open!"
|
||||
textbutton "Go" action [SetVariable("went", True), Jump("elsewhere")]
|
||||
key "K_h" action SetVariable("hotkey", True)
|
||||
timer 0.02 action SetVariable("ticked", True)
|
||||
|
||||
screen shop(item="none"):
|
||||
modal True
|
||||
imagebutton auto "buy_%s.png" action Return(item) at fade_in
|
||||
textbutton "Cancel" action Return(None) sensitive can_cancel
|
||||
|
||||
screen counter():
|
||||
add "#fff" xysize (10, 10)
|
||||
bar value VariableValue("score", 10) xsize 100
|
||||
|
||||
transform blink(delay, cycle=1.0):
|
||||
alpha 0.0
|
||||
pause delay
|
||||
linear cycle alpha 1.0
|
||||
|
||||
screen card(title):
|
||||
frame:
|
||||
has vbox
|
||||
text title
|
||||
transclude
|
||||
|
||||
screen deck():
|
||||
use card("Deck"):
|
||||
text "child " + "one"
|
||||
textbutton "Pick" action Return(1)
|
||||
add "pic.png" crop(1, 2, 30, 40)
|
||||
add "dot.png" at blink(0.02, 0.02)
|
||||
add "bg.png":
|
||||
alpha 0.0
|
||||
linear 0.1 alpha 1.0
|
||||
on "show" action SetVariable("shown", True)
|
||||
on "hide" action SetVariable("hid", True)
|
||||
text "x" pos(5, 6)
|
||||
vpgrid:
|
||||
cols 2
|
||||
text "a"
|
||||
text "b"
|
||||
textbutton "Language" action [Language("ru"), ToggleScreen("counter")]
|
||||
add Crop((0, 0, 8, 8), "sprite.png")
|
||||
|
||||
screen mood():
|
||||
imagebutton:
|
||||
if money > 10:
|
||||
idle "rich.png"
|
||||
else:
|
||||
idle "poor.png"
|
||||
action SetVariable("mood_clicked", 1), SetVariable("mood_done", True)
|
||||
|
||||
label start:
|
||||
show screen mood
|
||||
show screen deck
|
||||
show screen hud(2)
|
||||
call screen shop("sword")
|
||||
show screen counter
|
||||
return
|
||||
Reference in new issue
Block a user