Let the example-game smokes read texts in the game again
Since 89aa92d (#169) a text in the game is drawn as a picture of its
glyphs on a sprite mesh, not as a Pixi `Text`. The test hook
`__gm.locate` only looked for `Text` nodes, so every game text was
invisible to it. The smokes have been red in CI since then (tasks 385
to 395): 5 checks in jumprun, 1 in tetris. The e2e part stayed green,
because it reads editor labels only.
- `textPicture.ts` remembers, per mesh, the text a `TextPicture`
shows, and hands it out through `pictureText(node)`.
- `textProbe.eachText` reads both kinds and passes the text as a
string instead of the Pixi node. `locate`, `locateAll` and
`overlayTexts` use that string.
Tests:
- ./check.sh: 195 files, 2815 tests, CHECK EXIT 0
- smoke-jumprun: ALL PASSED, 24 checks
- smoke-tetris: ALL PASSED, 19 checks
- full e2e run (local): ALL PASSED, 1580 checks, the sum is unchanged
although `locate` now also sees texts in the scene
- counter-check: CI task 395 with the old code, same checks, 6 red
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cab1c0177f
commit
dded62b9f9
3 files changed
+26
-8
No files matched your search
+12
-6
@@ -1,5 +1,6 @@
|
||||
import { type Application, type Container, Graphics, Rectangle, Text } from 'pixi.js';
|
||||
import { Button, Widget } from '../ui';
|
||||
import { pictureText } from '../viewport/textPicture';
|
||||
|
||||
/** The global box of a widget: where it starts, and how large it is. */
|
||||
export function rectOf(widget: { getGlobalPosition(): { x: number; y: number }; w: number; h: number }): {
|
||||
@@ -36,7 +37,7 @@ export interface IconHit {
|
||||
* it the sign-in screen needs, since it exists before there is an editor to ask.
|
||||
*/
|
||||
export function textProbe(app: Application): {
|
||||
eachText: (root: Container, visit: (node: Text, point: { x: number; y: number }) => void) => void;
|
||||
eachText: (root: Container, visit: (text: string, point: { x: number; y: number }) => void) => void;
|
||||
locateAll: (text: string) => { x: number; y: number }[];
|
||||
locate: (text: string, last?: boolean) => { x: number; y: number } | null;
|
||||
locateIcons: (name: string) => IconHit[];
|
||||
@@ -76,14 +77,19 @@ export function textProbe(app: Application): {
|
||||
};
|
||||
walk(root, null, null);
|
||||
};
|
||||
const eachText = (root: Container, visit: (node: Text, point: { x: number; y: number }) => void): void => {
|
||||
const eachText = (
|
||||
root: Container,
|
||||
visit: (text: string, point: { x: number; y: number }) => void,
|
||||
): void => {
|
||||
eachShown(root, (node, clip) => {
|
||||
if (!(node instanceof Text)) return false;
|
||||
// A text object in the game is a picture of its glyphs (#169), not a Pixi `Text`.
|
||||
const text = node instanceof Text ? node.text : pictureText(node);
|
||||
if (text === undefined) return false;
|
||||
// Global bounds, not `width`/`height`: those are unscaled, and inside the graph canvas
|
||||
// (which is scaled by the zoom) that put the point right of the text it was meant to hit.
|
||||
const box = node.getBounds();
|
||||
const point = { x: box.x + box.width / 2, y: box.y + box.height / 2 };
|
||||
if (!clip || clip.contains(point.x, point.y)) visit(node, point);
|
||||
if (!clip || clip.contains(point.x, point.y)) visit(text, point);
|
||||
return true;
|
||||
});
|
||||
};
|
||||
@@ -105,8 +111,8 @@ export function textProbe(app: Application): {
|
||||
/** Centres of every visible text equal to `text`, in drawing order (the topmost last). */
|
||||
const locateAll = (text: string): { x: number; y: number }[] => {
|
||||
const hits: { x: number; y: number }[] = [];
|
||||
eachText(app.stage, (node, point) => {
|
||||
if (node.text === text) hits.push(point);
|
||||
eachText(app.stage, (shown, point) => {
|
||||
if (shown === text) hits.push(point);
|
||||
});
|
||||
return hits;
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user