feat: player runs the game's own text tags, layers and camera, real preferences and Color
Layers (config.layers, onlayer, add_layer, show_layer_at, camera with perspective), the
game's config.custom_text_tags called like Ren'Py does (the built-in {bt}/{fi}/... copies
are gone), built-in {font} {alpha} {k} {cps} {a} {rb}/{rt} {space} {alt} {image}, FontGroup,
mouse displayable, renpy.fetch, preferences backed by the player's settings, Color class,
Render.subsurface/zoom, `default obj.attr` on provided objects, and a repaint loop that
survives text being laid out again.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5da7ab1a90
commit
a7034b3563
13 files changed
+1563
-710
No files matched your search
@@ -193,3 +193,83 @@ test("starred items spread into tuples and lists", () => {
|
||||
assert.deepEqual(spread, [1, 2, 3, 4]);
|
||||
} finally { engine.destroy(); }
|
||||
});
|
||||
|
||||
test("pictures on a named layer stay on it, layers stack as config.layers says, and a save keeps both", () => {
|
||||
const { engine } = makeEngine(runtime());
|
||||
try {
|
||||
engine.newStore();
|
||||
engine.config.layers = ["bottom", "master", "screens", "top"];
|
||||
engine.syncLayers();
|
||||
const picture = engine.resolveImage(["background"]);
|
||||
engine.renderer.show(picture, "bg", [], {});
|
||||
engine.renderer.show(picture, "cloud", [], { layer: "top" });
|
||||
engine.renderer.show(picture, "floor", [], { layer: "bottom" });
|
||||
const depth = (name) => Number(engine.renderer.stage.querySelector(`[data-layer=${name}]`).style.zIndex);
|
||||
assert.ok(depth("bottom") < depth("master") && depth("master") < 0 && depth("top") > 0);
|
||||
assert.equal(engine.renderer.isShown("cloud"), false);
|
||||
assert.equal(engine.renderer.isShown("cloud", "top"), true);
|
||||
engine.renderer.layerAt("top", [{ props: { xoffset: 30 } }]);
|
||||
const saved = structuredClone(engine.snapshotState());
|
||||
assert.deepEqual(saved.scene.map((s) => [s.tag, s.layer ?? "master"]).sort(), [["bg", "master"], ["cloud", "top"], ["floor", "bottom"]]);
|
||||
assert.deepEqual(saved.layers, { top: [{ props: { xoffset: 30 } }] });
|
||||
engine.newStore();
|
||||
engine.applySave(saved);
|
||||
assert.equal(engine.renderer.isShown("cloud", "top"), true);
|
||||
assert.equal(engine.renderer.isShown("floor", "bottom"), true);
|
||||
engine.renderer.scene("top");
|
||||
assert.equal(engine.renderer.isShown("cloud", "top"), false);
|
||||
assert.equal(engine.renderer.isShown("bg"), true);
|
||||
} finally { engine.destroy(); }
|
||||
});
|
||||
|
||||
test("a layer added by the game is part of the save and comes back with it", () => {
|
||||
const { engine } = makeEngine(runtime());
|
||||
try {
|
||||
engine.newStore();
|
||||
engine.builtins.renpy.add_layer("hud", { __kw: { above: "master" } });
|
||||
assert.deepEqual(engine.config.layers, ["master", "hud", "transient", "screens", "overlay"]);
|
||||
const saved = structuredClone(engine.snapshotState());
|
||||
engine.newStore();
|
||||
assert.deepEqual(engine.config.layers, ["master", "transient", "screens", "overlay"]);
|
||||
engine.applySave(saved);
|
||||
assert.deepEqual(engine.config.layers, ["master", "hud", "transient", "screens", "overlay"]);
|
||||
} finally { engine.destroy(); }
|
||||
});
|
||||
|
||||
test("preferences are the player's settings", () => {
|
||||
const { engine } = makeEngine(runtime());
|
||||
try {
|
||||
engine.newStore();
|
||||
const prefs = engine.builtins.preferences;
|
||||
assert.equal(prefs.text_cps, engine.settings.cps);
|
||||
prefs.text_cps = 20;
|
||||
assert.equal(engine.settings.cps, 20);
|
||||
prefs.set_volume("music", 0.25);
|
||||
assert.equal(prefs.get_volume("music"), 0.25);
|
||||
prefs.set_mute("music", true);
|
||||
assert.equal(prefs.get_volume("music"), 0);
|
||||
assert.equal(prefs.get_mute("music"), true);
|
||||
prefs.set_mute("music", false);
|
||||
assert.equal(prefs.get_volume("music"), 0.25);
|
||||
engine.py.assignPath("preferences.chaos_on", true); // `default preferences.chaos_on = True`
|
||||
assert.equal(prefs.chaos_on, true);
|
||||
assert.equal(engine.builtins.preferences, prefs);
|
||||
} finally { engine.destroy(); }
|
||||
});
|
||||
|
||||
test("Rollback goes back one interaction", async () => {
|
||||
const { engine } = makeEngine(runtime());
|
||||
try {
|
||||
engine.newStore();
|
||||
engine.running = true;
|
||||
engine.cur = { label: "start", path: [0] };
|
||||
engine.store.n = 1;
|
||||
engine.interactionStart();
|
||||
engine.store.n = 2;
|
||||
engine.cur = { label: "start", path: [0] };
|
||||
engine.interactionStart();
|
||||
assert.equal(engine.rollbackLog.length, 2);
|
||||
engine.rollback();
|
||||
assert.equal(engine.store.n, 1);
|
||||
} finally { engine.destroy(); }
|
||||
});
|
||||
Reference in new issue
Block a user