@pixi-ui-editor/runtime-pixi 0.6.0 → 0.7.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.
@@ -20,6 +20,8 @@ export declare function sampleSpawnPoint(shape: ParticleSpawnShape, width: numbe
20
20
  /** A prewarmed pool entry: `render` is an opaque adapter-owned renderer object created by the same factory as the simulation slot. */
21
21
  export type ParticleSlot<TRender> = {
22
22
  render: TRender;
23
+ /** Adapter-owned static attributes must be uploaded once after this slot is (re)spawned. */
24
+ renderDirty: boolean;
23
25
  age: number;
24
26
  lifetime: number;
25
27
  x: number;
@@ -113,6 +115,7 @@ export declare class ParticleSimulator<TRender> {
113
115
  private multiplier;
114
116
  private emitting;
115
117
  private simulating;
118
+ private stopped;
116
119
  private disposed;
117
120
  private context;
118
121
  constructor(definition: ParticleEffectDefinition, hooks: ParticleRenderHooks<TRender>);
@@ -129,8 +132,8 @@ export declare class ParticleSimulator<TRender> {
129
132
  /** Idempotent terminal cleanup: destroys every pooled render object and excludes the view from further updates. */
130
133
  dispose(): void;
131
134
  /** Advances exactly one fixed step regardless of paused/stopped state, and never changes it. */
132
- step(context: ParticleSpawnContext): void;
133
- update(deltaSeconds: number, context: ParticleSpawnContext): void;
135
+ step(context: ParticleSpawnContext): boolean;
136
+ update(deltaSeconds: number, context: ParticleSpawnContext): boolean;
134
137
  getDiagnostics(): ParticleDiagnostics;
135
138
  private tick;
136
139
  private spawnParticle;
@@ -1 +1 @@
1
- {"version":3,"file":"particles.d.ts","sourceRoot":"","sources":["../src/particles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"particles.d.ts","sourceRoot":"","sources":["../src/particles.ts"],"names":[],"mappings":"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"}
package/dist/particles.js CHANGED
@@ -27,9 +27,32 @@ export function sampleSpawnPoint(shape, width, height, random) {
27
27
  return { x: cx + Math.cos(angle) * radius * cx, y: cy + Math.sin(angle) * radius * cy };
28
28
  }
29
29
  function createZeroedSlot(render) {
30
- return { render, 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 };
30
+ 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 };
31
+ }
32
+ function resetSlot(slot) {
33
+ // Hot release path: reset in place instead of allocating a temporary zeroed slot for Object.assign.
34
+ slot.renderDirty = false;
35
+ slot.age = 0;
36
+ slot.lifetime = 0;
37
+ slot.x = 0;
38
+ slot.y = 0;
39
+ slot.vx = 0;
40
+ slot.vy = 0;
41
+ slot.spawnX = 0;
42
+ slot.spawnY = 0;
43
+ slot.rotationDegrees = 0;
44
+ slot.angularVelocityDegrees = 0;
45
+ slot.scaleStart = 1;
46
+ slot.scaleEnd = 1;
47
+ slot.sourceIndex = 0;
48
+ slot.sequenceStart = 0;
49
+ slot.worldSpawnX = 0;
50
+ slot.worldSpawnY = 0;
51
+ slot.spawnMatrixA = 1;
52
+ slot.spawnMatrixB = 0;
53
+ slot.spawnMatrixC = 0;
54
+ slot.spawnMatrixD = 1;
31
55
  }
32
- function resetSlot(slot) { Object.assign(slot, createZeroedSlot(slot.render)); }
33
56
  /**
34
57
  * Prewarmed object pool. `acquire`/`release` never call the factory; only `resize` does, and only for
35
58
  * the capacity delta. Shrinking removes idle free slots immediately; active slots beyond the new
@@ -112,6 +135,7 @@ export class ParticleSimulator {
112
135
  multiplier = 1;
113
136
  emitting = false;
114
137
  simulating = false;
138
+ stopped = false;
115
139
  disposed = false;
116
140
  context = { width: 0, height: 0, space: "local" };
117
141
  constructor(definition, hooks) {
@@ -136,13 +160,18 @@ export class ParticleSimulator {
136
160
  this.burstCursors = cursors;
137
161
  }
138
162
  play() { if (this.disposed)
139
- return; this.emitting = true; this.simulating = true; }
163
+ return; this.emitting = true; this.simulating = true; this.stopped = false; }
140
164
  /** Freezes emission and every live particle without resetting time or PRNG. */
141
165
  pause() { if (this.disposed)
142
- return; this.emitting = false; this.simulating = false; }
166
+ return; this.emitting = false; this.simulating = false; this.stopped = false; }
143
167
  /** Stops new spawns; already-emitted particles keep simulating to their natural death. */
144
- stop() { if (this.disposed)
145
- return; this.emitting = false; this.simulating = true; }
168
+ stop() {
169
+ if (this.disposed)
170
+ return;
171
+ this.emitting = false;
172
+ this.simulating = this.pool.values.size > 0;
173
+ this.stopped = true;
174
+ }
146
175
  restart() {
147
176
  if (this.disposed)
148
177
  return;
@@ -156,6 +185,7 @@ export class ParticleSimulator {
156
185
  this.random = new SeededRandom(this.definition.seed);
157
186
  this.emitting = true;
158
187
  this.simulating = true;
188
+ this.stopped = false;
159
189
  }
160
190
  /** Idempotent terminal cleanup: destroys every pooled render object and excludes the view from further updates. */
161
191
  dispose() {
@@ -164,34 +194,39 @@ export class ParticleSimulator {
164
194
  this.disposed = true;
165
195
  this.emitting = false;
166
196
  this.simulating = false;
197
+ this.stopped = false;
167
198
  this.pool.clear();
168
199
  }
169
200
  /** Advances exactly one fixed step regardless of paused/stopped state, and never changes it. */
170
201
  step(context) {
171
202
  if (this.disposed)
172
- return;
203
+ return false;
173
204
  this.context = context;
174
205
  this.tick(ParticleSimulator.stepSeconds);
206
+ return true;
175
207
  }
176
208
  update(deltaSeconds, context) {
177
209
  if (this.disposed || !this.simulating)
178
- return;
210
+ return false;
179
211
  this.context = context;
180
212
  this.stepAccumulator = Math.min(this.stepAccumulator + Math.max(0, deltaSeconds), ParticleSimulator.stepSeconds * 8);
213
+ let advanced = false;
181
214
  while (this.stepAccumulator >= ParticleSimulator.stepSeconds) {
182
215
  this.stepAccumulator -= ParticleSimulator.stepSeconds;
183
216
  this.tick(ParticleSimulator.stepSeconds);
217
+ advanced = true;
184
218
  }
219
+ return advanced;
185
220
  }
186
221
  getDiagnostics() {
187
- return { active: this.pool.values.size, dropped: this.pool.dropped, playing: this.emitting, stopped: this.simulating && !this.emitting && !this.disposed, disposed: this.disposed };
222
+ return { active: this.pool.values.size, dropped: this.pool.dropped, playing: this.emitting, stopped: this.stopped && !this.disposed, disposed: this.disposed };
188
223
  }
189
224
  tick(dt) {
190
225
  // Age and move existing particles before spawning: a particle created this tick starts at age 0
191
226
  // and receives its first dt on the next tick, instead of being silently pre-aged by one step.
192
227
  const movement = this.definition.particle.movement;
193
228
  const drag = Math.max(0, 1 - movement.drag * dt);
194
- for (const slot of [...this.pool.values]) {
229
+ for (const slot of this.pool.values) {
195
230
  slot.age += dt;
196
231
  if (slot.age >= slot.lifetime) {
197
232
  this.releaseSlot(slot);
@@ -216,7 +251,8 @@ export class ParticleSimulator {
216
251
  this.spawnParticle();
217
252
  }
218
253
  }
219
- e.bursts.forEach((burst, index) => {
254
+ for (let index = 0; index < e.bursts.length; index++) {
255
+ const burst = e.bursts[index];
220
256
  const triggerBase = e.delay + burst.time;
221
257
  for (;;) {
222
258
  const cursor = this.burstCursors[index] ?? 0;
@@ -229,8 +265,16 @@ export class ParticleSimulator {
229
265
  this.spawnParticle();
230
266
  this.burstCursors[index] = cursor + 1;
231
267
  }
232
- });
268
+ }
269
+ if (!e.loop && this.elapsed >= e.delay + e.duration) {
270
+ this.emitting = false;
271
+ this.stopped = true;
272
+ }
233
273
  }
274
+ // A completed one-shot or a graceful stop must not keep an otherwise idle emitter on the hot
275
+ // ticker path forever. Preserve the stopped diagnostic while putting simulation fully to sleep.
276
+ if (!this.emitting && this.pool.values.size === 0)
277
+ this.simulating = false;
234
278
  }
235
279
  spawnParticle() {
236
280
  const slot = this.pool.acquire();
@@ -239,6 +283,7 @@ export class ParticleSimulator {
239
283
  const p = this.definition.particle;
240
284
  const rand = this.random;
241
285
  const point = sampleSpawnPoint(p.spawnShape.type, this.context.width, this.context.height, rand);
286
+ slot.renderDirty = true;
242
287
  slot.age = 0;
243
288
  slot.lifetime = rand.range(p.lifetime.min, p.lifetime.max);
244
289
  slot.spawnX = point.x;
@@ -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> = {\r\n render: TRender;\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, 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 { Object.assign(slot, createZeroedSlot(slot.render)); }\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 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; }\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; }\r\n /** Stops new spawns; already-emitted particles keep simulating to their natural death. */\r\n stop(): void { if (this.disposed) return; this.emitting = false; this.simulating = true; }\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 }\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.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): void {\r\n if (this.disposed) return;\r\n this.context = context;\r\n this.tick(ParticleSimulator.stepSeconds);\r\n }\r\n\r\n update(deltaSeconds: number, context: ParticleSpawnContext): void {\r\n if (this.disposed || !this.simulating) return;\r\n this.context = context;\r\n this.stepAccumulator = Math.min(this.stepAccumulator + Math.max(0, deltaSeconds), ParticleSimulator.stepSeconds * 8);\r\n while (this.stepAccumulator >= ParticleSimulator.stepSeconds) {\r\n this.stepAccumulator -= ParticleSimulator.stepSeconds;\r\n this.tick(ParticleSimulator.stepSeconds);\r\n }\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.simulating && !this.emitting && !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 e.bursts.forEach((burst, 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 }\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.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":"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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 +1 @@
1
- {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"scene.d.ts","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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"}
package/dist/scene.js CHANGED
@@ -15,8 +15,10 @@ import { PageGroupNodeView } from "./views/PageGroupNodeView.js";
15
15
  import { ScrollItemContainer } from "./scrollView.js";
16
16
  import { ScrollViewNodeView } from "./views/ScrollViewNodeView.js";
17
17
  import { SpineNodeView } from "./views/SpineNodeView.js";
18
+ import { ParticleEmitterNodeView } from "./views/ParticleEmitterNodeView.js";
18
19
  import { SceneLocalization } from "./localization.js";
19
20
  import { SceneViewport } from "./SceneViewport.js";
21
+ const particleEmitterRegistry = new WeakMap();
20
22
  function spineReferenceFrameFor(document, node) {
21
23
  if (node.type !== "spine")
22
24
  return undefined;
@@ -32,6 +34,7 @@ export function buildSceneView(document, sceneId, profile, options) {
32
34
  throw new Error(`Scene '${sceneId}' does not exist in the project document.`);
33
35
  }
34
36
  const nodeViews = new Map();
37
+ const particleEmitters = [];
35
38
  // Materialized prefab children use instance-scoped IDs, so authoring and runtime can address
36
39
  // multiple instances independently without changing canonical definition IDs.
37
40
  const screenSize = scene.layout.referenceViewports[profile];
@@ -56,6 +59,8 @@ export function buildSceneView(document, sceneId, profile, options) {
56
59
  // Yoga owns only the group's inner layoutContent; the outer NodeView keeps authored transform.
57
60
  view.update(node, profile, parentSize);
58
61
  nodeViews.set(node.id, view);
62
+ if (view instanceof ParticleEmitterNodeView)
63
+ particleEmitters.push(view);
59
64
  // Прямые дети корня сцены разрешают якоря относительно логического Canvas, а не размера корня.
60
65
  // Прямой ребёнок grid-layout (сам `node` здесь) не владеет своим отрисованным размером: Unity-подобная
61
66
  // фиксированная ячейка полностью переопределяет authored transform (см. applyLayoutItem). Его
@@ -114,6 +119,7 @@ export function buildSceneView(document, sceneId, profile, options) {
114
119
  const canvasRoot = buildOwner(canvasSize);
115
120
  canvasRoot.scale.set(canvasScale);
116
121
  const hostRoot = new SceneViewport(canvasRoot, screenSize, options.clipToViewport ?? interaction === "runtime");
122
+ particleEmitterRegistry.set(hostRoot, particleEmitters);
117
123
  // Контроллер применяет переводы сразу к уже созданным views, поэтому keyed Text показывает
118
124
  // базовую локаль без единого дополнительного вызова со стороны хоста.
119
125
  const localization = new SceneLocalization(document, scene, nodeViews, options.localization);
@@ -199,8 +205,20 @@ export function previewNodeView(view, node, profile, transform) {
199
205
  }
200
206
  /** Hosts call this from their own Application ticker; runtime never subscribes to Ticker.shared. */
201
207
  export function updateParticleEmitters(root, deltaSeconds) {
202
- const visit = (view) => { if ("updateParticles" in view && typeof view.updateParticles === "function")
203
- view.updateParticles(deltaSeconds); view.children.forEach(visit); };
208
+ const registered = particleEmitterRegistry.get(root);
209
+ if (registered !== undefined) {
210
+ for (const emitter of registered)
211
+ emitter.updateParticles(deltaSeconds);
212
+ return;
213
+ }
214
+ // Backward-compatible fallback for hosts that assemble a display tree manually instead of using
215
+ // buildSceneView. Built scenes always take the O(emitter count) registry path above.
216
+ const visit = (view) => {
217
+ if (view instanceof ParticleEmitterNodeView)
218
+ view.updateParticles(deltaSeconds);
219
+ for (const child of view.children)
220
+ visit(child);
221
+ };
204
222
  visit(root);
205
223
  }
206
224
  /** Lists the nodes a scene renders, including nodes of prefab definitions its prefab instances expand to. */
package/dist/scene.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"scene.js","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\r\nimport { createStableId, isLayoutGroup, isParticleEffect, resolveLayoutGroupSettings, resolveOwnerNodeGraph, type EffectDefinition, type GridLayoutSettings, type LayoutProfileId, type ProjectDocument, type Scene, type SpineReferenceFrame, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container, Texture, type Ticker } from \"pixi.js\";\r\nimport { loadSceneSpines } from \"./assets/spine.js\";\r\nimport { loadSceneTextures, type FileUrlResolver } from \"./assets/textures.js\";\r\nimport { loadSceneFonts } from \"./assets/fonts.js\";\r\nimport { loadSceneBitmapFonts } from \"./assets/bitmapFonts.js\";\r\nimport type { SceneAssetCache } from \"./assets/cache.js\";\r\nimport { getCanvasLogicalSize, getCanvasScale, resolveAnchoredTransform, resolveProfileTransform, type LayoutSize } from \"./layout.js\";\r\nimport { NodeView, type SceneInteractionMode } from \"./views/NodeView.js\";\r\nimport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\r\nimport { createNodeView } from \"./views/createNodeView.js\";\r\nimport { applyLayoutGroup, applyLayoutItem, createGridLineBreak, initializePixiLayout, LayoutItemContainer } from \"./layoutGroups.js\";\r\nimport { LayoutGroupNodeView } from \"./views/basic.js\";\r\nimport { PageItemContainer } from \"./pageGroup.js\";\r\nimport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\r\nimport { ScrollItemContainer } from \"./scrollView.js\";\r\nimport { ScrollViewNodeView } from \"./views/ScrollViewNodeView.js\";\r\nimport { SpineNodeView } from \"./views/SpineNodeView.js\";\r\nimport { SceneLocalization, type SceneLocalizationOptions } from \"./localization.js\";\r\nimport { SceneViewport } from \"./SceneViewport.js\";\r\nimport type { Sound } from \"@pixi/sound\";\r\n\r\nexport type BuildSceneViewOptions = {\r\n /** Explicit: an editor canvas must pass \"authoring\", Preview and the consuming app \"runtime\". */\r\n interaction: SceneInteractionMode;\r\n textures?: ReadonlyMap<string, Texture>;\r\n spines?: ReadonlyMap<string, SkeletonData>;\r\n fonts?: ReadonlyMap<string, string>;\r\n bitmapFonts?: ReadonlyMap<string, string>;\r\n sounds?: ReadonlyMap<string, Sound>;\r\n /**\r\n * The host's own Application ticker, driving self-updating content such as Spine skeletons.\r\n * Without it they fall back to `Ticker.shared`, which runs a second rAF loop independent of the\r\n * renderer that draws them — see the same rule as `updateParticleEmitters`.\r\n */\r\n ticker?: Ticker;\r\n /** Called after Yoga changes a managed rectangle; authoring hosts use it to refresh overlays. */\r\n onLayout?: () => void;\r\n /**\r\n * Начальное состояние локализации. Опция необязательна: при наличии `Text.textKey` base locale\r\n * каталога применяется и без неё, а документ без ключей выглядит ровно как раньше.\r\n */\r\n localization?: SceneLocalizationOptions;\r\n /** Internal host boundary override: prefab views are spawnable content, not screen viewports. */\r\n clipToViewport?: boolean;\r\n};\r\n\r\nexport type SceneViewResult = { root: SceneViewport; nodeViews: Map<string, Container>; localization: SceneLocalization };\r\n\r\nfunction spineReferenceFrameFor(document: ProjectDocument, node: UINode): SpineReferenceFrame | undefined {\r\n if (node.type !== \"spine\") return undefined;\r\n const asset = document.assets.find((candidate) => candidate.id === node.assetId);\r\n return asset?.type === \"spine\" ? asset.referenceFrame : undefined;\r\n}\r\n\r\n/** Builds a PixiJS display tree for a scene without depending on DOM or editor state. */\r\nexport function buildSceneView(\r\n document: ProjectDocument,\r\n sceneId: string,\r\n profile: LayoutProfileId,\r\n options: BuildSceneViewOptions,\r\n): SceneViewResult {\r\n initializePixiLayout();\r\n const { interaction, textures, spines, fonts, bitmapFonts, sounds, ticker, onLayout } = options;\r\n const scene = document.scenes.find((candidate) => candidate.id === sceneId);\r\n\r\n if (scene === undefined) {\r\n throw new Error(`Scene '${sceneId}' does not exist in the project document.`);\r\n }\r\n\r\n const nodeViews = new Map<string, Container>();\r\n\r\n // Materialized prefab children use instance-scoped IDs, so authoring and runtime can address\r\n // multiple instances independently without changing canonical definition IDs.\r\n const screenSize = scene.layout.referenceViewports[profile];\r\n const referenceResolution = scene.layout.preferredViewports[profile];\r\n const canvasScale = getCanvasScale(screenSize, referenceResolution);\r\n const canvasSize = getCanvasLogicalSize(screenSize, referenceResolution);\r\n\r\n // Единый резолвер иерархии: тот же граф, что видит редактор, включая вложенные пресеты.\r\n const owner = resolveOwnerNodeGraph(document, scene);\r\n const prefabIds = new Set(document.prefabs.map((prefab) => prefab.id));\r\n\r\n const buildOwner = (rootSize: LayoutSize): Container => {\r\n const nodesById = new Map(owner.nodes.map((node) => [node.id, node]));\r\n\r\n const buildNode = (nodeId: string, parentSize: LayoutSize): NodeView => {\r\n const node = nodesById.get(nodeId);\r\n\r\n if (node === undefined) {\r\n throw new Error(`Scene '${sceneId}' references missing node '${nodeId}'.`);\r\n }\r\n\r\n const resolved = resolveProfileTransform(node, profile);\r\n const transform = resolveAnchoredTransform(resolved.transform, parentSize);\r\n const view = createNodeView(node, interaction, textures, spines, (prefabId) => prefabIds.has(prefabId), fonts, sounds, node.type === \"particle-emitter\" ? document.effects.find((effect) => effect.id === node.effectId && isParticleEffect(effect)) : undefined, spineReferenceFrameFor(document, node), ticker, bitmapFonts);\r\n if (isLayoutGroup(node)) applyLayoutGroup(view, node, profile, parentSize);\r\n // Yoga owns only the group's inner layoutContent; the outer NodeView keeps authored transform.\r\n view.update(node, profile, parentSize);\r\n nodeViews.set(node.id, view);\r\n\r\n // Прямые дети корня сцены разрешают якоря относительно логического Canvas, а не размера корня.\r\n // Прямой ребёнок grid-layout (сам `node` здесь) не владеет своим отрисованным размером: Unity-подобная\r\n // фиксированная ячейка полностью переопределяет authored transform (см. applyLayoutItem). Его\r\n // собственным потомкам нужен именно cellWidth/cellHeight, а не anchor-resolved authored-размер —\r\n // иначе они не отслеживают изменение Cell width/height и якорятся относительно устаревшего размера.\r\n const gridParent = node.parentId === null ? undefined : nodesById.get(node.parentId);\r\n const gridCell = gridParent?.type === \"grid-layout\" ? resolveLayoutGroupSettings<GridLayoutSettings>(gridParent, profile) : undefined;\r\n const childSize = node.parentId === null\r\n ? rootSize\r\n : gridCell !== undefined\r\n ? { width: gridCell.cellWidth, height: gridCell.cellHeight }\r\n : { width: transform.width, height: transform.height };\r\n for (const [childIndex, childId] of node.children.entries()) {\r\n const childNode = nodesById.get(childId);\r\n const childView = buildNode(childId, childSize);\r\n if (isLayoutGroup(node) && childNode !== undefined && view instanceof LayoutGroupNodeView) {\r\n const layoutItem = new LayoutItemContainer(childView, onLayout);\r\n applyLayoutItem(layoutItem, childNode, node, profile);\r\n view.addLayoutChild(layoutItem);\r\n } else if (node.type === \"scroll-view\" && childNode !== undefined && view instanceof ScrollViewNodeView) {\r\n const scrollItem = new ScrollItemContainer(childView, onLayout);\r\n // Как и у layout-item: собственный (не растянутый якорями) размер ребёнка — List не\r\n // предоставляет per-item override размера, в отличие от Yoga flexGrow/cellSize.\r\n const own = resolveProfileTransform(childNode, profile).transform;\r\n scrollItem.sync(childNode, profile, { width: own.width, height: own.height });\r\n view.addScrollItem(scrollItem);\r\n } else if (node.type === \"page-group\" && childNode !== undefined && view instanceof PageGroupNodeView) {\r\n // Unlike a scroll-view item, a page fills the group's own resolved rect completely\r\n // (`childSize`, computed above): a page is a full sub-screen, not content sized to itself.\r\n const pageItem = new PageItemContainer(childView);\r\n pageItem.sync(childNode, profile, childSize);\r\n view.addPageItem(pageItem);\r\n } else {\r\n view.addChild(childView);\r\n }\r\n if (node.type === \"grid-layout\") {\r\n const settings = node.layoutGroup.overrides?.[profile] === undefined ? node.layoutGroup.base : { ...node.layoutGroup.base, ...node.layoutGroup.overrides[profile] };\r\n if (settings.constraint !== \"flexible\" && settings.constraintCount !== undefined && (childIndex + 1) % settings.constraintCount === 0 && childIndex + 1 < node.children.length) {\r\n const lineBreak = createGridLineBreak(node, profile);\r\n if (lineBreak !== undefined && view instanceof LayoutGroupNodeView) view.addLayoutChild(lineBreak);\r\n }\r\n }\r\n }\r\n\r\n return view;\r\n };\r\n\r\n const ownerRoot = new Container();\r\n for (const rootNodeId of owner.rootNodeIds) {\r\n ownerRoot.addChild(buildNode(rootNodeId, rootSize));\r\n }\r\n\r\n return ownerRoot;\r\n };\r\n\r\n const canvasRoot = buildOwner(canvasSize);\r\n canvasRoot.scale.set(canvasScale);\r\n const hostRoot = new SceneViewport(canvasRoot, screenSize, options.clipToViewport ?? interaction === \"runtime\");\r\n // Контроллер применяет переводы сразу к уже созданным views, поэтому keyed Text показывает\r\n // базовую локаль без единого дополнительного вызова со стороны хоста.\r\n const localization = new SceneLocalization(document, scene, nodeViews, options.localization);\r\n wireCheckboxGroups(owner.nodes, nodeViews);\r\n wireSpineConnectors(owner.nodes, nodeViews);\r\n return { root: hostRoot, nodeViews, localization };\r\n}\r\n\r\nfunction wireSpineConnectors(nodes: readonly UINode[], nodeViews: ReadonlyMap<string, Container>): void {\r\n for (const node of nodes) {\r\n if (node.type !== \"spine\") continue;\r\n const view = nodeViews.get(node.id);\r\n if (!(view instanceof SpineNodeView)) continue;\r\n view.setConnectorBones((node.connectors ?? []).flatMap((connector) => {\r\n const target = nodeViews.get(connector.targetNodeId);\r\n return target === undefined ? [] : [{ ...connector, target }];\r\n }));\r\n }\r\n}\r\n\r\n/**\r\n * Authored `group` gives sibling checkboxes radio-button behavior: checking one force-unchecks its\r\n * live group-mates (same `parentId`, same `group`), without touching the document. Runs once per\r\n * scene build; `CheckboxNodeView.forceCheck` never re-emits `onCheck`, so this can't recurse.\r\n */\r\nfunction wireCheckboxGroups(nodes: readonly UINode[], nodeViews: ReadonlyMap<string, Container>): void {\r\n const byGroup = new Map<string, CheckboxNodeView[]>();\r\n for (const node of nodes) {\r\n if (node.type !== \"checkbox\" || node.group === undefined) continue;\r\n const view = nodeViews.get(node.id);\r\n if (!(view instanceof CheckboxNodeView)) continue;\r\n const key = `${node.parentId ?? \"\"}::${node.group}`;\r\n const group = byGroup.get(key) ?? [];\r\n group.push(view);\r\n byGroup.set(key, group);\r\n }\r\n for (const group of byGroup.values()) {\r\n if (group.length < 2) continue;\r\n for (const view of group) {\r\n view.onCheck.connect((checked) => {\r\n if (!checked) return;\r\n for (const other of group) if (other !== view) other.forceCheck(false);\r\n });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Applies a node's resolved transform, visibility, and content to an existing display object,\r\n * so editors can update views in place without rebuilding the scene tree.\r\n */\r\nexport function updateNodeView(view: Container, node: UINode, profile: LayoutProfileId, parentSize?: LayoutSize, parentNode?: UINode, effect?: EffectDefinition, spineReferenceFrame?: SpineReferenceFrame): void {\r\n if (isLayoutGroup(node)) applyLayoutGroup(view, node, profile, parentSize);\r\n if (!(view instanceof NodeView)) return;\r\n if (view instanceof SpineNodeView) view.setReferenceFrame(spineReferenceFrame);\r\n if (node.type === \"particle-emitter\" && effect !== undefined && isParticleEffect(effect) && \"syncEffect\" in view && typeof (view as { syncEffect?: unknown }).syncEffect === \"function\") (view as { syncEffect(effect: import(\"@pixi-ui-editor/schema\").ParticleEffectDefinition): void }).syncEffect(effect);\r\n if (parentNode !== undefined && isLayoutGroup(parentNode) && view.parent instanceof LayoutItemContainer) {\r\n applyLayoutItem(view.parent, node, parentNode, profile);\r\n } else if (parentNode !== undefined && parentNode.type === \"scroll-view\" && view.parent instanceof ScrollItemContainer) {\r\n const own = resolveProfileTransform(node, profile).transform;\r\n view.parent.sync(node, profile, { width: own.width, height: own.height });\r\n } else {\r\n view.update(node, profile, parentSize);\r\n }\r\n}\r\n\r\n/** Previews a resolved editor rectangle without consulting content bounds or rebuilding the view. */\r\nexport function previewNodeView(view: Container, node: UINode, profile: LayoutProfileId, transform: UINode[\"transform\"]): void {\r\n if (isLayoutGroup(node)) applyLayoutGroup(view, node, profile, undefined, { width: transform.width, height: transform.height });\r\n if (view instanceof NodeView) view.preview(node, transform, resolveProfileTransform(node, profile).visible, profile);\r\n}\r\n\r\n/** Hosts call this from their own Application ticker; runtime never subscribes to Ticker.shared. */\r\nexport function updateParticleEmitters(root: Container, deltaSeconds: number): void {\r\n const visit = (view: Container): void => { if (\"updateParticles\" in view && typeof (view as { updateParticles?: unknown }).updateParticles === \"function\") (view as { updateParticles(delta: number): void }).updateParticles(deltaSeconds); view.children.forEach(visit); };\r\n visit(root);\r\n}\r\n\r\n/** Lists the nodes a scene renders, including nodes of prefab definitions its prefab instances expand to. */\r\nexport function collectRenderedNodes(document: ProjectDocument, scene: Scene): UINode[] {\r\n return resolveOwnerNodeGraph(document, scene).nodes;\r\n}\r\n\r\nexport type PrefabViewConfiguration = Pick<Extract<UINode, { type: \"prefab-instance\" }>, \"propertyOverrides\" | \"locallyAddedNodes\"> & { instanceId?: string };\r\n\r\nfunction prefabScene(document: ProjectDocument, prefabId: string, configuration: PrefabViewConfiguration = {}): { document: ProjectDocument; sceneId: string; instanceId: string } {\r\n const prefab = document.prefabs.find((candidate) => candidate.id === prefabId);\r\n if (prefab === undefined) throw new Error(`Prefab '${prefabId}' does not exist in the project document.`);\r\n const width = Math.max(1, ...prefab.nodes.map((node) => Math.abs(node.transform.x) + Math.max(0, node.transform.width)));\r\n const height = Math.max(1, ...prefab.nodes.map((node) => Math.abs(node.transform.y) + Math.max(0, node.transform.height)));\r\n const instanceId = configuration.instanceId ?? createStableId();\r\n const instance: Extract<UINode, { type: \"prefab-instance\" }> = {\r\n id: instanceId, name: prefab.name, type: \"prefab-instance\", prefabId, parentId: null, children: [],\r\n visible: true, transform: { x: 0, y: 0, width, height, scaleX: 1, scaleY: 1, rotation: 0, anchorMinX: 0, anchorMaxX: 0, anchorMinY: 0, anchorMaxY: 0, pivotX: 0, pivotY: 0 },\r\n ...(configuration.propertyOverrides === undefined ? {} : { propertyOverrides: structuredClone(configuration.propertyOverrides) }),\r\n ...(configuration.locallyAddedNodes === undefined ? {} : { locallyAddedNodes: structuredClone(configuration.locallyAddedNodes) }),\r\n };\r\n const sceneId = createStableId();\r\n const viewport = { width, height };\r\n const scene: Scene = { id: sceneId, name: prefab.name, rootNodeIds: [instance.id], nodes: [instance], layout: { referenceViewports: { desktop: viewport, mobile: viewport }, preferredViewports: { desktop: viewport, mobile: viewport } } };\r\n return { document: { ...document, scenes: [...document.scenes, scene] }, sceneId, instanceId };\r\n}\r\n\r\n/** Builds a fresh runtime prefab instance without requiring it to already exist in a scene. */\r\nexport function buildPrefabView(document: ProjectDocument, prefabId: string, profile: LayoutProfileId, options: BuildSceneViewOptions, configuration: PrefabViewConfiguration = {}): SceneViewResult & { instanceId: string } {\r\n const synthetic = prefabScene(document, prefabId, configuration);\r\n return { ...buildSceneView(synthetic.document, synthetic.sceneId, profile, { ...options, clipToViewport: false }), instanceId: synthetic.instanceId };\r\n}\r\n\r\n/** Loads a prefab's assets and returns a fresh display tree suitable for dynamic game-code spawning. */\r\nexport async function loadPrefabView(document: ProjectDocument, prefabId: string, profile: LayoutProfileId, resolveFileUrl: FileUrlResolver, options: { interaction: SceneInteractionMode; ticker?: Ticker; localization?: SceneLocalizationOptions; assetCache?: SceneAssetCache }, configuration: PrefabViewConfiguration = {}): Promise<SceneViewResult & { instanceId: string }> {\r\n const synthetic = prefabScene(document, prefabId, configuration);\r\n return { ...await loadSceneView(synthetic.document, synthetic.sceneId, profile, resolveFileUrl, { ...options, clipToViewport: false }), instanceId: synthetic.instanceId };\r\n}\r\n\r\n/** Loads a scene's textures and Spine data, then builds its display tree in one call. */\r\nexport async function loadSceneView(\r\n document: ProjectDocument,\r\n sceneId: string,\r\n profile: LayoutProfileId,\r\n resolveFileUrl: FileUrlResolver,\r\n options: { interaction: SceneInteractionMode; ticker?: Ticker; localization?: SceneLocalizationOptions; clipToViewport?: boolean; assetCache?: SceneAssetCache },\r\n): Promise<SceneViewResult> {\r\n // Без assetCache каждый вызов начинает с пустых кэшей: для одиночной загрузки сцены это нормально, а вот\r\n // игровой код, который поднимает пресеты по одному, обязан передать собственный кэш — иначе один и тот же\r\n // скелет, атлас и текстура парсятся заново на каждую вьюху и дублируются в видеопамяти.\r\n const cache = options.assetCache;\r\n const [textures, spines, fonts, bitmapFonts] = await Promise.all([\r\n loadSceneTextures(document, sceneId, (asset) => (asset.type === \"image\" ? resolveFileUrl(asset.source.uri) : undefined), resolveFileUrl, cache?.textures, cache?.spritesheets, cache?.bitmapFonts),\r\n loadSceneSpines(document, sceneId, resolveFileUrl, cache?.spines),\r\n loadSceneFonts(document, sceneId, resolveFileUrl, cache?.fonts),\r\n loadSceneBitmapFonts(document, sceneId, resolveFileUrl, cache?.bitmapFonts),\r\n ]);\r\n return buildSceneView(document, sceneId, profile, { interaction: options.interaction, textures, spines, fonts, bitmapFonts, ticker: options.ticker, localization: options.localization, clipToViewport: options.clipToViewport });\r\n}\r\n"]}
1
+ {"version":3,"file":"scene.js","sourceRoot":"","sources":["../src/scene.ts"],"names":[],"mappings":"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","sourcesContent":["import { type SkeletonData } from \"@esotericsoftware/spine-pixi-v8\";\r\nimport { createStableId, isLayoutGroup, isParticleEffect, resolveLayoutGroupSettings, resolveOwnerNodeGraph, type EffectDefinition, type GridLayoutSettings, type LayoutProfileId, type ProjectDocument, type Scene, type SpineReferenceFrame, type UINode } from \"@pixi-ui-editor/schema\";\r\nimport { Container, Texture, type Ticker } from \"pixi.js\";\r\nimport { loadSceneSpines } from \"./assets/spine.js\";\r\nimport { loadSceneTextures, type FileUrlResolver } from \"./assets/textures.js\";\r\nimport { loadSceneFonts } from \"./assets/fonts.js\";\r\nimport { loadSceneBitmapFonts } from \"./assets/bitmapFonts.js\";\r\nimport type { SceneAssetCache } from \"./assets/cache.js\";\r\nimport { getCanvasLogicalSize, getCanvasScale, resolveAnchoredTransform, resolveProfileTransform, type LayoutSize } from \"./layout.js\";\r\nimport { NodeView, type SceneInteractionMode } from \"./views/NodeView.js\";\r\nimport { CheckboxNodeView } from \"./views/CheckboxNodeView.js\";\r\nimport { createNodeView } from \"./views/createNodeView.js\";\r\nimport { applyLayoutGroup, applyLayoutItem, createGridLineBreak, initializePixiLayout, LayoutItemContainer } from \"./layoutGroups.js\";\r\nimport { LayoutGroupNodeView } from \"./views/basic.js\";\r\nimport { PageItemContainer } from \"./pageGroup.js\";\r\nimport { PageGroupNodeView } from \"./views/PageGroupNodeView.js\";\r\nimport { ScrollItemContainer } from \"./scrollView.js\";\r\nimport { ScrollViewNodeView } from \"./views/ScrollViewNodeView.js\";\r\nimport { SpineNodeView } from \"./views/SpineNodeView.js\";\nimport { ParticleEmitterNodeView } from \"./views/ParticleEmitterNodeView.js\";\nimport { SceneLocalization, type SceneLocalizationOptions } from \"./localization.js\";\r\nimport { SceneViewport } from \"./SceneViewport.js\";\r\nimport type { Sound } from \"@pixi/sound\";\r\n\r\nexport type BuildSceneViewOptions = {\r\n /** Explicit: an editor canvas must pass \"authoring\", Preview and the consuming app \"runtime\". */\r\n interaction: SceneInteractionMode;\r\n textures?: ReadonlyMap<string, Texture>;\r\n spines?: ReadonlyMap<string, SkeletonData>;\r\n fonts?: ReadonlyMap<string, string>;\r\n bitmapFonts?: ReadonlyMap<string, string>;\r\n sounds?: ReadonlyMap<string, Sound>;\r\n /**\r\n * The host's own Application ticker, driving self-updating content such as Spine skeletons.\r\n * Without it they fall back to `Ticker.shared`, which runs a second rAF loop independent of the\r\n * renderer that draws them — see the same rule as `updateParticleEmitters`.\r\n */\r\n ticker?: Ticker;\r\n /** Called after Yoga changes a managed rectangle; authoring hosts use it to refresh overlays. */\r\n onLayout?: () => void;\r\n /**\r\n * Начальное состояние локализации. Опция необязательна: при наличии `Text.textKey` base locale\r\n * каталога применяется и без неё, а документ без ключей выглядит ровно как раньше.\r\n */\r\n localization?: SceneLocalizationOptions;\r\n /** Internal host boundary override: prefab views are spawnable content, not screen viewports. */\r\n clipToViewport?: boolean;\r\n};\r\n\r\nexport type SceneViewResult = { root: SceneViewport; nodeViews: Map<string, Container>; localization: SceneLocalization };\nconst particleEmitterRegistry = new WeakMap<Container, readonly ParticleEmitterNodeView[]>();\n\r\nfunction spineReferenceFrameFor(document: ProjectDocument, node: UINode): SpineReferenceFrame | undefined {\r\n if (node.type !== \"spine\") return undefined;\r\n const asset = document.assets.find((candidate) => candidate.id === node.assetId);\r\n return asset?.type === \"spine\" ? asset.referenceFrame : undefined;\r\n}\r\n\r\n/** Builds a PixiJS display tree for a scene without depending on DOM or editor state. */\r\nexport function buildSceneView(\r\n document: ProjectDocument,\r\n sceneId: string,\r\n profile: LayoutProfileId,\r\n options: BuildSceneViewOptions,\r\n): SceneViewResult {\r\n initializePixiLayout();\r\n const { interaction, textures, spines, fonts, bitmapFonts, sounds, ticker, onLayout } = options;\r\n const scene = document.scenes.find((candidate) => candidate.id === sceneId);\r\n\r\n if (scene === undefined) {\r\n throw new Error(`Scene '${sceneId}' does not exist in the project document.`);\r\n }\r\n\r\n const nodeViews = new Map<string, Container>();\n const particleEmitters: ParticleEmitterNodeView[] = [];\n\r\n // Materialized prefab children use instance-scoped IDs, so authoring and runtime can address\r\n // multiple instances independently without changing canonical definition IDs.\r\n const screenSize = scene.layout.referenceViewports[profile];\r\n const referenceResolution = scene.layout.preferredViewports[profile];\r\n const canvasScale = getCanvasScale(screenSize, referenceResolution);\r\n const canvasSize = getCanvasLogicalSize(screenSize, referenceResolution);\r\n\r\n // Единый резолвер иерархии: тот же граф, что видит редактор, включая вложенные пресеты.\r\n const owner = resolveOwnerNodeGraph(document, scene);\r\n const prefabIds = new Set(document.prefabs.map((prefab) => prefab.id));\r\n\r\n const buildOwner = (rootSize: LayoutSize): Container => {\r\n const nodesById = new Map(owner.nodes.map((node) => [node.id, node]));\r\n\r\n const buildNode = (nodeId: string, parentSize: LayoutSize): NodeView => {\r\n const node = nodesById.get(nodeId);\r\n\r\n if (node === undefined) {\r\n throw new Error(`Scene '${sceneId}' references missing node '${nodeId}'.`);\r\n }\r\n\r\n const resolved = resolveProfileTransform(node, profile);\r\n const transform = resolveAnchoredTransform(resolved.transform, parentSize);\r\n const view = createNodeView(node, interaction, textures, spines, (prefabId) => prefabIds.has(prefabId), fonts, sounds, node.type === \"particle-emitter\" ? document.effects.find((effect) => effect.id === node.effectId && isParticleEffect(effect)) : undefined, spineReferenceFrameFor(document, node), ticker, bitmapFonts);\r\n if (isLayoutGroup(node)) applyLayoutGroup(view, node, profile, parentSize);\r\n // Yoga owns only the group's inner layoutContent; the outer NodeView keeps authored transform.\r\n view.update(node, profile, parentSize);\r\n nodeViews.set(node.id, view);\n if (view instanceof ParticleEmitterNodeView) particleEmitters.push(view);\n\r\n // Прямые дети корня сцены разрешают якоря относительно логического Canvas, а не размера корня.\r\n // Прямой ребёнок grid-layout (сам `node` здесь) не владеет своим отрисованным размером: Unity-подобная\r\n // фиксированная ячейка полностью переопределяет authored transform (см. applyLayoutItem). Его\r\n // собственным потомкам нужен именно cellWidth/cellHeight, а не anchor-resolved authored-размер —\r\n // иначе они не отслеживают изменение Cell width/height и якорятся относительно устаревшего размера.\r\n const gridParent = node.parentId === null ? undefined : nodesById.get(node.parentId);\r\n const gridCell = gridParent?.type === \"grid-layout\" ? resolveLayoutGroupSettings<GridLayoutSettings>(gridParent, profile) : undefined;\r\n const childSize = node.parentId === null\r\n ? rootSize\r\n : gridCell !== undefined\r\n ? { width: gridCell.cellWidth, height: gridCell.cellHeight }\r\n : { width: transform.width, height: transform.height };\r\n for (const [childIndex, childId] of node.children.entries()) {\r\n const childNode = nodesById.get(childId);\r\n const childView = buildNode(childId, childSize);\r\n if (isLayoutGroup(node) && childNode !== undefined && view instanceof LayoutGroupNodeView) {\r\n const layoutItem = new LayoutItemContainer(childView, onLayout);\r\n applyLayoutItem(layoutItem, childNode, node, profile);\r\n view.addLayoutChild(layoutItem);\r\n } else if (node.type === \"scroll-view\" && childNode !== undefined && view instanceof ScrollViewNodeView) {\r\n const scrollItem = new ScrollItemContainer(childView, onLayout);\r\n // Как и у layout-item: собственный (не растянутый якорями) размер ребёнка — List не\r\n // предоставляет per-item override размера, в отличие от Yoga flexGrow/cellSize.\r\n const own = resolveProfileTransform(childNode, profile).transform;\r\n scrollItem.sync(childNode, profile, { width: own.width, height: own.height });\r\n view.addScrollItem(scrollItem);\r\n } else if (node.type === \"page-group\" && childNode !== undefined && view instanceof PageGroupNodeView) {\r\n // Unlike a scroll-view item, a page fills the group's own resolved rect completely\r\n // (`childSize`, computed above): a page is a full sub-screen, not content sized to itself.\r\n const pageItem = new PageItemContainer(childView);\r\n pageItem.sync(childNode, profile, childSize);\r\n view.addPageItem(pageItem);\r\n } else {\r\n view.addChild(childView);\r\n }\r\n if (node.type === \"grid-layout\") {\r\n const settings = node.layoutGroup.overrides?.[profile] === undefined ? node.layoutGroup.base : { ...node.layoutGroup.base, ...node.layoutGroup.overrides[profile] };\r\n if (settings.constraint !== \"flexible\" && settings.constraintCount !== undefined && (childIndex + 1) % settings.constraintCount === 0 && childIndex + 1 < node.children.length) {\r\n const lineBreak = createGridLineBreak(node, profile);\r\n if (lineBreak !== undefined && view instanceof LayoutGroupNodeView) view.addLayoutChild(lineBreak);\r\n }\r\n }\r\n }\r\n\r\n return view;\r\n };\r\n\r\n const ownerRoot = new Container();\r\n for (const rootNodeId of owner.rootNodeIds) {\r\n ownerRoot.addChild(buildNode(rootNodeId, rootSize));\r\n }\r\n\r\n return ownerRoot;\r\n };\r\n\r\n const canvasRoot = buildOwner(canvasSize);\r\n canvasRoot.scale.set(canvasScale);\r\n const hostRoot = new SceneViewport(canvasRoot, screenSize, options.clipToViewport ?? interaction === \"runtime\");\n particleEmitterRegistry.set(hostRoot, particleEmitters);\n // Контроллер применяет переводы сразу к уже созданным views, поэтому keyed Text показывает\r\n // базовую локаль без единого дополнительного вызова со стороны хоста.\r\n const localization = new SceneLocalization(document, scene, nodeViews, options.localization);\r\n wireCheckboxGroups(owner.nodes, nodeViews);\r\n wireSpineConnectors(owner.nodes, nodeViews);\r\n return { root: hostRoot, nodeViews, localization };\r\n}\r\n\r\nfunction wireSpineConnectors(nodes: readonly UINode[], nodeViews: ReadonlyMap<string, Container>): void {\r\n for (const node of nodes) {\r\n if (node.type !== \"spine\") continue;\r\n const view = nodeViews.get(node.id);\r\n if (!(view instanceof SpineNodeView)) continue;\r\n view.setConnectorBones((node.connectors ?? []).flatMap((connector) => {\r\n const target = nodeViews.get(connector.targetNodeId);\r\n return target === undefined ? [] : [{ ...connector, target }];\r\n }));\r\n }\r\n}\r\n\r\n/**\r\n * Authored `group` gives sibling checkboxes radio-button behavior: checking one force-unchecks its\r\n * live group-mates (same `parentId`, same `group`), without touching the document. Runs once per\r\n * scene build; `CheckboxNodeView.forceCheck` never re-emits `onCheck`, so this can't recurse.\r\n */\r\nfunction wireCheckboxGroups(nodes: readonly UINode[], nodeViews: ReadonlyMap<string, Container>): void {\r\n const byGroup = new Map<string, CheckboxNodeView[]>();\r\n for (const node of nodes) {\r\n if (node.type !== \"checkbox\" || node.group === undefined) continue;\r\n const view = nodeViews.get(node.id);\r\n if (!(view instanceof CheckboxNodeView)) continue;\r\n const key = `${node.parentId ?? \"\"}::${node.group}`;\r\n const group = byGroup.get(key) ?? [];\r\n group.push(view);\r\n byGroup.set(key, group);\r\n }\r\n for (const group of byGroup.values()) {\r\n if (group.length < 2) continue;\r\n for (const view of group) {\r\n view.onCheck.connect((checked) => {\r\n if (!checked) return;\r\n for (const other of group) if (other !== view) other.forceCheck(false);\r\n });\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Applies a node's resolved transform, visibility, and content to an existing display object,\r\n * so editors can update views in place without rebuilding the scene tree.\r\n */\r\nexport function updateNodeView(view: Container, node: UINode, profile: LayoutProfileId, parentSize?: LayoutSize, parentNode?: UINode, effect?: EffectDefinition, spineReferenceFrame?: SpineReferenceFrame): void {\r\n if (isLayoutGroup(node)) applyLayoutGroup(view, node, profile, parentSize);\r\n if (!(view instanceof NodeView)) return;\r\n if (view instanceof SpineNodeView) view.setReferenceFrame(spineReferenceFrame);\r\n if (node.type === \"particle-emitter\" && effect !== undefined && isParticleEffect(effect) && \"syncEffect\" in view && typeof (view as { syncEffect?: unknown }).syncEffect === \"function\") (view as { syncEffect(effect: import(\"@pixi-ui-editor/schema\").ParticleEffectDefinition): void }).syncEffect(effect);\r\n if (parentNode !== undefined && isLayoutGroup(parentNode) && view.parent instanceof LayoutItemContainer) {\r\n applyLayoutItem(view.parent, node, parentNode, profile);\r\n } else if (parentNode !== undefined && parentNode.type === \"scroll-view\" && view.parent instanceof ScrollItemContainer) {\r\n const own = resolveProfileTransform(node, profile).transform;\r\n view.parent.sync(node, profile, { width: own.width, height: own.height });\r\n } else {\r\n view.update(node, profile, parentSize);\r\n }\r\n}\r\n\r\n/** Previews a resolved editor rectangle without consulting content bounds or rebuilding the view. */\r\nexport function previewNodeView(view: Container, node: UINode, profile: LayoutProfileId, transform: UINode[\"transform\"]): void {\r\n if (isLayoutGroup(node)) applyLayoutGroup(view, node, profile, undefined, { width: transform.width, height: transform.height });\r\n if (view instanceof NodeView) view.preview(node, transform, resolveProfileTransform(node, profile).visible, profile);\r\n}\r\n\r\n/** Hosts call this from their own Application ticker; runtime never subscribes to Ticker.shared. */\r\nexport function updateParticleEmitters(root: Container, deltaSeconds: number): void {\n const registered = particleEmitterRegistry.get(root);\n if (registered !== undefined) {\n for (const emitter of registered) emitter.updateParticles(deltaSeconds);\n return;\n }\n // Backward-compatible fallback for hosts that assemble a display tree manually instead of using\n // buildSceneView. Built scenes always take the O(emitter count) registry path above.\n const visit = (view: Container): void => {\n if (view instanceof ParticleEmitterNodeView) view.updateParticles(deltaSeconds);\n for (const child of view.children) visit(child);\n };\n visit(root);\n}\n\r\n/** Lists the nodes a scene renders, including nodes of prefab definitions its prefab instances expand to. */\r\nexport function collectRenderedNodes(document: ProjectDocument, scene: Scene): UINode[] {\r\n return resolveOwnerNodeGraph(document, scene).nodes;\r\n}\r\n\r\nexport type PrefabViewConfiguration = Pick<Extract<UINode, { type: \"prefab-instance\" }>, \"propertyOverrides\" | \"locallyAddedNodes\"> & { instanceId?: string };\r\n\r\nfunction prefabScene(document: ProjectDocument, prefabId: string, configuration: PrefabViewConfiguration = {}): { document: ProjectDocument; sceneId: string; instanceId: string } {\r\n const prefab = document.prefabs.find((candidate) => candidate.id === prefabId);\r\n if (prefab === undefined) throw new Error(`Prefab '${prefabId}' does not exist in the project document.`);\r\n const width = Math.max(1, ...prefab.nodes.map((node) => Math.abs(node.transform.x) + Math.max(0, node.transform.width)));\r\n const height = Math.max(1, ...prefab.nodes.map((node) => Math.abs(node.transform.y) + Math.max(0, node.transform.height)));\r\n const instanceId = configuration.instanceId ?? createStableId();\r\n const instance: Extract<UINode, { type: \"prefab-instance\" }> = {\r\n id: instanceId, name: prefab.name, type: \"prefab-instance\", prefabId, parentId: null, children: [],\r\n visible: true, transform: { x: 0, y: 0, width, height, scaleX: 1, scaleY: 1, rotation: 0, anchorMinX: 0, anchorMaxX: 0, anchorMinY: 0, anchorMaxY: 0, pivotX: 0, pivotY: 0 },\r\n ...(configuration.propertyOverrides === undefined ? {} : { propertyOverrides: structuredClone(configuration.propertyOverrides) }),\r\n ...(configuration.locallyAddedNodes === undefined ? {} : { locallyAddedNodes: structuredClone(configuration.locallyAddedNodes) }),\r\n };\r\n const sceneId = createStableId();\r\n const viewport = { width, height };\r\n const scene: Scene = { id: sceneId, name: prefab.name, rootNodeIds: [instance.id], nodes: [instance], layout: { referenceViewports: { desktop: viewport, mobile: viewport }, preferredViewports: { desktop: viewport, mobile: viewport } } };\r\n return { document: { ...document, scenes: [...document.scenes, scene] }, sceneId, instanceId };\r\n}\r\n\r\n/** Builds a fresh runtime prefab instance without requiring it to already exist in a scene. */\r\nexport function buildPrefabView(document: ProjectDocument, prefabId: string, profile: LayoutProfileId, options: BuildSceneViewOptions, configuration: PrefabViewConfiguration = {}): SceneViewResult & { instanceId: string } {\r\n const synthetic = prefabScene(document, prefabId, configuration);\r\n return { ...buildSceneView(synthetic.document, synthetic.sceneId, profile, { ...options, clipToViewport: false }), instanceId: synthetic.instanceId };\r\n}\r\n\r\n/** Loads a prefab's assets and returns a fresh display tree suitable for dynamic game-code spawning. */\r\nexport async function loadPrefabView(document: ProjectDocument, prefabId: string, profile: LayoutProfileId, resolveFileUrl: FileUrlResolver, options: { interaction: SceneInteractionMode; ticker?: Ticker; localization?: SceneLocalizationOptions; assetCache?: SceneAssetCache }, configuration: PrefabViewConfiguration = {}): Promise<SceneViewResult & { instanceId: string }> {\r\n const synthetic = prefabScene(document, prefabId, configuration);\r\n return { ...await loadSceneView(synthetic.document, synthetic.sceneId, profile, resolveFileUrl, { ...options, clipToViewport: false }), instanceId: synthetic.instanceId };\r\n}\r\n\r\n/** Loads a scene's textures and Spine data, then builds its display tree in one call. */\r\nexport async function loadSceneView(\r\n document: ProjectDocument,\r\n sceneId: string,\r\n profile: LayoutProfileId,\r\n resolveFileUrl: FileUrlResolver,\r\n options: { interaction: SceneInteractionMode; ticker?: Ticker; localization?: SceneLocalizationOptions; clipToViewport?: boolean; assetCache?: SceneAssetCache },\r\n): Promise<SceneViewResult> {\r\n // Без assetCache каждый вызов начинает с пустых кэшей: для одиночной загрузки сцены это нормально, а вот\r\n // игровой код, который поднимает пресеты по одному, обязан передать собственный кэш — иначе один и тот же\r\n // скелет, атлас и текстура парсятся заново на каждую вьюху и дублируются в видеопамяти.\r\n const cache = options.assetCache;\r\n const [textures, spines, fonts, bitmapFonts] = await Promise.all([\r\n loadSceneTextures(document, sceneId, (asset) => (asset.type === \"image\" ? resolveFileUrl(asset.source.uri) : undefined), resolveFileUrl, cache?.textures, cache?.spritesheets, cache?.bitmapFonts),\r\n loadSceneSpines(document, sceneId, resolveFileUrl, cache?.spines),\r\n loadSceneFonts(document, sceneId, resolveFileUrl, cache?.fonts),\r\n loadSceneBitmapFonts(document, sceneId, resolveFileUrl, cache?.bitmapFonts),\r\n ]);\r\n return buildSceneView(document, sceneId, profile, { interaction: options.interaction, textures, spines, fonts, bitmapFonts, ticker: options.ticker, localization: options.localization, clipToViewport: options.clipToViewport });\r\n}\r\n"]}
@@ -20,8 +20,8 @@ export declare abstract class NodeView extends Container {
20
20
  /** Node's own grab rectangle in local space, kept equal to its resolved layout rectangle. */
21
21
  private readonly grabRect;
22
22
  /** Authored/computed RectTransform-like rectangle; unlike Pixi bounds it also exists without content. */
23
- private layoutWidth;
24
- private layoutHeight;
23
+ protected layoutWidth: number;
24
+ protected layoutHeight: number;
25
25
  constructor(textures?: ReadonlyMap<string, Texture>);
26
26
  protected textureFor(assetId: string): Texture | undefined;
27
27
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"NodeView.d.ts","sourceRoot":"","sources":["../../src/views/NodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AACxD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAa,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAqD,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAElG;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE3D;;;;GAIG;AACH,8BAAsB,QAAS,SAAQ,SAAS;IAC9C,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC9B,4FAA4F;IAC5F,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtE,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,yGAAyG;IACzG,OAAO,CAAC,WAAW,CAAK;IACxB,OAAO,CAAC,YAAY,CAAK;gBAEb,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;IAKnD,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI1D;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAIxC,mGAAmG;IACnG,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAM9C,kGAAkG;IAClG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAE5G,OAAO,CAAC,sBAAsB;IAuB9B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI;IAK7E,mGAAmG;IACnG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,UAAO,EAAE,OAAO,GAAE,eAA2B,GAAG,IAAI;IAIjH,sEAAsE;IACtE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAK7E,IAAI,eAAe,IAAI,UAAU,CAEhC;IAED,QAAQ,IAAI,KAAK,GAAG,SAAS;IAI7B;;;;;;OAMG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;CAChD"}
1
+ {"version":3,"file":"NodeView.d.ts","sourceRoot":"","sources":["../../src/views/NodeView.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AACxD,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAa,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACxE,OAAO,EAAqD,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAElG;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG,WAAW,GAAG,SAAS,CAAC;AAE3D;;;;GAIG;AACH,8BAAsB,QAAS,SAAQ,SAAS;IAC9C,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAC9B,4FAA4F;IAC5F,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtE,6FAA6F;IAC7F,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmB;IAC5C,yGAAyG;IACzG,SAAS,CAAC,WAAW,SAAK;IAC1B,SAAS,CAAC,YAAY,SAAK;gBAEf,QAAQ,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC;IAKnD,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAI1D;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IAIxC,mGAAmG;IACnG,SAAS,CAAC,UAAU,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI;IAM9C,kGAAkG;IAClG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI;IAE5G,OAAO,CAAC,sBAAsB;IAuB9B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,UAAU,GAAG,IAAI;IAK7E,mGAAmG;IACnG,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,CAAC,EAAE,OAAO,UAAO,EAAE,OAAO,GAAE,eAA2B,GAAG,IAAI;IAIjH,sEAAsE;IACtE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAK7E,IAAI,eAAe,IAAI,UAAU,CAEhC;IAED,QAAQ,IAAI,KAAK,GAAG,SAAS;IAI7B;;;;;;OAMG;IACH,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;CAChD"}