@woosh/meep-engine 3.19.0 → 3.20.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 (123) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/editor/view/particles/effect/ParticleGraphEditorView.js +2 -2
  3. package/editor/view/particles/effect/ParticleNodeParametersView.d.ts.map +1 -1
  4. package/editor/view/particles/effect/ParticleNodeParametersView.js +7 -48
  5. package/package.json +1 -1
  6. package/src/core/collection/array/array_group_by.d.ts.map +1 -1
  7. package/src/core/collection/array/array_group_by.js +2 -11
  8. package/src/core/geom/3d/shape/HeightMapShape3D.d.ts.map +1 -1
  9. package/src/core/geom/3d/shape/HeightMapShape3D.js +4 -9
  10. package/src/core/model/object/optional_clone.d.ts +7 -0
  11. package/src/core/model/object/optional_clone.d.ts.map +1 -0
  12. package/src/core/model/object/optional_equality.d.ts +10 -0
  13. package/src/core/model/object/optional_equality.d.ts.map +1 -0
  14. package/src/{shade/descriptor/util → core/model/object}/optional_equality.js +2 -2
  15. package/src/core/model/object/optional_hash.d.ts +9 -0
  16. package/src/core/model/object/optional_hash.d.ts.map +1 -0
  17. package/src/{shade/descriptor/util → core/model/object}/optional_hash.js +3 -3
  18. package/src/engine/asset/Asset.d.ts +1 -1
  19. package/src/engine/asset/Asset.d.ts.map +1 -1
  20. package/src/engine/asset/Asset.js +3 -1
  21. package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.d.ts.map +1 -1
  22. package/src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js +9 -10
  23. package/src/engine/graphics/ecs/particles/ParticleEffect.d.ts.map +1 -1
  24. package/src/engine/graphics/ecs/particles/ParticleEffect.js +6 -22
  25. package/src/shade/descriptor/binding/BindGroupLayoutDescriptor.js +1 -1
  26. package/src/shade/descriptor/binding/BindGroupLayoutEntry.js +3 -3
  27. package/src/shade/descriptor/pipeline/PipelineDescriptorBase.js +1 -1
  28. package/src/shade/descriptor/pipeline/PipelineLayoutDescriptor.js +1 -1
  29. package/src/shade/descriptor/pipeline/render/ColorTargetState.js +3 -3
  30. package/src/shade/descriptor/pipeline/render/FragmentState.js +1 -1
  31. package/src/shade/descriptor/pipeline/render/RenderPipelineDescriptor.js +3 -3
  32. package/src/shade/playground/particle_editor/README.md +1 -1
  33. package/src/shade/playground/particle_system/particle_prototype.d.ts +7 -9
  34. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  35. package/src/shade/playground/particle_system/particle_prototype.js +7 -9
  36. package/src/shade/playground/ssr_motion/README.md +22 -0
  37. package/src/shade/playground/ssr_motion/index.html +18 -0
  38. package/src/shade/playground/ssr_motion/main.d.ts +2 -0
  39. package/src/shade/playground/ssr_motion/main.d.ts.map +1 -0
  40. package/src/shade/playground/ssr_motion/main.js +149 -0
  41. package/src/shade/playground/ssr_variance/index.html +1 -0
  42. package/src/shade/renderer/geometry/Geometry.d.ts.map +1 -1
  43. package/src/shade/renderer/geometry/Geometry.js +4 -7
  44. package/src/shade/renderer/material/StandardShadeMaterial.js +2 -2
  45. package/src/shade/renderer/particles/DESIGN.md +9 -11
  46. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  47. package/src/shade/renderer/particles/GPUParticleSystem.js +3 -1
  48. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +1 -1
  49. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.js +1 -1
  50. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.d.ts.map +1 -1
  51. package/src/shade/renderer/particles/graph/ParticleNodeRegistry.js +9 -15
  52. package/src/shade/renderer/particles/graph/particle_group_library.d.ts.map +1 -1
  53. package/src/shade/renderer/particles/graph/particle_group_library.js +8 -3
  54. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts +0 -2
  55. package/src/shade/renderer/particles/graph/particle_node_parameters.d.ts.map +1 -1
  56. package/src/shade/renderer/particles/graph/particle_node_parameters.js +0 -9
  57. package/src/shade/renderer/particles/graph/particle_node_presentation.d.ts.map +1 -1
  58. package/src/shade/renderer/particles/graph/particle_node_presentation.js +0 -10
  59. package/src/shade/renderer/particles/graph/particle_ramp.d.ts +2 -8
  60. package/src/shade/renderer/particles/graph/particle_ramp.d.ts.map +1 -1
  61. package/src/shade/renderer/particles/graph/particle_ramp.js +2 -8
  62. package/src/shade/renderer/particles/graph/validate_particle_graph.js +0 -6
  63. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  64. package/src/shade/renderer/particles/graph_particles_avboit.js +13 -4
  65. package/src/shade/renderer/particles/isa/InstructionStream.d.ts +1 -12
  66. package/src/shade/renderer/particles/isa/InstructionStream.d.ts.map +1 -1
  67. package/src/shade/renderer/particles/isa/InstructionStream.js +1 -12
  68. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts +54 -60
  69. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  70. package/src/shade/renderer/particles/isa/ParticleVMISA.js +9 -17
  71. package/src/shade/renderer/particles/isa/particle_assembly.d.ts +0 -1
  72. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  73. package/src/shade/renderer/particles/isa/particle_assembly.js +2 -16
  74. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.d.ts +1 -1
  75. package/src/shade/renderer/particles/optimizer/dag/particle_vector_graph.js +1 -1
  76. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.js +0 -14
  77. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.js +3 -17
  78. package/src/shade/renderer/particles/optimizer/particle_program_analysis.d.ts.map +1 -1
  79. package/src/shade/renderer/particles/optimizer/particle_program_analysis.js +15 -36
  80. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  81. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.js +1 -5
  82. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.d.ts.map +1 -1
  83. package/src/shade/renderer/particles/optimizer/particle_program_fuzz.js +1 -8
  84. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts +2 -11
  85. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.d.ts.map +1 -1
  86. package/src/shade/renderer/particles/optimizer/particle_vm_semantics.js +2 -11
  87. package/src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.d.ts.map +1 -1
  88. package/src/shade/renderer/particles/shaders/chunk_particle_avboit_contribution.js +13 -0
  89. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts +3 -6
  90. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.d.ts.map +1 -1
  91. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +49 -17
  92. package/src/shade/renderer/particles/shaders/shader_particle_emit.d.ts.map +1 -1
  93. package/src/shade/renderer/particles/shaders/shader_particle_emit.js +0 -2
  94. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.d.ts.map +1 -1
  95. package/src/shade/renderer/particles/shaders/shader_particle_emit_wide.js +0 -2
  96. package/src/shade/renderer/particles/shaders/shader_particle_simulate.d.ts.map +1 -1
  97. package/src/shade/renderer/particles/shaders/shader_particle_simulate.js +1 -5
  98. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.d.ts.map +1 -1
  99. package/src/shade/renderer/particles/shaders/shader_particle_simulate_wide.js +0 -2
  100. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts +1 -3
  101. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  102. package/src/shade/renderer/particles/vm/ParticleVMReference.js +4 -20
  103. package/src/shade/renderer/particles/vm/chunk_particle_vm.d.ts.map +1 -1
  104. package/src/shade/renderer/particles/vm/chunk_particle_vm.js +2 -5
  105. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.d.ts.map +1 -1
  106. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js +0 -2
  107. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.d.ts.map +1 -1
  108. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js +0 -2
  109. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts.map +1 -1
  110. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js +21 -0
  111. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.d.ts.map +1 -1
  112. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_temporal_accumulate.js +4 -0
  113. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
  114. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +2 -1
  115. package/src/shade/renderer/scene/Mesh.js +1 -1
  116. package/src/shade/renderer/texture/ShadeTexture.js +1 -1
  117. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts +0 -19
  118. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.d.ts.map +0 -1
  119. package/src/shade/renderer/particles/shaders/chunk_particle_curve_animation.js +0 -30
  120. package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.d.ts +0 -11
  121. package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.d.ts.map +0 -1
  122. package/src/shade/renderer/particles/shaders/chunk_particle_curve_disabled.js +0 -13
  123. /package/src/{shade/descriptor/util → core/model/object}/optional_clone.js +0 -0
@@ -135,10 +135,10 @@ const PARTICLE_TYPE_COLORS = new Map([
135
135
  * @type {Array<{name: string, types: string[]}>}
136
136
  */
137
137
  const PALETTE_CATEGORIES = [
138
- { name: "sources", types: ["const", "color", "builtin", "attribute", "random", "curve"] },
138
+ { name: "sources", types: ["const", "color", "builtin", "attribute", "random"] },
139
139
  { name: "output", types: ["setAttribute", "kill"] },
140
140
  // The three that are authored data rather than wiring, and are edited as a picture: a gradient
141
- // strip and a curve plot. Their own heading, because "a colour ramp" is a thing an
141
+ // strip and a curve plot. Their own heading, because "a colour ramp" is a thing an
142
142
  // author goes looking for by name and would not think to look for under `sources`.
143
143
  { name: "ramps", types: ["gradientRGBA", "gradientRGB", "curveLiteral"] },
144
144
  { name: "arithmetic", types: ["add", "sub", "mul", "div", "mad", "scale", "min", "max", "pow", "step", "mix", "clamp", "saturate", "smoothstep", "remap", "oneMinus"] },
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleNodeParametersView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleNodeParametersView.js"],"names":[],"mappings":"AAqCA;IAOI;;;;;;OAMG;IACH;QALyG,MAAM,EAApG,OAAO,qDAAqD,EAAE,sBAAsB;QAE9D,IAAI;QACG,MAAM,SAA1B,MAAM;OA6BzB;IAxBG,mBAAuC;IAIvC;;OAEG;IACH,mBAAgB;;CA4cvB;iBApgBgB,8BAA8B"}
1
+ {"version":3,"file":"ParticleNodeParametersView.d.ts","sourceRoot":"","sources":["../../../../../editor/view/particles/effect/ParticleNodeParametersView.js"],"names":[],"mappings":"AAqCA;IAOI;;;;;;OAMG;IACH;QALyG,MAAM,EAApG,OAAO,qDAAqD,EAAE,sBAAsB;QAE9D,IAAI;QACG,MAAM,SAA1B,MAAM;OA6BzB;IAxBG,mBAAuC;IAIvC;;OAEG;IACH,mBAAgB;;CAmavB;iBA3dgB,8BAA8B"}
@@ -87,9 +87,9 @@ export class ParticleNodeParametersView extends View {
87
87
  #buildRow(effect, parameter, commit) {
88
88
  const row = new EmptyView({ classList: ['parameter-row', `kind-${parameter.kind}`] });
89
89
 
90
- if (parameter.kind !== PARTICLE_PARAMETER_KIND.GRADIENT && parameter.kind !== PARTICLE_PARAMETER_KIND.CURVE) {
91
- row.addChild(new LabelView(parameter.name, { classList: ['name'] }));
92
- }
90
+ if (parameter.kind !== PARTICLE_PARAMETER_KIND.GRADIENT && parameter.kind !== PARTICLE_PARAMETER_KIND.CURVE) {
91
+ row.addChild(new LabelView(parameter.name, { classList: ['name'] }));
92
+ }
93
93
 
94
94
  if (typeof parameter.description === "string") {
95
95
  row.el.setAttribute('title', parameter.description);
@@ -138,10 +138,6 @@ export class ParticleNodeParametersView extends View {
138
138
  row.bindSignal(effect.on.changed, () => control.refresh());
139
139
  break;
140
140
 
141
- case PARTICLE_PARAMETER_KIND.INTEGER:
142
- control = this.#buildIntegerControl(parameter, value, write);
143
- break;
144
-
145
141
  case PARTICLE_PARAMETER_KIND.CURVE:
146
142
  control = editor_control(new ParticleCurveEditorView({ read: value, write }));
147
143
  break;
@@ -479,47 +475,10 @@ export class ParticleNodeParametersView extends View {
479
475
  return {
480
476
  view: new EmptyView({ el: select }),
481
477
  write: push,
482
- refresh
483
- };
484
- }
485
-
486
- /**
487
- * @param {object} parameter
488
- * @param {function():number} read
489
- * @param {function(number)} write
490
- * @returns {{view: View, write: function(*):void, refresh: function():void}}
491
- */
492
- #buildIntegerControl(parameter, read, write) {
493
- const field = create_input('number');
494
-
495
- field.classList.add('integer');
496
- field.setAttribute('min', '0');
497
- field.setAttribute('step', '1');
498
-
499
- const push = value => {
500
- field.value = String(value ?? 0);
501
- };
502
-
503
- field.addEventListener('change', () => {
504
- const parsed = Number.parseInt(field.value, 10);
505
-
506
- if (!Number.isInteger(parsed) || parsed < 0) {
507
- push(read());
508
- return;
509
- }
510
-
511
- write(parsed);
512
- });
513
-
514
- push(read());
515
-
516
- return {
517
- view: new EmptyView({ el: field }),
518
- write: push,
519
- refresh: () => push(read())
520
- };
521
- }
522
- }
478
+ refresh
479
+ };
480
+ }
481
+ }
523
482
 
524
483
  /**
525
484
  * A control that is a view of its own, in the shape the rest of this file uses.
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "description": "Advanced 3D game engine",
7
7
  "type": "module",
8
8
  "author": "Alexander Goldring",
9
- "version": "3.19.0",
9
+ "version": "3.20.0",
10
10
  "exports": {
11
11
  "./build/*": "./build/*",
12
12
  "./src/*": "./src/*",
@@ -1 +1 @@
1
- {"version":3,"file":"array_group_by.d.ts","sourceRoot":"","sources":["../../../../../src/core/collection/array/array_group_by.js"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,0IA+BC;2BAzC0B,8BAA8B"}
1
+ {"version":3,"file":"array_group_by.d.ts","sourceRoot":"","sources":["../../../../../src/core/collection/array/array_group_by.js"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,0IAqBC;2BA/B0B,8BAA8B"}
@@ -1,3 +1,4 @@
1
+ import { objectsEqual } from "../../function/objectsEqual.js";
1
2
  import { returnZero } from "../../function/returnZero.js";
2
3
  import { HashMap } from "../map/HashMap.js";
3
4
 
@@ -11,17 +12,7 @@ import { HashMap } from "../map/HashMap.js";
11
12
  export function array_group_by(array, grouping_key_producer, keyHashFunction = returnZero) {
12
13
  const result = new HashMap({
13
14
  keyHashFunction,
14
- keyEqualityFunction(a, b) {
15
- if (a === b) {
16
- return true;
17
- }
18
-
19
- if (typeof a === "object" && a !== null && typeof a.equals === "function") {
20
- return a.equals(b);
21
- }
22
-
23
- return false;
24
- }
15
+ keyEqualityFunction: objectsEqual
25
16
  });
26
17
 
27
18
  for (let i = 0; i < array.length; i++) {
@@ -1 +1 @@
1
- {"version":3,"file":"HeightMapShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/HeightMapShape3D.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH;IA4DI;;;;;;;;;;;OAWG;IACH,wCATW,MAAM,UACN,MAAM,UACN,MAAM,gBACN,OAAO,iBACP,MAAM,GAGJ,gBAAgB,CAqB5B;IA1FD;;;;;OAKG;IACH,sBAFU,OAAO,CAEkB;IAEnC;;;;;;;OAOG;IACH,eAFU,OAAO,CAEW;IAE5B;;;;;OAKG;IACH,SAFU,YAAY,IAAI,CAEX;IAEf;;;;;;;;;;;;;;;;OAgBG;IACH,cAFU,MAAM,CAEC;IAEjB;;;;;OAKG;IACH,eAA6B;IAG7B,6BAA2B;IAE3B,6BAA2B;IAC3B,6BAA2B;IAmC3B;;;;;;;;;OASG;IACH,sBA+CC;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;OAQG;IACH,8BALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAelB;IAED,wCA8BC;IAED,oCA2BC;IAED;;;;;;;;OAQG;IACH,6CAmBC;IAED;;;;OAIG;IACH,4DA2BC;IAED;;;;;;;;;OASG;IACH,qGAEC;IAED,kFAiBC;IA6CD;;;OAGG;IACH,cAHW,gBAAgB,GACd,OAAO,CAiBnB;IAWL;;;;;;OAMG;IACH,6BAFU,OAAO,CAE4B;CAT5C;gCAvc+B,sBAAsB;wBAD9B,kBAAkB"}
1
+ {"version":3,"file":"HeightMapShape3D.d.ts","sourceRoot":"","sources":["../../../../../../src/core/geom/3d/shape/HeightMapShape3D.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH;IA4DI;;;;;;;;;;;OAWG;IACH,wCATW,MAAM,UACN,MAAM,UACN,MAAM,gBACN,OAAO,iBACP,MAAM,GAGJ,gBAAgB,CAqB5B;IA1FD;;;;;OAKG;IACH,sBAFU,OAAO,CAEkB;IAEnC;;;;;;;OAOG;IACH,eAFU,OAAO,CAEW;IAE5B;;;;;OAKG;IACH,SAFU,YAAY,IAAI,CAEX;IAEf;;;;;;;;;;;;;;;;OAgBG;IACH,cAFU,MAAM,CAEC;IAEjB;;;;;OAKG;IACH,eAA6B;IAG7B,6BAA2B;IAE3B,6BAA2B;IAC3B,6BAA2B;IAmC3B;;;;;;;;;OASG;IACH,sBA+CC;IAED;;;;;;OAMG;IACH,yBAJW,MAAM,OACN,MAAM,GACJ,MAAM,CAIlB;IAED;;;;;;;;OAQG;IACH,8BALW,MAAM,MACN,MAAM,MACN,MAAM,GACJ,MAAM,CAelB;IAED,wCA8BC;IAED,oCA2BC;IAED;;;;;;;;OAQG;IACH,6CAmBC;IAED;;;;OAIG;IACH,4DA2BC;IAED;;;;;;;;;OASG;IACH,qGAEC;IAED,kFAiBC;IA6CD;;;OAGG;IACH,cAHW,gBAAgB,GACd,OAAO,CAUnB;IAWL;;;;;;OAMG;IACH,6BAFU,OAAO,CAE4B;CAT5C;gCAhc+B,sBAAsB;wBAD9B,kBAAkB"}
@@ -2,6 +2,8 @@ import { hash_mix3 } from "../../../math/hash/hash_mix3.js";
2
2
  import { hash_mix2 } from "../../../math/hash/hash_mix2.js";
3
3
  import { assert } from "../../../assert.js";
4
4
  import { clamp } from "../../../math/clamp.js";
5
+ import { optional_equality } from "../../../model/object/optional_equality.js";
6
+ import { optional_hash } from "../../../model/object/optional_hash.js";
5
7
  import { v3_length } from "../../vec3/v3_length.js";
6
8
  import { Vector3 } from "../../Vector3.js";
7
9
  import { AbstractShape3D } from "./AbstractShape3D.js";
@@ -442,20 +444,13 @@ export class HeightMapShape3D extends AbstractShape3D {
442
444
  if (!this.size.equals(other.size)) return false;
443
445
  if (this.tessellation !== other.tessellation) return false;
444
446
 
445
- // strict identity is enough for sampler equality in the common case;
446
- // fall through to value equality so two shapes built from independent
447
- // but identical sampler instances still compare equal
448
- if (this.sampler === other.sampler) return true;
449
-
450
- if (this.sampler === null || other.sampler === null) return false;
451
-
452
- return this.sampler.equals(other.sampler);
447
+ return optional_equality(this.sampler, other.sampler);
453
448
  }
454
449
 
455
450
  hash() {
456
451
  const a = this.orientation.hash();
457
452
  const b = this.size.hash();
458
- const c = this.sampler !== null ? this.sampler.hash() : 0;
453
+ const c = optional_hash(this.sampler);
459
454
 
460
455
  return hash_mix2(hash_mix3(a, b, c), this.tessellation);
461
456
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @template T
3
+ * @param {T} obj
4
+ * @return {T}
5
+ */
6
+ export function optional_clone<T>(obj: T): T;
7
+ //# sourceMappingURL=optional_clone.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional_clone.d.ts","sourceRoot":"","sources":["../../../../../src/core/model/object/optional_clone.js"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,6CAcC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @template {{equals(T):boolean}} T
3
+ * @param {undefined|null|T} a
4
+ * @param {undefined|null|T} b
5
+ * @return {boolean}
6
+ */
7
+ export function optional_equality<T extends {
8
+ equals(T: any): boolean;
9
+ }>(a: T, b: T): boolean;
10
+ //# sourceMappingURL=optional_equality.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional_equality.d.ts","sourceRoot":"","sources":["../../../../../src/core/model/object/optional_equality.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH;oBALyB,OAAO;gBAGpB,OAAO,CAsBlB"}
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @template {{equals(T):boolean}} T
3
- * @param {undefined|T} a
4
- * @param {undefined|T} b
3
+ * @param {undefined|null|T} a
4
+ * @param {undefined|null|T} b
5
5
  * @return {boolean}
6
6
  */
7
7
  export function optional_equality(a, b) {
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @template {{hash():number}} T
3
+ * @param {T|null|undefined} thing
4
+ * @return {number}
5
+ */
6
+ export function optional_hash<T extends {
7
+ hash(): number;
8
+ }>(thing: T): number;
9
+ //# sourceMappingURL=optional_hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"optional_hash.d.ts","sourceRoot":"","sources":["../../../../../src/core/model/object/optional_hash.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH;YAJsB,MAAM;cAEhB,MAAM,CAYjB"}
@@ -1,12 +1,12 @@
1
- import { assert } from "../../../core/assert.js";
1
+ import { assert } from "../../assert.js";
2
2
 
3
3
  /**
4
4
  * @template {{hash():number}} T
5
- * @param {T|undefined} thing
5
+ * @param {T|null|undefined} thing
6
6
  * @return {number}
7
7
  */
8
8
  export function optional_hash(thing) {
9
- if (thing === undefined) {
9
+ if (thing === undefined || thing === null) {
10
10
  return 0;
11
11
  }
12
12
 
@@ -37,7 +37,7 @@ export class Asset<T> {
37
37
  * @returns {boolean}
38
38
  */
39
39
  equals(other: Asset<any>): boolean;
40
- hash(): any;
40
+ hash(): number;
41
41
  /**
42
42
  *
43
43
  * @returns {T}
@@ -1 +1 @@
1
- {"version":3,"file":"Asset.d.ts","sourceRoot":"","sources":["../../../../src/engine/asset/Asset.js"],"names":[],"mappings":"AAAA;;;GAGG;AACH;IAcI;;;;;OAKG;IACH,4CAHW,MAAM,EAehB;IA/BD;;;;OAIG;IACH,cAFU,uBAAuB,CAEf;IAElB;;;OAGG;IACH,8BAAmB;IASf;;;OAGG;IACH,mBAAsB;IAEtB;;;OAGG;IACH,UAFU,MAAM,CAEQ;IAG5B;;;;OAIG;IACH,2BAFa,OAAO,CAgBnB;IAED,YAEC;IAED;;;OAGG;IACH,UAFa,CAAC,CAIb;CACJ"}
1
+ {"version":3,"file":"Asset.d.ts","sourceRoot":"","sources":["../../../../src/engine/asset/Asset.js"],"names":[],"mappings":"AAEA;;;GAGG;AACH;IAcI;;;;;OAKG;IACH,4CAHW,MAAM,EAehB;IA/BD;;;;OAIG;IACH,cAFU,uBAAuB,CAEf;IAElB;;;OAGG;IACH,8BAAmB;IASf;;;OAGG;IACH,mBAAsB;IAEtB;;;OAGG;IACH,UAFU,MAAM,CAEQ;IAG5B;;;;OAIG;IACH,2BAFa,OAAO,CAgBnB;IAED,eAEC;IAED;;;OAGG;IACH,UAFa,CAAC,CAIb;CACJ"}
@@ -1,3 +1,5 @@
1
+ import { optional_hash } from "../../core/model/object/optional_hash.js";
2
+
1
3
  /**
2
4
  * @template T
3
5
  *
@@ -58,7 +60,7 @@ export class Asset {
58
60
  }
59
61
 
60
62
  hash() {
61
- return this.description === null ? 0 : this.description.hash();
63
+ return optional_hash(this.description);
62
64
  }
63
65
 
64
66
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"HeadsUpDisplaySystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js"],"names":[],"mappings":";AAsBA;;;;;GAKG;AACH;IASI;;;OAGG;IACH,4CAmBC;IA/BD,wCAAgC;IAGhC,2HAGE;IAaE,yBAA8B;IAM9B;;;;OAIG;IACH,+BAAiD;IAGrD,iCAGC;IAED,gCAIC;IAED;;;;;;;;;OASG;IACH,sCAkJC;IAED,6BAsBC;CACJ;uBAxPsB,iBAAiB;2BAIb,qBAAqB;uBAFzB,kBAAkB;4CAJG,uDAAuD;6BAKtE,iCAAiC"}
1
+ {"version":3,"file":"HeadsUpDisplaySystem.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/ecs/gui/hud/HeadsUpDisplaySystem.js"],"names":[],"mappings":";AAsBA;;;;;GAKG;AACH;IASI;;;OAGG;IACH,4CAmBC;IA/BD,wCAAgC;IAGhC,2HAGE;IAaE,yBAA8B;IAM9B;;;;OAIG;IACH,+BAAiD;IAGrD,iCAGC;IAED,gCAIC;IAED;;;;;;;;;OASG;IACH,sCAiJC;IAED,6BAsBC;CACJ;uBAvPsB,iBAAiB;2BAIb,qBAAqB;uBAFzB,kBAAkB;4CAJG,uDAAuD;6BAKtE,iCAAiC"}
@@ -95,9 +95,10 @@ class HeadsUpDisplaySystem extends System {
95
95
  y *= transform.scale_y;
96
96
  z *= transform.scale_z;
97
97
 
98
- const q = transform.rotation;
99
-
100
- v3_quaternion_apply(scratch_rotated_offset, 0, x, y, z, q[0], q[1], q[2], q[3]);
98
+ v3_quaternion_apply(
99
+ scratch_rotated_offset, 0, x, y, z,
100
+ transform.rotation_x, transform.rotation_y, transform.rotation_z, transform.rotation_w
101
+ );
101
102
 
102
103
  x = scratch_rotated_offset[0];
103
104
  y = scratch_rotated_offset[1];
@@ -105,11 +106,9 @@ class HeadsUpDisplaySystem extends System {
105
106
  }
106
107
 
107
108
  // add transform position to get final world position
108
- const position = transform.translation;
109
-
110
- x += position[0];
111
- y += position[1];
112
- z += position[2];
109
+ x += transform.translation_x;
110
+ y += transform.translation_y;
111
+ z += transform.translation_z;
113
112
 
114
113
  const worldPositionX = x;
115
114
  const worldPositionY = y;
@@ -187,8 +186,8 @@ class HeadsUpDisplaySystem extends System {
187
186
  ndcY = 0.5 + dy;
188
187
  }
189
188
 
190
- vp.position[0] = ndcX;
191
- position[1] = ndcY;
189
+ // Notify ViewportPositionSystem so it updates the label's placement and visibility.
190
+ vp.position.set(ndcX, ndcY);
192
191
 
193
192
  const visible = (!trackedPositionOutOfBounds || vp.stickToScreenEdge) && this.__visibility_predicate.test(worldPositionX, worldPositionY, worldPositionZ);
194
193
 
@@ -1 +1 @@
1
- {"version":3,"file":"ParticleEffect.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/particles/ParticleEffect.js"],"names":[],"mappings":"AAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH;IAoRI;;;;;;;;;;;;;;;;;;OAkBG;IACH;QAZ2G,MAAM,GAAtG,OAAO,+DAA+D,EAAE,cAAc;QACS,OAAO,GAAtG,OAAO,6DAA6D,EAAE,eAAe;QAChE,OAAO,GAA5B,MAAM,GAAC,IAAI;QACK,IAAI,GAApB,MAAM;QACU,UAAU,GAA1B,MAAM;QACW,QAAQ,GAAzB,OAAO;QACS,OAAO,GAAvB,MAAM;QACU,KAAK,GAArB,MAAM;QACyB,MAAM;gBAA9B,MAAM,GAAC,MAAM;;QACO,QAAQ,GAAnC,UAAU,MAAM,CAAC;QACf,cAAc,CA8C1B;IAjVD;;;;;;;;;OASG;IACH,QAFU,OAAO,+DAA+D,EAAE,cAAc,GAAC,IAAI,CAEvF;IAEd;;;;;OAKG;IACH,SAFU,OAAO,6DAA6D,EAAE,eAAe,GAAC,IAAI,CAErF;IAEf;;;;;;;;;OASG;IACH,SAFU,MAAM,GAAC,IAAI,CAEN;IAEf;;;;;;;;OAQG;IACH,MAFU,MAAM,CAEP;IAET;;;;;OAKG;IACH,YAFU,MAAM,CAED;IAEf;;;;;;;;;;OAUG;IACH,UAFU,OAAO,CAED;IAEhB;;;;;;;;;;;;;OAaG;IACH,SAFU,MAAM,CAEJ;IAEZ;;;;;OAKG;IACH,OAFU,MAAM,CAEN;IAEV;;;;;OAKG;IACH,UAFU,YAAY,CAEc;IAEpC,+FAA+F;IAC/F,iBADW,MAAM,CAC0B;IAC3C,gDAAgD;IAChD,aADW,MAAM,CACsB;IACvC,uDAAuD;IACvD,cADW,MAAM,CACuB;IACxC,+DAA+D;IAC/D,iBADW,MAAM,CAC0B;IAC3C,gEAAgE;IAChE,cADW,MAAM,CACuB;IACxC,sFAAsF;IACtF,iBADW,MAAM,CAC0B;IAE3C;;;;;OAKG;IACH,mCAEC;IAED;;;;;;;;;;;;;;;OAeG;IACH;YAJkB,MAAM,GAAC,MAAM;QAElB,cAAc,CAuC1B;IAED;;;;;;;;;OASG;IACH,cAHW,cAAc,GACZ,OAAO,CAsBnB;IAED;;;;OAIG;IACH,QAFa,MAAM,CAuBlB;IAED;;;;;;;;;OASG;IACH,YAHW,cAAc,GACZ,cAAc,CAuB1B;IAED;;OAEG;IACH,SAFa,cAAc,CAI1B;IAkGL;;;;;OAKG;IACH,2BAFU,OAAO,CAEwB;CAtCxC;;kBA4BS,MAAM"}
1
+ {"version":3,"file":"ParticleEffect.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/ecs/particles/ParticleEffect.js"],"names":[],"mappings":"AAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8DG;AACH;IAoRI;;;;;;;;;;;;;;;;;;OAkBG;IACH;QAZ2G,MAAM,GAAtG,OAAO,+DAA+D,EAAE,cAAc;QACS,OAAO,GAAtG,OAAO,6DAA6D,EAAE,eAAe;QAChE,OAAO,GAA5B,MAAM,GAAC,IAAI;QACK,IAAI,GAApB,MAAM;QACU,UAAU,GAA1B,MAAM;QACW,QAAQ,GAAzB,OAAO;QACS,OAAO,GAAvB,MAAM;QACU,KAAK,GAArB,MAAM;QACyB,MAAM;gBAA9B,MAAM,GAAC,MAAM;;QACO,QAAQ,GAAnC,UAAU,MAAM,CAAC;QACf,cAAc,CA8C1B;IAjVD;;;;;;;;;OASG;IACH,QAFU,OAAO,+DAA+D,EAAE,cAAc,GAAC,IAAI,CAEvF;IAEd;;;;;OAKG;IACH,SAFU,OAAO,6DAA6D,EAAE,eAAe,GAAC,IAAI,CAErF;IAEf;;;;;;;;;OASG;IACH,SAFU,MAAM,GAAC,IAAI,CAEN;IAEf;;;;;;;;OAQG;IACH,MAFU,MAAM,CAEP;IAET;;;;;OAKG;IACH,YAFU,MAAM,CAED;IAEf;;;;;;;;;;OAUG;IACH,UAFU,OAAO,CAED;IAEhB;;;;;;;;;;;;;OAaG;IACH,SAFU,MAAM,CAEJ;IAEZ;;;;;OAKG;IACH,OAFU,MAAM,CAEN;IAEV;;;;;OAKG;IACH,UAFU,YAAY,CAEc;IAEpC,+FAA+F;IAC/F,iBADW,MAAM,CAC0B;IAC3C,gDAAgD;IAChD,aADW,MAAM,CACsB;IACvC,uDAAuD;IACvD,cADW,MAAM,CACuB;IACxC,+DAA+D;IAC/D,iBADW,MAAM,CAC0B;IAC3C,gEAAgE;IAChE,cADW,MAAM,CACuB;IACxC,sFAAsF;IACtF,iBADW,MAAM,CAC0B;IAE3C;;;;;OAKG;IACH,mCAEC;IAED;;;;;;;;;;;;;;;OAeG;IACH;YAJkB,MAAM,GAAC,MAAM;QAElB,cAAc,CAuC1B;IAED;;;;;;;;;OASG;IACH,cAHW,cAAc,GACZ,OAAO,CAsBnB;IAED;;;;OAIG;IACH,QAFa,MAAM,CAuBlB;IAED;;;;;;;;;OASG;IACH,YAHW,cAAc,GACZ,cAAc,CAuB1B;IAED;;OAEG;IACH,SAFa,cAAc,CAI1B;IAgFL;;;;;OAKG;IACH,2BAFU,OAAO,CAEwB;CApBxC;;kBAUS,MAAM"}
@@ -3,6 +3,8 @@ import { float32_array_hash } from "../../../../core/collection/array/typed/floa
3
3
  import { is_typed_array_equals } from "../../../../core/collection/array/typed/is_typed_array_equals.js";
4
4
  import { hash_mix2 } from "../../../../core/math/hash/hash_mix2.js";
5
5
  import { hash_mix3 } from "../../../../core/math/hash/hash_mix3.js";
6
+ import { optional_equality } from "../../../../core/model/object/optional_equality.js";
7
+ import { optional_hash } from "../../../../core/model/object/optional_hash.js";
6
8
  import { computeHashFloat } from "../../../../core/primitives/numbers/computeHashFloat.js";
7
9
  import { computeStringHash } from "../../../../core/primitives/strings/computeStringHash.js";
8
10
  import {
@@ -278,8 +280,8 @@ export class ParticleEffect {
278
280
  && this.render_frame === other.render_frame
279
281
  && this.render_velocity === other.render_velocity
280
282
  && is_typed_array_equals(this.flipbook, other.flipbook)
281
- && optional_equals(this.layout, other.layout)
282
- && optional_equals(this.program, other.program);
283
+ && optional_equality(this.layout, other.layout)
284
+ && optional_equality(this.program, other.program);
283
285
  }
284
286
 
285
287
  /**
@@ -304,8 +306,8 @@ export class ParticleEffect {
304
306
  hash_mix2(bindings, float32_array_hash(this.flipbook, 0, this.flipbook.length)),
305
307
  appearance,
306
308
  hash_mix2(
307
- this.layout === null ? 0 : this.layout.hash(),
308
- this.program === null ? 0 : this.program.hash()
309
+ optional_hash(this.layout),
310
+ optional_hash(this.program)
309
311
  )
310
312
  );
311
313
  }
@@ -416,24 +418,6 @@ export class ParticleEffect {
416
418
  }
417
419
  }
418
420
 
419
- /**
420
- * Compare two things that are either both absent or both know how to compare themselves.
421
- *
422
- * A component with no effect is an ordinary state — it is what an entity has while its effect is
423
- * still being compiled — so `null` has to be a value here rather than a precondition.
424
- *
425
- * @param {{equals: function(*): boolean}|null} a
426
- * @param {{equals: function(*): boolean}|null} b
427
- * @returns {boolean}
428
- */
429
- function optional_equals(a, b) {
430
- if (a === null || b === null) {
431
- return a === b;
432
- }
433
-
434
- return a.equals(b);
435
- }
436
-
437
421
  /**
438
422
  * The name this component is written under, and looked up by when a save is read. A serialization
439
423
  * registry infers nothing from a class — see
@@ -3,7 +3,7 @@ import { combine_hash } from "../../../core/collection/array/combine_hash.js";
3
3
  import { computeHashArray } from "../../../core/collection/array/computeHashArray.js";
4
4
  import { isArrayEqual } from "../../../core/collection/array/isArrayEqual.js";
5
5
  import { invokeObjectHash } from "../../../core/model/object/invokeObjectHash.js";
6
- import { optional_clone } from "../util/optional_clone.js";
6
+ import { optional_clone } from "../../../core/model/object/optional_clone.js";
7
7
  import { ObjectDescriptorBase } from "../ObjectDescriptorBase.js";
8
8
  import { BindGroupLayoutEntry } from "./BindGroupLayoutEntry.js";
9
9
 
@@ -1,8 +1,8 @@
1
1
  import { assert } from "../../../core/assert.js";
2
2
  import { combine_hash } from "../../../core/collection/array/combine_hash.js";
3
- import { optional_clone } from "../util/optional_clone.js";
4
- import { optional_equality } from "../util/optional_equality.js";
5
- import { optional_hash } from "../util/optional_hash.js";
3
+ import { optional_clone } from "../../../core/model/object/optional_clone.js";
4
+ import { optional_equality } from "../../../core/model/object/optional_equality.js";
5
+ import { optional_hash } from "../../../core/model/object/optional_hash.js";
6
6
  import { BufferBindingLayout } from "./BufferBindingLayout.js";
7
7
  import { ExternalTextureBindingLayout } from "./ExternalTextureBindingLayout.js";
8
8
  import { SamplerBindingLayout } from "./SamplerBindingLayout.js";
@@ -1,6 +1,6 @@
1
1
  import { assert } from "../../../core/assert.js";
2
2
  import { combine_hash } from "../../../core/collection/array/combine_hash.js";
3
- import { optional_clone } from "../util/optional_clone.js";
3
+ import { optional_clone } from "../../../core/model/object/optional_clone.js";
4
4
  import { ObjectDescriptorBase } from "../ObjectDescriptorBase.js";
5
5
  import { PipelineLayoutDescriptor } from "./PipelineLayoutDescriptor.js";
6
6
 
@@ -3,7 +3,7 @@ import { combine_hash } from "../../../core/collection/array/combine_hash.js";
3
3
  import { computeHashArray } from "../../../core/collection/array/computeHashArray.js";
4
4
  import { isArrayEqual } from "../../../core/collection/array/isArrayEqual.js";
5
5
  import { invokeObjectHash } from "../../../core/model/object/invokeObjectHash.js";
6
- import { optional_clone } from "../util/optional_clone.js";
6
+ import { optional_clone } from "../../../core/model/object/optional_clone.js";
7
7
  import { BindGroupLayoutDescriptor } from "../binding/BindGroupLayoutDescriptor.js";
8
8
  import { ObjectDescriptorBase } from "../ObjectDescriptorBase.js";
9
9
 
@@ -1,9 +1,9 @@
1
1
  import { assert } from "../../../../core/assert.js";
2
2
  import { combine_hash } from "../../../../core/collection/array/combine_hash.js";
3
3
  import { computeStringHash } from "../../../../core/primitives/strings/computeStringHash.js";
4
- import { optional_clone } from "../../util/optional_clone.js";
5
- import { optional_equality } from "../../util/optional_equality.js";
6
- import { optional_hash } from "../../util/optional_hash.js";
4
+ import { optional_clone } from "../../../../core/model/object/optional_clone.js";
5
+ import { optional_equality } from "../../../../core/model/object/optional_equality.js";
6
+ import { optional_hash } from "../../../../core/model/object/optional_hash.js";
7
7
  import {
8
8
  gpu_texture_format_channel_bit_count
9
9
  } from "../../texture/format/gpu_texture_format_channel_bit_count.js";
@@ -3,7 +3,7 @@ import { combine_hash } from "../../../../core/collection/array/combine_hash.js"
3
3
  import { computeHashArray } from "../../../../core/collection/array/computeHashArray.js";
4
4
  import { isArrayEqual } from "../../../../core/collection/array/isArrayEqual.js";
5
5
  import { invokeObjectHash } from "../../../../core/model/object/invokeObjectHash.js";
6
- import { optional_clone } from "../../util/optional_clone.js";
6
+ import { optional_clone } from "../../../../core/model/object/optional_clone.js";
7
7
  import { ProgrammableStage } from "../ProgrammableStage.js";
8
8
  import { ColorTargetState } from "./ColorTargetState.js";
9
9
 
@@ -1,8 +1,8 @@
1
1
  import { assert } from "../../../../core/assert.js";
2
2
  import { combine_hash } from "../../../../core/collection/array/combine_hash.js";
3
- import { optional_clone } from "../../util/optional_clone.js";
4
- import { optional_equality } from "../../util/optional_equality.js";
5
- import { optional_hash } from "../../util/optional_hash.js";
3
+ import { optional_clone } from "../../../../core/model/object/optional_clone.js";
4
+ import { optional_equality } from "../../../../core/model/object/optional_equality.js";
5
+ import { optional_hash } from "../../../../core/model/object/optional_hash.js";
6
6
  import { PipelineDescriptorBase } from "../PipelineDescriptorBase.js";
7
7
  import { DepthStencilState } from "./DepthStencilState.js";
8
8
  import { FragmentState } from "./FragmentState.js";
@@ -82,7 +82,7 @@ edits it at both altitudes.
82
82
  curve, including peaks between keys. Its fields edit the selected key's time, value and tangents.
83
83
  The scale stays fixed during a drag and refits on release. Neither ramp is sampled from a table
84
84
  at runtime: both are written out into the program as arithmetic, which is what the **Code** tab
85
- shows. `Curve Table`, which *is* the table, is the other node — it takes a row handle rather than a curve.
85
+ shows.
86
86
  - The strip along the bottom lists every problem with the effect, from **both** phases, loudest
87
87
  first. Click one to jump to the phase it is in and select the node; the node is outlined in the
88
88
  graph too.
@@ -1,31 +1,29 @@
1
1
  /**
2
2
  * Worked examples of authoring particle effects with the node graph + placing them in a scene for a
3
3
  * {@link GPUParticleSystem} to run. Demonstrates: distinct per-particle lifecycle (no built-in age — the
4
- * effect declares it), AnimationCurve sampling over life, flipbook frames, random emission,
4
+ * effect declares it), authored curves over life, flipbook frames, random emission,
5
5
  * additive vs alpha blending, projection modes, soft depth and lighting toggles.
6
6
  *
7
7
  * These are examples, not engine code, which is why they sit here rather than under
8
8
  * `renderer/particles/`: the only thing that opens them is this playground's page, and keeping them
9
9
  * on this side of the line means the dependency runs playground -> renderer and never back.
10
10
  *
11
- * `curves` is a `GPUAnimationManager` (or anything with `register_curve(AnimationCurve) -> handle`);
12
- * `size_curve` / `alpha_curve` are meep `AnimationCurve`s. Both are optional — passing `undefined`
13
- * yields effects that use constant size/alpha instead (curve handle 0, evaluated as 0 by the
14
- * disabled provider), which is handy for the headless tests.
11
+ * `size_curve` / `alpha_curve` are authored curve parameters compiled into arithmetic. Both are
12
+ * optional; omitted curves leave the initial size/colour unchanged.
15
13
  */
16
14
  /**
17
15
  * A fire effect: buoyant, turbulent, additive-blended camera-facing sprites whose size and opacity
18
16
  * follow curves over their lifetime and whose flipbook advances with age.
19
17
  *
20
18
  * @param {object} [options]
21
- * @param {number} [options.size_curve] curve handle for size(normalizedAge)
22
- * @param {number} [options.alpha_curve] curve handle for alpha(normalizedAge)
19
+ * @param {import("../../renderer/particles/graph/particle_ramp.js").ParticleCurveParameter} [options.size_curve] size(normalizedAge)
20
+ * @param {import("../../renderer/particles/graph/particle_ramp.js").ParticleCurveParameter} [options.alpha_curve] alpha(normalizedAge)
23
21
  * @param {number} [options.flipbook_frames]
24
22
  * @returns {{layout: ParticleLayout, effect: object, emitter: object}}
25
23
  */
26
24
  export function fire_effect({ size_curve, alpha_curve, flipbook_frames }?: {
27
- size_curve?: number;
28
- alpha_curve?: number;
25
+ size_curve?: import("../../renderer/particles/graph/particle_ramp.js").ParticleCurveParameter;
26
+ alpha_curve?: import("../../renderer/particles/graph/particle_ramp.js").ParticleCurveParameter;
29
27
  flipbook_frames?: number;
30
28
  }): {
31
29
  layout: ParticleLayout;
@@ -1 +1 @@
1
- {"version":3,"file":"particle_prototype.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/particle_system/particle_prototype.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;GASG;AACH;IAL4B,UAAU,GAA3B,MAAM;IACW,WAAW,GAA5B,MAAM;IACW,eAAe,GAAhC,MAAM;;YACK,cAAc;YAAU,MAAM;aAAW,MAAM;EA+GpE;AAED;;;;GAIG;AACH;YAFsB,cAAc;YAAU,MAAM;aAAW,MAAM;EAYpE;AAED;;;;;;;;;;;;;GAaG;AACH,yCANW,OAAO,+BAA+B,EAAE,KAAK;IAEa,IAAI,GAA9D,OAAO,gCAAgC,EAAE,MAAM;;UAEtC,eAAe;WAAS,eAAe;EAe1D;+BAzL8B,mDAAmD;gCAElD,qDAAqD"}
1
+ {"version":3,"file":"particle_prototype.d.ts","sourceRoot":"","sources":["../../../../../src/shade/playground/particle_system/particle_prototype.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;GAYG;AAEH;;;;;;;;;GASG;AACH;IALsG,UAAU,GAArG,OAAO,iDAAiD,EAAE,sBAAsB;IACW,WAAW,GAAtG,OAAO,iDAAiD,EAAE,sBAAsB;IAC/D,eAAe,GAAhC,MAAM;;YACK,cAAc;YAAU,MAAM;aAAW,MAAM;EA+GpE;AAED;;;;GAIG;AACH;YAFsB,cAAc;YAAU,MAAM;aAAW,MAAM;EAYpE;AAED;;;;;;;;;;;;;GAaG;AACH,yCANW,OAAO,+BAA+B,EAAE,KAAK;IAEa,IAAI,GAA9D,OAAO,gCAAgC,EAAE,MAAM;;UAEtC,eAAe;WAAS,eAAe;EAe1D;+BAvL8B,mDAAmD;gCAElD,qDAAqD"}
@@ -13,17 +13,15 @@ import { ParticleEmitter } from "../../renderer/particles/runtime/ParticleEmitte
13
13
  /**
14
14
  * Worked examples of authoring particle effects with the node graph + placing them in a scene for a
15
15
  * {@link GPUParticleSystem} to run. Demonstrates: distinct per-particle lifecycle (no built-in age — the
16
- * effect declares it), AnimationCurve sampling over life, flipbook frames, random emission,
16
+ * effect declares it), authored curves over life, flipbook frames, random emission,
17
17
  * additive vs alpha blending, projection modes, soft depth and lighting toggles.
18
18
  *
19
19
  * These are examples, not engine code, which is why they sit here rather than under
20
20
  * `renderer/particles/`: the only thing that opens them is this playground's page, and keeping them
21
21
  * on this side of the line means the dependency runs playground -> renderer and never back.
22
22
  *
23
- * `curves` is a `GPUAnimationManager` (or anything with `register_curve(AnimationCurve) -> handle`);
24
- * `size_curve` / `alpha_curve` are meep `AnimationCurve`s. Both are optional — passing `undefined`
25
- * yields effects that use constant size/alpha instead (curve handle 0, evaluated as 0 by the
26
- * disabled provider), which is handy for the headless tests.
23
+ * `size_curve` / `alpha_curve` are authored curve parameters compiled into arithmetic. Both are
24
+ * optional; omitted curves leave the initial size/colour unchanged.
27
25
  */
28
26
 
29
27
  /**
@@ -31,8 +29,8 @@ import { ParticleEmitter } from "../../renderer/particles/runtime/ParticleEmitte
31
29
  * follow curves over their lifetime and whose flipbook advances with age.
32
30
  *
33
31
  * @param {object} [options]
34
- * @param {number} [options.size_curve] curve handle for size(normalizedAge)
35
- * @param {number} [options.alpha_curve] curve handle for alpha(normalizedAge)
32
+ * @param {import("../../renderer/particles/graph/particle_ramp.js").ParticleCurveParameter} [options.size_curve] size(normalizedAge)
33
+ * @param {import("../../renderer/particles/graph/particle_ramp.js").ParticleCurveParameter} [options.alpha_curve] alpha(normalizedAge)
36
34
  * @param {number} [options.flipbook_frames]
37
35
  * @returns {{layout: ParticleLayout, effect: object, emitter: object}}
38
36
  */
@@ -111,12 +109,12 @@ export function fire_effect({ size_curve, alpha_curve, flipbook_frames = 16 } =
111
109
 
112
110
  // size + alpha from curves over life (or constants if no curve provided)
113
111
  if (size_curve !== undefined) {
114
- const sc = particle_node(update, "curve", { handle: size_curve }); particle_wire(update, sc, "t", nAge);
112
+ const sc = particle_node(update, "curveLiteral", { curve: size_curve }); particle_wire(update, sc, "t", nAge);
115
113
  particle_wire(update, particle_node(update, "setAttribute", { name: "size" }), "value", sc);
116
114
  }
117
115
  const color = particle_node(update, "attribute", { name: "color" });
118
116
  if (alpha_curve !== undefined) {
119
- const ac = particle_node(update, "curve", { handle: alpha_curve }); particle_wire(update, ac, "t", nAge);
117
+ const ac = particle_node(update, "curveLiteral", { curve: alpha_curve }); particle_wire(update, ac, "t", nAge);
120
118
  // color.rgb unchanged, color.a = ac : rebuild via select on a swizzle mask is overkill;
121
119
  // simplest: multiply color by (1,1,1,ac_normalized) — approximate by scaling alpha only.
122
120
  const alphaVec = particle_node(update, "mul");
@@ -0,0 +1,22 @@
1
+ # SSR cross camera playground
2
+
3
+ Open `/src/shade/playground/ssr_motion/` on the engine's Vite development server.
4
+ It shares the exact scene, camera lens, resolution and fixed exposure of
5
+ `ssr_variance`: one metallic floor and an emissive cross card with two colored
6
+ markers. Final-image TAA and raster jitter default off independently.
7
+
8
+ Drag to orbit, right-drag to pan, wheel to zoom, or focus the canvas and use WASD.
9
+ Floor roughness changes live from 0.01 to 1.00. Material changes clear history;
10
+ ordinary camera movement does not. The lateral path uses the same motion-speed
11
+ scale as `ssr_reprojection` (x = 2 sin(phase), phase rate = 0.7 × speed).
12
+ Choose speed 2.0 to reproduce the faster lateral movement.
13
+
14
+ Pause motion continues sampling at the current pose. Pause rendering freezes the
15
+ image. Step frame submits one 1/60-second frame. SSR parallax, surface-only and
16
+ no-history modes, spatial denoising, final TAA and jitter can be compared separately.
17
+
18
+ Query controls: `?motion=lateral&speed=2&roughness=0.3`, `taa=on`, `jitter=on`,
19
+ `spatial=off`, and `temporal=0|1|2`. `manual` starts at frame zero with rendering
20
+ paused. `await ssr_motion_ready` exposes the renderer, camera, scene, `pose`,
21
+ `frame`, and `step(n, advance=true)` for controlled experiments. `advance=false`
22
+ keeps the current pose while sampling. Exact stepping requires rendering paused.