@pixi-ui-editor/runtime-pixi 0.5.1 → 0.6.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.
Files changed (55) hide show
  1. package/dist/controls.d.ts +19 -0
  2. package/dist/controls.d.ts.map +1 -1
  3. package/dist/controls.js +40 -0
  4. package/dist/controls.js.map +1 -1
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/layoutGroups.js.map +1 -1
  10. package/dist/pageGroup.d.ts +17 -0
  11. package/dist/pageGroup.d.ts.map +1 -0
  12. package/dist/pageGroup.js +20 -0
  13. package/dist/pageGroup.js.map +1 -0
  14. package/dist/scene.d.ts.map +1 -1
  15. package/dist/scene.js +23 -0
  16. package/dist/scene.js.map +1 -1
  17. package/dist/views/PageGroupNodeView.d.ts +42 -0
  18. package/dist/views/PageGroupNodeView.d.ts.map +1 -0
  19. package/dist/views/PageGroupNodeView.js +72 -0
  20. package/dist/views/PageGroupNodeView.js.map +1 -0
  21. package/dist/views/PaginationNodeView.d.ts +59 -0
  22. package/dist/views/PaginationNodeView.d.ts.map +1 -0
  23. package/dist/views/PaginationNodeView.js +238 -0
  24. package/dist/views/PaginationNodeView.js.map +1 -0
  25. package/dist/views/SpineNodeView.d.ts +23 -2
  26. package/dist/views/SpineNodeView.d.ts.map +1 -1
  27. package/dist/views/SpineNodeView.js +131 -2
  28. package/dist/views/SpineNodeView.js.map +1 -1
  29. package/dist/views/basic.d.ts.map +1 -1
  30. package/dist/views/basic.js +3 -1
  31. package/dist/views/basic.js.map +1 -1
  32. package/dist/views/createNodeView.d.ts.map +1 -1
  33. package/dist/views/createNodeView.js +9 -0
  34. package/dist/views/createNodeView.js.map +1 -1
  35. package/package.json +5 -3
  36. package/dist/assets/spine.test.d.ts +0 -2
  37. package/dist/assets/spine.test.d.ts.map +0 -1
  38. package/dist/assets/spine.test.js +0 -42
  39. package/dist/assets/spine.test.js.map +0 -1
  40. package/dist/index.test.d.ts +0 -2
  41. package/dist/index.test.d.ts.map +0 -1
  42. package/dist/index.test.js +0 -485
  43. package/dist/index.test.js.map +0 -1
  44. package/dist/particles.test.d.ts +0 -2
  45. package/dist/particles.test.d.ts.map +0 -1
  46. package/dist/particles.test.js +0 -210
  47. package/dist/particles.test.js.map +0 -1
  48. package/dist/test.setup.d.ts +0 -2
  49. package/dist/test.setup.d.ts.map +0 -1
  50. package/dist/test.setup.js +0 -6
  51. package/dist/test.setup.js.map +0 -1
  52. package/dist/views/ParticleEmitterNodeView.test.d.ts +0 -2
  53. package/dist/views/ParticleEmitterNodeView.test.d.ts.map +0 -1
  54. package/dist/views/ParticleEmitterNodeView.test.js +0 -148
  55. package/dist/views/ParticleEmitterNodeView.test.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\r\nimport { describe, expect, it } from \"vitest\";\r\nimport { materializedPrefabNodeId, serializeProjectDocument, type ProjectDocument, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container, Graphics, NineSliceSprite, Sprite, Texture } from \"pixi.js\";\r\nimport { TextureAtlas } from \"@esotericsoftware/spine-pixi-v8\";\r\nimport { assignAtlasPageTextures, buildPrefabView, buildSceneView, ButtonNodeView, CheckboxNodeView, collectNodeAssetIds, fitSpineToTransform, getCanvasLogicalSize, getCanvasScale, MaskNodeView, NodeView, parseProjectDocumentJson, ProjectDocumentJsonParseError, resolveAnchoredTransform, resolveProfileForViewport, resolveProfileTransform, resolveSpineSettings, resolveTextStyle } from \"./index.js\";\r\nimport { createNodeView } from \"./views/createNodeView.js\";\r\nimport { ContainerNodeView } from \"./views/basic.js\";\r\n\r\nconst sampleUrl = new URL(\"../../../examples/sample-project/project.json\", import.meta.url);\r\nconst sampleJson = readFileSync(sampleUrl, \"utf8\");\r\nconst ids = {\r\n scene: \"10000000-0000-4000-8000-000000000002\",\r\n root: \"10000000-0000-4000-8000-000000000003\",\r\n image: \"10000000-0000-4000-8000-000000000051\",\r\n asset: \"10000000-0000-4000-8000-000000000010\",\r\n text: \"10000000-0000-4000-8000-000000000006\",\r\n};\r\nconst clone = <T>(value: T): T => structuredClone(value);\r\nconst buttonIds = { node: \"10000000-0000-4000-8000-000000000008\", pressedAsset: \"10000000-0000-4000-8000-000000000009\" };\r\n\r\n/** Rendering contracts use a DOM-free mini scene; the repository sample itself also exercises Yoga groups. */\r\nfunction renderDocument(): ProjectDocument {\r\n const document = parseProjectDocumentJson(sampleJson);\r\n const scene = document.scenes[0]!;\r\n const root = scene.nodes.find((node) => node.id === ids.root)!;\r\n const image = scene.nodes.find((node) => node.id === ids.image)!;\r\n const text = scene.nodes.find((node) => node.id === ids.text)!;\r\n image.parentId = root.id;\r\n text.parentId = root.id;\r\n root.children = [image.id, text.id];\r\n scene.nodes = [root, image, text];\r\n return document;\r\n}\r\n\r\n/** Sample scene plus a button whose pressed state has its own image and whose hover/disabled states have none. */\r\nfunction documentWithButton(): ProjectDocument {\r\n const document = renderDocument();\r\n const scene = document.scenes[0]!;\r\n const root = scene.nodes.find((node) => node.id === ids.root)!;\r\n document.assets.push({ id: buttonIds.pressedAsset, name: \"Pressed\", type: \"image\", source: { uri: \"assets/pressed.png\", mediaType: \"image/png\" } });\r\n scene.nodes.push({\r\n id: buttonIds.node,\r\n name: \"Play\",\r\n type: \"button\",\r\n parentId: ids.root,\r\n children: [],\r\n visible: true,\r\n enabled: true,\r\n states: { normalAssetId: ids.asset, pressedAssetId: buttonIds.pressedAsset },\r\n transform: { x: 0, y: 0, width: 120, height: 40, scaleX: 1, scaleY: 1, rotation: 0 },\r\n });\r\n root.children.push(buttonIds.node);\r\n return document;\r\n}\r\n\r\ntype NodeBaseFields = Pick<Extract<UINode, { type: \"container\" }>, \"id\" | \"name\" | \"parentId\" | \"children\" | \"visible\" | \"transform\">;\r\n\r\n/**\r\n * По одному узлу каждого типа, который можно вытащить на сцену.\r\n * `Record<UINode[\"type\"], ...>` — намеренно: компилятор не даст добавить новый тип ноды,\r\n * не дописав его сюда, а значит новый тип не сможет молча потерять selection и drag.\r\n */\r\nconst NODE_TYPE_FIXTURES: Record<UINode[\"type\"], (base: NodeBaseFields) => UINode> = {\r\n container: (base) => ({ ...base, type: \"container\" }),\r\n mask: (base) => ({ ...base, type: \"mask\" }),\r\n \"horizontal-layout\": (base) => ({ ...base, type: \"horizontal-layout\", layoutGroup: { base: { padding: { left: 0, right: 0, top: 0, bottom: 0 }, spacing: 0, childAlignment: \"upper-left\", reverseOrder: false, controlChildWidth: true, controlChildHeight: true, forceExpandWidth: false, forceExpandHeight: false } } }),\r\n \"vertical-layout\": (base) => ({ ...base, type: \"vertical-layout\", layoutGroup: { base: { padding: { left: 0, right: 0, top: 0, bottom: 0 }, spacing: 0, childAlignment: \"upper-left\", reverseOrder: false, controlChildWidth: true, controlChildHeight: true, forceExpandWidth: false, forceExpandHeight: false } } }),\r\n \"grid-layout\": (base) => ({ ...base, type: \"grid-layout\", layoutGroup: { base: { padding: { left: 0, right: 0, top: 0, bottom: 0 }, spacingX: 0, spacingY: 0, cellWidth: 20, cellHeight: 20, startCorner: \"upper-left\", startAxis: \"horizontal\", childAlignment: \"upper-left\", constraint: \"flexible\" } } }),\r\n image: (base) => ({ ...base, type: \"image\", assetId: ids.asset }),\r\n text: (base) => ({ ...base, type: \"text\", text: \"Label\" }),\r\n \"bitmap-text\": (base) => ({ ...base, type: \"bitmap-text\", text: \"0\", assetId: ids.asset, fontSize: 24, fill: \"#FFFFFF\", align: \"left\", verticalAlign: \"top\", letterSpacing: 0, wordWrap: false }),\r\n spine: (base) => ({ ...base, type: \"spine\", assetId: ids.asset }),\r\n button: (base) => ({ ...base, type: \"button\", enabled: true, states: { normalAssetId: ids.asset } }),\r\n \"staged-button\": (base) => ({ ...base, type: \"staged-button\", enabled: true, wrap: true, stages: [{ id: \"40000000-0000-4000-8000-0000000000fe\", value: \"1x\", states: { normalAssetId: ids.asset } }], defaultStageId: \"40000000-0000-4000-8000-0000000000fe\" }),\r\n checkbox: (base) => ({ ...base, type: \"checkbox\", enabled: true, defaultChecked: false, states: { uncheckedAssetId: ids.asset, checkedAssetId: ids.asset } }),\r\n \"prefab-instance\": (base) => ({ ...base, type: \"prefab-instance\", prefabId: \"40000000-0000-4000-8000-00000000000f\" }),\r\n \"scroll-view\": (base) => ({ ...base, type: \"scroll-view\", scrollView: { direction: \"vertical\", padding: { left: 0, right: 0, top: 0, bottom: 0 }, itemSpacing: 0, cornerRadius: 0, easingEnabled: true } }),\r\n input: (base) => ({ ...base, type: \"input\", placeholder: \"Enter text\", defaultValue: \"\", secure: false, align: \"left\", padding: { left: 0, right: 0, top: 0, bottom: 0 }, cleanOnFocus: false, clipText: true, textStyle: { fontFamily: \"Arial\", fontSize: 24, fontWeight: \"normal\", fontStyle: \"normal\", fill: \"#FFFFFF\", align: \"left\", verticalAlign: \"top\", wordWrap: false, breakWords: false, letterSpacing: 0 } }),\r\n slider: (base) => ({ ...base, type: \"slider\", backgroundAssetId: ids.asset, fillAssetId: ids.asset, handleAssetId: ids.asset, min: 0, max: 100, step: 1, defaultValue: 50, fillPadding: { left: 0, right: 0, top: 0, bottom: 0 } }),\r\n \"progress-bar\": (base) => ({ ...base, type: \"progress-bar\", backgroundAssetId: ids.asset, fillAssetId: ids.asset, defaultProgress: 50, fillPadding: { left: 0, right: 0, top: 0, bottom: 0 } }),\r\n \"particle-emitter\": (base) => ({ ...base, type: \"particle-emitter\", effectId: \"40000000-0000-4000-8000-00000000000f\", autoplay: true, simulationSpace: \"local\" }),\r\n};\r\n\r\n/** FancyButton keeps exactly one state view visible, so the shown texture identifies the active state. */\r\nfunction shownStateTexture(view: Container): Texture | undefined {\r\n const shown: Sprite[] = [];\r\n const walk = (container: Container): void => {\r\n if (container instanceof Sprite && container.visible) shown.push(container);\r\n container.children.forEach(walk);\r\n };\r\n walk(view);\r\n return shown.length === 1 ? shown[0]!.texture : undefined;\r\n}\r\n\r\ndescribe(\"sample project loader smoke test\", () => {\r\n it(\"materializes independently addressable overridden and local prefab nodes\", () => {\r\n const document = renderDocument();\r\n const scene = document.scenes[0]!;\r\n const root = scene.nodes[0]!;\r\n const definitionNode = structuredClone(scene.nodes.find((node) => node.type === \"text\")!);\r\n definitionNode.id = \"50000000-0000-4000-8000-000000000001\";\r\n definitionNode.parentId = null;\r\n definitionNode.children = [];\r\n const prefabId = \"50000000-0000-4000-8000-000000000002\";\r\n document.prefabs = [{ id: prefabId, name: \"Label\", rootNodeIds: [definitionNode.id], nodes: [definitionNode], exposedProperties: [] }];\r\n const instanceId = \"50000000-0000-4000-8000-000000000003\";\r\n const localId = \"50000000-0000-4000-8000-000000000004\";\r\n scene.nodes.push({\r\n id: instanceId, name: \"Configured label\", type: \"prefab-instance\", prefabId, parentId: root.id, children: [], visible: true,\r\n transform: { x: 0, y: 0, width: 200, height: 80, scaleX: 1, scaleY: 1, rotation: 0 },\r\n propertyOverrides: [{ nodeId: definitionNode.id, patch: { text: \"Overridden\" } }],\r\n locallyAddedNodes: [{ id: localId, name: \"Local\", type: \"text\", text: \"Extra\", parentId: null, children: [], visible: true, transform: { x: 0, y: 30, width: 100, height: 20, scaleX: 1, scaleY: 1, rotation: 0 } }],\r\n });\r\n root.children.push(instanceId);\r\n\r\n const sceneView = buildSceneView(document, scene.id, \"desktop\", { interaction: \"runtime\" });\r\n expect(sceneView.nodeViews.has(materializedPrefabNodeId(instanceId, definitionNode.id))).toBe(true);\r\n expect(sceneView.nodeViews.has(localId)).toBe(true);\r\n const viewport = scene.layout.referenceViewports.desktop;\r\n sceneView.root.resize({ width: viewport.width * 2, height: viewport.height * 3 });\r\n expect(sceneView.root.scale.x).toBe(2);\r\n expect(sceneView.root.scale.y).toBe(2);\r\n expect(sceneView.root.position).toMatchObject({ x: 0, y: viewport.height / 2 });\r\n expect(sceneView.root.content.mask).not.toBeNull();\r\n\r\n const spawned = buildPrefabView(document, prefabId, \"desktop\", { interaction: \"runtime\" }, {\r\n propertyOverrides: [{ nodeId: definitionNode.id, patch: { text: \"Spawned\" } }],\r\n });\r\n expect(spawned.nodeViews.size).toBeGreaterThan(1);\r\n expect(spawned.root.content.mask).toBeUndefined();\r\n });\r\n it(\"matches atlas pages to texture files by name\", () => {\r\n const atlas = new TextureAtlas(\"second.png\\nsize: 1,1\\nformat: RGBA8888\\nfilter: Linear,Linear\\nrepeat: none\\n\\nfirst.png\\nsize: 1,1\\nformat: RGBA8888\\nfilter: Linear,Linear\\nrepeat: none\\n\");\r\n assignAtlasPageTextures(atlas, new Map([[\"first.png\", Texture.WHITE], [\"second.png\", Texture.WHITE]]));\r\n expect(atlas.pages.every((page) => page.texture !== null)).toBe(true);\r\n });\r\n it(\"resolves base transforms, partial desktop overrides, and profile visibility\", () => {\r\n const document = renderDocument();\r\n const node = document.scenes[0]!.nodes[1]!;\r\n\r\n expect(resolveProfileTransform(node, \"desktop\")).toEqual({ transform: node.transform, visible: true });\r\n\r\n const withDesktopOverride = clone(node);\r\n withDesktopOverride.layoutOverrides = { desktop: { transform: { x: 12, scaleY: 2 } } };\r\n expect(resolveProfileTransform(withDesktopOverride, \"desktop\")).toEqual({\r\n transform: { ...node.transform, x: 12, scaleY: 2 },\r\n visible: true,\r\n });\r\n\r\n withDesktopOverride.layoutOverrides.desktop!.visible = false;\r\n expect(resolveProfileTransform(withDesktopOverride, \"desktop\").visible).toBe(false);\r\n });\r\n\r\n it(\"resolves sparse text styles and includes profile-only fonts in asset collection\", () => {\r\n const document = renderDocument();\r\n const node = document.scenes[0]!.nodes.find((candidate): candidate is Extract<UINode, { type: \"text\" }> => candidate.type === \"text\")!;\r\n const base = resolveTextStyle(node, \"desktop\")!;\r\n const mobileFontId = \"60000000-0000-4000-8000-000000000001\";\r\n node.textStyleOverrides = { mobile: { fontSize: 42, align: \"center\", fontAssetId: mobileFontId } };\r\n\r\n expect(resolveTextStyle(node, \"desktop\")).toEqual(base);\r\n expect(resolveTextStyle(node, \"mobile\")).toMatchObject({ ...base, fontSize: 42, align: \"center\", fontAssetId: mobileFontId });\r\n expect(collectNodeAssetIds(node)).toContain(mobileFontId);\r\n });\r\n\r\n it(\"resolves Spine settings per profile and supports explicitly clearing animation\", () => {\r\n const node: Extract<UINode, { type: \"spine\" }> = {\r\n id: \"60000000-0000-4000-8000-000000000002\", name: \"Hero\", type: \"spine\", assetId: ids.asset,\r\n animation: \"idle\", autoplay: true, loop: true, animationSpeed: 1, parentId: null, children: [], visible: true,\r\n transform: { x: 0, y: 0, width: 100, height: 100, scaleX: 1, scaleY: 1, rotation: 0 },\r\n spineOverrides: { mobile: { animation: null, autoplay: false, loop: false, animationSpeed: 0.5 } },\r\n };\r\n\r\n expect(resolveSpineSettings(node, \"desktop\")).toEqual({ animation: \"idle\", autoplay: true, loop: true, animationSpeed: 1 });\r\n expect(resolveSpineSettings(node, \"mobile\")).toEqual({ animation: undefined, autoplay: false, loop: false, animationSpeed: 0.5 });\r\n });\r\n\r\n it(\"resolves normalized anchors against the parent rectangle\", () => {\r\n const transform = { x: -160, y: -50, width: 320, height: 100, scaleX: 1, scaleY: 1, rotation: 0, anchorMinX: 0.5, anchorMaxX: 0.5, anchorMinY: 1, anchorMaxY: 1 };\r\n expect(resolveAnchoredTransform(transform, { width: 1920, height: 1080 })).toMatchObject({ x: 800, y: 1030, width: 320, height: 100 });\r\n });\r\n\r\n it(\"uses Unity's uniform logarithmic Canvas Scaler blend at match 0.5\", () => {\r\n const preferred = { width: 1920, height: 1080 };\r\n expect(getCanvasScale({ width: 3840, height: 2160 }, preferred)).toBeCloseTo(2);\r\n expect(getCanvasScale({ width: 1920, height: 2160 }, preferred)).toBeCloseTo(Math.sqrt(2));\r\n expect(getCanvasScale({ width: 3840, height: 1080 }, preferred)).toBeCloseTo(Math.sqrt(2));\r\n });\r\n\r\n it(\"keeps point-anchor rect proportions in logical Canvas space\", () => {\r\n const preferred = { width: 1920, height: 1080 };\r\n const screen = { width: 1920, height: 2160 };\r\n const scale = getCanvasScale(screen, preferred);\r\n const canvas = getCanvasLogicalSize(screen, preferred);\r\n const transform = { x: 0, y: 0, width: 50, height: 50, scaleX: 1, scaleY: 1, rotation: 0, anchorMinX: 0.5, anchorMaxX: 0.5, anchorMinY: 0.5, anchorMaxY: 0.5, pivotX: 0.5, pivotY: 0.5 };\r\n const resolved = resolveAnchoredTransform(transform, canvas);\r\n expect(resolved).toMatchObject({ x: canvas.width / 2, y: canvas.height / 2, width: 50, height: 50 });\r\n expect(resolved.width * scale).toBeCloseTo(50 * Math.sqrt(2));\r\n expect(resolved.height * scale).toBeCloseTo(50 * Math.sqrt(2));\r\n });\r\n\r\n it(\"uses anchorMax and sizeDelta for Unity-style stretch\", () => {\r\n const parent = { width: 800, height: 600 };\r\n const transform = { x: 0, y: 0, width: -30, height: -40, scaleX: 1, scaleY: 1, rotation: 0, anchorMinX: 0, anchorMaxX: 1, anchorMinY: 0, anchorMaxY: 1, pivotX: 0.5, pivotY: 0.5 };\r\n expect(resolveAnchoredTransform(transform, parent)).toMatchObject({ x: 400, y: 300, width: 770, height: 560 });\r\n });\r\n\r\n it(\"resolves the viewport profile on both sides of the breakpoint and picks mobile exactly on it\", () => {\r\n const settings = { layoutProfileSelection: { mode: \"aspect-ratio\" as const, mobileMaxAspectRatio: 1 } };\r\n\r\n expect(resolveProfileForViewport(settings, 1920, 1080)).toBe(\"desktop\");\r\n expect(resolveProfileForViewport(settings, 390, 844)).toBe(\"mobile\");\r\n expect(resolveProfileForViewport(settings, 1000, 1000)).toBe(\"mobile\");\r\n });\r\n\r\n it(\"fits Spine setup bounds to the node transform dimensions\", () => {\r\n const transform = { x: 0, y: 0, width: 200, height: 200, scaleX: 1, scaleY: 1, rotation: 0 };\r\n\r\n expect(fitSpineToTransform({ x: -50, y: 20, width: 100, height: 400 }, transform)).toEqual({ scaleX: 2, scaleY: 0.5, x: 100, y: -10 });\r\n expect(fitSpineToTransform({ x: 0, y: 0, width: 0, height: 400 }, transform)).toBeUndefined();\r\n });\r\n\r\n it(\"uses supplied textures for image nodes and otherwise preserves the placeholder\", () => {\r\n const document = renderDocument();\r\n const textured = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"authoring\", textures: new Map([[ids.asset, Texture.WHITE]]) });\r\n const imageView = textured.nodeViews.get(ids.image)!;\r\n const sprite = imageView.children[0];\r\n expect(imageView).not.toBeInstanceOf(Sprite);\r\n expect(sprite).toBeInstanceOf(Sprite);\r\n expect(sprite?.width).toBe(240);\r\n\r\n const placeholder = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"authoring\" }).nodeViews.get(ids.image)?.children[0];\r\n expect(placeholder).not.toBeInstanceOf(Sprite);\r\n\r\n const anchoredDocument = clone(document);\r\n const anchoredNode = anchoredDocument.scenes[0]!.nodes.find((node) => node.id === ids.image)!;\r\n anchoredNode.transform = { ...anchoredNode.transform, anchorMinX: 1, anchorMaxX: 1, pivotX: 1, x: 0 };\r\n const anchoredView = buildSceneView(anchoredDocument, ids.scene, \"desktop\", { interaction: \"authoring\", textures: new Map([[ids.asset, Texture.WHITE]]) }).nodeViews.get(ids.image)!;\r\n const anchoredSprite = anchoredView.children[0] as Sprite;\r\n const renderedRight = anchoredView.position.x + (anchoredSprite.width - anchoredView.pivot.x) * anchoredView.scale.x;\r\n expect(renderedRight).toBe(anchoredDocument.scenes[0]!.layout.referenceViewports.desktop.width);\r\n\r\n const mobileNode = anchoredDocument.scenes[0]!.nodes.find((node) => node.id === ids.image)!;\r\n mobileNode.layoutOverrides = { mobile: { transform: { anchorMinX: 1, anchorMaxX: 1, pivotX: 1, x: 0 } } };\r\n const mobileView = buildSceneView(anchoredDocument, ids.scene, \"mobile\", { interaction: \"authoring\", textures: new Map([[ids.asset, Texture.WHITE]]) }).nodeViews.get(ids.image)!;\r\n const mobileSprite = mobileView.children[0] as Sprite;\r\n const mobileRight = mobileView.position.x + (mobileSprite.width - mobileView.pivot.x) * mobileView.scale.x;\r\n expect(mobileRight).toBe(anchoredDocument.scenes[0]!.layout.referenceViewports.mobile.width);\r\n });\r\n\r\n it(\"places a zero-offset centred pivot at the centre of its parent\", () => {\r\n const document = renderDocument();\r\n const imageNode = document.scenes[0]!.nodes.find((node) => node.id === ids.image)!;\r\n imageNode.transform = {\r\n ...imageNode.transform,\r\n x: 0,\r\n y: 0,\r\n anchorMinX: 0.5,\r\n anchorMaxX: 0.5,\r\n anchorMinY: 0.5,\r\n anchorMaxY: 0.5,\r\n pivotX: 0.5,\r\n pivotY: 0.5,\r\n };\r\n\r\n const imageView = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"authoring\" }).nodeViews.get(ids.image)!;\r\n const viewport = document.scenes[0]!.layout.referenceViewports.desktop;\r\n expect(imageView.position).toMatchObject({ x: viewport.width / 2, y: viewport.height / 2 });\r\n });\r\n\r\n it(\"keeps node geometry logical and applies one uniform scale on the Canvas root\", () => {\r\n const document = renderDocument();\r\n const scene = document.scenes[0]!;\r\n scene.layout.referenceViewports.desktop.height *= 2;\r\n const expectedScale = Math.sqrt(2);\r\n\r\n const built = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"authoring\", textures: new Map([[ids.asset, Texture.WHITE]]) });\r\n const canvasRoot = built.root.children[0]!;\r\n const imageView = built.nodeViews.get(ids.image)! as NodeView;\r\n const authored = scene.nodes.find((node) => node.id === ids.image)!.transform;\r\n\r\n expect(canvasRoot.scale).toMatchObject({ x: expectedScale, y: expectedScale });\r\n expect(imageView.layoutRectangle).toEqual({ width: authored.width, height: authored.height });\r\n expect(imageView.layoutRectangle.width * canvasRoot.scale.x).toBeCloseTo(authored.width * expectedScale);\r\n expect(imageView.layoutRectangle.height * canvasRoot.scale.y).toBeCloseTo(authored.height * expectedScale);\r\n });\r\n\r\n it(\"gives every node type the same grab rectangle, whatever it renders\", () => {\r\n const types = Object.keys(NODE_TYPE_FIXTURES) as UINode[\"type\"][];\r\n const nodeId = (index: number) => `40000000-0000-4000-8000-00000000000${index}`;\r\n\r\n const views = types.map((type, index) => {\r\n const node = NODE_TYPE_FIXTURES[type]({\r\n id: nodeId(index),\r\n name: type,\r\n parentId: ids.root,\r\n children: [],\r\n visible: true,\r\n transform: { x: 10, y: 20, width: 120, height: 40, scaleX: 1, scaleY: 1, rotation: 0 },\r\n });\r\n // Input and ScrollBox create DOM controls; their NodeView-level grab contract is the same.\r\n const view = node.type === \"scroll-view\" || node.type === \"input\" ? new ContainerNodeView() : createNodeView(node, \"authoring\");\r\n view.update(node, \"desktop\", { width: 1920, height: 1080 });\r\n return view;\r\n });\r\n\r\n // Ни текстур, ни Spine-данных: grab-зона не должна зависеть ни от контента ноды, ни от загруженных ассетов.\r\n const grab = (index: number, x: number, y: number) => views[index]?.containsPoint({ x, y });\r\n const grabbedInsideRect = types.map((type, index) => [type, grab(index, 60, 20) ?? false] as const);\r\n const missedOutsideRect = types.map((type, index) => [type, grab(index, 200, 20) ?? true] as const);\r\n\r\n expect(grabbedInsideRect).toEqual(types.map((type) => [type, true]));\r\n expect(missedOutsideRect).toEqual(types.map((type) => [type, false]));\r\n });\r\n\r\n it(\"clips a mask subtree to the resolved rectangular layout area and resizes the mask in place\", () => {\r\n const mask: UINode = {\r\n id: \"40000000-0000-4000-8000-000000000099\",\r\n name: \"Mask\",\r\n type: \"mask\",\r\n parentId: null,\r\n children: [],\r\n visible: true,\r\n transform: { x: 0, y: 0, width: 120, height: 40, scaleX: 1, scaleY: 1, rotation: 0 },\r\n };\r\n const view = createNodeView(mask, \"runtime\");\r\n view.update(mask, \"desktop\");\r\n\r\n expect(view).toBeInstanceOf(MaskNodeView);\r\n expect(view.mask).toBeInstanceOf(Graphics);\r\n expect(view.children).toContain(view.mask as Container);\r\n expect((view.mask as Graphics).getLocalBounds()).toMatchObject({ x: 0, y: 0, width: 120, height: 40 });\r\n\r\n mask.transform.width = 75;\r\n mask.transform.height = 25;\r\n view.update(mask, \"desktop\");\r\n expect((view.mask as Graphics).getLocalBounds()).toMatchObject({ x: 0, y: 0, width: 75, height: 25 });\r\n });\r\n\r\n it(\"keeps a child grabbable where it reaches past its parent's rectangle\", () => {\r\n const document = renderDocument();\r\n const scene = document.scenes[0]!;\r\n const root = scene.nodes.find((node) => node.id === ids.root)!;\r\n const parentId = \"50000000-0000-4000-8000-000000000001\";\r\n const childId = \"50000000-0000-4000-8000-000000000002\";\r\n const transform = { scaleX: 1, scaleY: 1, rotation: 0 };\r\n // Ребёнок по умолчанию смещён на 50/50 внутри родителя 100x100, поэтому наполовину торчит наружу.\r\n scene.nodes.push({ id: parentId, name: \"Parent\", type: \"container\", parentId: ids.root, children: [childId], visible: true, transform: { ...transform, x: 0, y: 0, width: 100, height: 100 } });\r\n scene.nodes.push({ id: childId, name: \"Child\", type: \"container\", parentId, children: [], visible: true, transform: { ...transform, x: 50, y: 50, width: 100, height: 100 } });\r\n root.children.push(parentId);\r\n\r\n const { nodeViews } = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"authoring\" });\r\n const child = nodeViews.get(childId) as NodeView;\r\n\r\n // Точка (90, 90) в локальных координатах ребёнка лежит за границей родителя.\r\n expect(child.containsPoint({ x: 90, y: 90 })).toBe(true);\r\n // hitArea родителя обрезала бы здесь всё поддерево, поэтому её быть не должно.\r\n expect(nodeViews.get(parentId)!.hitArea).toBeUndefined();\r\n });\r\n\r\n it(\"falls back to the normal image for states without an asset and switches the shown view on every state\", () => {\r\n const document = documentWithButton();\r\n const textures = new Map([[ids.asset, Texture.WHITE], [buttonIds.pressedAsset, Texture.EMPTY]]);\r\n const view = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"runtime\", textures }).nodeViews.get(buttonIds.node) as ButtonNodeView;\r\n\r\n expect(view.state).toBe(\"normal\");\r\n expect(shownStateTexture(view)).toBe(Texture.WHITE);\r\n\r\n // hover и disabled не имеют своего asset и обязаны показывать normal; pressed — собственный.\r\n const shown = ([\"hover\", \"pressed\", \"normal\", \"disabled\"] as const).map((state) => {\r\n view.setState(state);\r\n return [view.state, shownStateTexture(view)] as const;\r\n });\r\n expect(shown).toEqual([\r\n [\"hover\", Texture.WHITE],\r\n [\"pressed\", Texture.EMPTY],\r\n [\"normal\", Texture.WHITE],\r\n [\"disabled\", Texture.WHITE],\r\n ]);\r\n });\r\n\r\n it(\"uses a NineSliceSprite for every button state once nineSlice is set, carrying the authored borders\", () => {\r\n const document = documentWithButton();\r\n const buttonNode = document.scenes[0]!.nodes.find((node) => node.id === buttonIds.node)! as Extract<UINode, { type: \"button\" }>;\r\n buttonNode.nineSlice = { left: 6, top: 4, right: 6, bottom: 4 };\r\n const textures = new Map([[ids.asset, Texture.WHITE], [buttonIds.pressedAsset, Texture.EMPTY]]);\r\n const view = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"runtime\", textures }).nodeViews.get(buttonIds.node) as ButtonNodeView;\r\n\r\n const stateViews: Container[] = [];\r\n const walk = (container: Container): void => { if (container instanceof Sprite || container instanceof NineSliceSprite) stateViews.push(container); container.children.forEach(walk); };\r\n walk(view);\r\n\r\n // normal/hover/disabled fall back to the normal asset; pressed has its own — all four are sliced.\r\n expect(stateViews).toHaveLength(4);\r\n expect(stateViews.every((child) => child instanceof NineSliceSprite)).toBe(true);\r\n expect((stateViews as NineSliceSprite[]).map((child) => [child.leftWidth, child.topHeight, child.rightWidth, child.bottomHeight])).toEqual([[6, 4, 6, 4], [6, 4, 6, 4], [6, 4, 6, 4], [6, 4, 6, 4]]);\r\n });\r\n\r\n it(\"renders a plain Sprite without nineSlice and a NineSliceSprite with it, carrying the authored borders\", () => {\r\n const document = renderDocument();\r\n const textures = new Map([[ids.asset, Texture.WHITE]]);\r\n\r\n const plain = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"runtime\", textures }).nodeViews.get(ids.image)!;\r\n expect(plain.children[0]).toBeInstanceOf(Sprite);\r\n expect(plain.children[0]).not.toBeInstanceOf(NineSliceSprite);\r\n\r\n const imageNode = document.scenes[0]!.nodes.find((node) => node.id === ids.image && node.type === \"image\")!;\r\n (imageNode as Extract<UINode, { type: \"image\" }>).nineSlice = { left: 8, top: 6, right: 8, bottom: 6 };\r\n const sliced = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"runtime\", textures }).nodeViews.get(ids.image)!;\r\n const sprite = sliced.children[0];\r\n expect(sprite).toBeInstanceOf(NineSliceSprite);\r\n expect(sprite).toMatchObject({ leftWidth: 8, topHeight: 6, rightWidth: 8, bottomHeight: 6 });\r\n });\r\n\r\n it(\"swaps a checkbox's shown texture on hover, independently for its checked and unchecked views\", () => {\r\n const document = renderDocument();\r\n const scene = document.scenes[0]!;\r\n const root = scene.nodes.find((node) => node.id === ids.root)!;\r\n const checkboxId = \"10000000-0000-4000-8000-000000000011\";\r\n const uncheckedHoverAsset = \"10000000-0000-4000-8000-000000000012\";\r\n const checkedHoverAsset = \"10000000-0000-4000-8000-000000000013\";\r\n document.assets.push({ id: uncheckedHoverAsset, name: \"Unchecked hover\", type: \"image\", source: { uri: \"assets/unchecked-hover.png\", mediaType: \"image/png\" } });\r\n document.assets.push({ id: checkedHoverAsset, name: \"Checked hover\", type: \"image\", source: { uri: \"assets/checked-hover.png\", mediaType: \"image/png\" } });\r\n scene.nodes.push({\r\n id: checkboxId, name: \"Agree\", type: \"checkbox\", parentId: root.id, children: [], visible: true,\r\n enabled: true, defaultChecked: false,\r\n // Hover textures deliberately mirror the *other* base state, so a swap is unambiguous with only two Texture identities available offscreen.\r\n states: { uncheckedAssetId: ids.asset, checkedAssetId: buttonIds.pressedAsset, uncheckedHoverAssetId: buttonIds.pressedAsset, checkedHoverAssetId: ids.asset },\r\n transform: { x: 0, y: 0, width: 32, height: 32, scaleX: 1, scaleY: 1, rotation: 0 },\r\n });\r\n root.children.push(checkboxId);\r\n\r\n const textures = new Map([[ids.asset, Texture.WHITE], [buttonIds.pressedAsset, Texture.EMPTY]]);\r\n const view = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"runtime\", textures }).nodeViews.get(checkboxId) as CheckboxNodeView;\r\n // Pixi's typed Container.emit requires a payload for known federated event names; the listener\r\n // only reads the event name, so a loosely-typed emit is enough to exercise it here.\r\n const innerView = (view.children[0] as unknown as { innerView: { emit: (event: string) => void } }).innerView;\r\n\r\n expect(shownStateTexture(view)).toBe(Texture.WHITE);\r\n innerView.emit(\"pointerover\");\r\n expect(shownStateTexture(view)).toBe(Texture.EMPTY);\r\n innerView.emit(\"pointerout\");\r\n expect(shownStateTexture(view)).toBe(Texture.WHITE);\r\n\r\n view.checked = true;\r\n expect(shownStateTexture(view)).toBe(Texture.EMPTY);\r\n innerView.emit(\"pointerover\");\r\n expect(shownStateTexture(view)).toBe(Texture.WHITE);\r\n });\r\n\r\n it(\"stops dispatching pointer events to a disabled button without writing runtime state back to the document\", () => {\r\n const document = documentWithButton();\r\n const view = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"runtime\", textures: new Map([[ids.asset, Texture.WHITE]]) }).nodeViews.get(buttonIds.node) as ButtonNodeView;\r\n const node = document.scenes[0]!.nodes.find((candidate) => candidate.id === buttonIds.node)!;\r\n const button = view.children[0]!;\r\n\r\n expect(view.enabled).toBe(true);\r\n expect(button.eventMode).toBe(\"static\");\r\n\r\n view.enabled = false;\r\n\r\n expect(view.enabled).toBe(false);\r\n expect(view.state).toBe(\"disabled\");\r\n // Именно так @pixi/ui глушит press: EventSystem не доставляет события неинтерактивному view.\r\n expect(button.eventMode).not.toBe(\"static\");\r\n // Enabled — только начальное presentation-состояние: runtime setter документ не трогает.\r\n expect(node).toMatchObject({ type: \"button\", enabled: true });\r\n });\r\n\r\n it(\"builds an inert button on an authoring canvas while keeping the node itself grabbable\", () => {\r\n const document = documentWithButton();\r\n const view = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"authoring\", textures: new Map([[ids.asset, Texture.WHITE]]) }).nodeViews.get(buttonIds.node)!;\r\n\r\n // FancyButton не реагирует на pointer во время authoring...\r\n expect(view.children[0]!.eventMode).toBe(\"none\");\r\n // ...но выделение и drag идут через grab-прямоугольник самого NodeView и обязаны продолжать работать.\r\n expect((view as NodeView).containsPoint({ x: 60, y: 20 })).toBe(true);\r\n });\r\n\r\n it(\"applies identical layout coordinates to image, text, and Spine node containers\", () => {\r\n const document = renderDocument();\r\n const scene = document.scenes[0]!;\r\n const root = scene.nodes.find((node) => node.id === ids.root)!;\r\n const image = scene.nodes.find((node) => node.id === ids.image)!;\r\n const text = scene.nodes.find((node) => node.id === ids.text)!;\r\n const spineId = \"10000000-0000-4000-8000-000000000007\";\r\n const transform = { x: -240, y: -90, width: 320, height: 180, scaleX: 1.25, scaleY: 0.75, rotation: 0.2, anchorMinX: 1, anchorMaxX: 1, anchorMinY: 0.5, anchorMaxY: 0.5, pivotX: 0.75, pivotY: 0.5 };\r\n image.transform = { ...transform };\r\n text.transform = { ...transform };\r\n const spine: UINode = { id: spineId, name: \"Spine\", type: \"spine\", assetId: ids.asset, parentId: ids.root, children: [], visible: true, transform: { ...transform } };\r\n scene.nodes.push(spine);\r\n root.children.push(spineId);\r\n\r\n const views = buildSceneView(document, ids.scene, \"desktop\", { interaction: \"authoring\", textures: new Map([[ids.asset, Texture.WHITE]]) }).nodeViews;\r\n const snapshot = (nodeId: string) => {\r\n const view = views.get(nodeId)!;\r\n return { position: { x: view.position.x, y: view.position.y }, pivot: { x: view.pivot.x, y: view.pivot.y }, scale: { x: view.scale.x, y: view.scale.y }, rotation: view.rotation };\r\n };\r\n\r\n expect(snapshot(ids.text)).toEqual(snapshot(ids.image));\r\n expect(snapshot(spineId)).toEqual(snapshot(ids.image));\r\n });\r\n\r\n it(\"loads the repository fixture through migration and validation\", () => {\r\n const document = parseProjectDocumentJson(sampleJson);\r\n const scene = document.scenes[0]!;\r\n expect(scene.id).toBe(ids.scene);\r\n expect(scene.rootNodeIds).toEqual([ids.root]);\r\n expect(scene.nodes.find((node) => node.id === ids.image && node.type === \"image\")).toMatchObject({ assetId: ids.asset });\r\n expect(scene.nodes.find((node) => node.id === ids.text)).toMatchObject({ bindingKey: \"showcase.title\" });\r\n expect(scene.layout.referenceViewports).toHaveProperty(\"desktop\");\r\n expect(scene.layout.referenceViewports).toHaveProperty(\"mobile\");\r\n });\r\n\r\n it(\"round-trips deterministically while retaining semantic child order\", () => {\r\n const document = parseProjectDocumentJson(sampleJson);\r\n const serialized = serializeProjectDocument(document);\r\n const roundTripped = parseProjectDocumentJson(serialized);\r\n expect(roundTripped).toEqual(document);\r\n expect(serializeProjectDocument(roundTripped)).toBe(serialized);\r\n expect(roundTripped.scenes[0]!.nodes[0]!.children).toEqual([\r\n ids.text,\r\n \"10000000-0000-4000-8000-000000000020\",\r\n \"10000000-0000-4000-8000-000000000030\",\r\n \"10000000-0000-4000-8000-000000000040\",\r\n \"10000000-0000-4000-8000-000000000050\",\r\n \"10000000-0000-4000-8000-000000000062\",\r\n \"10000000-0000-4000-8000-000000000063\",\r\n ]);\r\n });\r\n\r\n it(\"does not use display names as references\", () => {\r\n const document = parseProjectDocumentJson(sampleJson);\r\n const renamed = clone(document);\r\n const image = renamed.scenes[0]!.nodes.find((node) => node.id === ids.image)!;\r\n image.name = \"Renamed image\";\r\n expect(parseProjectDocumentJson(serializeProjectDocument(renamed)).scenes[0]!.nodes.find((node) => node.id === ids.image)).toMatchObject({ id: ids.image, assetId: ids.asset });\r\n });\r\n\r\n it(\"surfaces schema validation codes through the JSON loading boundary\", () => {\r\n const invalid = clone(parseProjectDocumentJson(sampleJson));\r\n (invalid.scenes[0]!.nodes.find((node) => node.id === ids.image)! as { assetId: string }).assetId = ids.text;\r\n expect(() => parseProjectDocumentJson(JSON.stringify(invalid))).toThrow(\"MISSING_ASSET_REFERENCE\");\r\n });\r\n\r\n it(\"distinguishes malformed JSON from schema errors\", () => {\r\n expect(() => parseProjectDocumentJson(\"{not json\")).toThrow(ProjectDocumentJsonParseError);\r\n const invalid = clone(parseProjectDocumentJson(sampleJson));\r\n delete (invalid.scenes[0]!.layout.referenceViewports as Record<string, unknown>).mobile;\r\n expect(() => parseProjectDocumentJson(JSON.stringify(invalid))).toThrow(TypeError);\r\n });\r\n});\r\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=particles.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"particles.test.d.ts","sourceRoot":"","sources":["../src/particles.test.ts"],"names":[],"mappings":""}
@@ -1,210 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { ParticlePool, ParticleSimulator } from "./particles.js";
3
- function definition(overrides = {}) {
4
- return {
5
- id: "effect-1", name: "Effect", type: "particles", maxParticles: 8, seed: 42,
6
- emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [] },
7
- particle: {
8
- lifetime: { min: 0.5, max: 0.5 },
9
- spawnShape: { type: "point" },
10
- movement: { speed: { min: 0, max: 0 }, directionDegrees: 0, spreadDegrees: 0, accelerationX: 0, accelerationY: 0, drag: 0 },
11
- visual: {
12
- source: { type: "single", assetId: "asset-1" },
13
- alpha: { start: 1, end: 0 },
14
- scale: { start: { min: 1, max: 1 }, end: { min: 1, max: 1 } },
15
- tint: { start: "#FFFFFF", end: "#FFFFFF" },
16
- rotation: { initialDegrees: { min: 0, max: 0 }, angularVelocityDegrees: { min: 0, max: 0 } },
17
- blendMode: "normal",
18
- },
19
- },
20
- ...overrides,
21
- };
22
- }
23
- function makeHooks() {
24
- const created = [];
25
- const destroyed = [];
26
- const hooks = {
27
- createRender: () => { const render = { visible: false }; created.push(render); return render; },
28
- hideRender: (render) => { render.visible = false; },
29
- destroyRender: (render) => { destroyed.push(render); },
30
- getWorldTransform: () => ({ a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }),
31
- };
32
- return { hooks, created, destroyed };
33
- }
34
- const area = { width: 100, height: 100, space: "local" };
35
- describe("ParticlePool", () => {
36
- it("prewarms exactly capacity slots, never calls the factory on acquire/release, and reuses released identity", () => {
37
- let created = 0;
38
- const pool = new ParticlePool(() => ({ id: created++ }), 3);
39
- expect(created).toBe(3);
40
- const a = pool.acquire();
41
- pool.acquire();
42
- expect(created).toBe(3);
43
- pool.release(a);
44
- expect(pool.acquire()).toBe(a);
45
- expect(created).toBe(3);
46
- });
47
- it("increments dropped and never exceeds capacity on exhaustion", () => {
48
- const pool = new ParticlePool(() => ({}), 1);
49
- pool.acquire();
50
- expect(pool.acquire()).toBeUndefined();
51
- expect(pool.dropped).toBe(1);
52
- });
53
- it("creates only the delta on growth and drains active slots beyond a shrunk capacity without recycling them", () => {
54
- const destroyed = [];
55
- let created = 0;
56
- const pool = new ParticlePool(() => created++, 2, (value) => destroyed.push(value));
57
- const a = pool.acquire(), b = pool.acquire();
58
- pool.resize(4);
59
- expect(created).toBe(4);
60
- pool.resize(1);
61
- expect(destroyed).toHaveLength(2); // the two idle free slots are destroyed immediately
62
- pool.release(a); // still over the new capacity: destroyed instead of recycled
63
- expect(destroyed).toHaveLength(3);
64
- pool.release(b); // back at capacity: recycled normally
65
- expect(destroyed).toHaveLength(3);
66
- expect(pool.acquire()).toBe(b);
67
- });
68
- });
69
- describe("ParticleSimulator determinism", () => {
70
- it("gives the same active-slot state at fixed-step boundaries regardless of how render delta is split", () => {
71
- const def = definition({ emission: { delay: 0, duration: 10, loop: true, rate: 30, bursts: [] } });
72
- const simA = new ParticleSimulator(def, makeHooks().hooks);
73
- const simB = new ParticleSimulator(def, makeHooks().hooks);
74
- simA.play();
75
- simB.play();
76
- // Total stays comfortably under the 8-step catch-up cap for both splits, so the cap itself
77
- // never becomes the variable under test — only the splitting is.
78
- simA.update(0.1, area);
79
- for (const chunk of [0.03, 0.02, 0.05])
80
- simB.update(chunk, area);
81
- const snapshot = (sim) => [...sim.activeSlots]
82
- .map((slot) => ({ age: Math.round(slot.age * 1e6), x: Math.round(slot.x * 1e6), y: Math.round(slot.y * 1e6) }))
83
- .sort((p, q) => p.age - q.age);
84
- expect(snapshot(simA)).toEqual(snapshot(simB));
85
- expect(simA.getDiagnostics()).toEqual(simB.getDiagnostics());
86
- });
87
- });
88
- describe("ParticleSimulator burst scheduling", () => {
89
- it("fires a burst with time 0 on the very first fixed step after start", () => {
90
- const def = definition({ emission: { delay: 0, duration: 0.2, loop: true, rate: 0, bursts: [{ time: 0, count: 3 }] } });
91
- def.particle.lifetime = { min: 100, max: 100 };
92
- const sim = new ParticleSimulator(def, makeHooks().hooks);
93
- sim.play();
94
- sim.step(area);
95
- expect(sim.activeSlots.size).toBe(3);
96
- });
97
- it("fires a non-loop burst exactly once even when stepped well past its trigger and duration", () => {
98
- const def = definition({ emission: { delay: 0, duration: 0.5, loop: false, rate: 0, bursts: [{ time: 0.1, count: 2 }] } });
99
- def.particle.lifetime = { min: 100, max: 100 };
100
- const sim = new ParticleSimulator(def, makeHooks().hooks);
101
- sim.play();
102
- for (let i = 0; i < 4; i++)
103
- sim.step(area); // well before the 0.1s trigger
104
- expect(sim.activeSlots.size).toBe(0);
105
- for (let i = 0; i < 4; i++)
106
- sim.step(area); // now solidly past the trigger (8/60 ≈ 0.133s)
107
- expect(sim.activeSlots.size).toBe(2);
108
- for (let i = 0; i < 60; i++)
109
- sim.step(area); // well past duration and beyond
110
- expect(sim.activeSlots.size).toBe(2);
111
- });
112
- it("fires a loop burst again on the next cycle, including across the cycle boundary", () => {
113
- const def = definition({ emission: { delay: 0, duration: 0.1, loop: true, rate: 0, bursts: [{ time: 0, count: 1 }] } });
114
- def.particle.lifetime = { min: 100, max: 100 };
115
- const sim = new ParticleSimulator(def, makeHooks().hooks);
116
- sim.play();
117
- sim.step(area); // first fixed step: elapsed ≈ 1/60, burst fires
118
- expect(sim.activeSlots.size).toBe(1);
119
- for (let i = 0; i < 3; i++)
120
- sim.step(area); // elapsed ≈ 4/60, still inside the first cycle
121
- expect(sim.activeSlots.size).toBe(1);
122
- for (let i = 0; i < 3; i++)
123
- sim.step(area); // elapsed ≈ 7/60, solidly past the 0.1s cycle boundary
124
- expect(sim.activeSlots.size).toBe(2);
125
- });
126
- });
127
- describe("ParticleSimulator lifecycle", () => {
128
- it("stop() blocks new spawns while already-emitted particles drain to active === 0", () => {
129
- const def = definition({ emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 4 }] } });
130
- def.particle.lifetime = { min: 2 / 60, max: 2 / 60 };
131
- const sim = new ParticleSimulator(def, makeHooks().hooks);
132
- sim.play();
133
- sim.step(area);
134
- expect(sim.activeSlots.size).toBe(4);
135
- sim.stop();
136
- expect(sim.getDiagnostics()).toMatchObject({ playing: false, stopped: true });
137
- sim.step(area); // still simulating: ages toward death but hasn't reached lifetime yet
138
- expect(sim.activeSlots.size).toBe(4);
139
- sim.step(area); // lifetime reached; particles die and are not replaced because spawning is blocked
140
- expect(sim.activeSlots.size).toBe(0);
141
- });
142
- it("dispose() immediately clears every slot, is idempotent, and excludes the simulator from further updates", () => {
143
- const { hooks, created, destroyed } = makeHooks();
144
- const def = definition({ maxParticles: 5, emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 2 }] } });
145
- const sim = new ParticleSimulator(def, hooks);
146
- sim.play();
147
- sim.step(area);
148
- expect(sim.activeSlots.size).toBe(2);
149
- sim.dispose();
150
- expect(sim.activeSlots.size).toBe(0);
151
- expect(destroyed).toHaveLength(created.length);
152
- expect(sim.getDiagnostics()).toMatchObject({ active: 0, disposed: true });
153
- sim.dispose(); // idempotent
154
- sim.play();
155
- sim.step(area);
156
- sim.restart();
157
- expect(sim.activeSlots.size).toBe(0);
158
- expect(sim.getDiagnostics().disposed).toBe(true);
159
- });
160
- it("pause() freezes state, step() advances one fixed step regardless, and restart() replays the initial sequence and resets dropped", () => {
161
- const def = definition({ maxParticles: 2, emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 3 }] } });
162
- const sim = new ParticleSimulator(def, makeHooks().hooks);
163
- sim.play();
164
- sim.step(area); // burst of 3 into a pool of 2: one dropped
165
- expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 });
166
- sim.pause();
167
- sim.update(1, area); // paused: no time passes, no state changes
168
- expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1, playing: false, stopped: false }); // paused is distinct from stopped
169
- sim.step(area); // step still advances one fixed tick even while paused
170
- expect(sim.getDiagnostics().playing).toBe(false); // ...without leaving pause
171
- sim.restart();
172
- expect(sim.getDiagnostics()).toMatchObject({ active: 0, dropped: 0, playing: true });
173
- sim.step(area);
174
- expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 });
175
- });
176
- });
177
- describe("ParticleSimulator incremental sync", () => {
178
- it("never restarts on an unrelated clone or a seed edit", () => {
179
- const def = definition({ maxParticles: 3, seed: 7, emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 2 }] } });
180
- const sim = new ParticleSimulator(def, makeHooks().hooks);
181
- sim.play();
182
- sim.step(area);
183
- expect(sim.activeSlots.size).toBe(2);
184
- const renamed = structuredClone(def);
185
- renamed.name = "Renamed";
186
- sim.syncEffect(renamed);
187
- expect(sim.activeSlots.size).toBe(2);
188
- const reseeded = structuredClone(renamed);
189
- reseeded.seed = 999;
190
- sim.syncEffect(reseeded);
191
- expect(sim.activeSlots.size).toBe(2); // seed only applies at the next explicit restart()
192
- });
193
- it("resizes the pool live on a maxParticles change without disturbing existing particles", () => {
194
- const def = definition({ maxParticles: 2, emission: { delay: 0, duration: 10, loop: true, rate: 60, bursts: [] } });
195
- const sim = new ParticleSimulator(def, makeHooks().hooks);
196
- sim.play();
197
- sim.step(area);
198
- sim.step(area);
199
- sim.step(area); // 3 spawns attempted at 1/tick, pool holds 2, 1 dropped
200
- expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 });
201
- const grown = structuredClone(def);
202
- grown.maxParticles = 4;
203
- sim.syncEffect(grown);
204
- expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 }); // sync itself changes nothing
205
- sim.step(area);
206
- sim.step(area); // 2 more spawns now fit in the grown pool
207
- expect(sim.getDiagnostics()).toMatchObject({ active: 4, dropped: 1 });
208
- });
209
- });
210
- //# sourceMappingURL=particles.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"particles.test.js","sourceRoot":"","sources":["../src/particles.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAuD,MAAM,gBAAgB,CAAC;AAEtH,SAAS,UAAU,CAAC,YAA+C,EAAE;IACnE,OAAO;QACL,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;QAC5E,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACrE,QAAQ,EAAE;YACR,QAAQ,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;YAChC,UAAU,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;YAC7B,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,gBAAgB,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;YAC3H,MAAM,EAAE;gBACN,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE;gBAC9C,KAAK,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;gBAC3B,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;gBAC7D,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE;gBAC1C,QAAQ,EAAE,EAAE,cAAc,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,sBAAsB,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE;gBAC5F,SAAS,EAAE,QAAQ;aACpB;SACF;QACD,GAAG,SAAS;KACe,CAAC;AAChC,CAAC;AAGD,SAAS,SAAS;IAChB,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,MAAM,SAAS,GAAiB,EAAE,CAAC;IACnC,MAAM,KAAK,GAAoC;QAC7C,YAAY,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC;QAC/F,UAAU,EAAE,CAAC,MAAM,EAAE,EAAE,GAAG,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC;QACnD,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACtD,iBAAiB,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC;KACpE,CAAC;IACF,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,IAAI,GAAyB,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAE/E,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,EAAE,CAAC,2GAA2G,EAAE,GAAG,EAAE;QACnH,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,EAAG,CAAC;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QAChB,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC;QACvC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0GAA0G,EAAE,GAAG,EAAE;QAClH,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACpF,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,EAAG,EAAE,CAAC,GAAG,IAAI,CAAC,OAAO,EAAG,CAAC;QAC/C,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACf,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACf,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,oDAAoD;QACvF,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,6DAA6D;QAC9E,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,sCAAsC;QACvD,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;IAC7C,EAAE,CAAC,mGAAmG,EAAE,GAAG,EAAE;QAC3G,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACnG,MAAM,IAAI,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,2FAA2F;QAC3F,iEAAiE;QACjE,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvB,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QACjE,MAAM,QAAQ,GAAG,CAAC,GAAkC,EAAE,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC;aAC1E,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,EAAE,CAAC,CAAC;aAC9G,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/C,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxH,GAAG,CAAC,QAAQ,CAAC,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0FAA0F,EAAE,GAAG,EAAE;QAClG,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3H,GAAG,CAAC,QAAQ,CAAC,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,+BAA+B;QAC3E,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,+CAA+C;QAC3F,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,gCAAgC;QAC7E,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QACzF,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxH,GAAG,CAAC,QAAQ,CAAC,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;QAC/C,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,gDAAgD;QAChE,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,+CAA+C;QAC3F,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,uDAAuD;QACnG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;IAC3C,EAAE,CAAC,gFAAgF,EAAE,GAAG,EAAE;QACxF,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACvH,GAAG,CAAC,QAAQ,CAAC,QAAQ,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9E,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,sEAAsE;QACtF,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,mFAAmF;QACnG,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yGAAyG,EAAE,GAAG,EAAE;QACjH,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;QAClD,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxI,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9C,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAErC,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QAE1E,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC,aAAa;QAC5B,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iIAAiI,EAAE,GAAG,EAAE;QACzI,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACxI,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,2CAA2C;QAC3D,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAEtE,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,2CAA2C;QAChE,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,kCAAkC;QACzI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,uDAAuD;QACvE,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,2BAA2B;QAE7E,GAAG,CAAC,OAAO,EAAE,CAAC;QACd,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;IAClD,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACjJ,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAErC,MAAM,OAAO,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;QACzB,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAErC,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;QAC1C,QAAQ,CAAC,IAAI,GAAG,GAAG,CAAC;QACpB,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QACzB,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,mDAAmD;IAC3F,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,GAAG,EAAE;QAC9F,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QACpH,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,CAAC;QAC1D,GAAG,CAAC,IAAI,EAAE,CAAC;QACX,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,wDAAwD;QACxE,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QAEtE,MAAM,KAAK,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;QACnC,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC;QACvB,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACtB,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,8BAA8B;QAErG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACf,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,0CAA0C;QAC1D,MAAM,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { describe, expect, it } from \"vitest\";\r\nimport type { ParticleEffectDefinition } from \"@pixi-ui-editor/schema\";\r\nimport { ParticlePool, ParticleSimulator, type ParticleRenderHooks, type ParticleSpawnContext } from \"./particles.js\";\r\n\r\nfunction definition(overrides: Partial<ParticleEffectDefinition> = {}): ParticleEffectDefinition {\r\n return {\r\n id: \"effect-1\", name: \"Effect\", type: \"particles\", maxParticles: 8, seed: 42,\r\n emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [] },\r\n particle: {\r\n lifetime: { min: 0.5, max: 0.5 },\r\n spawnShape: { type: \"point\" },\r\n movement: { speed: { min: 0, max: 0 }, directionDegrees: 0, spreadDegrees: 0, accelerationX: 0, accelerationY: 0, drag: 0 },\r\n visual: {\r\n source: { type: \"single\", assetId: \"asset-1\" },\r\n alpha: { start: 1, end: 0 },\r\n scale: { start: { min: 1, max: 1 }, end: { min: 1, max: 1 } },\r\n tint: { start: \"#FFFFFF\", end: \"#FFFFFF\" },\r\n rotation: { initialDegrees: { min: 0, max: 0 }, angularVelocityDegrees: { min: 0, max: 0 } },\r\n blendMode: \"normal\",\r\n },\r\n },\r\n ...overrides,\r\n } as ParticleEffectDefinition;\r\n}\r\n\r\ntype FakeRender = { visible: boolean };\r\nfunction makeHooks() {\r\n const created: FakeRender[] = [];\r\n const destroyed: FakeRender[] = [];\r\n const hooks: ParticleRenderHooks<FakeRender> = {\r\n createRender: () => { const render = { visible: false }; created.push(render); return render; },\r\n hideRender: (render) => { render.visible = false; },\r\n destroyRender: (render) => { destroyed.push(render); },\r\n getWorldTransform: () => ({ a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }),\r\n };\r\n return { hooks, created, destroyed };\r\n}\r\n\r\nconst area: ParticleSpawnContext = { width: 100, height: 100, space: \"local\" };\r\n\r\ndescribe(\"ParticlePool\", () => {\r\n it(\"prewarms exactly capacity slots, never calls the factory on acquire/release, and reuses released identity\", () => {\r\n let created = 0;\r\n const pool = new ParticlePool(() => ({ id: created++ }), 3);\r\n expect(created).toBe(3);\r\n const a = pool.acquire()!;\r\n pool.acquire();\r\n expect(created).toBe(3);\r\n pool.release(a);\r\n expect(pool.acquire()).toBe(a);\r\n expect(created).toBe(3);\r\n });\r\n\r\n it(\"increments dropped and never exceeds capacity on exhaustion\", () => {\r\n const pool = new ParticlePool(() => ({}), 1);\r\n pool.acquire();\r\n expect(pool.acquire()).toBeUndefined();\r\n expect(pool.dropped).toBe(1);\r\n });\r\n\r\n it(\"creates only the delta on growth and drains active slots beyond a shrunk capacity without recycling them\", () => {\r\n const destroyed: number[] = [];\r\n let created = 0;\r\n const pool = new ParticlePool(() => created++, 2, (value) => destroyed.push(value));\r\n const a = pool.acquire()!, b = pool.acquire()!;\r\n pool.resize(4);\r\n expect(created).toBe(4);\r\n pool.resize(1);\r\n expect(destroyed).toHaveLength(2); // the two idle free slots are destroyed immediately\r\n pool.release(a); // still over the new capacity: destroyed instead of recycled\r\n expect(destroyed).toHaveLength(3);\r\n pool.release(b); // back at capacity: recycled normally\r\n expect(destroyed).toHaveLength(3);\r\n expect(pool.acquire()).toBe(b);\r\n });\r\n});\r\n\r\ndescribe(\"ParticleSimulator determinism\", () => {\r\n it(\"gives the same active-slot state at fixed-step boundaries regardless of how render delta is split\", () => {\r\n const def = definition({ emission: { delay: 0, duration: 10, loop: true, rate: 30, bursts: [] } });\r\n const simA = new ParticleSimulator(def, makeHooks().hooks);\r\n const simB = new ParticleSimulator(def, makeHooks().hooks);\r\n simA.play();\r\n simB.play();\r\n // Total stays comfortably under the 8-step catch-up cap for both splits, so the cap itself\r\n // never becomes the variable under test — only the splitting is.\r\n simA.update(0.1, area);\r\n for (const chunk of [0.03, 0.02, 0.05]) simB.update(chunk, area);\r\n const snapshot = (sim: ParticleSimulator<FakeRender>) => [...sim.activeSlots]\r\n .map((slot) => ({ age: Math.round(slot.age * 1e6), x: Math.round(slot.x * 1e6), y: Math.round(slot.y * 1e6) }))\r\n .sort((p, q) => p.age - q.age);\r\n expect(snapshot(simA)).toEqual(snapshot(simB));\r\n expect(simA.getDiagnostics()).toEqual(simB.getDiagnostics());\r\n });\r\n});\r\n\r\ndescribe(\"ParticleSimulator burst scheduling\", () => {\r\n it(\"fires a burst with time 0 on the very first fixed step after start\", () => {\r\n const def = definition({ emission: { delay: 0, duration: 0.2, loop: true, rate: 0, bursts: [{ time: 0, count: 3 }] } });\r\n def.particle.lifetime = { min: 100, max: 100 };\r\n const sim = new ParticleSimulator(def, makeHooks().hooks);\r\n sim.play();\r\n sim.step(area);\r\n expect(sim.activeSlots.size).toBe(3);\r\n });\r\n\r\n it(\"fires a non-loop burst exactly once even when stepped well past its trigger and duration\", () => {\r\n const def = definition({ emission: { delay: 0, duration: 0.5, loop: false, rate: 0, bursts: [{ time: 0.1, count: 2 }] } });\r\n def.particle.lifetime = { min: 100, max: 100 };\r\n const sim = new ParticleSimulator(def, makeHooks().hooks);\r\n sim.play();\r\n for (let i = 0; i < 4; i++) sim.step(area); // well before the 0.1s trigger\r\n expect(sim.activeSlots.size).toBe(0);\r\n for (let i = 0; i < 4; i++) sim.step(area); // now solidly past the trigger (8/60 ≈ 0.133s)\r\n expect(sim.activeSlots.size).toBe(2);\r\n for (let i = 0; i < 60; i++) sim.step(area); // well past duration and beyond\r\n expect(sim.activeSlots.size).toBe(2);\r\n });\r\n\r\n it(\"fires a loop burst again on the next cycle, including across the cycle boundary\", () => {\r\n const def = definition({ emission: { delay: 0, duration: 0.1, loop: true, rate: 0, bursts: [{ time: 0, count: 1 }] } });\r\n def.particle.lifetime = { min: 100, max: 100 };\r\n const sim = new ParticleSimulator(def, makeHooks().hooks);\r\n sim.play();\r\n sim.step(area); // first fixed step: elapsed ≈ 1/60, burst fires\r\n expect(sim.activeSlots.size).toBe(1);\r\n for (let i = 0; i < 3; i++) sim.step(area); // elapsed ≈ 4/60, still inside the first cycle\r\n expect(sim.activeSlots.size).toBe(1);\r\n for (let i = 0; i < 3; i++) sim.step(area); // elapsed ≈ 7/60, solidly past the 0.1s cycle boundary\r\n expect(sim.activeSlots.size).toBe(2);\r\n });\r\n});\r\n\r\ndescribe(\"ParticleSimulator lifecycle\", () => {\r\n it(\"stop() blocks new spawns while already-emitted particles drain to active === 0\", () => {\r\n const def = definition({ emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 4 }] } });\r\n def.particle.lifetime = { min: 2 / 60, max: 2 / 60 };\r\n const sim = new ParticleSimulator(def, makeHooks().hooks);\r\n sim.play();\r\n sim.step(area);\r\n expect(sim.activeSlots.size).toBe(4);\r\n sim.stop();\r\n expect(sim.getDiagnostics()).toMatchObject({ playing: false, stopped: true });\r\n sim.step(area); // still simulating: ages toward death but hasn't reached lifetime yet\r\n expect(sim.activeSlots.size).toBe(4);\r\n sim.step(area); // lifetime reached; particles die and are not replaced because spawning is blocked\r\n expect(sim.activeSlots.size).toBe(0);\r\n });\r\n\r\n it(\"dispose() immediately clears every slot, is idempotent, and excludes the simulator from further updates\", () => {\r\n const { hooks, created, destroyed } = makeHooks();\r\n const def = definition({ maxParticles: 5, emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 2 }] } });\r\n const sim = new ParticleSimulator(def, hooks);\r\n sim.play();\r\n sim.step(area);\r\n expect(sim.activeSlots.size).toBe(2);\r\n\r\n sim.dispose();\r\n expect(sim.activeSlots.size).toBe(0);\r\n expect(destroyed).toHaveLength(created.length);\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 0, disposed: true });\r\n\r\n sim.dispose(); // idempotent\r\n sim.play();\r\n sim.step(area);\r\n sim.restart();\r\n expect(sim.activeSlots.size).toBe(0);\r\n expect(sim.getDiagnostics().disposed).toBe(true);\r\n });\r\n\r\n it(\"pause() freezes state, step() advances one fixed step regardless, and restart() replays the initial sequence and resets dropped\", () => {\r\n const def = definition({ maxParticles: 2, emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 3 }] } });\r\n const sim = new ParticleSimulator(def, makeHooks().hooks);\r\n sim.play();\r\n sim.step(area); // burst of 3 into a pool of 2: one dropped\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 });\r\n\r\n sim.pause();\r\n sim.update(1, area); // paused: no time passes, no state changes\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1, playing: false, stopped: false }); // paused is distinct from stopped\r\n sim.step(area); // step still advances one fixed tick even while paused\r\n expect(sim.getDiagnostics().playing).toBe(false); // ...without leaving pause\r\n\r\n sim.restart();\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 0, dropped: 0, playing: true });\r\n sim.step(area);\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 });\r\n });\r\n});\r\n\r\ndescribe(\"ParticleSimulator incremental sync\", () => {\r\n it(\"never restarts on an unrelated clone or a seed edit\", () => {\r\n const def = definition({ maxParticles: 3, seed: 7, emission: { delay: 0, duration: 10, loop: true, rate: 0, bursts: [{ time: 0, count: 2 }] } });\r\n const sim = new ParticleSimulator(def, makeHooks().hooks);\r\n sim.play();\r\n sim.step(area);\r\n expect(sim.activeSlots.size).toBe(2);\r\n\r\n const renamed = structuredClone(def);\r\n renamed.name = \"Renamed\";\r\n sim.syncEffect(renamed);\r\n expect(sim.activeSlots.size).toBe(2);\r\n\r\n const reseeded = structuredClone(renamed);\r\n reseeded.seed = 999;\r\n sim.syncEffect(reseeded);\r\n expect(sim.activeSlots.size).toBe(2); // seed only applies at the next explicit restart()\r\n });\r\n\r\n it(\"resizes the pool live on a maxParticles change without disturbing existing particles\", () => {\r\n const def = definition({ maxParticles: 2, emission: { delay: 0, duration: 10, loop: true, rate: 60, bursts: [] } });\r\n const sim = new ParticleSimulator(def, makeHooks().hooks);\r\n sim.play();\r\n sim.step(area);\r\n sim.step(area);\r\n sim.step(area); // 3 spawns attempted at 1/tick, pool holds 2, 1 dropped\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 });\r\n\r\n const grown = structuredClone(def);\r\n grown.maxParticles = 4;\r\n sim.syncEffect(grown);\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 2, dropped: 1 }); // sync itself changes nothing\r\n\r\n sim.step(area);\r\n sim.step(area); // 2 more spawns now fit in the grown pool\r\n expect(sim.getDiagnostics()).toMatchObject({ active: 4, dropped: 1 });\r\n });\r\n});\r\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=test.setup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test.setup.d.ts","sourceRoot":"","sources":["../src/test.setup.ts"],"names":[],"mappings":""}
@@ -1,6 +0,0 @@
1
- Object.defineProperty(globalThis, "navigator", {
2
- configurable: true,
3
- value: { userAgent: "node" },
4
- });
5
- export {};
6
- //# sourceMappingURL=test.setup.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test.setup.js","sourceRoot":"","sources":["../src/test.setup.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,cAAc,CAAC,UAAU,EAAE,WAAW,EAAE;IAC7C,YAAY,EAAE,IAAI;IAClB,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE;CAC7B,CAAC,CAAC","sourcesContent":["Object.defineProperty(globalThis, \"navigator\", {\n configurable: true,\n value: { userAgent: \"node\" },\n});\n"]}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ParticleEmitterNodeView.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ParticleEmitterNodeView.test.d.ts","sourceRoot":"","sources":["../../src/views/ParticleEmitterNodeView.test.ts"],"names":[],"mappings":""}