feat: Kinetic Text Tags letters ({bt} {fi} {sc} {rotat} {glitch}) use the library's own formulas; Flatten; screen 3D
Each letter is moved by one animation loop with the formulas of BounceText, FadeInText, ScareText and GlitchText (fi follows the text speed, bt keeps its phase while a line is typed out, glitch cuts the text into strips that jump sideways). Flatten and `at Flatten` isolate their children as one picture, screens get the 3D turns, matrixtransform and blend of their widgets, and RotateMatrix/OffsetMatrix/ScaleMatrix exist in Python. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5ff43038ae
commit
ea351e44b3
5 files changed
+189
-23
No files matched your search
@@ -9,6 +9,7 @@ import { galleryClass } from "./gallery";
|
||||
import { parseExpression } from "./pyparse";
|
||||
import { movieDisplayable } from "./movie";
|
||||
import { RenderHost, isDisplayableInstance } from "./render";
|
||||
import { Matrix4, blendMode } from "./rendertransform";
|
||||
import { strftime } from "./pymodules";
|
||||
import { OBJECT, PyClass, PyDict, PyInstance, callableOf, nativeMethod, pyEq, pyStr, registerNativeClass, truthy, type Python } from "./python";
|
||||
import type { AtSpec, Expr } from "./types";
|
||||
@@ -1184,6 +1185,13 @@ export class ScreenManager {
|
||||
const name = pyStr(a).replace(/\[([A-Za-z_][\w.]*)\]/g, (_m, source: string) => pyStr(this.host.py.eval(parseExpression(source))));
|
||||
return this.displayable(name, depth + 1);
|
||||
}
|
||||
case "flatten": { // the children are drawn as one picture: opacity and filters then act on the whole
|
||||
const group = document.createElement("div");
|
||||
group.style.isolation = "isolate";
|
||||
const child = this.displayable(a, depth + 1);
|
||||
if (child) group.append(child);
|
||||
return group;
|
||||
}
|
||||
case "animation": { // pictures that take turns; the last one stays when it has no time
|
||||
const box = document.createElement("div");
|
||||
const pictures: HTMLElement[] = [];
|
||||
@@ -1591,7 +1599,14 @@ export class ScreenManager {
|
||||
if (p.xoffset || p.yoffset) parts.push(`translate(${p.xoffset ?? 0}px, ${p.yoffset ?? 0}px)`);
|
||||
if (xz !== 1 || yz !== 1) parts.push(`scale(${xz}, ${yz})`);
|
||||
if (p.rotate) parts.push(`rotate(${p.rotate}deg)`);
|
||||
// 3D turns about the widget's centre (the default matrixanchor) are Ren'Py's own matrices
|
||||
if (p.xrotate || p.yrotate || p.zrotate || p.zpos) {
|
||||
const turn = Matrix4.offset(0, 0, p.zpos ?? 0).mul(Matrix4.rotate(p.xrotate ?? 0, p.yrotate ?? 0, p.zrotate ?? 0));
|
||||
parts.unshift(turn.toCss());
|
||||
}
|
||||
if (p.matrixtransform instanceof Matrix4) parts.unshift(p.matrixtransform.toCss());
|
||||
el.style.transform = parts.join(" ");
|
||||
el.style.mixBlendMode = blendMode(p);
|
||||
if (p.alpha !== undefined) el.style.opacity = String(p.alpha);
|
||||
if (p.rounded !== undefined) { // RoundedCorners(radius): one radius or four (the game's own shader)
|
||||
const radius = Array.isArray(p.rounded) ? p.rounded.map((r: number) => `${r}px`).join(" ") : `${p.rounded}px`;
|
||||
@@ -1600,6 +1615,7 @@ export class ScreenManager {
|
||||
}
|
||||
applyFilters(el, p);
|
||||
};
|
||||
if (specs.some((spec) => spec.name === "Flatten")) el.style.isolation = "isolate"; // `at Flatten`: the widget is one picture
|
||||
for (const spec of specs) {
|
||||
Object.assign(live, spec.props ?? {}, spec.name ? this.host.transform(spec.name) ?? {} : {});
|
||||
}
|
||||
@@ -2027,7 +2043,10 @@ export class ScreenManager {
|
||||
out.Fixed = shape("composite");
|
||||
out.Composite = shape("composite");
|
||||
out.LiveComposite = shape("composite");
|
||||
out.Flatten = (child: any) => child; // flattening only changes how the browser composites, not what is drawn
|
||||
out.Flatten = shape("flatten");
|
||||
out.RotateMatrix = (x: number, y: number, z: number) => Matrix4.rotate(x, y, z);
|
||||
out.OffsetMatrix = (x: number, y: number, z: number) => Matrix4.offset(x, y, z);
|
||||
out.ScaleMatrix = (x: number, y: number, z: number) => Matrix4.scale(x, y, z);
|
||||
out.AlphaMask = shape("alphamask");
|
||||
out.TrackCursor = shape("trackcursor");
|
||||
out.PreviewSlowText = shape("text");
|
||||
|
||||
Reference in new issue
Block a user