@moku-labs/game 0.15.8 → 0.15.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/page.d.mts +1 -1
- package/dist/app/page.mjs +1 -1
- package/dist/app/system.d.mts +3 -3
- package/dist/app.d.mts +3 -3
- package/dist/app.mjs +1 -1
- package/dist/assets.d.mts +1 -1
- package/dist/{commands-DWyII1jn.d.mts → commands-DoMH0hnR.d.mts} +5 -5
- package/dist/control.d.mts +4 -4
- package/dist/{define-Bebctfvs.d.mts → define-B8A5IoeS.d.mts} +2 -2
- package/dist/{headless-DobgwTKK.d.mts → headless-CrxofjLt.d.mts} +1 -1
- package/dist/{index-B3dfnsUZ.d.mts → index-PbX7OQIC.d.mts} +3 -3
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +2 -2
- package/dist/inspect.d.mts +6 -6
- package/dist/inspect.mjs +1 -1
- package/dist/jsx-dev-runtime.d.mts +1 -1
- package/dist/jsx-runtime.d.mts +1 -1
- package/dist/{runtime-gnMApclv.d.mts → runtime-Bk_rHR3K.d.mts} +1 -1
- package/dist/{sources-OvHvyeJS.mjs → sources-QCowxSpC.mjs} +1 -1
- package/dist/{src-DNVAJHwd.mjs → src-zXAFOqEc.mjs} +359 -60
- package/dist/testing.d.mts +4 -4
- package/dist/testing.mjs +1 -1
- package/dist/{types-CPxx3NSG.d.mts → types-B73p1XBn.d.mts} +2 -2
- package/dist/{types-BcEtn9XV.d.mts → types-Dr5uC2fS.d.mts} +4 -4
- package/dist/{types-CYoGvBkh.d.mts → types-DwktxRrt.d.mts} +18 -6
- package/dist/{types-Mj75CDO6.d.mts → types-YXykgTOp.d.mts} +2 -2
- package/dist/{types-C4D9UVgb.d.mts → types-i77Nrrv-.d.mts} +29 -16
- package/dist/{visual-2m4wJL_z.mjs → visual-CIUx49C0.mjs} +26 -6
- package/dist/{visual-CxQ4Iqd3.d.mts → visual-CQnurNOj.d.mts} +6 -6
- package/dist/visual.d.mts +1 -1
- package/dist/visual.mjs +1 -1
- package/llms.txt +4 -3
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.mjs";
|
|
|
2
2
|
import { r as systemSource, t as memory } from "./memory-CWlqhS7l.mjs";
|
|
3
3
|
import { a as finishDrafts, i as enableDraftPatches, n as deepFreeze$1, o as openDrafts, r as dropDrafts } from "./drafts-BawpSaVp.mjs";
|
|
4
4
|
import { d as graphHash, f as isRestCheckpoint, h as pushEntry, i as servePaused, l as findNode, m as compact, n as captureFrame, o as collectFlows, p as slotNames, r as serveCaptures, s as describeGraph, t as cancelCaptures, u as framePath } from "./capture-D7XvoHdH.mjs";
|
|
5
|
-
import { A as
|
|
5
|
+
import { A as Now, C as Sprite, E as componentsFor, F as resource, I as system, L as systemsFor, M as Tree, N as component, O as Exiting, R as tag, S as Shape, T as arcDefaults, _ as HudPart, b as OverlayLevel, c as Countdown, d as builtInStyles, g as Display, h as textFor, i as samePose, j as Order, k as Layer, l as Text, m as readStyle, n as drawnRect, o as visualOf$1, r as fitScaleOf, s as visualRectOf, t as CONTENT$1, v as NineSlice, w as Transform, x as Parent, y as Overlay } from "./visual-CIUx49C0.mjs";
|
|
6
6
|
import { a as isDev } from "./dev-BNndV-hU.mjs";
|
|
7
7
|
import { i as isComponentDefinition, n as flatten, r as defineComponent } from "./flatten-BkXuscAV.mjs";
|
|
8
8
|
import { envPlugin, logPlugin } from "@moku-labs/common/browser";
|
|
@@ -16484,8 +16484,9 @@ function writeTakeKeys(record, now, box) {
|
|
|
16484
16484
|
}
|
|
16485
16485
|
/**
|
|
16486
16486
|
* Takes or retakes the picture of a record: stages 1, 2 (when its first filter has inputs) and 3, at the phase of this
|
|
16487
|
-
* frame.
|
|
16488
|
-
* over 4096 device pixels, or a budget that
|
|
16487
|
+
* frame. The bounds are cut to the filter area of the top when it holds one (F43). Refused, and the view drawn live,
|
|
16488
|
+
* for a `Display` in the subtree without `onDemand`, empty bounds, a picture over 4096 device pixels, or a budget that
|
|
16489
|
+
* has no room (P6.3, warned once).
|
|
16489
16490
|
*
|
|
16490
16491
|
* @param kctx - The kept context.
|
|
16491
16492
|
* @param pixi - The module that draws.
|
|
@@ -16498,7 +16499,7 @@ function writeTakeKeys(record, now, box) {
|
|
|
16498
16499
|
function takePicture(kctx, pixi, matrices, record, view, now) {
|
|
16499
16500
|
const { top } = record;
|
|
16500
16501
|
if (!kctx.ctx.config.onDemand && holdsDisplay(kctx, top)) return false;
|
|
16501
|
-
const local = top.getLocalBounds();
|
|
16502
|
+
const local = clippedToArea(top.getLocalBounds(), top.filterArea);
|
|
16502
16503
|
if (isEmptyBounds(local)) return false;
|
|
16503
16504
|
const box = linearBounds(now.a, now.b, now.c, now.d, local);
|
|
16504
16505
|
const x = gridSpan(now.tx + box.x0, now.tx + box.x1, now.rs);
|
|
@@ -16530,6 +16531,27 @@ function takePicture(kctx, pixi, matrices, record, view, now) {
|
|
|
16530
16531
|
return ok;
|
|
16531
16532
|
}
|
|
16532
16533
|
/**
|
|
16534
|
+
* The local bounds of a top cut to its filter area, both in the top's own units: its filters draw nothing outside
|
|
16535
|
+
* the area. With no area the bounds are returned as they are. Pure.
|
|
16536
|
+
*
|
|
16537
|
+
* @param bounds - The top's local bounds.
|
|
16538
|
+
* @param area - The filter area on the top, or none.
|
|
16539
|
+
* @returns The bounds the picture takes.
|
|
16540
|
+
* @example
|
|
16541
|
+
* ```ts
|
|
16542
|
+
* clippedToArea({ minX: 0, minY: 0, maxX: 400, maxY: 400 }, { x: 100, y: 100, width: 40, height: 40 }); // { minX: 100, minY: 100, maxX: 140, maxY: 140 }
|
|
16543
|
+
* ```
|
|
16544
|
+
*/
|
|
16545
|
+
function clippedToArea(bounds, area) {
|
|
16546
|
+
if (area === null || area === void 0) return bounds;
|
|
16547
|
+
return {
|
|
16548
|
+
minX: Math.max(bounds.minX, area.x),
|
|
16549
|
+
minY: Math.max(bounds.minY, area.y),
|
|
16550
|
+
maxX: Math.min(bounds.maxX, area.x + area.width),
|
|
16551
|
+
maxY: Math.min(bounds.maxY, area.y + area.height)
|
|
16552
|
+
};
|
|
16553
|
+
}
|
|
16554
|
+
/**
|
|
16533
16555
|
* Tells whether local bounds hold nothing to draw: no width or no height. Pure.
|
|
16534
16556
|
*
|
|
16535
16557
|
* @param bounds - The bounds of a subtree in its own space.
|
|
@@ -25527,10 +25549,22 @@ function stopOverlays(state) {
|
|
|
25527
25549
|
}
|
|
25528
25550
|
//#endregion
|
|
25529
25551
|
//#region src/plugins/renderer/sync/shape-path.ts
|
|
25552
|
+
/**
|
|
25553
|
+
* @file renderer/sync — the path of a `Shape`: a rectangle, a rounded rectangle or a triangle,
|
|
25554
|
+
* its fill, and its stroke, solid or dashed, or an arc, a stroke alone. A dashed stroke walks the
|
|
25555
|
+
* outline (straight edges, and rounded corners sampled as arcs) and strokes one open line per dash.
|
|
25556
|
+
* An arc runs on the circle inscribed in its box, from 12 o'clock clockwise.
|
|
25557
|
+
*/
|
|
25530
25558
|
/** Chords per rounded corner of a dashed outline: under 0.3 u off the arc at a 48 u radius. */
|
|
25531
25559
|
const CORNER_SAMPLES = 8;
|
|
25532
25560
|
/** The gap between two dashes, as a fraction of the dash length. */
|
|
25533
25561
|
const GAP_RATIO = .5;
|
|
25562
|
+
/** Segments of a full ring: a ring of 28 u across strays under 0.03 u off its circle. */
|
|
25563
|
+
const RING_SEGMENTS = 48;
|
|
25564
|
+
/** The fewest segments of an arc that draws: a sliver still bends. */
|
|
25565
|
+
const ARC_MIN_SEGMENTS = 2;
|
|
25566
|
+
/** 12 o'clock, where an arc starts: Pixi's angles run clockwise from 3 o'clock. */
|
|
25567
|
+
const TWELVE = -Math.PI / 2;
|
|
25534
25568
|
/**
|
|
25535
25569
|
* The corner radius the rectangle is drawn with: Pixi clamps it to half the shorter side.
|
|
25536
25570
|
*
|
|
@@ -25715,8 +25749,9 @@ function dashesOf(outline, dash) {
|
|
|
25715
25749
|
}
|
|
25716
25750
|
/**
|
|
25717
25751
|
* Draws the path of a shape and fills it in a colour at the alpha given. At alpha 0 the path stays unfilled, so only
|
|
25718
|
-
* a stroke shows. A clip mask is drawn here too, never dashed
|
|
25719
|
-
* object's tint, so a colour change draws
|
|
25752
|
+
* a stroke shows. A clip mask is drawn here too, never dashed; the path of an arc here is its box, which is what it
|
|
25753
|
+
* clips its children to. A fill-only shape is drawn white and coloured by the object's tint, so a colour change draws
|
|
25754
|
+
* no path (spec 26 R2.1).
|
|
25720
25755
|
*
|
|
25721
25756
|
* @param object - The graphics to draw on.
|
|
25722
25757
|
* @param value - The shape value.
|
|
@@ -25726,7 +25761,7 @@ function dashesOf(outline, dash) {
|
|
|
25726
25761
|
function drawShapePath(object, value, fillAlpha, color = value.fill) {
|
|
25727
25762
|
object.clear();
|
|
25728
25763
|
if (value.kind === "triangle") object.moveTo(0, 0).lineTo(value.w, value.h / 2).lineTo(0, value.h).closePath();
|
|
25729
|
-
else if (value.radius > 0) object.roundRect(0, 0, value.w, value.h, value.radius);
|
|
25764
|
+
else if (value.kind === "rect" && value.radius > 0) object.roundRect(0, 0, value.w, value.h, value.radius);
|
|
25730
25765
|
else object.rect(0, 0, value.w, value.h);
|
|
25731
25766
|
if (fillAlpha <= 0) return;
|
|
25732
25767
|
object.fill(fillAlpha < 1 ? {
|
|
@@ -25759,6 +25794,102 @@ function strokeShape(object, value) {
|
|
|
25759
25794
|
}
|
|
25760
25795
|
object.stroke(style);
|
|
25761
25796
|
}
|
|
25797
|
+
/**
|
|
25798
|
+
* The share of the circle an arc sweeps, clamped to 0..1: anything not above 0, `NaN` too, is 0; a whole ring when
|
|
25799
|
+
* the value leaves it out.
|
|
25800
|
+
*
|
|
25801
|
+
* @param value - The shape value.
|
|
25802
|
+
* @returns The share.
|
|
25803
|
+
* @example
|
|
25804
|
+
* ```ts
|
|
25805
|
+
* sweepOf({ ...Shape.defaults, kind: "arc", sweep: 1.4 }); // 1
|
|
25806
|
+
* ```
|
|
25807
|
+
*/
|
|
25808
|
+
function sweepOf(value) {
|
|
25809
|
+
const sweep = value.sweep ?? arcDefaults.sweep;
|
|
25810
|
+
if (Number.isNaN(sweep) || sweep <= 0) return 0;
|
|
25811
|
+
return Math.min(sweep, 1);
|
|
25812
|
+
}
|
|
25813
|
+
/**
|
|
25814
|
+
* The radius of the circle an arc runs on: inscribed in the shorter side of its box, inside its stroke.
|
|
25815
|
+
*
|
|
25816
|
+
* @param value - The shape value.
|
|
25817
|
+
* @returns The radius in reference units; 0 or below when the stroke leaves no circle.
|
|
25818
|
+
* @example
|
|
25819
|
+
* ```ts
|
|
25820
|
+
* arcRadiusOf({ ...Shape.defaults, kind: "arc", w: 28, h: 40, strokeWidth: 2 }); // 13
|
|
25821
|
+
* ```
|
|
25822
|
+
*/
|
|
25823
|
+
function arcRadiusOf(value) {
|
|
25824
|
+
return (Math.min(value.w, value.h) - value.strokeWidth) / 2;
|
|
25825
|
+
}
|
|
25826
|
+
/**
|
|
25827
|
+
* Tells whether an arc draws nothing: no stroke width, no sweep, or no circle inside its stroke.
|
|
25828
|
+
*
|
|
25829
|
+
* @param value - The shape value, an arc.
|
|
25830
|
+
* @returns True for an arc whose `Graphics` would hold no instruction.
|
|
25831
|
+
* @example
|
|
25832
|
+
* ```ts
|
|
25833
|
+
* isEmptyArc({ ...Shape.defaults, kind: "arc", w: 28, h: 28, strokeWidth: 2, sweep: 0 }); // true
|
|
25834
|
+
* ```
|
|
25835
|
+
*/
|
|
25836
|
+
function isEmptyArc(value) {
|
|
25837
|
+
return value.strokeWidth <= 0 || sweepOf(value) <= 0 || arcRadiusOf(value) <= 0;
|
|
25838
|
+
}
|
|
25839
|
+
/**
|
|
25840
|
+
* Strokes an arc: from 12 o'clock clockwise over its share of the circle, in segments as many as its angle needs (48
|
|
25841
|
+
* for a ring, at least 2), ended by its `cap`. A full ring is closed and has no ends. Nothing for an empty arc. Drawn
|
|
25842
|
+
* only when the shape changed: never rebuilt per frame.
|
|
25843
|
+
*
|
|
25844
|
+
* @param object - The graphics, cleared.
|
|
25845
|
+
* @param value - The shape value, an arc.
|
|
25846
|
+
*/
|
|
25847
|
+
function strokeArc(object, value) {
|
|
25848
|
+
if (isEmptyArc(value)) return;
|
|
25849
|
+
const sweep = sweepOf(value);
|
|
25850
|
+
const radius = arcRadiusOf(value);
|
|
25851
|
+
const ring = sweep >= 1;
|
|
25852
|
+
const segments = Math.max(ARC_MIN_SEGMENTS, Math.ceil(sweep * RING_SEGMENTS));
|
|
25853
|
+
const step = sweep * 2 * Math.PI / segments;
|
|
25854
|
+
const centreX = value.w / 2;
|
|
25855
|
+
const centreY = value.h / 2;
|
|
25856
|
+
const last = ring ? segments - 1 : segments;
|
|
25857
|
+
object.moveTo(centreX, centreY - radius);
|
|
25858
|
+
for (let index = 1; index <= last; index += 1) {
|
|
25859
|
+
const angle = TWELVE + index * step;
|
|
25860
|
+
object.lineTo(centreX + radius * Math.cos(angle), centreY + radius * Math.sin(angle));
|
|
25861
|
+
}
|
|
25862
|
+
if (ring) {
|
|
25863
|
+
object.closePath();
|
|
25864
|
+
object.stroke({
|
|
25865
|
+
color: value.stroke,
|
|
25866
|
+
width: value.strokeWidth
|
|
25867
|
+
});
|
|
25868
|
+
return;
|
|
25869
|
+
}
|
|
25870
|
+
object.stroke({
|
|
25871
|
+
color: value.stroke,
|
|
25872
|
+
width: value.strokeWidth,
|
|
25873
|
+
cap: value.cap ?? arcDefaults.cap
|
|
25874
|
+
});
|
|
25875
|
+
}
|
|
25876
|
+
/**
|
|
25877
|
+
* Paints a shape on its graphics: an arc as its stroke alone, every other kind as its path, its fill in a colour at its
|
|
25878
|
+
* own fill alpha, and its stroke. The one call that draws a shape's visual.
|
|
25879
|
+
*
|
|
25880
|
+
* @param object - The graphics.
|
|
25881
|
+
* @param value - The shape value.
|
|
25882
|
+
* @param color - The colour of the fill: white for a tinted shape, the value's own otherwise.
|
|
25883
|
+
*/
|
|
25884
|
+
function paintShape(object, value, color) {
|
|
25885
|
+
if (value.kind === "arc") {
|
|
25886
|
+
object.clear();
|
|
25887
|
+
strokeArc(object, value);
|
|
25888
|
+
return;
|
|
25889
|
+
}
|
|
25890
|
+
drawShapePath(object, value, value.fillAlpha, color);
|
|
25891
|
+
strokeShape(object, value);
|
|
25892
|
+
}
|
|
25762
25893
|
//#endregion
|
|
25763
25894
|
//#region src/plugins/renderer/sync/sizing.ts
|
|
25764
25895
|
/**
|
|
@@ -26738,8 +26869,20 @@ function copyClip(drawn, value) {
|
|
|
26738
26869
|
return drawn;
|
|
26739
26870
|
}
|
|
26740
26871
|
/**
|
|
26872
|
+
* Tells whether an arc was drawn with this value already: only what its stroke is built from, its
|
|
26873
|
+
* box, its stroke, its share and its ends. A new fill, fill alpha, radius or dash builds nothing.
|
|
26874
|
+
*
|
|
26875
|
+
* @param drawn - What the graphics was last drawn with, an arc too.
|
|
26876
|
+
* @param value - The arc now.
|
|
26877
|
+
* @returns True when nothing has to be drawn.
|
|
26878
|
+
*/
|
|
26879
|
+
function sameArc(drawn, value) {
|
|
26880
|
+
return drawn.w === value.w && drawn.h === value.h && drawn.stroke === value.stroke && drawn.strokeWidth === value.strokeWidth && drawn.sweep === value.sweep && drawn.cap === value.cap;
|
|
26881
|
+
}
|
|
26882
|
+
/**
|
|
26741
26883
|
* Tells whether a shape's graphics was drawn with this value already: the path, the fill and the
|
|
26742
|
-
* stroke. Its alpha, its clip and the fill of a tinted shape (its tint)
|
|
26884
|
+
* stroke; for an arc only its stroke. Its alpha, its clip and the fill of a tinted shape (its tint)
|
|
26885
|
+
* are written apart.
|
|
26743
26886
|
*
|
|
26744
26887
|
* @param drawn - What the graphics was last drawn with.
|
|
26745
26888
|
* @param value - The shape value now.
|
|
@@ -26747,7 +26890,9 @@ function copyClip(drawn, value) {
|
|
|
26747
26890
|
* @returns True when nothing has to be drawn.
|
|
26748
26891
|
*/
|
|
26749
26892
|
function sameShape$1(drawn, value, tinted) {
|
|
26750
|
-
|
|
26893
|
+
if (drawn === void 0 || drawn.tinted !== tinted || drawn.kind !== value.kind) return false;
|
|
26894
|
+
if (value.kind === "arc") return sameArc(drawn, value);
|
|
26895
|
+
return (tinted || drawn.fill === value.fill) && drawn.w === value.w && drawn.h === value.h && drawn.fillAlpha === value.fillAlpha && drawn.radius === value.radius && drawn.stroke === value.stroke && drawn.strokeWidth === value.strokeWidth && drawn.dash === value.dash && drawn.sweep === value.sweep && drawn.cap === value.cap;
|
|
26751
26896
|
}
|
|
26752
26897
|
/**
|
|
26753
26898
|
* Keeps what a shape's graphics was drawn with, in the object it had, or in a new one the first
|
|
@@ -26760,7 +26905,7 @@ function sameShape$1(drawn, value, tinted) {
|
|
|
26760
26905
|
*/
|
|
26761
26906
|
function copyShape(drawn, value, tinted) {
|
|
26762
26907
|
if (drawn === void 0) {
|
|
26763
|
-
const { kind, w, h, fill, fillAlpha, radius, stroke, strokeWidth, dash } = value;
|
|
26908
|
+
const { kind, w, h, fill, fillAlpha, radius, stroke, strokeWidth, dash, sweep, cap } = value;
|
|
26764
26909
|
return {
|
|
26765
26910
|
tinted,
|
|
26766
26911
|
kind,
|
|
@@ -26771,7 +26916,9 @@ function copyShape(drawn, value, tinted) {
|
|
|
26771
26916
|
radius,
|
|
26772
26917
|
stroke,
|
|
26773
26918
|
strokeWidth,
|
|
26774
|
-
dash
|
|
26919
|
+
dash,
|
|
26920
|
+
sweep,
|
|
26921
|
+
cap
|
|
26775
26922
|
};
|
|
26776
26923
|
}
|
|
26777
26924
|
const copy = drawn;
|
|
@@ -26785,10 +26932,13 @@ function copyShape(drawn, value, tinted) {
|
|
|
26785
26932
|
copy.stroke = value.stroke;
|
|
26786
26933
|
copy.strokeWidth = value.strokeWidth;
|
|
26787
26934
|
copy.dash = value.dash;
|
|
26935
|
+
copy.sweep = value.sweep;
|
|
26936
|
+
copy.cap = value.cap;
|
|
26788
26937
|
return copy;
|
|
26789
26938
|
}
|
|
26790
26939
|
/**
|
|
26791
|
-
* Tells whether a shape draws nothing: no stroke, and no fill alpha or no area
|
|
26940
|
+
* Tells whether a shape draws nothing: no stroke, and no fill alpha or no area; an arc with no stroke, no sweep or no
|
|
26941
|
+
* circle inside its stroke. Pure.
|
|
26792
26942
|
*
|
|
26793
26943
|
* @param value - The shape value.
|
|
26794
26944
|
* @returns True for a shape whose `Graphics` would hold no instruction.
|
|
@@ -26798,6 +26948,7 @@ function copyShape(drawn, value, tinted) {
|
|
|
26798
26948
|
* ```
|
|
26799
26949
|
*/
|
|
26800
26950
|
function isEmptyShape(value) {
|
|
26951
|
+
if (value.kind === "arc") return isEmptyArc(value);
|
|
26801
26952
|
return value.strokeWidth <= 0 && (value.fillAlpha <= 0 || value.w <= 0 || value.h <= 0);
|
|
26802
26953
|
}
|
|
26803
26954
|
/**
|
|
@@ -26815,8 +26966,7 @@ function drawShape(sctx, entity, view, object, value) {
|
|
|
26815
26966
|
const tinted = value.strokeWidth <= 0;
|
|
26816
26967
|
if (!sameShape$1(view.drawn, value, tinted)) {
|
|
26817
26968
|
markView(sctx, entity);
|
|
26818
|
-
|
|
26819
|
-
strokeShape(object, value);
|
|
26969
|
+
paintShape(object, value, tinted ? WHITE$1 : value.fill);
|
|
26820
26970
|
sctx.ctx.state.sync.redraws += 1;
|
|
26821
26971
|
view.drawn = copyShape(view.drawn, value, tinted);
|
|
26822
26972
|
}
|
|
@@ -27201,7 +27351,9 @@ function displayObjectOf(sctx, entity) {
|
|
|
27201
27351
|
}
|
|
27202
27352
|
/**
|
|
27203
27353
|
* Detaches the children of a parent that left, and names the ones that stay. A child that leaves in the same teardown
|
|
27204
|
-
* is no orphan: its view goes in this very pass (it waits in `removed`), or it plays its exit (`Exiting`).
|
|
27354
|
+
* is no orphan: its view goes in this very pass (it waits in `removed`), or it plays its exit (`Exiting`). Nor is a
|
|
27355
|
+
* child whose `Parent` names another entity, or none, by now: it moved in the same frame (a hosted view a restore
|
|
27356
|
+
* hung under the rebuilt host, F44), and the later steps of this pass hang it where it belongs.
|
|
27205
27357
|
*
|
|
27206
27358
|
* @param sctx - Domain context of the sync module.
|
|
27207
27359
|
* @param entity - The parent entity.
|
|
@@ -27209,7 +27361,6 @@ function displayObjectOf(sctx, entity) {
|
|
|
27209
27361
|
*/
|
|
27210
27362
|
function detachChildren(sctx, entity, host) {
|
|
27211
27363
|
const state = sctx.ctx.state.sync;
|
|
27212
|
-
const ecs = sctx.ctx.deps.world.ecs;
|
|
27213
27364
|
const orphans = [];
|
|
27214
27365
|
for (const [child, childView] of state.views) {
|
|
27215
27366
|
if (child === entity) continue;
|
|
@@ -27218,7 +27369,7 @@ function detachChildren(sctx, entity, host) {
|
|
|
27218
27369
|
markView(sctx, child);
|
|
27219
27370
|
detach$1(object);
|
|
27220
27371
|
state.orphans.add(child);
|
|
27221
|
-
if (
|
|
27372
|
+
if (isLostOrphan(sctx, child, entity)) orphans.push(child);
|
|
27222
27373
|
}
|
|
27223
27374
|
if (orphans.length > 0) sctx.ctx.log.warn("renderer: parent left before its children", {
|
|
27224
27375
|
parent: entity,
|
|
@@ -27226,6 +27377,19 @@ function detachChildren(sctx, entity, host) {
|
|
|
27226
27377
|
});
|
|
27227
27378
|
}
|
|
27228
27379
|
/**
|
|
27380
|
+
* Tells whether a child of a parent that left is an orphan worth a warning: it does not go in this pass, it plays no
|
|
27381
|
+
* exit, and its `Parent` still names the parent that left.
|
|
27382
|
+
*
|
|
27383
|
+
* @param sctx - Domain context of the sync module.
|
|
27384
|
+
* @param child - The child entity.
|
|
27385
|
+
* @param parent - The parent that left.
|
|
27386
|
+
* @returns True when the child stays behind with no parent.
|
|
27387
|
+
*/
|
|
27388
|
+
function isLostOrphan(sctx, child, parent) {
|
|
27389
|
+
const ecs = sctx.ctx.deps.world.ecs;
|
|
27390
|
+
return !sctx.ctx.state.sync.removed.has(child) && !isLeaving(ecs, child) && parentOf$1(ecs, child) === parent;
|
|
27391
|
+
}
|
|
27392
|
+
/**
|
|
27229
27393
|
* Takes a view out of the tree and gives its object back to the pool.
|
|
27230
27394
|
*
|
|
27231
27395
|
* @param sctx - Domain context of the sync module.
|
|
@@ -32811,9 +32975,23 @@ function startTrack$1(actx, entity, component, to, options, muted, driven = fals
|
|
|
32811
32975
|
countPlaying(actx.deps.world.ecs, entity, 1);
|
|
32812
32976
|
actx.deps.time.wake();
|
|
32813
32977
|
warnIfCrowded(actx);
|
|
32978
|
+
if (landsAtStart(track, options)) writeFields(actx, track, true);
|
|
32814
32979
|
return track;
|
|
32815
32980
|
}
|
|
32816
32981
|
/**
|
|
32982
|
+
* Tells whether a track writes its target as it starts: an absolute one of 0 ms with no delay,
|
|
32983
|
+
* no repeat and no keys, started so by its caller (not cut by reduced motion). A rest pose a
|
|
32984
|
+
* caller sets in phase `layout` so lands with the fields written beside it in that frame (F47);
|
|
32985
|
+
* the next frame step ends it, where its `Animation` count lands too.
|
|
32986
|
+
*
|
|
32987
|
+
* @param track - The track that starts.
|
|
32988
|
+
* @param options - What its caller asked for.
|
|
32989
|
+
* @returns True when it lands now.
|
|
32990
|
+
*/
|
|
32991
|
+
function landsAtStart(track, options) {
|
|
32992
|
+
return options.ms === 0 && track.delayMs === 0 && !track.additive && !track.driven && track.repeatsLeft === 0 && track.segments === void 0;
|
|
32993
|
+
}
|
|
32994
|
+
/**
|
|
32817
32995
|
* Tells whether a loop stands on its first key instead of walking: with reduced motion on, unless
|
|
32818
32996
|
* the author kept it, or when it has no length to walk. It stays in the table either way, so it
|
|
32819
32997
|
* never ends by itself.
|
|
@@ -42224,16 +42402,20 @@ function boxCovers(ectx, entity, width, height, size) {
|
|
|
42224
42402
|
return width * scale >= size.width && height * scale >= size.height;
|
|
42225
42403
|
}
|
|
42226
42404
|
/**
|
|
42227
|
-
* Tells whether a filtered view covers the whole viewport
|
|
42228
|
-
*
|
|
42229
|
-
*
|
|
42405
|
+
* Tells whether a filtered view covers the whole viewport. A view whose enabled filters declare an
|
|
42406
|
+
* area draws only there: that area, times the view's scale, covers the reference size on both axes
|
|
42407
|
+
* (F43, a lens over a full-screen sprite is not full screen). Otherwise the box its sprite, its
|
|
42408
|
+
* nine-slice or its shape declares, times its scale, does. A sprite without a size declares none.
|
|
42409
|
+
* Read from components and the area handed over last, never from Pixi bounds.
|
|
42230
42410
|
*
|
|
42231
42411
|
* @param ectx - Domain context of the effects plugin.
|
|
42232
|
-
* @param
|
|
42412
|
+
* @param view - The view's record.
|
|
42233
42413
|
* @param size - The viewport size.
|
|
42234
42414
|
* @returns True for a full-screen view.
|
|
42235
42415
|
*/
|
|
42236
|
-
function coversScreen(ectx,
|
|
42416
|
+
function coversScreen(ectx, view, size) {
|
|
42417
|
+
const { entity, areaSent } = view;
|
|
42418
|
+
if (areaSent.some) return boxCovers(ectx, entity, areaSent.width, areaSent.height, size);
|
|
42237
42419
|
const ecs = ectx.deps.world.ecs;
|
|
42238
42420
|
const sprite = ecs.get(entity, Sprite);
|
|
42239
42421
|
if (sprite !== void 0) {
|
|
@@ -42308,7 +42490,7 @@ function countFullScreen(ectx, size) {
|
|
|
42308
42490
|
let count = 0;
|
|
42309
42491
|
for (const view of ectx.state.viewList) {
|
|
42310
42492
|
if (view.gone) continue;
|
|
42311
|
-
if (hasEnabledFilter(ectx, view) && coversScreen(ectx, view
|
|
42493
|
+
if (hasEnabledFilter(ectx, view) && coversScreen(ectx, view, size)) count += 1;
|
|
42312
42494
|
}
|
|
42313
42495
|
return count;
|
|
42314
42496
|
}
|
|
@@ -49225,24 +49407,37 @@ function createTextSystem(ctx, frame) {
|
|
|
49225
49407
|
});
|
|
49226
49408
|
}
|
|
49227
49409
|
/**
|
|
49228
|
-
* Resolves the labels whose `Text` came after the layout system ran. `ui` adds a label in
|
|
49229
|
-
* solve, and the flush at the end of phase `layout` attaches it with the rest of its batch, a
|
|
49230
|
-
* component included; this runs right after that flush and before phase `sync`, so the
|
|
49231
|
-
* builds the label with its string, and lists it, so the next system run writes its `Text`
|
|
49232
|
-
* more for the remeasure of `ui`. A label whose content
|
|
49233
|
-
*
|
|
49234
|
-
*
|
|
49410
|
+
* Resolves the labels whose `Text` came or changed after the layout system ran. `ui` adds a label in
|
|
49411
|
+
* its solve, and the flush at the end of phase `layout` attaches it with the rest of its batch, a
|
|
49412
|
+
* bound component included; this runs right after that flush and before phase `sync`, so the
|
|
49413
|
+
* renderer builds the label with its string, and lists it, so the next system run writes its `Text`
|
|
49414
|
+
* once more for the remeasure of `ui`. A label whose content or style `ui` changed in its reconcile
|
|
49415
|
+
* is resolved here too, in the frame of the change (F45): `ui` measured its content itself, so it is
|
|
49416
|
+
* not listed. While the world is not live its layout phase did not run: the list is dropped, and the
|
|
49417
|
+
* labels, marked, wait for the next live run, as every label does.
|
|
49235
49418
|
*
|
|
49236
49419
|
* @param ctx - Domain context of the text plugin.
|
|
49237
49420
|
* @param frame - What the system's runs share.
|
|
49238
49421
|
*/
|
|
49239
49422
|
function resolveAdded(ctx, frame) {
|
|
49240
49423
|
const added = ctx.state.added;
|
|
49241
|
-
if (added.length
|
|
49242
|
-
|
|
49243
|
-
|
|
49244
|
-
|
|
49424
|
+
if (added.length > 0) {
|
|
49425
|
+
if (ctx.deps.world.ecs.mode() !== "live") {
|
|
49426
|
+
added.length = 0;
|
|
49427
|
+
return;
|
|
49428
|
+
}
|
|
49429
|
+
resolveCame(ctx, frame, added);
|
|
49245
49430
|
}
|
|
49431
|
+
resolveChanged(ctx, frame);
|
|
49432
|
+
}
|
|
49433
|
+
/**
|
|
49434
|
+
* Resolves the labels whose `Text` came with the layout flush, and lists them for the remeasure.
|
|
49435
|
+
*
|
|
49436
|
+
* @param ctx - Domain context of the text plugin.
|
|
49437
|
+
* @param frame - What the system's runs share.
|
|
49438
|
+
* @param added - The labels that came.
|
|
49439
|
+
*/
|
|
49440
|
+
function resolveCame(ctx, frame, added) {
|
|
49246
49441
|
frame.now = NaN;
|
|
49247
49442
|
frame.locale = ctx.deps.i18n.locale();
|
|
49248
49443
|
for (const entity of added) {
|
|
@@ -49254,6 +49449,25 @@ function resolveAdded(ctx, frame) {
|
|
|
49254
49449
|
forgetAdded(added);
|
|
49255
49450
|
}
|
|
49256
49451
|
/**
|
|
49452
|
+
* Resolves the labels of this frame's `changed(Text)` whose content or style moved since they were
|
|
49453
|
+
* resolved: `ui` writes `Text` after the layout system. The labels this frame resolved already
|
|
49454
|
+
* stand on what they show; a bound label shows its value, as in the system.
|
|
49455
|
+
*
|
|
49456
|
+
* @param ctx - Domain context of the text plugin.
|
|
49457
|
+
* @param frame - What the system's runs share; the locale of this frame is already in it.
|
|
49458
|
+
*/
|
|
49459
|
+
function resolveChanged(ctx, frame) {
|
|
49460
|
+
const ecs = ctx.deps.world.ecs;
|
|
49461
|
+
let live = false;
|
|
49462
|
+
for (const entity of ecs.changed(Text)) {
|
|
49463
|
+
const text = ecs.get(entity, Text);
|
|
49464
|
+
if (text === void 0 || !isStale(ctx, entity, text, frame)) continue;
|
|
49465
|
+
if (!live && ecs.mode() !== "live") return;
|
|
49466
|
+
live = true;
|
|
49467
|
+
stepText(ctx, entity, text, frame);
|
|
49468
|
+
}
|
|
49469
|
+
}
|
|
49470
|
+
/**
|
|
49257
49471
|
* Marks labels for the next layout phase: every one of them, or only the ones `keep` names. A
|
|
49258
49472
|
* locale change names the labels whose content is a message; a dev hot swap names the labels
|
|
49259
49473
|
* drawn with a replaced font or icon.
|
|
@@ -53845,7 +54059,10 @@ function recordRest(ctx, element, value) {
|
|
|
53845
54059
|
* @param name - The component name of the extra.
|
|
53846
54060
|
*/
|
|
53847
54061
|
function cancelExtra(element, name) {
|
|
53848
|
-
element.extraHandles.get(name)
|
|
54062
|
+
const last = element.extraHandles.get(name);
|
|
54063
|
+
if (last === void 0) return;
|
|
54064
|
+
last.cancel();
|
|
54065
|
+
element.endless?.delete(last);
|
|
53849
54066
|
element.extraHandles.delete(name);
|
|
53850
54067
|
}
|
|
53851
54068
|
//#endregion
|
|
@@ -55559,10 +55776,11 @@ function createReconciler(ctx, modules, fields) {
|
|
|
55559
55776
|
*/
|
|
55560
55777
|
function subtreeSettled(element) {
|
|
55561
55778
|
if (!modules.layout.settled(element)) return false;
|
|
55562
|
-
|
|
55779
|
+
for (const child of element.children) {
|
|
55563
55780
|
const childElement = state.elements.get(child);
|
|
55564
|
-
|
|
55565
|
-
}
|
|
55781
|
+
if (childElement !== void 0 && !subtreeSettled(childElement)) return false;
|
|
55782
|
+
}
|
|
55783
|
+
return true;
|
|
55566
55784
|
}
|
|
55567
55785
|
/**
|
|
55568
55786
|
* Drops the identity, the key and the key registration of an element and of everything under
|
|
@@ -55617,6 +55835,24 @@ function createReconciler(ctx, modules, fields) {
|
|
|
55617
55835
|
if (!subtreeSettled(element)) continue;
|
|
55618
55836
|
despawnTree(element);
|
|
55619
55837
|
}
|
|
55838
|
+
dropRemovedRoots();
|
|
55839
|
+
}
|
|
55840
|
+
/**
|
|
55841
|
+
* Despawns every exiting element at once, finished or not, and drops the roots that were leaving:
|
|
55842
|
+
* what a restore or a load does, as a page reload would (F42).
|
|
55843
|
+
*/
|
|
55844
|
+
function dropLeaving() {
|
|
55845
|
+
for (const entity of state.exiting) {
|
|
55846
|
+
const element = state.elements.get(entity);
|
|
55847
|
+
if (element === void 0) state.exiting.delete(entity);
|
|
55848
|
+
else despawnTree(element);
|
|
55849
|
+
}
|
|
55850
|
+
dropRemovedRoots();
|
|
55851
|
+
}
|
|
55852
|
+
/**
|
|
55853
|
+
* Drops every removed root whose element tree is gone, and closes its popup.
|
|
55854
|
+
*/
|
|
55855
|
+
function dropRemovedRoots() {
|
|
55620
55856
|
for (const entity of state.removing) {
|
|
55621
55857
|
const root = state.roots.get(entity);
|
|
55622
55858
|
if (root === void 0) continue;
|
|
@@ -55951,11 +56187,12 @@ function createReconciler(ctx, modules, fields) {
|
|
|
55951
56187
|
* element stands exactly as if its root had just been mounted with the restored state: a new
|
|
55952
56188
|
* entity with the components of the description, then its `enter` hook, then its loop. What a
|
|
55953
56189
|
* mount does not bring is gone with the old tree: the local state of a component, a scroll
|
|
55954
|
-
* offset, the keyboard focus, a text being edited, a hover.
|
|
55955
|
-
* leaving.
|
|
56190
|
+
* offset, the keyboard focus, a text being edited, a hover. An element or a root that is
|
|
56191
|
+
* leaving is dropped at once, as a page reload drops it.
|
|
55956
56192
|
*/
|
|
55957
56193
|
function remountRoots() {
|
|
55958
56194
|
state.remount = false;
|
|
56195
|
+
dropLeaving();
|
|
55959
56196
|
for (const root of state.roots.values()) {
|
|
55960
56197
|
if (state.removing.has(root.entity)) continue;
|
|
55961
56198
|
const element = root.element === void 0 ? void 0 : lookup(root.element);
|
|
@@ -56119,8 +56356,8 @@ function createReconciler(ctx, modules, fields) {
|
|
|
56119
56356
|
/**
|
|
56120
56357
|
* The second system of phase `layout`: every root takes its slot, then one solve per marked
|
|
56121
56358
|
* root, a root in a slot after the root of its slot and in its content box, then the rects, the
|
|
56122
|
-
* rest poses and the hooks, the scrolls settled on what the solve and the render gave them,
|
|
56123
|
-
*
|
|
56359
|
+
* rest poses and the hooks, the scrolls settled on what the solve and the render gave them, the
|
|
56360
|
+
* hosting of the hosts that came, and a sweep of what left with nothing to wait for. The hints released since the last frame step are dropped
|
|
56124
56361
|
* at its end, so the `change.Box` and `change.Transform` hooks the solve plays get the hint the
|
|
56125
56362
|
* reconcile routed, and the next frame starts with none.
|
|
56126
56363
|
*
|
|
@@ -56140,6 +56377,7 @@ function createReconciler(ctx, modules, fields) {
|
|
|
56140
56377
|
hostViews(ctx, state, state.risen);
|
|
56141
56378
|
state.risen.clear();
|
|
56142
56379
|
}
|
|
56380
|
+
if (state.exiting.size > 0 || state.removing.size > 0) sweep();
|
|
56143
56381
|
state.hints.length = 0;
|
|
56144
56382
|
writeCounters();
|
|
56145
56383
|
}
|
|
@@ -56722,14 +56960,15 @@ function noteTrack(span, options) {
|
|
|
56722
56960
|
span.reduced = options.reduced;
|
|
56723
56961
|
}
|
|
56724
56962
|
/**
|
|
56725
|
-
* The view handle of a hook
|
|
56726
|
-
* their track
|
|
56963
|
+
* The view handle of a watched hook: every call goes to the real handle; `tween` notes whether its track repeats
|
|
56964
|
+
* forever, and with a span `tween` and `toRest` note their track for the level of an overlay.
|
|
56727
56965
|
*
|
|
56728
56966
|
* @param handle - The real handle.
|
|
56729
|
-
* @param span - The span being measured.
|
|
56730
|
-
* @
|
|
56967
|
+
* @param span - The span being measured, or nothing.
|
|
56968
|
+
* @param watch - Where a track that repeats forever is noted.
|
|
56969
|
+
* @returns The watching handle.
|
|
56731
56970
|
*/
|
|
56732
|
-
function
|
|
56971
|
+
function watched(handle, span, watch) {
|
|
56733
56972
|
return {
|
|
56734
56973
|
entity: handle.entity,
|
|
56735
56974
|
key: handle.key,
|
|
@@ -56737,11 +56976,12 @@ function spanned(handle, span) {
|
|
|
56737
56976
|
rest: (component) => handle.rest(component),
|
|
56738
56977
|
set: (component, patch) => handle.set(component, patch),
|
|
56739
56978
|
tween: (component, to, options) => {
|
|
56740
|
-
|
|
56979
|
+
if (options.repeat === "forever") watch.forever = true;
|
|
56980
|
+
if (span !== void 0) noteTrack(span, options);
|
|
56741
56981
|
return handle.tween(component, to, options);
|
|
56742
56982
|
},
|
|
56743
56983
|
toRest: (component, options) => {
|
|
56744
|
-
noteTrack(span, options);
|
|
56984
|
+
if (span !== void 0) noteTrack(span, options);
|
|
56745
56985
|
return handle.toRest(component, options);
|
|
56746
56986
|
},
|
|
56747
56987
|
all: (handles) => handle.all(handles),
|
|
@@ -56750,8 +56990,9 @@ function spanned(handle, span) {
|
|
|
56750
56990
|
}
|
|
56751
56991
|
/**
|
|
56752
56992
|
* Runs one motion hook and keeps the handle it returned, so the exit sweep knows when the
|
|
56753
|
-
* element is still playing.
|
|
56754
|
-
*
|
|
56993
|
+
* element is still playing. A motion whose hook started a track that repeats forever is also
|
|
56994
|
+
* noted as endless: the sweep never waits for it. Without a hook the value the solve wrote stands;
|
|
56995
|
+
* a throwing hook is logged and the same happens.
|
|
56755
56996
|
*
|
|
56756
56997
|
* @param ctx - Domain context of the ui plugin.
|
|
56757
56998
|
* @param element - The element the hook belongs to.
|
|
@@ -56764,9 +57005,11 @@ function play(ctx, element, hook, span) {
|
|
|
56764
57005
|
const handle = handleOf(ctx, element);
|
|
56765
57006
|
if (handle === void 0) return void 0;
|
|
56766
57007
|
try {
|
|
56767
|
-
const
|
|
57008
|
+
const watch = { forever: false };
|
|
57009
|
+
const motion = hook(watched(handle, span, watch));
|
|
56768
57010
|
if (motion === void 0) return void 0;
|
|
56769
57011
|
element.handles.push(motion);
|
|
57012
|
+
if (watch.forever) noteEndless(element, motion);
|
|
56770
57013
|
return motion;
|
|
56771
57014
|
} catch (error) {
|
|
56772
57015
|
ctx.log.error("ui:motion-failed", {
|
|
@@ -56777,6 +57020,16 @@ function play(ctx, element, hook, span) {
|
|
|
56777
57020
|
}
|
|
56778
57021
|
}
|
|
56779
57022
|
/**
|
|
57023
|
+
* Notes a motion that never ends on its element, the set made with the first one.
|
|
57024
|
+
*
|
|
57025
|
+
* @param element - The element the motion plays on.
|
|
57026
|
+
* @param motion - The endless motion.
|
|
57027
|
+
*/
|
|
57028
|
+
function noteEndless(element, motion) {
|
|
57029
|
+
element.endless ??= /* @__PURE__ */ new Set();
|
|
57030
|
+
element.endless.add(motion);
|
|
57031
|
+
}
|
|
57032
|
+
/**
|
|
56780
57033
|
* Plays the `change` hook of one extra component whose fields changed. The motion the last change
|
|
56781
57034
|
* of that name started is cancelled first, so its value stays where it is and the new motion
|
|
56782
57035
|
* starts from there; the new motion is kept with the element's handles, so an exit waits for it.
|
|
@@ -56791,8 +57044,12 @@ function play(ctx, element, hook, span) {
|
|
|
56791
57044
|
* @returns True when the hook returned a motion: the caller writes nothing directly.
|
|
56792
57045
|
*/
|
|
56793
57046
|
function playExtraChange(ctx, element, name, values, hint) {
|
|
56794
|
-
element.extraHandles.get(name)
|
|
56795
|
-
|
|
57047
|
+
const last = element.extraHandles.get(name);
|
|
57048
|
+
if (last !== void 0) {
|
|
57049
|
+
last.cancel();
|
|
57050
|
+
element.endless?.delete(last);
|
|
57051
|
+
element.extraHandles.delete(name);
|
|
57052
|
+
}
|
|
56796
57053
|
const hook = element.motion?.change?.[name];
|
|
56797
57054
|
if (hook === void 0) return false;
|
|
56798
57055
|
const motion = play(ctx, element, (view) => hook(view, values.previous, values.next, hint));
|
|
@@ -56828,19 +57085,23 @@ function startLoop(ctx, element) {
|
|
|
56828
57085
|
}
|
|
56829
57086
|
/**
|
|
56830
57087
|
* Tells whether every motion of an element has finished, which is when an exiting element may
|
|
56831
|
-
* be despawned.
|
|
57088
|
+
* be despawned. A motion over a track that repeats forever never finishes, so it does not count:
|
|
57089
|
+
* waiting for it would keep the element for the life of the page (F42).
|
|
56832
57090
|
*
|
|
56833
57091
|
* @param element - The element to ask about.
|
|
56834
|
-
* @returns True when nothing is still playing.
|
|
57092
|
+
* @returns True when nothing that can end is still playing.
|
|
56835
57093
|
*/
|
|
56836
57094
|
function still(element) {
|
|
56837
|
-
|
|
57095
|
+
const { handles, endless } = element;
|
|
57096
|
+
for (const handle of handles) if (handle.active() && endless?.has(handle) !== true) return false;
|
|
57097
|
+
return true;
|
|
56838
57098
|
}
|
|
56839
57099
|
/**
|
|
56840
57100
|
* Moves the rest `Transform` of an element to where its rect, style and fit put it now. A live
|
|
56841
57101
|
* element plays its `change.Transform` motion when it has one, else takes the pose through a
|
|
56842
|
-
* 0 ms rest track
|
|
56843
|
-
*
|
|
57102
|
+
* 0 ms rest track. That track writes the pose as it starts, so the pivot and the position land in
|
|
57103
|
+
* the same frame, and ends at the next frame step, where an additive loop re-bases on the new
|
|
57104
|
+
* rest. An element that has not spawned yet only records it, and so does one whose
|
|
56844
57105
|
* `change.Box` motion already played. The content of a scroll keeps its `Transform` and records
|
|
56845
57106
|
* no rest with the world: the scroll step owns it.
|
|
56846
57107
|
*
|
|
@@ -56953,10 +57214,14 @@ function placeChildren(state, parent, children) {
|
|
|
56953
57214
|
* @file ui/layout — exiting elements, policy "leave": the element leaves the flow in the same
|
|
56954
57215
|
* reconcile, so its siblings reflow this frame while it plays its exit over them.
|
|
56955
57216
|
*/
|
|
57217
|
+
/** The dev warning of an element that left while a motion of it repeated forever. */
|
|
57218
|
+
const EXIT_WAITS_FOREVER = "ui:exit-waits-forever";
|
|
56956
57219
|
/**
|
|
56957
57220
|
* Starts the exit of one element: out of the Yoga tree at once, tagged `Exiting` so `input`
|
|
56958
57221
|
* never hits it, then the hook plays over the siblings that already moved. A `change` motion of
|
|
56959
57222
|
* an extra component that still runs, a counter's roll, is kept, so the sweep waits for it too.
|
|
57223
|
+
* One that repeats forever, a hot pulse, is cancelled where it stands: it would never end, and a
|
|
57224
|
+
* dev build names the element once (F42).
|
|
56960
57225
|
*
|
|
56961
57226
|
* @param ctx - Domain context of the ui plugin.
|
|
56962
57227
|
* @param state - The layout state.
|
|
@@ -56970,11 +57235,45 @@ function beginExit(ctx, state, element, cause, span) {
|
|
|
56970
57235
|
element.dropKey = void 0;
|
|
56971
57236
|
if (!element.live) return;
|
|
56972
57237
|
ctx.deps.world.ecs.tag(element.entity, Exiting);
|
|
56973
|
-
element.handles =
|
|
57238
|
+
element.handles = keptExtras(ctx, element);
|
|
56974
57239
|
const hook = element.motion?.exit;
|
|
56975
57240
|
play(ctx, element, hook === void 0 ? void 0 : (view) => hook(view, element.node, void 0, cause), span);
|
|
56976
57241
|
}
|
|
56977
57242
|
/**
|
|
57243
|
+
* The `change` motions of the extras an exit waits for: the ones still running that can end. One
|
|
57244
|
+
* that repeats forever is cancelled where it stands, and a dev build warns once per element.
|
|
57245
|
+
*
|
|
57246
|
+
* @param ctx - Domain context of the ui plugin.
|
|
57247
|
+
* @param element - The element that starts its exit.
|
|
57248
|
+
* @returns The motions the sweep waits for.
|
|
57249
|
+
*/
|
|
57250
|
+
function keptExtras(ctx, element) {
|
|
57251
|
+
const kept = [];
|
|
57252
|
+
for (const handle of element.extraHandles.values()) {
|
|
57253
|
+
if (!handle.active()) continue;
|
|
57254
|
+
if (element.endless?.has(handle) !== true) {
|
|
57255
|
+
kept.push(handle);
|
|
57256
|
+
continue;
|
|
57257
|
+
}
|
|
57258
|
+
handle.cancel();
|
|
57259
|
+
warnEndless(ctx, element);
|
|
57260
|
+
}
|
|
57261
|
+
return kept;
|
|
57262
|
+
}
|
|
57263
|
+
/**
|
|
57264
|
+
* Names an element that left while a motion of it repeated forever, once per element, in a dev
|
|
57265
|
+
* build: the motion is cut where it stands, which the author may want to end in the exit instead.
|
|
57266
|
+
*
|
|
57267
|
+
* @param ctx - Domain context of the ui plugin.
|
|
57268
|
+
* @param element - The leaving element.
|
|
57269
|
+
*/
|
|
57270
|
+
function warnEndless(ctx, element) {
|
|
57271
|
+
if (typeof __MOKU_GAME_DEV__ === "undefined" || !__MOKU_GAME_DEV__) return;
|
|
57272
|
+
if (element.warned.has(EXIT_WAITS_FOREVER)) return;
|
|
57273
|
+
element.warned.add(EXIT_WAITS_FOREVER);
|
|
57274
|
+
ctx.log.warn(EXIT_WAITS_FOREVER, { key: element.key ?? element.identity });
|
|
57275
|
+
}
|
|
57276
|
+
/**
|
|
56978
57277
|
* Tells whether an exiting element may be despawned: no hook, or every hook finished.
|
|
56979
57278
|
*
|
|
56980
57279
|
* @param element - The exiting element.
|