@pixi-ui-editor/runtime-pixi 0.12.0 → 0.14.0
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/SceneViewport.js.map +1 -1
- package/dist/assets/bitmapFonts.d.ts.map +1 -1
- package/dist/assets/bitmapFonts.js +3 -1
- package/dist/assets/bitmapFonts.js.map +1 -1
- package/dist/controls.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +3 -1
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +13 -0
- package/dist/layout.js.map +1 -1
- package/dist/particles.js.map +1 -1
- package/dist/scene.js.map +1 -1
- package/dist/views/ButtonNodeView.d.ts +1 -0
- package/dist/views/ButtonNodeView.d.ts.map +1 -1
- package/dist/views/ButtonNodeView.js +6 -0
- package/dist/views/ButtonNodeView.js.map +1 -1
- package/dist/views/ItemTableNodeView.js.map +1 -1
- package/dist/views/PaginationNodeView.js.map +1 -1
- package/dist/views/ParticleEmitterNodeView.js.map +1 -1
- package/dist/views/StagedButtonNodeView.d.ts +1 -0
- package/dist/views/StagedButtonNodeView.d.ts.map +1 -1
- package/dist/views/StagedButtonNodeView.js +6 -0
- package/dist/views/StagedButtonNodeView.js.map +1 -1
- package/dist/views/basic.d.ts +1 -1
- package/dist/views/basic.d.ts.map +1 -1
- package/dist/views/basic.js +13 -12
- package/dist/views/basic.js.map +1 -1
- package/dist/views/createNodeView.js +1 -1
- package/dist/views/createNodeView.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SceneViewport.js","sourceRoot":"","sources":["../src/SceneViewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAwC,MAAM,aAAa,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,OAAO,aAAc,SAAQ,SAAS;IACjC,iBAAiB,CAAa;IAC9B,OAAO,CAAY;IAE5B,YAAY,OAAkB,EAAE,iBAA6B,EAAE,IAAa;QAC1E,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,iBAAiB,GAAG,EAAE,GAAG,iBAAiB,EAAE,CAAC;QAElD,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,YAAY,GAAG,IAAI,QAAQ,EAAE;iBAChC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,CAAC;iBAC7D,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClB,YAAY,CAAC,SAAS,GAAG,MAAM,CAAC;YAChC,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,sFAAsF;IACtF,MAAM,CAAC,IAAgB;QACrB,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["import { Container, Graphics } from \"pixi.js\";\nimport { fitViewportToHost, type FittedViewport, type LayoutSize } from \"./layout.js\";\n\n/**\n * The single host boundary for a built scene.\n *\n * Runtime scenes are clipped to the authored reference viewport and can only be fitted with one\n * uniform scale. Authoring scenes use the same wrapper without clipping so the editor can expose\n * off-viewport content while arranging it.\n */\nexport class SceneViewport extends Container {\n readonly referenceViewport: LayoutSize;\n readonly content: Container;\n\n constructor(content: Container, referenceViewport: LayoutSize, clip: boolean) {\n super();\n this.content = content;\n this.referenceViewport = { ...referenceViewport };\n\n if (clip) {\n const viewportMask = new Graphics()\n .rect(0, 0, referenceViewport.width, referenceViewport.height)\n .fill(0xffffff);\n viewportMask.eventMode = \"none\";\n content.mask = viewportMask;\n this.addChild(viewportMask);\n }\n\n this.addChild(content);\n }\n\n /** Uniformly contains and centers this authored viewport inside the physical host. */\n resize(host: LayoutSize): FittedViewport {\n const fitted = fitViewportToHost(this.referenceViewport, host);\n this.scale.set(fitted.scale);\n this.position.set(fitted.x, fitted.y);\n return fitted;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"SceneViewport.js","sourceRoot":"","sources":["../src/SceneViewport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAwC,MAAM,aAAa,CAAC;AAEtF;;;;;;GAMG;AACH,MAAM,OAAO,aAAc,SAAQ,SAAS;IACjC,iBAAiB,CAAa;IAC9B,OAAO,CAAY;IAE5B,YAAY,OAAkB,EAAE,iBAA6B,EAAE,IAAa;QAC1E,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,iBAAiB,GAAG,EAAE,GAAG,iBAAiB,EAAE,CAAC;QAElD,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,YAAY,GAAG,IAAI,QAAQ,EAAE;iBAChC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,iBAAiB,CAAC,KAAK,EAAE,iBAAiB,CAAC,MAAM,CAAC;iBAC7D,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClB,YAAY,CAAC,SAAS,GAAG,MAAM,CAAC;YAChC,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC;YAC5B,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,sFAAsF;IACtF,MAAM,CAAC,IAAgB;QACrB,MAAM,MAAM,GAAG,iBAAiB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QACtC,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["import { Container, Graphics } from \"pixi.js\";\r\nimport { fitViewportToHost, type FittedViewport, type LayoutSize } from \"./layout.js\";\r\n\r\n/**\r\n * The single host boundary for a built scene.\r\n *\r\n * Runtime scenes are clipped to the authored reference viewport and can only be fitted with one\r\n * uniform scale. Authoring scenes use the same wrapper without clipping so the editor can expose\r\n * off-viewport content while arranging it.\r\n */\r\nexport class SceneViewport extends Container {\r\n readonly referenceViewport: LayoutSize;\r\n readonly content: Container;\r\n\r\n constructor(content: Container, referenceViewport: LayoutSize, clip: boolean) {\r\n super();\r\n this.content = content;\r\n this.referenceViewport = { ...referenceViewport };\r\n\r\n if (clip) {\r\n const viewportMask = new Graphics()\r\n .rect(0, 0, referenceViewport.width, referenceViewport.height)\r\n .fill(0xffffff);\r\n viewportMask.eventMode = \"none\";\r\n content.mask = viewportMask;\r\n this.addChild(viewportMask);\r\n }\r\n\r\n this.addChild(content);\r\n }\r\n\r\n /** Uniformly contains and centers this authored viewport inside the physical host. */\r\n resize(host: LayoutSize): FittedViewport {\r\n const fitted = fitViewportToHost(this.referenceViewport, host);\r\n this.scale.set(fitted.scale);\r\n this.position.set(fitted.x, fitted.y);\r\n return fitted;\r\n }\r\n}\r\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFonts.d.ts","sourceRoot":"","sources":["../../src/assets/bitmapFonts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAU,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAoC,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAMrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,KAAK,eAAe,GAAG,OAAO,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"bitmapFonts.d.ts","sourceRoot":"","sources":["../../src/assets/bitmapFonts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,eAAe,EAAU,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAoC,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAMrF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAErD,KAAK,eAAe,GAAG,OAAO,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC,CAAC;AAuC9D;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,GAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAyB,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAYjO;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,KAAK,GAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAyB,GAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAGlO"}
|
|
@@ -9,7 +9,9 @@ const keyOf = (asset) => `${asset.files.xml.uri}#${asset.files.texture.uri}`;
|
|
|
9
9
|
* asset id is the only identity PixiJS's `${fontFamily}-bitmap` Cache key is guaranteed not to collide on.
|
|
10
10
|
*/
|
|
11
11
|
const familyOf = (assetId) => `bitmap-font-${assetId}`;
|
|
12
|
-
const fromNodes = (nodes) => nodes.flatMap((node) =>
|
|
12
|
+
const fromNodes = (nodes) => nodes.flatMap((node) => node.type === "bitmap-text"
|
|
13
|
+
? [node.assetId, node.bitmapTextOverrides?.desktop?.assetId, node.bitmapTextOverrides?.mobile?.assetId].filter((assetId) => assetId !== undefined)
|
|
14
|
+
: []);
|
|
13
15
|
/**
|
|
14
16
|
* Shared by `loadSceneFonts`'s reasoning (see `sharedFontCache`): a loaded `BitmapFont` registers into
|
|
15
17
|
* PixiJS's own global `Cache`, so re-parsing the same asset under a caller-scoped cache would still
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bitmapFonts.js","sourceRoot":"","sources":["../../src/assets/bitmapFonts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,yBAAyB,EAAgB,MAAM,SAAS,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAO/C,MAAM,KAAK,GAAG,CAAC,KAAsB,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;AAC9F;;;;GAIG;AACH,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,eAAe,OAAO,EAAE,CAAC;AAC/D,MAAM,SAAS,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"bitmapFonts.js","sourceRoot":"","sources":["../../src/assets/bitmapFonts.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Asset, ProjectDocument, UINode } from \"@pixi-ui-editor/schema\";\r\nimport { BitmapFont, Cache, bitmapFontXMLStringParser, type Texture } from \"pixi.js\";\r\nimport { collectRenderedNodes } from \"../scene.js\";\r\nimport { sharedBitmapFontCache } from \"./cache.js\";\r\nimport { loadTexture } from \"./loadTexture.js\";\r\n// Type-only: erased at compile time, so this does not create a runtime import cycle even though\r\n// `textures.ts` imports a value (`loadBitmapFontGlyphTexture`) from this file.\r\nimport type { FileUrlResolver } from \"./textures.js\";\r\n\r\ntype BitmapFontAsset = Extract<Asset, { type: \"bitmapFont\" }>;\r\n\r\nconst keyOf = (asset: BitmapFontAsset) => `${asset.files.xml.uri}#${asset.files.texture.uri}`;\r\n/**\r\n * The synthetic family every loaded font installs under — never whatever `<info face>` its XML\r\n * declares. Two uploaded bitmap fonts could share the same exporter-generated face name, and the\r\n * asset id is the only identity PixiJS's `${fontFamily}-bitmap` Cache key is guaranteed not to collide on.\r\n */\r\nconst familyOf = (assetId: string) => `bitmap-font-${assetId}`;\r\nconst fromNodes = (nodes: UINode[]) => nodes.flatMap((node) => node.type === \"bitmap-text\"\r\n ? [node.assetId, node.bitmapTextOverrides?.desktop?.assetId, node.bitmapTextOverrides?.mobile?.assetId].filter((assetId): assetId is string => assetId !== undefined)\r\n : []);\r\n\r\n/**\r\n * Shared by `loadSceneFonts`'s reasoning (see `sharedFontCache`): a loaded `BitmapFont` registers into\r\n * PixiJS's own global `Cache`, so re-parsing the same asset under a caller-scoped cache would still\r\n * collide there. `cache` defaults to that shared map but accepts a `SceneAssetCache.bitmapFonts` from\r\n * the caller, the same override every other scene asset loader takes.\r\n */\r\nfunction loadFont(asset: BitmapFontAsset, resolveFileUrl: FileUrlResolver, cache: Map<string, Promise<BitmapFont | undefined>>): Promise<BitmapFont | undefined> {\r\n const key = keyOf(asset);\r\n let pending = cache.get(key);\r\n if (pending === undefined) {\r\n pending = (async () => {\r\n const xmlUrl = resolveFileUrl(asset.files.xml.uri);\r\n const textureUrl = resolveFileUrl(asset.files.texture.uri);\r\n if (xmlUrl === undefined || textureUrl === undefined) return undefined;\r\n try {\r\n const [xml, texture] = await Promise.all([fetch(xmlUrl).then((response) => response.text()), loadTexture(textureUrl)]);\r\n const font = new BitmapFont({ data: bitmapFontXMLStringParser.parse(xml), textures: [texture] });\r\n Cache.set(`${familyOf(asset.id)}-bitmap`, font);\r\n return font;\r\n } catch (error) { console.warn(`Unable to load bitmap font asset '${asset.id}'. Text using it will not render.`, error); return undefined; }\r\n })();\r\n cache.set(key, pending);\r\n }\r\n return pending;\r\n}\r\n\r\n/**\r\n * Loads scene bitmap fonts before views are built, mirroring `loadSceneFonts`. Unlike a regular\r\n * `FontFace`, PixiJS resolves a `BitmapText`'s font by looking up `Cache` for `${fontFamily}-bitmap`\r\n * (see `BitmapFontManager.getFont`), so loading here means parsing the XML, building one `BitmapFont`\r\n * from the already-fetched texture, and registering it in that cache — there is no URL-based loader\r\n * to delegate to, since our XML and texture live at unrelated asset URIs, not a fixed relative pair.\r\n */\r\nexport async function loadSceneBitmapFonts(document: ProjectDocument, sceneId: string, resolveFileUrl: FileUrlResolver, cache: Map<string, Promise<BitmapFont | undefined>> = sharedBitmapFontCache): Promise<Map<string, string>> {\r\n const scene = document.scenes.find((item) => item.id === sceneId);\r\n if (scene === undefined) throw new Error(`Scene '${sceneId}' does not exist in the project document.`);\r\n const ids = new Set(fromNodes(collectRenderedNodes(document, scene)));\r\n const fonts = new Map<string, string>();\r\n await Promise.all([...ids].map(async (id) => {\r\n const asset = document.assets.find((item) => item.id === id);\r\n if (asset?.type !== \"bitmapFont\") return;\r\n const font = await loadFont(asset, resolveFileUrl, cache);\r\n if (font !== undefined) fonts.set(id, familyOf(asset.id));\r\n }));\r\n return fonts;\r\n}\r\n\r\n/**\r\n * Resolves one glyph's already-cropped `Texture` from a bitmap font asset, for reuse as a plain image\r\n * asset (an Image node, a Button/Checkbox state, ...) — see `BitmapFontAsset.frames`. `BitmapFont`\r\n * builds one `Texture` per character up front (see its constructor), so this is a lookup, not a crop.\r\n */\r\nexport async function loadBitmapFontGlyphTexture(asset: BitmapFontAsset, glyph: string, resolveFileUrl: FileUrlResolver, cache: Map<string, Promise<BitmapFont | undefined>> = sharedBitmapFontCache): Promise<Texture | undefined> {\r\n const font = await loadFont(asset, resolveFileUrl, cache);\r\n return font?.chars[glyph]?.texture;\r\n}\r\n"]}
|
package/dist/controls.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controls.js","sourceRoot":"","sources":["../src/controls.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SkeletonData, Spine } from \"@esotericsoftware/spine-pixi-v8\";\nimport { type ButtonStateKey, type LayoutPadding } from \"@pixi-ui-editor/schema\";\nimport { Container } from \"pixi.js\";\nimport { ButtonNodeView } from \"./views/ButtonNodeView.js\";\nimport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\nimport { ItemTableNodeView } from \"./views/ItemTableNodeView.js\";\nimport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\nimport { PaginationNodeView } from \"./views/PaginationNodeView.js\";\nimport { StagedButtonNodeView } from \"./views/StagedButtonNodeView.js\";\nimport { ImageNodeView, OpacityGroupNodeView } from \"./views/basic.js\";\nimport { NodeView } from \"./views/NodeView.js\";\nimport { ProgressBarNodeView, SliderNodeView } from \"./views/ValueControlNodeViews.js\";\nimport { SpineNodeView } from \"./views/SpineNodeView.js\";\n\nfunction findSpineChild(view: Container): Spine | undefined {\n if (view instanceof NodeView) return view.getSpine();\n return view instanceof Spine ? view : view.children.find((child): child is Spine => child instanceof Spine);\n}\n\n/** Reads the current 1-based animation frame for an editor Spine node. */\nexport function getSpineViewPlayback(view: Container, skeletonData: SkeletonData, animation: string): { current: number; total: number } | undefined {\n const spine = findSpineChild(view);\n const track = spine?.state.tracks[0];\n const duration = skeletonData.findAnimation(animation)?.duration;\n if (track === null || track === undefined || duration === undefined || duration <= 0) return undefined;\n const fps = skeletonData.fps && skeletonData.fps > 0 ? skeletonData.fps : 60;\n const total = Math.max(1, Math.round(duration * fps));\n const time = track.loop ? track.trackTime % duration : Math.min(track.trackTime, duration);\n return { current: Math.min(total, Math.floor(time * fps) + 1), total };\n}\n\n/** Seeks an editor Spine node to a 1-based animation frame without changing its serialized animation settings. */\nexport function setSpineViewFrame(view: Container, frame: number, skeletonData: SkeletonData, animation: string): void {\n const spine = findSpineChild(view);\n const track = spine?.state.tracks[0];\n const duration = skeletonData.findAnimation(animation)?.duration;\n if (track === null || track === undefined || duration === undefined || duration <= 0) return;\n const fps = skeletonData.fps && skeletonData.fps > 0 ? skeletonData.fps : 60;\n const total = Math.max(1, Math.round(duration * fps));\n track.trackTime = Math.min(total, Math.max(1, Math.round(frame)) - 1) / fps;\n spine?.update(0);\n}\n\n/** Forces an editor-only button state; the node's serialized `enabled` and states stay untouched. */\nexport function setButtonViewState(view: Container, state: ButtonStateKey): void {\n if (view instanceof ButtonNodeView) view.setState(state);\n}\n\n/** Forces an editor-only checkbox checked state; the node's serialized `defaultChecked` stays untouched. */\nexport function setCheckboxViewChecked(view: Container, checked: boolean): void {\n if (view instanceof CheckboxNodeView) view.forceCheck(checked);\n}\n\n/** Forces an editor-only staged button preview stage; the document's `stages`/current stage stay untouched. */\nexport function setStagedButtonViewStage(view: Container, index: number): void {\n if (view instanceof StagedButtonNodeView) view.forceStage(index);\n}\n\n/** Forces an editor-only staged button visual state; the node's serialized `enabled` stays untouched. */\nexport function setStagedButtonViewState(view: Container, state: ButtonStateKey): void {\n if (view instanceof StagedButtonNodeView) view.setState(state);\n}\n\n/** Live-previews nine-slice border edits while dragging the canvas gizmo; commits only on release. */\nexport function previewNineSlice(view: Container, nineSlice: LayoutPadding): void {\n if (view instanceof ImageNodeView || view instanceof ButtonNodeView || view instanceof StagedButtonNodeView) view.previewNineSlice(nineSlice);\n}\n\n/** Applies an editor-only slider preview value without touching the document. */\nexport function setSliderViewValue(view: Container, value: number): void {\n if (view instanceof SliderNodeView) view.value = value;\n}\n\n/** Applies an editor-only progress preview without touching the document. */\nexport function setProgressBarViewProgress(view: Container, progress: number): void {\n if (view instanceof ProgressBarNodeView) view.progress = progress;\n}\n\n/** One-way sync from game code (or editor preview) into the widget: highlights a dot without emitting `onPageChange`. */\nexport function setPaginationViewPage(view: Container, page: number): void {\n if (view instanceof PaginationNodeView) view.page = page;\n}\n\n/**\n * Rebuilds the widget's dots for a runtime-known page count, e.g. once actual content length is known.\n * Ignored while the widget pages through authored `items`: there the item list already fixes the count.\n */\nexport function setPaginationViewPageCount(view: Container, pageCount: number): void {\n if (view instanceof PaginationNodeView) view.pageCount = pageCount;\n}\n\n/**\n * Все элементы таблицы в порядке иерархии, включая скрытые вместимостью — «что вообще есть».\n * Возвращает пустой список, если `view` не item-table.\n */\nexport function getItemTableViewItems(view: Container): Container[] {\n return view instanceof ItemTableNodeView ? view.items : [];\n}\n\n/** Элементы, показанные прямо сейчас: столько, сколько влезает в текущем профиле. */\nexport function getItemTableViewVisibleItems(view: Container): Container[] {\n return view instanceof ItemTableNodeView ? view.visibleItems : [];\n}\n\n/** Один элемент по индексу — адресация, на которой игровой код раскладывает свои данные. */\nexport function getItemTableViewItem(view: Container, index: number): Container | undefined {\n return view instanceof ItemTableNodeView ? view.itemAt(index) : undefined;\n}\n\n/** Транзиентно меняет вместимость; `undefined` возвращает авторское значение профиля. */\nexport function setItemTableViewVisibleCount(view: Container, count: number | undefined): void {\n if (view instanceof ItemTableNodeView) view.visibleCount = count;\n}\n\n/** Показывает или прячет все элементы разом; `undefined` возвращает управление вместимости. */\nexport function setItemTableViewItemsVisible(view: Container, visible: boolean | undefined): void {\n if (view instanceof ItemTableNodeView) view.setItemsVisible(visible);\n}\n\n/** Switches which direct child (\"page\") of a page group is shown; every other child is hidden. Out-of-range indices clamp into range, so passing whatever a caller has on hand can never throw or leave the group blank. */\nexport function setPageGroupViewPage(view: Container, page: number): void {\n if (view instanceof PageGroupNodeView) view.page = page;\n}\n\n/** Currently shown page index, or `undefined` if `view` is not a page group. */\nexport function getPageGroupViewPage(view: Container): number | undefined {\n return view instanceof PageGroupNodeView ? view.page : undefined;\n}\n\n/** Total number of pages (authored children plus any appended via `addPageGroupViewPage`); `0` if `view` is not a page group. */\nexport function getPageGroupViewPageCount(view: Container): number {\n return view instanceof PageGroupNodeView ? view.pageCount : 0;\n}\n\n/**\n * Appends a page built at runtime (e.g. the `root` from `buildPrefabView`/`loadPrefabView`, or any\n * hand-built `Container`) after the last one — for a dataset that grows during play (a spin history\n * list, a chat log, ...) rather than one fully known at authoring time. Fits the page to the group's\n * current rectangle and hides it until switched to. Returns the new page's index, or `undefined` if\n * `view` is not a page group. Keep `setPaginationViewPageCount` in sync with the resulting `pageCount`\n * if a `pagination` widget is showing this group's page count.\n */\nexport function addPageGroupViewPage(view: Container, page: Container): number | undefined {\n return view instanceof PageGroupNodeView ? view.addPage(page) : undefined;\n}\n\n/**\n * Fades a whole subtree by driving one opacity group, the cheap `CanvasGroup.alpha` equivalent: the\n * value multiplies into every descendant through PixiJS `worldAlpha`, so animating a fade is one write\n * per frame regardless of how many nodes are inside. The node's authored `opacity` stays untouched in\n * the document; pass `undefined` to hand control back to it. Tweening itself belongs to game code —\n * the runtime deliberately ships no animation engine, the same way `page-group` ships no swipe gesture.\n */\nexport function setOpacityGroupViewOpacity(view: Container, opacity: number | undefined): void {\n if (view instanceof OpacityGroupNodeView) view.setOpacity(opacity);\n}\n\n/** Enables or pauses editor-only automatic playback without affecting serialized node data. */\nexport function setSpineViewAutoplay(view: Container, autoplay: boolean): void {\n const spine = findSpineChild(view);\n if (spine !== undefined) spine.autoUpdate = autoplay;\n}\n\n/** Activates authored bone/slot part connectors on one Spine node without mutating the document. */\nexport function setSpineConnectorBonesActive(view: Container, active: boolean): void {\n if (view instanceof SpineNodeView) view.activeConnectorBones = active;\n}\n\n/** Reasserts active connector matrices after a host performs live node-view updates. */\nexport function refreshSpineConnectorBones(nodeViews: ReadonlyMap<string, Container>): void {\n for (const view of nodeViews.values()) if (view instanceof SpineNodeView && view.activeConnectorBones) view.refreshConnectorBones();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"controls.js","sourceRoot":"","sources":["../src/controls.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SkeletonData, Spine } from \"@esotericsoftware/spine-pixi-v8\";\r\nimport { type ButtonStateKey, type LayoutPadding } from \"@pixi-ui-editor/schema\";\r\nimport { Container } from \"pixi.js\";\r\nimport { ButtonNodeView } from \"./views/ButtonNodeView.js\";\r\nimport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\r\nimport { ItemTableNodeView } from \"./views/ItemTableNodeView.js\";\r\nimport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\r\nimport { PaginationNodeView } from \"./views/PaginationNodeView.js\";\r\nimport { StagedButtonNodeView } from \"./views/StagedButtonNodeView.js\";\r\nimport { ImageNodeView, OpacityGroupNodeView } from \"./views/basic.js\";\r\nimport { NodeView } from \"./views/NodeView.js\";\r\nimport { ProgressBarNodeView, SliderNodeView } from \"./views/ValueControlNodeViews.js\";\r\nimport { SpineNodeView } from \"./views/SpineNodeView.js\";\r\n\r\nfunction findSpineChild(view: Container): Spine | undefined {\r\n if (view instanceof NodeView) return view.getSpine();\r\n return view instanceof Spine ? view : view.children.find((child): child is Spine => child instanceof Spine);\r\n}\r\n\r\n/** Reads the current 1-based animation frame for an editor Spine node. */\r\nexport function getSpineViewPlayback(view: Container, skeletonData: SkeletonData, animation: string): { current: number; total: number } | undefined {\r\n const spine = findSpineChild(view);\r\n const track = spine?.state.tracks[0];\r\n const duration = skeletonData.findAnimation(animation)?.duration;\r\n if (track === null || track === undefined || duration === undefined || duration <= 0) return undefined;\r\n const fps = skeletonData.fps && skeletonData.fps > 0 ? skeletonData.fps : 60;\r\n const total = Math.max(1, Math.round(duration * fps));\r\n const time = track.loop ? track.trackTime % duration : Math.min(track.trackTime, duration);\r\n return { current: Math.min(total, Math.floor(time * fps) + 1), total };\r\n}\r\n\r\n/** Seeks an editor Spine node to a 1-based animation frame without changing its serialized animation settings. */\r\nexport function setSpineViewFrame(view: Container, frame: number, skeletonData: SkeletonData, animation: string): void {\r\n const spine = findSpineChild(view);\r\n const track = spine?.state.tracks[0];\r\n const duration = skeletonData.findAnimation(animation)?.duration;\r\n if (track === null || track === undefined || duration === undefined || duration <= 0) return;\r\n const fps = skeletonData.fps && skeletonData.fps > 0 ? skeletonData.fps : 60;\r\n const total = Math.max(1, Math.round(duration * fps));\r\n track.trackTime = Math.min(total, Math.max(1, Math.round(frame)) - 1) / fps;\r\n spine?.update(0);\r\n}\r\n\r\n/** Forces an editor-only button state; the node's serialized `enabled` and states stay untouched. */\r\nexport function setButtonViewState(view: Container, state: ButtonStateKey): void {\r\n if (view instanceof ButtonNodeView) view.setState(state);\r\n}\r\n\r\n/** Forces an editor-only checkbox checked state; the node's serialized `defaultChecked` stays untouched. */\r\nexport function setCheckboxViewChecked(view: Container, checked: boolean): void {\r\n if (view instanceof CheckboxNodeView) view.forceCheck(checked);\r\n}\r\n\r\n/** Forces an editor-only staged button preview stage; the document's `stages`/current stage stay untouched. */\r\nexport function setStagedButtonViewStage(view: Container, index: number): void {\r\n if (view instanceof StagedButtonNodeView) view.forceStage(index);\r\n}\r\n\r\n/** Forces an editor-only staged button visual state; the node's serialized `enabled` stays untouched. */\r\nexport function setStagedButtonViewState(view: Container, state: ButtonStateKey): void {\r\n if (view instanceof StagedButtonNodeView) view.setState(state);\r\n}\r\n\r\n/** Live-previews nine-slice border edits while dragging the canvas gizmo; commits only on release. */\r\nexport function previewNineSlice(view: Container, nineSlice: LayoutPadding): void {\r\n if (view instanceof ImageNodeView || view instanceof ButtonNodeView || view instanceof StagedButtonNodeView) view.previewNineSlice(nineSlice);\r\n}\r\n\r\n/** Applies an editor-only slider preview value without touching the document. */\r\nexport function setSliderViewValue(view: Container, value: number): void {\r\n if (view instanceof SliderNodeView) view.value = value;\r\n}\r\n\r\n/** Applies an editor-only progress preview without touching the document. */\r\nexport function setProgressBarViewProgress(view: Container, progress: number): void {\r\n if (view instanceof ProgressBarNodeView) view.progress = progress;\r\n}\r\n\r\n/** One-way sync from game code (or editor preview) into the widget: highlights a dot without emitting `onPageChange`. */\r\nexport function setPaginationViewPage(view: Container, page: number): void {\r\n if (view instanceof PaginationNodeView) view.page = page;\r\n}\r\n\r\n/**\r\n * Rebuilds the widget's dots for a runtime-known page count, e.g. once actual content length is known.\r\n * Ignored while the widget pages through authored `items`: there the item list already fixes the count.\r\n */\r\nexport function setPaginationViewPageCount(view: Container, pageCount: number): void {\r\n if (view instanceof PaginationNodeView) view.pageCount = pageCount;\r\n}\r\n\r\n/**\r\n * Все элементы таблицы в порядке иерархии, включая скрытые вместимостью — «что вообще есть».\r\n * Возвращает пустой список, если `view` не item-table.\r\n */\r\nexport function getItemTableViewItems(view: Container): Container[] {\r\n return view instanceof ItemTableNodeView ? view.items : [];\r\n}\r\n\r\n/** Элементы, показанные прямо сейчас: столько, сколько влезает в текущем профиле. */\r\nexport function getItemTableViewVisibleItems(view: Container): Container[] {\r\n return view instanceof ItemTableNodeView ? view.visibleItems : [];\r\n}\r\n\r\n/** Один элемент по индексу — адресация, на которой игровой код раскладывает свои данные. */\r\nexport function getItemTableViewItem(view: Container, index: number): Container | undefined {\r\n return view instanceof ItemTableNodeView ? view.itemAt(index) : undefined;\r\n}\r\n\r\n/** Транзиентно меняет вместимость; `undefined` возвращает авторское значение профиля. */\r\nexport function setItemTableViewVisibleCount(view: Container, count: number | undefined): void {\r\n if (view instanceof ItemTableNodeView) view.visibleCount = count;\r\n}\r\n\r\n/** Показывает или прячет все элементы разом; `undefined` возвращает управление вместимости. */\r\nexport function setItemTableViewItemsVisible(view: Container, visible: boolean | undefined): void {\r\n if (view instanceof ItemTableNodeView) view.setItemsVisible(visible);\r\n}\r\n\r\n/** Switches which direct child (\"page\") of a page group is shown; every other child is hidden. Out-of-range indices clamp into range, so passing whatever a caller has on hand can never throw or leave the group blank. */\r\nexport function setPageGroupViewPage(view: Container, page: number): void {\r\n if (view instanceof PageGroupNodeView) view.page = page;\r\n}\r\n\r\n/** Currently shown page index, or `undefined` if `view` is not a page group. */\r\nexport function getPageGroupViewPage(view: Container): number | undefined {\r\n return view instanceof PageGroupNodeView ? view.page : undefined;\r\n}\r\n\r\n/** Total number of pages (authored children plus any appended via `addPageGroupViewPage`); `0` if `view` is not a page group. */\r\nexport function getPageGroupViewPageCount(view: Container): number {\r\n return view instanceof PageGroupNodeView ? view.pageCount : 0;\r\n}\r\n\r\n/**\r\n * Appends a page built at runtime (e.g. the `root` from `buildPrefabView`/`loadPrefabView`, or any\r\n * hand-built `Container`) after the last one — for a dataset that grows during play (a spin history\r\n * list, a chat log, ...) rather than one fully known at authoring time. Fits the page to the group's\r\n * current rectangle and hides it until switched to. Returns the new page's index, or `undefined` if\r\n * `view` is not a page group. Keep `setPaginationViewPageCount` in sync with the resulting `pageCount`\r\n * if a `pagination` widget is showing this group's page count.\r\n */\r\nexport function addPageGroupViewPage(view: Container, page: Container): number | undefined {\r\n return view instanceof PageGroupNodeView ? view.addPage(page) : undefined;\r\n}\r\n\r\n/**\r\n * Fades a whole subtree by driving one opacity group, the cheap `CanvasGroup.alpha` equivalent: the\r\n * value multiplies into every descendant through PixiJS `worldAlpha`, so animating a fade is one write\r\n * per frame regardless of how many nodes are inside. The node's authored `opacity` stays untouched in\r\n * the document; pass `undefined` to hand control back to it. Tweening itself belongs to game code —\r\n * the runtime deliberately ships no animation engine, the same way `page-group` ships no swipe gesture.\r\n */\r\nexport function setOpacityGroupViewOpacity(view: Container, opacity: number | undefined): void {\r\n if (view instanceof OpacityGroupNodeView) view.setOpacity(opacity);\r\n}\r\n\r\n/** Enables or pauses editor-only automatic playback without affecting serialized node data. */\r\nexport function setSpineViewAutoplay(view: Container, autoplay: boolean): void {\r\n const spine = findSpineChild(view);\r\n if (spine !== undefined) spine.autoUpdate = autoplay;\r\n}\r\n\r\n/** Activates authored bone/slot part connectors on one Spine node without mutating the document. */\r\nexport function setSpineConnectorBonesActive(view: Container, active: boolean): void {\r\n if (view instanceof SpineNodeView) view.activeConnectorBones = active;\r\n}\r\n\r\n/** Reasserts active connector matrices after a host performs live node-view updates. */\r\nexport function refreshSpineConnectorBones(nodeViews: ReadonlyMap<string, Container>): void {\r\n for (const view of nodeViews.values()) if (view instanceof SpineNodeView && view.activeConnectorBones) view.refreshConnectorBones();\r\n}\r\n"]}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEvH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3K,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC","sourcesContent":["export type { SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\nexport type { Sound } from \"@pixi/sound\";\nexport * from \"./document.js\";\nexport * from \"./layout.js\";\nexport { SceneViewport } from \"./SceneViewport.js\";\nexport * from \"./layoutGroups.js\";\nexport * from \"./scrollView.js\";\nexport * from \"./pageGroup.js\";\nexport * from \"./views/NodeView.js\";\nexport { ButtonNodeView } from \"./views/ButtonNodeView.js\";\nexport { StagedButtonNodeView } from \"./views/StagedButtonNodeView.js\";\nexport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\nexport { InputNodeView } from \"./views/InputNodeView.js\";\nexport { ScrollViewNodeView } from \"./views/ScrollViewNodeView.js\";\nexport { SpineNodeView } from \"./views/SpineNodeView.js\";\nexport { ProgressBarNodeView, SliderNodeView } from \"./views/ValueControlNodeViews.js\";\nexport { PaginationNodeView } from \"./views/PaginationNodeView.js\";\nexport { ItemTableNodeView } from \"./views/ItemTableNodeView.js\";\nexport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\nexport { ParticleEmitterNodeView } from \"./views/ParticleEmitterNodeView.js\";\nexport * from \"./particles.js\";\nexport { collectNodeAssetIds } from \"./views/createNodeView.js\";\nexport { SceneLocalization } from \"./localization.js\";\nexport type { SceneLocalizationOptions } from \"./localization.js\";\nexport { BitmapTextNodeView, ImageNodeView, MaskNodeView, OpacityGroupNodeView, TextNodeView } from \"./views/basic.js\";\nexport type { BuildSceneViewOptions, PrefabViewConfiguration, SceneViewResult } from \"./scene.js\";\nexport { buildPrefabView, buildSceneView, collectRenderedNodes, loadPrefabView, previewNodeView, updateNodeView, updateParticleEmitters, loadSceneView } from \"./scene.js\";\nexport * from \"./controls.js\";\nexport { createSceneAssetCache } from \"./assets/cache.js\";\nexport type { SceneAssetCache } from \"./assets/cache.js\";\nexport * from \"./assets/textures.js\";\nexport * from \"./assets/spine.js\";\nexport * from \"./assets/fonts.js\";\nexport * from \"./assets/bitmapFonts.js\";\nexport * from \"./assets/sounds.js\";\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACvF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAC;AAC7E,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEvH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,oBAAoB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,sBAAsB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3K,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,yBAAyB,CAAC;AACxC,cAAc,oBAAoB,CAAC","sourcesContent":["export type { SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\r\nexport type { Sound } from \"@pixi/sound\";\r\nexport * from \"./document.js\";\r\nexport * from \"./layout.js\";\r\nexport { SceneViewport } from \"./SceneViewport.js\";\r\nexport * from \"./layoutGroups.js\";\r\nexport * from \"./scrollView.js\";\r\nexport * from \"./pageGroup.js\";\r\nexport * from \"./views/NodeView.js\";\r\nexport { ButtonNodeView } from \"./views/ButtonNodeView.js\";\r\nexport { StagedButtonNodeView } from \"./views/StagedButtonNodeView.js\";\r\nexport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\r\nexport { InputNodeView } from \"./views/InputNodeView.js\";\r\nexport { ScrollViewNodeView } from \"./views/ScrollViewNodeView.js\";\r\nexport { SpineNodeView } from \"./views/SpineNodeView.js\";\r\nexport { ProgressBarNodeView, SliderNodeView } from \"./views/ValueControlNodeViews.js\";\r\nexport { PaginationNodeView } from \"./views/PaginationNodeView.js\";\r\nexport { ItemTableNodeView } from \"./views/ItemTableNodeView.js\";\r\nexport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\r\nexport { ParticleEmitterNodeView } from \"./views/ParticleEmitterNodeView.js\";\r\nexport * from \"./particles.js\";\r\nexport { collectNodeAssetIds } from \"./views/createNodeView.js\";\r\nexport { SceneLocalization } from \"./localization.js\";\r\nexport type { SceneLocalizationOptions } from \"./localization.js\";\r\nexport { BitmapTextNodeView, ImageNodeView, MaskNodeView, OpacityGroupNodeView, TextNodeView } from \"./views/basic.js\";\r\nexport type { BuildSceneViewOptions, PrefabViewConfiguration, SceneViewResult } from \"./scene.js\";\r\nexport { buildPrefabView, buildSceneView, collectRenderedNodes, loadPrefabView, previewNodeView, updateNodeView, updateParticleEmitters, loadSceneView } from \"./scene.js\";\r\nexport * from \"./controls.js\";\r\nexport { createSceneAssetCache } from \"./assets/cache.js\";\r\nexport type { SceneAssetCache } from \"./assets/cache.js\";\r\nexport * from \"./assets/textures.js\";\r\nexport * from \"./assets/spine.js\";\r\nexport * from \"./assets/fonts.js\";\r\nexport * from \"./assets/bitmapFonts.js\";\r\nexport * from \"./assets/sounds.js\";\r\n"]}
|
package/dist/layout.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type LayoutProfileId, type ProjectDocument, type SpineReferenceFrame, type TextNode, type TextStyleDefinition, type UINode } from "@pixi-ui-editor/schema";
|
|
1
|
+
import { type BitmapTextNode, type BitmapTextStyle, type LayoutProfileId, type ProjectDocument, type SpineReferenceFrame, type TextNode, type TextStyleDefinition, type UINode } from "@pixi-ui-editor/schema";
|
|
2
2
|
export type ResolvedProfileTransform = {
|
|
3
3
|
transform: UINode["transform"];
|
|
4
4
|
visible: boolean;
|
|
@@ -38,6 +38,8 @@ export declare function getCanvasLogicalSize(screenSize: LayoutSize, referenceRe
|
|
|
38
38
|
export declare function resolveProfileTransform(node: UINode, profile: LayoutProfileId): ResolvedProfileTransform;
|
|
39
39
|
/** Resolves a text node's optional base style with the active profile's sparse style override. */
|
|
40
40
|
export declare function resolveTextStyle(node: TextNode, profile: LayoutProfileId): TextStyleDefinition | undefined;
|
|
41
|
+
/** Resolves bitmap text's base visual presentation with the active sparse profile override. */
|
|
42
|
+
export declare function resolveBitmapTextStyle(node: BitmapTextNode, profile: LayoutProfileId): BitmapTextStyle;
|
|
41
43
|
/** Resolves the authored initial Spine presentation; `null` explicitly clears a base animation. */
|
|
42
44
|
export declare function resolveSpineSettings(node: SpineNode, profile: LayoutProfileId): ResolvedSpineSettings;
|
|
43
45
|
/**
|
package/dist/layout.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,QAAQ,EAAE,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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"}
|
package/dist/layout.js
CHANGED
|
@@ -47,6 +47,19 @@ export function resolveTextStyle(node, profile) {
|
|
|
47
47
|
return undefined;
|
|
48
48
|
return { ...DEFAULT_TEXT_STYLE, ...node.style, ...override };
|
|
49
49
|
}
|
|
50
|
+
/** Resolves bitmap text's base visual presentation with the active sparse profile override. */
|
|
51
|
+
export function resolveBitmapTextStyle(node, profile) {
|
|
52
|
+
return {
|
|
53
|
+
assetId: node.assetId,
|
|
54
|
+
fontSize: node.fontSize,
|
|
55
|
+
fill: node.fill,
|
|
56
|
+
align: node.align,
|
|
57
|
+
verticalAlign: node.verticalAlign,
|
|
58
|
+
letterSpacing: node.letterSpacing,
|
|
59
|
+
wordWrap: node.wordWrap,
|
|
60
|
+
...node.bitmapTextOverrides?.[profile],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
50
63
|
/** Resolves the authored initial Spine presentation; `null` explicitly clears a base animation. */
|
|
51
64
|
export function resolveSpineSettings(node, profile) {
|
|
52
65
|
const override = node.spineOverrides?.[profile];
|
package/dist/layout.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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","sourcesContent":["import { type LayoutProfileId, type ProjectDocument, type SpineReferenceFrame, type TextNode, type TextStyleDefinition, type UINode } from \"@pixi-ui-editor/schema\";\r\n\r\nexport type ResolvedProfileTransform = {\r\n transform: UINode[\"transform\"];\r\n visible: boolean;\r\n};\r\n\r\nexport type LayoutSize = { width: number; height: number };\n\nexport type FittedViewport = {\n scale: number;\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\r\ntype SpineNode = Extract<UINode, { type: \"spine\" }>;\r\nexport type ResolvedSpineSettings = { animation: string | undefined; autoplay: boolean; loop: boolean; animationSpeed: number };\r\n\r\nexport const DEFAULT_TEXT_STYLE: TextStyleDefinition = {\r\n fontFamily: \"Arial\", fontSize: 24, fontWeight: \"normal\", fontStyle: \"normal\", fill: \"#FFFFFF\",\r\n align: \"left\", verticalAlign: \"top\", wordWrap: false, breakWords: false, letterSpacing: 0,\r\n};\r\n\r\nexport const CANVAS_SCALER_MATCH_WIDTH_OR_HEIGHT = 0.5;\n\n/** Uniformly contains an authored viewport inside a physical host without changing its aspect ratio. */\nexport function fitViewportToHost(viewport: LayoutSize, host: LayoutSize): FittedViewport {\n const scale = Math.min(host.width / viewport.width, host.height / viewport.height);\n const width = viewport.width * scale;\n const height = viewport.height * scale;\n return {\n scale,\n x: (host.width - width) / 2,\n y: (host.height - height) / 2,\n width,\n height,\n };\n}\n\r\n/**\r\n * Unity Canvas Scaler's `Scale With Screen Size / Match Width Or Height` calculation.\r\n * Width and height are blended in logarithmic space, producing one uniform scale for the Canvas.\r\n */\r\nexport function getCanvasScale(\r\n screenSize: LayoutSize,\r\n referenceResolution: LayoutSize,\r\n matchWidthOrHeight = CANVAS_SCALER_MATCH_WIDTH_OR_HEIGHT,\r\n): number {\r\n const widthScale = screenSize.width / referenceResolution.width;\r\n const heightScale = screenSize.height / referenceResolution.height;\r\n const logWidth = Math.log2(widthScale);\r\n const logHeight = Math.log2(heightScale);\r\n return 2 ** (logWidth + (logHeight - logWidth) * matchWidthOrHeight);\r\n}\r\n\r\n/** Logical RectTransform space exposed by a scaled Canvas at the current screen aspect ratio. */\r\nexport function getCanvasLogicalSize(screenSize: LayoutSize, referenceResolution: LayoutSize): LayoutSize {\r\n const scale = getCanvasScale(screenSize, referenceResolution);\r\n return { width: screenSize.width / scale, height: screenSize.height / scale };\r\n}\r\n\r\n/** Resolves a node's base transform with a profile override applied field by field. */\r\nexport function resolveProfileTransform(node: UINode, profile: LayoutProfileId): ResolvedProfileTransform {\r\n const override = node.layoutOverrides?.[profile];\r\n\r\n return {\r\n transform: { ...node.transform, ...override?.transform },\r\n visible: override?.visible ?? node.visible,\r\n };\r\n}\r\n\r\n/** Resolves a text node's optional base style with the active profile's sparse style override. */\r\nexport function resolveTextStyle(node: TextNode, profile: LayoutProfileId): TextStyleDefinition | undefined {\r\n const override = node.textStyleOverrides?.[profile];\r\n if (node.style === undefined && override === undefined) return undefined;\r\n return { ...DEFAULT_TEXT_STYLE, ...node.style, ...override };\r\n}\r\n\r\n/** Resolves the authored initial Spine presentation; `null` explicitly clears a base animation. */\r\nexport function resolveSpineSettings(node: SpineNode, profile: LayoutProfileId): ResolvedSpineSettings {\r\n const override = node.spineOverrides?.[profile];\r\n return {\r\n animation: override?.animation === null ? undefined : override?.animation ?? node.animation,\r\n autoplay: override?.autoplay ?? node.autoplay ?? true,\r\n loop: override?.loop ?? node.loop ?? true,\r\n animationSpeed: override?.animationSpeed ?? node.animationSpeed ?? 1,\r\n };\r\n}\r\n\r\n/**\r\n * Resolves a Unity-style RectTransform in logical Canvas units.\r\n *\r\n * `x/y` are anchoredPosition (the pivot offset from the anchor reference), while `width/height`\r\n * are sizeDelta. A point anchor therefore keeps an absolute logical size; a split anchor adds its\r\n * share of the parent rectangle. Canvas Scaler is deliberately outside this function.\r\n */\r\nexport function resolveAnchoredTransform(transform: UINode[\"transform\"], parentSize?: LayoutSize): UINode[\"transform\"] {\r\n if (parentSize === undefined) return transform;\r\n const minX = transform.anchorMinX ?? 0;\r\n const minY = transform.anchorMinY ?? 0;\r\n const maxX = transform.anchorMaxX ?? minX;\r\n const maxY = transform.anchorMaxY ?? minY;\r\n const pivotX = transform.pivotX ?? 0;\r\n const pivotY = transform.pivotY ?? 0;\r\n return {\r\n ...transform,\r\n x: (minX + (maxX - minX) * pivotX) * parentSize.width + transform.x,\r\n y: (minY + (maxY - minY) * pivotY) * parentSize.height + transform.y,\r\n width: (maxX - minX) * parentSize.width + transform.width,\r\n height: (maxY - minY) * parentSize.height + transform.height,\r\n };\r\n}\r\n\r\n/** Picks the layout profile for a viewport using the document's aspect-ratio rule; the breakpoint itself is mobile. */\r\nexport function resolveProfileForViewport(settings: ProjectDocument[\"settings\"], width: number, height: number): LayoutProfileId {\r\n return width / height <= settings.layoutProfileSelection.mobileMaxAspectRatio ? \"mobile\" : \"desktop\";\r\n}\r\n\r\nexport function fitSpineToTransform(\r\n bounds: { x: number; y: number; width: number; height: number },\r\n transform: UINode[\"transform\"],\r\n referenceFrame?: SpineReferenceFrame,\r\n): { scaleX: number; scaleY: number; x: number; y: number } | undefined {\r\n const fitBounds = referenceFrame ?? bounds;\r\n if (!Number.isFinite(fitBounds.x) || !Number.isFinite(fitBounds.y) || !Number.isFinite(fitBounds.width) || !Number.isFinite(fitBounds.height) || fitBounds.width <= 0 || fitBounds.height <= 0) return undefined;\r\n if (referenceFrame !== undefined) {\r\n const scale = Math.min(transform.width / referenceFrame.width, transform.height / referenceFrame.height);\r\n return Number.isFinite(scale) && scale > 0\r\n ? {\r\n scaleX: scale,\r\n scaleY: scale,\r\n x: (transform.width - referenceFrame.width * scale) / 2 - referenceFrame.x * scale,\r\n y: (transform.height - referenceFrame.height * scale) / 2 - referenceFrame.y * scale,\r\n }\r\n : undefined;\r\n }\r\n const scaleX = transform.width / bounds.width;\r\n const scaleY = transform.height / bounds.height;\r\n return Number.isFinite(scaleX) && scaleX > 0 && Number.isFinite(scaleY) && scaleY > 0\r\n ? { scaleX, scaleY, x: -bounds.x * scaleX, y: -bounds.y * scaleY }\r\n : undefined;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../src/layout.ts"],"names":[],"mappings":"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","sourcesContent":["import { type BitmapTextNode, type BitmapTextStyle, type LayoutProfileId, type ProjectDocument, type SpineReferenceFrame, type TextNode, type TextStyleDefinition, type UINode } from \"@pixi-ui-editor/schema\";\r\n\r\nexport type ResolvedProfileTransform = {\r\n transform: UINode[\"transform\"];\r\n visible: boolean;\r\n};\r\n\r\nexport type LayoutSize = { width: number; height: number };\r\n\r\nexport type FittedViewport = {\r\n scale: number;\r\n x: number;\r\n y: number;\r\n width: number;\r\n height: number;\r\n};\r\n\r\ntype SpineNode = Extract<UINode, { type: \"spine\" }>;\r\nexport type ResolvedSpineSettings = { animation: string | undefined; autoplay: boolean; loop: boolean; animationSpeed: number };\r\n\r\nexport const DEFAULT_TEXT_STYLE: TextStyleDefinition = {\r\n fontFamily: \"Arial\", fontSize: 24, fontWeight: \"normal\", fontStyle: \"normal\", fill: \"#FFFFFF\",\r\n align: \"left\", verticalAlign: \"top\", wordWrap: false, breakWords: false, letterSpacing: 0,\r\n};\r\n\r\nexport const CANVAS_SCALER_MATCH_WIDTH_OR_HEIGHT = 0.5;\r\n\r\n/** Uniformly contains an authored viewport inside a physical host without changing its aspect ratio. */\r\nexport function fitViewportToHost(viewport: LayoutSize, host: LayoutSize): FittedViewport {\r\n const scale = Math.min(host.width / viewport.width, host.height / viewport.height);\r\n const width = viewport.width * scale;\r\n const height = viewport.height * scale;\r\n return {\r\n scale,\r\n x: (host.width - width) / 2,\r\n y: (host.height - height) / 2,\r\n width,\r\n height,\r\n };\r\n}\r\n\r\n/**\r\n * Unity Canvas Scaler's `Scale With Screen Size / Match Width Or Height` calculation.\r\n * Width and height are blended in logarithmic space, producing one uniform scale for the Canvas.\r\n */\r\nexport function getCanvasScale(\r\n screenSize: LayoutSize,\r\n referenceResolution: LayoutSize,\r\n matchWidthOrHeight = CANVAS_SCALER_MATCH_WIDTH_OR_HEIGHT,\r\n): number {\r\n const widthScale = screenSize.width / referenceResolution.width;\r\n const heightScale = screenSize.height / referenceResolution.height;\r\n const logWidth = Math.log2(widthScale);\r\n const logHeight = Math.log2(heightScale);\r\n return 2 ** (logWidth + (logHeight - logWidth) * matchWidthOrHeight);\r\n}\r\n\r\n/** Logical RectTransform space exposed by a scaled Canvas at the current screen aspect ratio. */\r\nexport function getCanvasLogicalSize(screenSize: LayoutSize, referenceResolution: LayoutSize): LayoutSize {\r\n const scale = getCanvasScale(screenSize, referenceResolution);\r\n return { width: screenSize.width / scale, height: screenSize.height / scale };\r\n}\r\n\r\n/** Resolves a node's base transform with a profile override applied field by field. */\r\nexport function resolveProfileTransform(node: UINode, profile: LayoutProfileId): ResolvedProfileTransform {\r\n const override = node.layoutOverrides?.[profile];\r\n\r\n return {\r\n transform: { ...node.transform, ...override?.transform },\r\n visible: override?.visible ?? node.visible,\r\n };\r\n}\r\n\r\n/** Resolves a text node's optional base style with the active profile's sparse style override. */\r\nexport function resolveTextStyle(node: TextNode, profile: LayoutProfileId): TextStyleDefinition | undefined {\r\n const override = node.textStyleOverrides?.[profile];\r\n if (node.style === undefined && override === undefined) return undefined;\r\n return { ...DEFAULT_TEXT_STYLE, ...node.style, ...override };\r\n}\r\n\r\n/** Resolves bitmap text's base visual presentation with the active sparse profile override. */\r\nexport function resolveBitmapTextStyle(node: BitmapTextNode, profile: LayoutProfileId): BitmapTextStyle {\r\n return {\r\n assetId: node.assetId,\r\n fontSize: node.fontSize,\r\n fill: node.fill,\r\n align: node.align,\r\n verticalAlign: node.verticalAlign,\r\n letterSpacing: node.letterSpacing,\r\n wordWrap: node.wordWrap,\r\n ...node.bitmapTextOverrides?.[profile],\r\n };\r\n}\r\n\r\n/** Resolves the authored initial Spine presentation; `null` explicitly clears a base animation. */\r\nexport function resolveSpineSettings(node: SpineNode, profile: LayoutProfileId): ResolvedSpineSettings {\r\n const override = node.spineOverrides?.[profile];\r\n return {\r\n animation: override?.animation === null ? undefined : override?.animation ?? node.animation,\r\n autoplay: override?.autoplay ?? node.autoplay ?? true,\r\n loop: override?.loop ?? node.loop ?? true,\r\n animationSpeed: override?.animationSpeed ?? node.animationSpeed ?? 1,\r\n };\r\n}\r\n\r\n/**\r\n * Resolves a Unity-style RectTransform in logical Canvas units.\r\n *\r\n * `x/y` are anchoredPosition (the pivot offset from the anchor reference), while `width/height`\r\n * are sizeDelta. A point anchor therefore keeps an absolute logical size; a split anchor adds its\r\n * share of the parent rectangle. Canvas Scaler is deliberately outside this function.\r\n */\r\nexport function resolveAnchoredTransform(transform: UINode[\"transform\"], parentSize?: LayoutSize): UINode[\"transform\"] {\r\n if (parentSize === undefined) return transform;\r\n const minX = transform.anchorMinX ?? 0;\r\n const minY = transform.anchorMinY ?? 0;\r\n const maxX = transform.anchorMaxX ?? minX;\r\n const maxY = transform.anchorMaxY ?? minY;\r\n const pivotX = transform.pivotX ?? 0;\r\n const pivotY = transform.pivotY ?? 0;\r\n return {\r\n ...transform,\r\n x: (minX + (maxX - minX) * pivotX) * parentSize.width + transform.x,\r\n y: (minY + (maxY - minY) * pivotY) * parentSize.height + transform.y,\r\n width: (maxX - minX) * parentSize.width + transform.width,\r\n height: (maxY - minY) * parentSize.height + transform.height,\r\n };\r\n}\r\n\r\n/** Picks the layout profile for a viewport using the document's aspect-ratio rule; the breakpoint itself is mobile. */\r\nexport function resolveProfileForViewport(settings: ProjectDocument[\"settings\"], width: number, height: number): LayoutProfileId {\r\n return width / height <= settings.layoutProfileSelection.mobileMaxAspectRatio ? \"mobile\" : \"desktop\";\r\n}\r\n\r\nexport function fitSpineToTransform(\r\n bounds: { x: number; y: number; width: number; height: number },\r\n transform: UINode[\"transform\"],\r\n referenceFrame?: SpineReferenceFrame,\r\n): { scaleX: number; scaleY: number; x: number; y: number } | undefined {\r\n const fitBounds = referenceFrame ?? bounds;\r\n if (!Number.isFinite(fitBounds.x) || !Number.isFinite(fitBounds.y) || !Number.isFinite(fitBounds.width) || !Number.isFinite(fitBounds.height) || fitBounds.width <= 0 || fitBounds.height <= 0) return undefined;\r\n if (referenceFrame !== undefined) {\r\n const scale = Math.min(transform.width / referenceFrame.width, transform.height / referenceFrame.height);\r\n return Number.isFinite(scale) && scale > 0\r\n ? {\r\n scaleX: scale,\r\n scaleY: scale,\r\n x: (transform.width - referenceFrame.width * scale) / 2 - referenceFrame.x * scale,\r\n y: (transform.height - referenceFrame.height * scale) / 2 - referenceFrame.y * scale,\r\n }\r\n : undefined;\r\n }\r\n const scaleX = transform.width / bounds.width;\r\n const scaleY = transform.height / bounds.height;\r\n return Number.isFinite(scaleX) && scaleX > 0 && Number.isFinite(scaleY) && scaleY > 0\r\n ? { scaleX, scaleY, x: -bounds.x * scaleX, y: -bounds.y * scaleY }\r\n : undefined;\r\n}\r\n"]}
|
package/dist/particles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"particles.js","sourceRoot":"","sources":["../src/particles.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ParticleEffectDefinition } from \"@pixi-ui-editor/schema\";\r\n\r\nconst DEG_TO_RAD = Math.PI / 180;\r\n\r\n/** Deterministic xorshift32 generator; it has no DOM/Pixi/ticker dependency. */\r\nexport class SeededRandom {\r\n private state: number;\r\n constructor(seed: number) { this.state = seed === 0 ? 0x9e3779b9 : seed >>> 0; }\r\n next(): number { this.state ^= this.state << 13; this.state ^= this.state >>> 17; this.state ^= this.state << 5; return (this.state >>> 0) / 0x1_0000_0000; }\r\n range(min: number, max: number): number { return min + (max - min) * this.next(); }\r\n /** A uniform index in `[0, length)`; used to pick a random asset/frame. */\r\n index(length: number): number { return Math.min(length - 1, Math.floor(this.next() * length)); }\r\n}\r\n\r\nexport function lerp(a: number, b: number, t: number): number { return a + (b - a) * t; }\r\n\r\nfunction hexChannel(hex: string, offset: number): number { return parseInt(hex.slice(offset, offset + 2), 16); }\r\n/** Lerps two `#RRGGBB[AA]` strings channel-by-channel; a trailing alpha byte, if any, is ignored. */\r\nexport function lerpColorHex(start: string, end: string, t: number): string {\r\n const channel = (offset: number) => Math.round(lerp(hexChannel(start, offset), hexChannel(end, offset), t)).toString(16).padStart(2, \"0\");\r\n return `#${channel(1)}${channel(3)}${channel(5)}`;\r\n}\r\n\r\nexport type ParticleSpawnShape = \"point\" | \"rectangle\" | \"circle\";\r\n\r\n/** `point` returns the rect centre; `rectangle` is uniform over the area; `circle` is uniform over the ellipse inscribed in the rect. */\r\nexport function sampleSpawnPoint(shape: ParticleSpawnShape, width: number, height: number, random: SeededRandom): { x: number; y: number } {\r\n const cx = width / 2, cy = height / 2;\r\n if (shape === \"point\") return { x: cx, y: cy };\r\n if (shape === \"rectangle\") return { x: random.next() * width, y: random.next() * height };\r\n const angle = random.next() * Math.PI * 2;\r\n const radius = Math.sqrt(random.next());\r\n return { x: cx + Math.cos(angle) * radius * cx, y: cy + Math.sin(angle) * radius * cy };\r\n}\r\n\r\n/** A prewarmed pool entry: `render` is an opaque adapter-owned renderer object created by the same factory as the simulation slot. */\r\nexport type ParticleSlot<TRender> = {\n render: TRender;\n /** Adapter-owned static attributes must be uploaded once after this slot is (re)spawned. */\n renderDirty: boolean;\n age: number;\r\n lifetime: number;\r\n x: number;\r\n y: number;\r\n vx: number;\r\n vy: number;\r\n /** Spawn-local position; used to derive the physics delta for world-space reprojection. */\r\n spawnX: number;\r\n spawnY: number;\r\n rotationDegrees: number;\r\n angularVelocityDegrees: number;\r\n scaleStart: number;\r\n scaleEnd: number;\r\n /** Index into `random`/`sequence` source `assetIds`, picked once at spawn. */\r\n sourceIndex: number;\r\n /** Starting frame offset for a `sequence` source with `randomStartFrame`. */\r\n sequenceStart: number;\r\n /** World-space spawn position and the linear (rotate+scale) part of the emitter's world transform at spawn time; only meaningful for `world` space particles. */\r\n worldSpawnX: number;\r\n worldSpawnY: number;\r\n spawnMatrixA: number;\r\n spawnMatrixB: number;\r\n spawnMatrixC: number;\r\n spawnMatrixD: number;\r\n};\r\n\r\nfunction createZeroedSlot<TRender>(render: TRender): ParticleSlot<TRender> {\n return { render, renderDirty: false, age: 0, lifetime: 0, x: 0, y: 0, vx: 0, vy: 0, spawnX: 0, spawnY: 0, rotationDegrees: 0, angularVelocityDegrees: 0, scaleStart: 1, scaleEnd: 1, sourceIndex: 0, sequenceStart: 0, worldSpawnX: 0, worldSpawnY: 0, spawnMatrixA: 1, spawnMatrixB: 0, spawnMatrixC: 0, spawnMatrixD: 1 };\n}\nfunction resetSlot<TRender>(slot: ParticleSlot<TRender>): void {\n // Hot release path: reset in place instead of allocating a temporary zeroed slot for Object.assign.\n slot.renderDirty = false; slot.age = 0; slot.lifetime = 0; slot.x = 0; slot.y = 0; slot.vx = 0; slot.vy = 0;\n slot.spawnX = 0; slot.spawnY = 0; slot.rotationDegrees = 0; slot.angularVelocityDegrees = 0;\n slot.scaleStart = 1; slot.scaleEnd = 1; slot.sourceIndex = 0; slot.sequenceStart = 0;\n slot.worldSpawnX = 0; slot.worldSpawnY = 0;\n slot.spawnMatrixA = 1; slot.spawnMatrixB = 0; slot.spawnMatrixC = 0; slot.spawnMatrixD = 1;\n}\n\r\n/**\r\n * Prewarmed object pool. `acquire`/`release` never call the factory; only `resize` does, and only for\r\n * the capacity delta. Shrinking removes idle free slots immediately; active slots beyond the new\r\n * capacity keep running and are permanently destroyed (via `onRemove`, never recycled) the next time\r\n * they are released instead of returning to the free list.\r\n */\r\nexport class ParticlePool<T> {\r\n private readonly free: T[] = [];\r\n private readonly active = new Set<T>();\r\n private capacity: number;\r\n public dropped = 0;\r\n constructor(private readonly factory: () => T, capacity: number, private readonly onRemove?: (value: T) => void) {\r\n this.capacity = capacity;\r\n for (let i = 0; i < capacity; i++) this.free.push(factory());\r\n }\r\n acquire(): T | undefined {\r\n const value = this.free.pop();\r\n if (value === undefined) { this.dropped++; return undefined; }\r\n this.active.add(value);\r\n return value;\r\n }\r\n release(value: T): void {\r\n if (!this.active.has(value)) return;\r\n const overCapacity = this.free.length + this.active.size > this.capacity;\r\n this.active.delete(value);\r\n if (overCapacity) this.onRemove?.(value);\r\n else this.free.push(value);\r\n }\r\n resize(capacity: number): void {\r\n if (capacity > this.capacity) {\r\n const total = this.free.length + this.active.size;\r\n for (let i = total; i < capacity; i++) this.free.push(this.factory());\r\n } else if (capacity < this.capacity) {\r\n while (this.free.length + this.active.size > capacity && this.free.length > 0) this.onRemove?.(this.free.pop()!);\r\n }\r\n this.capacity = capacity;\r\n }\r\n /** Permanently destroys every slot, free and active alike; used by `dispose()`. */\r\n clear(): void {\r\n for (const value of this.free.splice(0, this.free.length)) this.onRemove?.(value);\r\n for (const value of this.active) this.onRemove?.(value);\r\n this.active.clear();\r\n this.capacity = 0;\r\n }\r\n get values(): ReadonlySet<T> { return this.active; }\r\n get limit(): number { return this.capacity; }\r\n}\r\n\r\nexport type ParticleSpawnContext = { width: number; height: number; space: \"local\" | \"world\" };\r\nexport type ParticleDiagnostics = { active: number; dropped: number; playing: boolean; stopped: boolean; disposed: boolean };\r\n\r\n/** Adapter-supplied, renderer-specific operations. The simulator never imports Pixi. */\r\nexport type ParticleRenderHooks<TRender> = {\n createRender(): TRender;\r\n hideRender(render: TRender): void;\r\n destroyRender(render: TRender): void;\r\n /** The emitter's current world transform linear part `{a,b,c,d}` and translation `{tx,ty}`; read only when a `world`-space particle spawns. */\r\n getWorldTransform(): { a: number; b: number; c: number; d: number; tx: number; ty: number };\r\n};\n\r\n/**\r\n * Schema-neutral, deterministic particle simulation over a prewarmed pool. Owns lifecycle\r\n * (`play`/`pause`/`step`/`restart`/`stop`/`dispose`), fixed-step ticking, seeded spawn parameters and\r\n * burst/rate scheduling. Rendering (texture, tint, local/world projection) is the adapter's job; this\r\n * class only exposes the pool's active slots and the effect definition for it to read.\r\n */\r\nexport class ParticleSimulator<TRender> {\n static readonly stepSeconds = 1 / 60;\r\n private readonly pool: ParticlePool<ParticleSlot<TRender>>;\r\n private random: SeededRandom;\r\n private elapsed = 0;\r\n private stepAccumulator = 0;\r\n private emissionAccumulator = 0;\r\n private burstCursors: number[];\r\n private multiplier = 1;\r\n private emitting = false;\n private simulating = false;\n private stopped = false;\n private disposed = false;\n private context: ParticleSpawnContext = { width: 0, height: 0, space: \"local\" };\r\n\r\n constructor(public definition: ParticleEffectDefinition, private readonly hooks: ParticleRenderHooks<TRender>) {\r\n this.random = new SeededRandom(definition.seed);\r\n this.burstCursors = definition.emission.bursts.map(() => 0);\r\n this.pool = new ParticlePool<ParticleSlot<TRender>>(\r\n () => createZeroedSlot(hooks.createRender()),\r\n definition.maxParticles,\r\n (slot) => hooks.destroyRender(slot.render),\r\n );\r\n }\r\n\r\n get activeSlots(): ReadonlySet<ParticleSlot<TRender>> { return this.pool.values; }\r\n\r\n setEmissionMultiplier(value: number): void {\r\n if (!Number.isFinite(value) || value < 0) throw new RangeError(\"Emission multiplier must be finite and non-negative.\");\r\n this.multiplier = value;\r\n }\r\n\r\n /** Adopts a new definition reference without ever comparing identity: unrelated edits, seed changes and texture changes never reset accumulator, PRNG or live particles. Only `maxParticles` triggers a pool resize. */\r\n syncEffect(effect: ParticleEffectDefinition): void {\r\n this.definition = effect;\r\n if (this.pool.limit !== effect.maxParticles) this.pool.resize(effect.maxParticles);\r\n const cursors = effect.emission.bursts.map((_, index) => this.burstCursors[index] ?? 0);\r\n this.burstCursors = cursors;\r\n }\r\n\r\n play(): void { if (this.disposed) return; this.emitting = true; this.simulating = true; this.stopped = false; }\n /** Freezes emission and every live particle without resetting time or PRNG. */\n pause(): void { if (this.disposed) return; this.emitting = false; this.simulating = false; this.stopped = false; }\n /** Stops new spawns; already-emitted particles keep simulating to their natural death. */\n stop(): void {\n if (this.disposed) return;\n this.emitting = false;\n this.simulating = this.pool.values.size > 0;\n this.stopped = true;\n }\n\r\n restart(): void {\r\n if (this.disposed) return;\r\n for (const slot of [...this.pool.values]) this.releaseSlot(slot);\r\n this.elapsed = 0;\r\n this.stepAccumulator = 0;\r\n this.emissionAccumulator = 0;\r\n this.burstCursors = this.definition.emission.bursts.map(() => 0);\n this.pool.dropped = 0;\n this.random = new SeededRandom(this.definition.seed);\n this.emitting = true;\n this.simulating = true;\n this.stopped = false;\n }\r\n\r\n /** Idempotent terminal cleanup: destroys every pooled render object and excludes the view from further updates. */\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\n this.emitting = false;\n this.simulating = false;\n this.stopped = false;\n this.pool.clear();\r\n }\r\n\r\n /** Advances exactly one fixed step regardless of paused/stopped state, and never changes it. */\r\n step(context: ParticleSpawnContext): boolean {\n if (this.disposed) return false;\n this.context = context;\n this.tick(ParticleSimulator.stepSeconds);\n return true;\n }\n\n update(deltaSeconds: number, context: ParticleSpawnContext): boolean {\n if (this.disposed || !this.simulating) return false;\n this.context = context;\n this.stepAccumulator = Math.min(this.stepAccumulator + Math.max(0, deltaSeconds), ParticleSimulator.stepSeconds * 8);\n let advanced = false;\n while (this.stepAccumulator >= ParticleSimulator.stepSeconds) {\n this.stepAccumulator -= ParticleSimulator.stepSeconds;\n this.tick(ParticleSimulator.stepSeconds);\n advanced = true;\n }\n return advanced;\n }\n\n getDiagnostics(): ParticleDiagnostics {\n return { active: this.pool.values.size, dropped: this.pool.dropped, playing: this.emitting, stopped: this.stopped && !this.disposed, disposed: this.disposed };\n }\r\n\r\n private tick(dt: number): void {\r\n // Age and move existing particles before spawning: a particle created this tick starts at age 0\r\n // and receives its first dt on the next tick, instead of being silently pre-aged by one step.\r\n const movement = this.definition.particle.movement;\r\n const drag = Math.max(0, 1 - movement.drag * dt);\r\n for (const slot of this.pool.values) {\n slot.age += dt;\r\n if (slot.age >= slot.lifetime) { this.releaseSlot(slot); continue; }\r\n slot.vx = (slot.vx + movement.accelerationX * dt) * drag;\r\n slot.vy = (slot.vy + movement.accelerationY * dt) * drag;\r\n slot.x += slot.vx * dt;\r\n slot.y += slot.vy * dt;\r\n slot.rotationDegrees += slot.angularVelocityDegrees * dt;\r\n }\r\n\r\n const e = this.definition.emission;\r\n const cycle = e.duration + e.delay;\r\n this.elapsed += dt;\r\n if (this.emitting) {\r\n const cycleElapsed = e.loop ? this.elapsed % cycle : this.elapsed;\r\n const inWindow = cycleElapsed >= e.delay && cycleElapsed <= e.delay + e.duration;\r\n if (inWindow && e.rate > 0) {\r\n this.emissionAccumulator += e.rate * this.multiplier * dt;\r\n while (this.emissionAccumulator >= 1) { this.emissionAccumulator -= 1; this.spawnParticle(); }\r\n }\r\n for (let index = 0; index < e.bursts.length; index++) {\n const burst = e.bursts[index]!;\n const triggerBase = e.delay + burst.time;\n for (;;) {\r\n const cursor = this.burstCursors[index] ?? 0;\r\n if (!e.loop && cursor >= 1) break;\r\n const triggerAt = e.loop ? cursor * cycle + triggerBase : triggerBase;\r\n if (this.elapsed < triggerAt) break;\r\n for (let i = 0; i < burst.count; i++) this.spawnParticle();\r\n this.burstCursors[index] = cursor + 1;\n }\n }\n if (!e.loop && this.elapsed >= e.delay + e.duration) {\n this.emitting = false;\n this.stopped = true;\n }\n }\n // A completed one-shot or a graceful stop must not keep an otherwise idle emitter on the hot\n // ticker path forever. Preserve the stopped diagnostic while putting simulation fully to sleep.\n if (!this.emitting && this.pool.values.size === 0) this.simulating = false;\n }\r\n\r\n private spawnParticle(): void {\r\n const slot = this.pool.acquire();\r\n if (!slot) return;\r\n const p = this.definition.particle;\n const rand = this.random;\r\n const point = sampleSpawnPoint(p.spawnShape.type, this.context.width, this.context.height, rand);\n slot.renderDirty = true;\n slot.age = 0;\r\n slot.lifetime = rand.range(p.lifetime.min, p.lifetime.max);\r\n slot.spawnX = point.x;\r\n slot.spawnY = point.y;\r\n slot.x = point.x;\r\n slot.y = point.y;\r\n const speed = rand.range(p.movement.speed.min, p.movement.speed.max);\r\n const angle = (p.movement.directionDegrees + (rand.next() - 0.5) * p.movement.spreadDegrees) * DEG_TO_RAD;\r\n slot.vx = Math.cos(angle) * speed;\r\n slot.vy = Math.sin(angle) * speed;\r\n slot.rotationDegrees = rand.range(p.visual.rotation.initialDegrees.min, p.visual.rotation.initialDegrees.max);\r\n slot.angularVelocityDegrees = rand.range(p.visual.rotation.angularVelocityDegrees.min, p.visual.rotation.angularVelocityDegrees.max);\r\n slot.scaleStart = rand.range(p.visual.scale.start.min, p.visual.scale.start.max);\r\n slot.scaleEnd = rand.range(p.visual.scale.end.min, p.visual.scale.end.max);\r\n const source = p.visual.source;\r\n slot.sourceIndex = source.type === \"single\" ? 0 : rand.index(source.assetIds.length);\r\n slot.sequenceStart = source.type === \"sequence\" && source.randomStartFrame ? rand.index(source.assetIds.length) : 0;\r\n if (this.context.space === \"world\") {\r\n const m = this.hooks.getWorldTransform();\r\n slot.worldSpawnX = m.a * point.x + m.c * point.y + m.tx;\r\n slot.worldSpawnY = m.b * point.x + m.d * point.y + m.ty;\r\n slot.spawnMatrixA = m.a;\r\n slot.spawnMatrixB = m.b;\r\n slot.spawnMatrixC = m.c;\r\n slot.spawnMatrixD = m.d;\r\n }\r\n }\r\n\r\n private releaseSlot(slot: ParticleSlot<TRender>): void {\r\n resetSlot(slot);\r\n this.hooks.hideRender(slot.render);\r\n this.pool.release(slot);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"particles.js","sourceRoot":"","sources":["../src/particles.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG,IAAI,CAAC,EAAE,GAAG,GAAG,CAAC;AAEjC,gFAAgF;AAChF,MAAM,OAAO,YAAY;IACf,KAAK,CAAS;IACtB,YAAY,IAAY,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC;IAChF,IAAI,KAAa,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC;IAC7J,KAAK,CAAC,GAAW,EAAE,GAAW,IAAY,OAAO,GAAG,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACnF,2EAA2E;IAC3E,KAAK,CAAC,MAAc,IAAY,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;CACjG;AAED,MAAM,UAAU,IAAI,CAAC,CAAS,EAAE,CAAS,EAAE,CAAS,IAAY,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAEzF,SAAS,UAAU,CAAC,GAAW,EAAE,MAAc,IAAY,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAChH,qGAAqG;AACrG,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,GAAW,EAAE,CAAS;IAChE,MAAM,OAAO,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1I,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;AACpD,CAAC;AAID,yIAAyI;AACzI,MAAM,UAAU,gBAAgB,CAAC,KAAyB,EAAE,KAAa,EAAE,MAAc,EAAE,MAAoB;IAC7G,MAAM,EAAE,GAAG,KAAK,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,GAAG,CAAC,CAAC;IACtC,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC;IAC/C,IAAI,KAAK,KAAK,WAAW;QAAE,OAAO,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,GAAG,MAAM,EAAE,CAAC;IAC1F,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,OAAO,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,EAAE,EAAE,CAAC;AAC1F,CAAC;AAiCD,SAAS,gBAAgB,CAAU,MAAe;IAChD,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,sBAAsB,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;AAC9T,CAAC;AACD,SAAS,SAAS,CAAU,IAA2B;IACrD,oGAAoG;IACpG,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;IAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5G,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,sBAAsB,GAAG,CAAC,CAAC;IAC5F,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;IACrF,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC;IAC3C,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;IAAC,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC;AAC7F,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,YAAY;IAKM,OAAO;IAA8C,QAAQ;IAJzE,IAAI,GAAQ,EAAE,CAAC;IACf,MAAM,GAAG,IAAI,GAAG,EAAK,CAAC;IAC/B,QAAQ,CAAS;IAClB,OAAO,GAAG,CAAC,CAAC;IACnB,YAA6B,OAAgB,EAAE,QAAgB,EAAmB,QAA6B;uBAAlF,OAAO;wBAA8C,QAAQ;QACxF,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO;QACL,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAC,OAAO,SAAS,CAAC;QAAC,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,CAAC,KAAQ;QACd,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;YAAE,OAAO;QACpC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC;QACzE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,YAAY;YAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;;YACpC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,MAAM,CAAC,QAAgB;QACrB,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YAClD,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,CAAC,EAAE;gBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACxE,CAAC;aAAM,IAAI,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAG,CAAC,CAAC;QACnH,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IACD,mFAAmF;IACnF,KAAK;QACH,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;QAClF,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM;YAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,MAAM,KAAqB,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACpD,IAAI,KAAK,KAAa,OAAO,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;CAC9C;AAcD;;;;;GAKG;AACH,MAAM,OAAO,iBAAiB;IAeT,UAAU;IAA6C,KAAK;IAd/E,MAAM,CAAU,WAAW,GAAG,CAAC,GAAG,EAAE,CAAC;IACpB,IAAI,CAAsC;IACnD,MAAM,CAAe;IACrB,OAAO,GAAG,CAAC,CAAC;IACZ,eAAe,GAAG,CAAC,CAAC;IACpB,mBAAmB,GAAG,CAAC,CAAC;IACxB,YAAY,CAAW;IACvB,UAAU,GAAG,CAAC,CAAC;IACf,QAAQ,GAAG,KAAK,CAAC;IACjB,UAAU,GAAG,KAAK,CAAC;IACnB,OAAO,GAAG,KAAK,CAAC;IAChB,QAAQ,GAAG,KAAK,CAAC;IACjB,OAAO,GAAyB,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAEhF,YAAmB,UAAoC,EAAmB,KAAmC;0BAA1F,UAAU;qBAA6C,KAAK;QAC7E,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,IAAI,YAAY,CAC1B,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,YAAY,EAAE,CAAC,EAC5C,UAAU,CAAC,YAAY,EACvB,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAC3C,CAAC;IACJ,CAAC;IAED,IAAI,WAAW,KAAyC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAElF,qBAAqB,CAAC,KAAa;QACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;YAAE,MAAM,IAAI,UAAU,CAAC,sDAAsD,CAAC,CAAC;QACvH,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,wNAAwN;IACxN,UAAU,CAAC,MAAgC;QACzC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,YAAY;YAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACxF,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC;IAC9B,CAAC;IAED,IAAI,KAAW,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;IAC/G,+EAA+E;IAC/E,KAAK,KAAW,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;IAClH,0FAA0F;IAC1F,IAAI;QACF,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,OAAO;QACL,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACjE,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACjB,IAAI,CAAC,eAAe,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QACjE,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACrD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,CAAC;IAED,mHAAmH;IACnH,OAAO;QACL,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;QACtB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC;IAED,gGAAgG;IAChG,IAAI,CAAC,OAA6B;QAChC,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,KAAK,CAAC;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,CAAC,YAAoB,EAAE,OAA6B;QACxD,IAAI,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QACpD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,CAAC,EAAE,iBAAiB,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QACrH,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,OAAO,IAAI,CAAC,eAAe,IAAI,iBAAiB,CAAC,WAAW,EAAE,CAAC;YAC7D,IAAI,CAAC,eAAe,IAAI,iBAAiB,CAAC,WAAW,CAAC;YACtD,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACzC,QAAQ,GAAG,IAAI,CAAC;QAClB,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,cAAc;QACZ,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;IACjK,CAAC;IAEO,IAAI,CAAC,EAAU;QACrB,gGAAgG;QAChG,8FAA8F;QAC9F,MAAM,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QACjD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACpC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBAAC,SAAS;YAAC,CAAC;YACpE,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;YACzD,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;YACzD,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;YACvB,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC;QAC3D,CAAC;QAED,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QACnC,MAAM,KAAK,GAAG,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC;QACnC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,YAAY,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;YAClE,MAAM,QAAQ,GAAG,YAAY,IAAI,CAAC,CAAC,KAAK,IAAI,YAAY,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,CAAC;YACjF,IAAI,QAAQ,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAC3B,IAAI,CAAC,mBAAmB,IAAI,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;gBAC1D,OAAO,IAAI,CAAC,mBAAmB,IAAI,CAAC,EAAE,CAAC;oBAAC,IAAI,CAAC,mBAAmB,IAAI,CAAC,CAAC;oBAAC,IAAI,CAAC,aAAa,EAAE,CAAC;gBAAC,CAAC;YAChG,CAAC;YACD,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBACrD,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAE,CAAC;gBAC/B,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC;gBACzC,SAAS,CAAC;oBACR,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC7C,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,MAAM,IAAI,CAAC;wBAAE,MAAM;oBAClC,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC;oBACtE,IAAI,IAAI,CAAC,OAAO,GAAG,SAAS;wBAAE,MAAM;oBACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE;wBAAE,IAAI,CAAC,aAAa,EAAE,CAAC;oBAC3D,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;gBACxC,CAAC;YACH,CAAC;YACD,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;gBACpD,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;gBACtB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;YACtB,CAAC;QACH,CAAC;QACD,6FAA6F;QAC7F,gGAAgG;QAChG,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC;YAAE,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC7E,CAAC;IAEO,aAAa;QACnB,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,MAAM,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QACnC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC;QACzB,MAAM,KAAK,GAAG,gBAAgB,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACjG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;QACb,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC;QACtB,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;QACjB,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;QACjB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrE,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,UAAU,CAAC;QAC1G,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;QAClC,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QAC9G,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC;QACrI,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjF,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC3E,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;QAC/B,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACrF,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,KAAK,UAAU,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpH,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,KAAK,OAAO,EAAE,CAAC;YACnC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,iBAAiB,EAAE,CAAC;YACzC,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACxD,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAEO,WAAW,CAAC,IAA2B;QAC7C,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;CACF","sourcesContent":["import type { ParticleEffectDefinition } from \"@pixi-ui-editor/schema\";\r\n\r\nconst DEG_TO_RAD = Math.PI / 180;\r\n\r\n/** Deterministic xorshift32 generator; it has no DOM/Pixi/ticker dependency. */\r\nexport class SeededRandom {\r\n private state: number;\r\n constructor(seed: number) { this.state = seed === 0 ? 0x9e3779b9 : seed >>> 0; }\r\n next(): number { this.state ^= this.state << 13; this.state ^= this.state >>> 17; this.state ^= this.state << 5; return (this.state >>> 0) / 0x1_0000_0000; }\r\n range(min: number, max: number): number { return min + (max - min) * this.next(); }\r\n /** A uniform index in `[0, length)`; used to pick a random asset/frame. */\r\n index(length: number): number { return Math.min(length - 1, Math.floor(this.next() * length)); }\r\n}\r\n\r\nexport function lerp(a: number, b: number, t: number): number { return a + (b - a) * t; }\r\n\r\nfunction hexChannel(hex: string, offset: number): number { return parseInt(hex.slice(offset, offset + 2), 16); }\r\n/** Lerps two `#RRGGBB[AA]` strings channel-by-channel; a trailing alpha byte, if any, is ignored. */\r\nexport function lerpColorHex(start: string, end: string, t: number): string {\r\n const channel = (offset: number) => Math.round(lerp(hexChannel(start, offset), hexChannel(end, offset), t)).toString(16).padStart(2, \"0\");\r\n return `#${channel(1)}${channel(3)}${channel(5)}`;\r\n}\r\n\r\nexport type ParticleSpawnShape = \"point\" | \"rectangle\" | \"circle\";\r\n\r\n/** `point` returns the rect centre; `rectangle` is uniform over the area; `circle` is uniform over the ellipse inscribed in the rect. */\r\nexport function sampleSpawnPoint(shape: ParticleSpawnShape, width: number, height: number, random: SeededRandom): { x: number; y: number } {\r\n const cx = width / 2, cy = height / 2;\r\n if (shape === \"point\") return { x: cx, y: cy };\r\n if (shape === \"rectangle\") return { x: random.next() * width, y: random.next() * height };\r\n const angle = random.next() * Math.PI * 2;\r\n const radius = Math.sqrt(random.next());\r\n return { x: cx + Math.cos(angle) * radius * cx, y: cy + Math.sin(angle) * radius * cy };\r\n}\r\n\r\n/** A prewarmed pool entry: `render` is an opaque adapter-owned renderer object created by the same factory as the simulation slot. */\r\nexport type ParticleSlot<TRender> = {\r\n render: TRender;\r\n /** Adapter-owned static attributes must be uploaded once after this slot is (re)spawned. */\r\n renderDirty: boolean;\r\n age: number;\r\n lifetime: number;\r\n x: number;\r\n y: number;\r\n vx: number;\r\n vy: number;\r\n /** Spawn-local position; used to derive the physics delta for world-space reprojection. */\r\n spawnX: number;\r\n spawnY: number;\r\n rotationDegrees: number;\r\n angularVelocityDegrees: number;\r\n scaleStart: number;\r\n scaleEnd: number;\r\n /** Index into `random`/`sequence` source `assetIds`, picked once at spawn. */\r\n sourceIndex: number;\r\n /** Starting frame offset for a `sequence` source with `randomStartFrame`. */\r\n sequenceStart: number;\r\n /** World-space spawn position and the linear (rotate+scale) part of the emitter's world transform at spawn time; only meaningful for `world` space particles. */\r\n worldSpawnX: number;\r\n worldSpawnY: number;\r\n spawnMatrixA: number;\r\n spawnMatrixB: number;\r\n spawnMatrixC: number;\r\n spawnMatrixD: number;\r\n};\r\n\r\nfunction createZeroedSlot<TRender>(render: TRender): ParticleSlot<TRender> {\r\n return { render, renderDirty: false, age: 0, lifetime: 0, x: 0, y: 0, vx: 0, vy: 0, spawnX: 0, spawnY: 0, rotationDegrees: 0, angularVelocityDegrees: 0, scaleStart: 1, scaleEnd: 1, sourceIndex: 0, sequenceStart: 0, worldSpawnX: 0, worldSpawnY: 0, spawnMatrixA: 1, spawnMatrixB: 0, spawnMatrixC: 0, spawnMatrixD: 1 };\r\n}\r\nfunction resetSlot<TRender>(slot: ParticleSlot<TRender>): void {\r\n // Hot release path: reset in place instead of allocating a temporary zeroed slot for Object.assign.\r\n slot.renderDirty = false; slot.age = 0; slot.lifetime = 0; slot.x = 0; slot.y = 0; slot.vx = 0; slot.vy = 0;\r\n slot.spawnX = 0; slot.spawnY = 0; slot.rotationDegrees = 0; slot.angularVelocityDegrees = 0;\r\n slot.scaleStart = 1; slot.scaleEnd = 1; slot.sourceIndex = 0; slot.sequenceStart = 0;\r\n slot.worldSpawnX = 0; slot.worldSpawnY = 0;\r\n slot.spawnMatrixA = 1; slot.spawnMatrixB = 0; slot.spawnMatrixC = 0; slot.spawnMatrixD = 1;\r\n}\r\n\r\n/**\r\n * Prewarmed object pool. `acquire`/`release` never call the factory; only `resize` does, and only for\r\n * the capacity delta. Shrinking removes idle free slots immediately; active slots beyond the new\r\n * capacity keep running and are permanently destroyed (via `onRemove`, never recycled) the next time\r\n * they are released instead of returning to the free list.\r\n */\r\nexport class ParticlePool<T> {\r\n private readonly free: T[] = [];\r\n private readonly active = new Set<T>();\r\n private capacity: number;\r\n public dropped = 0;\r\n constructor(private readonly factory: () => T, capacity: number, private readonly onRemove?: (value: T) => void) {\r\n this.capacity = capacity;\r\n for (let i = 0; i < capacity; i++) this.free.push(factory());\r\n }\r\n acquire(): T | undefined {\r\n const value = this.free.pop();\r\n if (value === undefined) { this.dropped++; return undefined; }\r\n this.active.add(value);\r\n return value;\r\n }\r\n release(value: T): void {\r\n if (!this.active.has(value)) return;\r\n const overCapacity = this.free.length + this.active.size > this.capacity;\r\n this.active.delete(value);\r\n if (overCapacity) this.onRemove?.(value);\r\n else this.free.push(value);\r\n }\r\n resize(capacity: number): void {\r\n if (capacity > this.capacity) {\r\n const total = this.free.length + this.active.size;\r\n for (let i = total; i < capacity; i++) this.free.push(this.factory());\r\n } else if (capacity < this.capacity) {\r\n while (this.free.length + this.active.size > capacity && this.free.length > 0) this.onRemove?.(this.free.pop()!);\r\n }\r\n this.capacity = capacity;\r\n }\r\n /** Permanently destroys every slot, free and active alike; used by `dispose()`. */\r\n clear(): void {\r\n for (const value of this.free.splice(0, this.free.length)) this.onRemove?.(value);\r\n for (const value of this.active) this.onRemove?.(value);\r\n this.active.clear();\r\n this.capacity = 0;\r\n }\r\n get values(): ReadonlySet<T> { return this.active; }\r\n get limit(): number { return this.capacity; }\r\n}\r\n\r\nexport type ParticleSpawnContext = { width: number; height: number; space: \"local\" | \"world\" };\r\nexport type ParticleDiagnostics = { active: number; dropped: number; playing: boolean; stopped: boolean; disposed: boolean };\r\n\r\n/** Adapter-supplied, renderer-specific operations. The simulator never imports Pixi. */\r\nexport type ParticleRenderHooks<TRender> = {\r\n createRender(): TRender;\r\n hideRender(render: TRender): void;\r\n destroyRender(render: TRender): void;\r\n /** The emitter's current world transform linear part `{a,b,c,d}` and translation `{tx,ty}`; read only when a `world`-space particle spawns. */\r\n getWorldTransform(): { a: number; b: number; c: number; d: number; tx: number; ty: number };\r\n};\r\n\r\n/**\r\n * Schema-neutral, deterministic particle simulation over a prewarmed pool. Owns lifecycle\r\n * (`play`/`pause`/`step`/`restart`/`stop`/`dispose`), fixed-step ticking, seeded spawn parameters and\r\n * burst/rate scheduling. Rendering (texture, tint, local/world projection) is the adapter's job; this\r\n * class only exposes the pool's active slots and the effect definition for it to read.\r\n */\r\nexport class ParticleSimulator<TRender> {\r\n static readonly stepSeconds = 1 / 60;\r\n private readonly pool: ParticlePool<ParticleSlot<TRender>>;\r\n private random: SeededRandom;\r\n private elapsed = 0;\r\n private stepAccumulator = 0;\r\n private emissionAccumulator = 0;\r\n private burstCursors: number[];\r\n private multiplier = 1;\r\n private emitting = false;\r\n private simulating = false;\r\n private stopped = false;\r\n private disposed = false;\r\n private context: ParticleSpawnContext = { width: 0, height: 0, space: \"local\" };\r\n\r\n constructor(public definition: ParticleEffectDefinition, private readonly hooks: ParticleRenderHooks<TRender>) {\r\n this.random = new SeededRandom(definition.seed);\r\n this.burstCursors = definition.emission.bursts.map(() => 0);\r\n this.pool = new ParticlePool<ParticleSlot<TRender>>(\r\n () => createZeroedSlot(hooks.createRender()),\r\n definition.maxParticles,\r\n (slot) => hooks.destroyRender(slot.render),\r\n );\r\n }\r\n\r\n get activeSlots(): ReadonlySet<ParticleSlot<TRender>> { return this.pool.values; }\r\n\r\n setEmissionMultiplier(value: number): void {\r\n if (!Number.isFinite(value) || value < 0) throw new RangeError(\"Emission multiplier must be finite and non-negative.\");\r\n this.multiplier = value;\r\n }\r\n\r\n /** Adopts a new definition reference without ever comparing identity: unrelated edits, seed changes and texture changes never reset accumulator, PRNG or live particles. Only `maxParticles` triggers a pool resize. */\r\n syncEffect(effect: ParticleEffectDefinition): void {\r\n this.definition = effect;\r\n if (this.pool.limit !== effect.maxParticles) this.pool.resize(effect.maxParticles);\r\n const cursors = effect.emission.bursts.map((_, index) => this.burstCursors[index] ?? 0);\r\n this.burstCursors = cursors;\r\n }\r\n\r\n play(): void { if (this.disposed) return; this.emitting = true; this.simulating = true; this.stopped = false; }\r\n /** Freezes emission and every live particle without resetting time or PRNG. */\r\n pause(): void { if (this.disposed) return; this.emitting = false; this.simulating = false; this.stopped = false; }\r\n /** Stops new spawns; already-emitted particles keep simulating to their natural death. */\r\n stop(): void {\r\n if (this.disposed) return;\r\n this.emitting = false;\r\n this.simulating = this.pool.values.size > 0;\r\n this.stopped = true;\r\n }\r\n\r\n restart(): void {\r\n if (this.disposed) return;\r\n for (const slot of [...this.pool.values]) this.releaseSlot(slot);\r\n this.elapsed = 0;\r\n this.stepAccumulator = 0;\r\n this.emissionAccumulator = 0;\r\n this.burstCursors = this.definition.emission.bursts.map(() => 0);\r\n this.pool.dropped = 0;\r\n this.random = new SeededRandom(this.definition.seed);\r\n this.emitting = true;\r\n this.simulating = true;\r\n this.stopped = false;\r\n }\r\n\r\n /** Idempotent terminal cleanup: destroys every pooled render object and excludes the view from further updates. */\r\n dispose(): void {\r\n if (this.disposed) return;\r\n this.disposed = true;\r\n this.emitting = false;\r\n this.simulating = false;\r\n this.stopped = false;\r\n this.pool.clear();\r\n }\r\n\r\n /** Advances exactly one fixed step regardless of paused/stopped state, and never changes it. */\r\n step(context: ParticleSpawnContext): boolean {\r\n if (this.disposed) return false;\r\n this.context = context;\r\n this.tick(ParticleSimulator.stepSeconds);\r\n return true;\r\n }\r\n\r\n update(deltaSeconds: number, context: ParticleSpawnContext): boolean {\r\n if (this.disposed || !this.simulating) return false;\r\n this.context = context;\r\n this.stepAccumulator = Math.min(this.stepAccumulator + Math.max(0, deltaSeconds), ParticleSimulator.stepSeconds * 8);\r\n let advanced = false;\r\n while (this.stepAccumulator >= ParticleSimulator.stepSeconds) {\r\n this.stepAccumulator -= ParticleSimulator.stepSeconds;\r\n this.tick(ParticleSimulator.stepSeconds);\r\n advanced = true;\r\n }\r\n return advanced;\r\n }\r\n\r\n getDiagnostics(): ParticleDiagnostics {\r\n return { active: this.pool.values.size, dropped: this.pool.dropped, playing: this.emitting, stopped: this.stopped && !this.disposed, disposed: this.disposed };\r\n }\r\n\r\n private tick(dt: number): void {\r\n // Age and move existing particles before spawning: a particle created this tick starts at age 0\r\n // and receives its first dt on the next tick, instead of being silently pre-aged by one step.\r\n const movement = this.definition.particle.movement;\r\n const drag = Math.max(0, 1 - movement.drag * dt);\r\n for (const slot of this.pool.values) {\r\n slot.age += dt;\r\n if (slot.age >= slot.lifetime) { this.releaseSlot(slot); continue; }\r\n slot.vx = (slot.vx + movement.accelerationX * dt) * drag;\r\n slot.vy = (slot.vy + movement.accelerationY * dt) * drag;\r\n slot.x += slot.vx * dt;\r\n slot.y += slot.vy * dt;\r\n slot.rotationDegrees += slot.angularVelocityDegrees * dt;\r\n }\r\n\r\n const e = this.definition.emission;\r\n const cycle = e.duration + e.delay;\r\n this.elapsed += dt;\r\n if (this.emitting) {\r\n const cycleElapsed = e.loop ? this.elapsed % cycle : this.elapsed;\r\n const inWindow = cycleElapsed >= e.delay && cycleElapsed <= e.delay + e.duration;\r\n if (inWindow && e.rate > 0) {\r\n this.emissionAccumulator += e.rate * this.multiplier * dt;\r\n while (this.emissionAccumulator >= 1) { this.emissionAccumulator -= 1; this.spawnParticle(); }\r\n }\r\n for (let index = 0; index < e.bursts.length; index++) {\r\n const burst = e.bursts[index]!;\r\n const triggerBase = e.delay + burst.time;\r\n for (;;) {\r\n const cursor = this.burstCursors[index] ?? 0;\r\n if (!e.loop && cursor >= 1) break;\r\n const triggerAt = e.loop ? cursor * cycle + triggerBase : triggerBase;\r\n if (this.elapsed < triggerAt) break;\r\n for (let i = 0; i < burst.count; i++) this.spawnParticle();\r\n this.burstCursors[index] = cursor + 1;\r\n }\r\n }\r\n if (!e.loop && this.elapsed >= e.delay + e.duration) {\r\n this.emitting = false;\r\n this.stopped = true;\r\n }\r\n }\r\n // A completed one-shot or a graceful stop must not keep an otherwise idle emitter on the hot\r\n // ticker path forever. Preserve the stopped diagnostic while putting simulation fully to sleep.\r\n if (!this.emitting && this.pool.values.size === 0) this.simulating = false;\r\n }\r\n\r\n private spawnParticle(): void {\r\n const slot = this.pool.acquire();\r\n if (!slot) return;\r\n const p = this.definition.particle;\r\n const rand = this.random;\r\n const point = sampleSpawnPoint(p.spawnShape.type, this.context.width, this.context.height, rand);\r\n slot.renderDirty = true;\r\n slot.age = 0;\r\n slot.lifetime = rand.range(p.lifetime.min, p.lifetime.max);\r\n slot.spawnX = point.x;\r\n slot.spawnY = point.y;\r\n slot.x = point.x;\r\n slot.y = point.y;\r\n const speed = rand.range(p.movement.speed.min, p.movement.speed.max);\r\n const angle = (p.movement.directionDegrees + (rand.next() - 0.5) * p.movement.spreadDegrees) * DEG_TO_RAD;\r\n slot.vx = Math.cos(angle) * speed;\r\n slot.vy = Math.sin(angle) * speed;\r\n slot.rotationDegrees = rand.range(p.visual.rotation.initialDegrees.min, p.visual.rotation.initialDegrees.max);\r\n slot.angularVelocityDegrees = rand.range(p.visual.rotation.angularVelocityDegrees.min, p.visual.rotation.angularVelocityDegrees.max);\r\n slot.scaleStart = rand.range(p.visual.scale.start.min, p.visual.scale.start.max);\r\n slot.scaleEnd = rand.range(p.visual.scale.end.min, p.visual.scale.end.max);\r\n const source = p.visual.source;\r\n slot.sourceIndex = source.type === \"single\" ? 0 : rand.index(source.assetIds.length);\r\n slot.sequenceStart = source.type === \"sequence\" && source.randomStartFrame ? rand.index(source.assetIds.length) : 0;\r\n if (this.context.space === \"world\") {\r\n const m = this.hooks.getWorldTransform();\r\n slot.worldSpawnX = m.a * point.x + m.c * point.y + m.tx;\r\n slot.worldSpawnY = m.b * point.x + m.d * point.y + m.ty;\r\n slot.spawnMatrixA = m.a;\r\n slot.spawnMatrixB = m.b;\r\n slot.spawnMatrixC = m.c;\r\n slot.spawnMatrixD = m.d;\r\n }\r\n }\r\n\r\n private releaseSlot(slot: ParticleSlot<TRender>): void {\r\n resetSlot(slot);\r\n this.hooks.hideRender(slot.render);\r\n this.pool.release(slot);\r\n }\r\n}\r\n"]}
|