@needle-tools/engine 4.6.1 → 4.6.2-next.fb486b2

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 (102) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/generateMeshBVH.worker-BaNp_Xtp.js +25 -0
  3. package/dist/{gltf-progressive-Bm9eEfgu.min.js → gltf-progressive-Bl4okF1b.min.js} +1 -1
  4. package/dist/{gltf-progressive-GjIqwSG3.js → gltf-progressive-DSpdn0QT.js} +2 -2
  5. package/dist/{gltf-progressive-Dn6o99rH.umd.cjs → gltf-progressive-P8b8a0qY.umd.cjs} +1 -1
  6. package/dist/needle-engine.bundle-CJ4jhuta.min.js +1575 -0
  7. package/dist/{needle-engine.bundle-BVg46UWZ.js → needle-engine.bundle-CQzZighj.js} +9722 -9554
  8. package/dist/needle-engine.bundle-CdAK5p8o.umd.cjs +1575 -0
  9. package/dist/needle-engine.js +352 -351
  10. package/dist/needle-engine.min.js +1 -1
  11. package/dist/needle-engine.umd.cjs +1 -1
  12. package/dist/{postprocessing-CRQa6Qxn.umd.cjs → postprocessing-CjW23fio.umd.cjs} +18 -18
  13. package/dist/{postprocessing-D6W1EyZ-.js → postprocessing-DYLNOL3W.js} +4 -3
  14. package/dist/{postprocessing-DF8AlRgW.min.js → postprocessing-xYQWCHFu.min.js} +26 -26
  15. package/dist/{three-DMrv-4ar.umd.cjs → three-B_hneGZr.umd.cjs} +4 -4
  16. package/dist/{three-Bz6X1mrw.js → three-DrqIzZTH.js} +4198 -4198
  17. package/dist/{three-Boa-jOq-.min.js → three-DuDKwKB8.min.js} +33 -33
  18. package/dist/{three-examples-GggCDHv0.js → three-examples-B50TT3Iu.js} +5 -5
  19. package/dist/{three-examples-DuVhxqft.min.js → three-examples-DaDLBuy6.min.js} +14 -14
  20. package/dist/{three-examples-C7ryg8vN.umd.cjs → three-examples-X3OadjXB.umd.cjs} +3 -3
  21. package/dist/{three-mesh-ui-CY6Izc7C.min.js → three-mesh-ui-B3p3gyUz.min.js} +1 -1
  22. package/dist/{three-mesh-ui-CwlN0FUC.umd.cjs → three-mesh-ui-CQiIQIlA.umd.cjs} +1 -1
  23. package/dist/{three-mesh-ui-CLNOfsWn.js → three-mesh-ui-CxuWt7m-.js} +1 -1
  24. package/dist/{vendor-zxXa3Dmr.min.js → vendor-BlSxe9JJ.min.js} +3 -3
  25. package/dist/{vendor-BSD1RQIh.js → vendor-BmYIgaS1.js} +3 -3
  26. package/dist/{vendor-DHr4aqIZ.umd.cjs → vendor-Cavtu3CP.umd.cjs} +3 -3
  27. package/lib/engine/engine_context.d.ts +4 -1
  28. package/lib/engine/engine_context.js +9 -2
  29. package/lib/engine/engine_context.js.map +1 -1
  30. package/lib/engine/engine_three_utils.d.ts +17 -14
  31. package/lib/engine/engine_three_utils.js +106 -53
  32. package/lib/engine/engine_three_utils.js.map +1 -1
  33. package/lib/engine/engine_tonemapping.d.ts +4 -0
  34. package/lib/engine/engine_tonemapping.js +21 -18
  35. package/lib/engine/engine_tonemapping.js.map +1 -1
  36. package/lib/engine/engine_utils.js.map +1 -1
  37. package/lib/engine/engine_utils_screenshot.d.ts +1 -1
  38. package/lib/engine/engine_utils_screenshot.js +11 -2
  39. package/lib/engine/engine_utils_screenshot.js.map +1 -1
  40. package/lib/engine/webcomponents/needle-engine.d.ts +4 -1
  41. package/lib/engine/webcomponents/needle-engine.extras.js +3 -3
  42. package/lib/engine/webcomponents/needle-engine.extras.js.map +1 -1
  43. package/lib/engine/webcomponents/needle-engine.js +11 -21
  44. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  45. package/lib/engine-components/CameraUtils.js.map +1 -1
  46. package/lib/engine-components/postprocessing/Effects/Antialiasing.js +3 -1
  47. package/lib/engine-components/postprocessing/Effects/Antialiasing.js.map +1 -1
  48. package/lib/engine-components/postprocessing/Effects/BloomEffect.d.ts +2 -2
  49. package/lib/engine-components/postprocessing/Effects/BloomEffect.js +2 -2
  50. package/lib/engine-components/postprocessing/Effects/ColorAdjustments.d.ts +8 -0
  51. package/lib/engine-components/postprocessing/Effects/ColorAdjustments.js +27 -8
  52. package/lib/engine-components/postprocessing/Effects/ColorAdjustments.js.map +1 -1
  53. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js +1 -0
  54. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js.map +1 -1
  55. package/lib/engine-components/postprocessing/Effects/Sharpening.d.ts +1 -0
  56. package/lib/engine-components/postprocessing/Effects/Sharpening.js +4 -0
  57. package/lib/engine-components/postprocessing/Effects/Sharpening.js.map +1 -1
  58. package/lib/engine-components/postprocessing/Effects/Tonemapping.d.ts +2 -9
  59. package/lib/engine-components/postprocessing/Effects/Tonemapping.js +23 -71
  60. package/lib/engine-components/postprocessing/Effects/Tonemapping.js.map +1 -1
  61. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +13 -0
  62. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.js +52 -0
  63. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.js.map +1 -0
  64. package/lib/engine-components/postprocessing/PostProcessingEffect.d.ts +18 -0
  65. package/lib/engine-components/postprocessing/PostProcessingEffect.js +22 -3
  66. package/lib/engine-components/postprocessing/PostProcessingEffect.js.map +1 -1
  67. package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +20 -4
  68. package/lib/engine-components/postprocessing/PostProcessingHandler.js +231 -116
  69. package/lib/engine-components/postprocessing/PostProcessingHandler.js.map +1 -1
  70. package/lib/engine-components/postprocessing/Volume.d.ts +2 -1
  71. package/lib/engine-components/postprocessing/Volume.js +51 -33
  72. package/lib/engine-components/postprocessing/Volume.js.map +1 -1
  73. package/lib/engine-components/postprocessing/index.d.ts +1 -0
  74. package/lib/engine-components/postprocessing/index.js +1 -0
  75. package/lib/engine-components/postprocessing/index.js.map +1 -1
  76. package/lib/engine-components/postprocessing/utils.d.ts +44 -0
  77. package/lib/engine-components/postprocessing/utils.js +82 -0
  78. package/lib/engine-components/postprocessing/utils.js.map +1 -1
  79. package/package.json +2 -2
  80. package/src/engine/engine_context.ts +13 -4
  81. package/src/engine/engine_three_utils.ts +134 -58
  82. package/src/engine/engine_tonemapping.ts +23 -24
  83. package/src/engine/engine_utils.ts +2 -2
  84. package/src/engine/engine_utils_screenshot.ts +13 -3
  85. package/src/engine/webcomponents/needle-engine.extras.ts +3 -3
  86. package/src/engine/webcomponents/needle-engine.ts +14 -25
  87. package/src/engine-components/CameraUtils.ts +3 -3
  88. package/src/engine-components/postprocessing/Effects/Antialiasing.ts +3 -1
  89. package/src/engine-components/postprocessing/Effects/BloomEffect.ts +4 -4
  90. package/src/engine-components/postprocessing/Effects/ColorAdjustments.ts +24 -13
  91. package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +1 -0
  92. package/src/engine-components/postprocessing/Effects/Sharpening.ts +5 -0
  93. package/src/engine-components/postprocessing/Effects/Tonemapping.ts +26 -80
  94. package/src/engine-components/postprocessing/Effects/Tonemapping.utils.ts +60 -0
  95. package/src/engine-components/postprocessing/PostProcessingEffect.ts +23 -3
  96. package/src/engine-components/postprocessing/PostProcessingHandler.ts +267 -122
  97. package/src/engine-components/postprocessing/Volume.ts +54 -38
  98. package/src/engine-components/postprocessing/index.ts +2 -1
  99. package/src/engine-components/postprocessing/utils.ts +103 -2
  100. package/dist/generateMeshBVH.worker-Cdfpaq5W.js +0 -25
  101. package/dist/needle-engine.bundle-AOXFIsYk.umd.cjs +0 -1563
  102. package/dist/needle-engine.bundle-Dt52m2jf.min.js +0 -1563
@@ -1,4 +1,4 @@
1
- import type { Effect } from "postprocessing";
1
+ import type { Effect, EffectComposer } from "postprocessing";
2
2
 
3
3
  import { isDevEnvironment, showBalloonMessage } from "../../engine/debug/index.js";
4
4
  import { Context } from "../../engine/engine_context.js";
@@ -56,6 +56,9 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
56
56
  return this._activeEffects;
57
57
  }
58
58
 
59
+ get dirty() { return this._isDirty; }
60
+ set dirty(value: boolean) { this._isDirty = value; }
61
+
59
62
  @serializeable(VolumeProfile)
60
63
  sharedProfile?: VolumeProfile;
61
64
 
@@ -184,38 +187,56 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
184
187
 
185
188
  this.context.composer.setMainScene(this.context.scene);
186
189
 
187
- const composer = this.context.composer;
188
190
  if (this.multisampling === "auto") {
189
191
 
190
- const timeSinceLastChange = this.context.time.realtimeSinceStartup - this._multisampleAutoChangeTime;
191
-
192
- if (this.context.time.realtimeSinceStartup - this._componentEnabledTime > 2
193
- && timeSinceLastChange > .5
194
- ) {
195
- const prev = composer.multisampling;
196
-
197
- if (composer.multisampling > 0 && this.context.time.smoothedFps <= 50) {
198
- this._multisampleAutoChangeTime = this.context.time.realtimeSinceStartup;
199
- this._multisampleAutoDecreaseTime = this.context.time.realtimeSinceStartup;
200
- composer.multisampling *= .5;
201
- composer.multisampling = Math.floor(composer.multisampling);
202
- if (debug) console.debug(`[PostProcessing] Reduced multisampling from ${prev} to ${composer.multisampling}`);
192
+ // If the postprocessing handler is using depth+normals (e.g. with SMAA) we ALWAYS disable multisampling to avoid ugly edges
193
+ if (this._postprocessing && (this._postprocessing.hasSmaaEffect)) {
194
+ if (this._postprocessing.multisampling !== 0) {
195
+ this._postprocessing.multisampling = 0;
196
+ if (debug || isDevEnvironment()) {
197
+ console.warn(`[PostProcessing] Disabling multisampling you're using SMAA and have set the 'multisampling: auto' on your PostprocessingManager/Volume component. If you need anti-aliasing, consider adding an Antialiasing component or SMAA effect to the PostprocessingManager.`);
198
+ }
203
199
  }
204
- // if performance is good for a while try increasing multisampling again
205
- else if (timeSinceLastChange > 1
206
- && this.context.time.smoothedFps >= 59
207
- && composer.multisampling < this.context.renderer.capabilities.maxSamples
208
- && this.context.time.realtimeSinceStartup - this._multisampleAutoDecreaseTime > 10
200
+ }
201
+ else {
202
+ const timeSinceLastChange = this.context.time.realtimeSinceStartup - this._multisampleAutoChangeTime;
203
+
204
+ if (this.context.time.realtimeSinceStartup - this._componentEnabledTime > 2
205
+ && timeSinceLastChange > .5
209
206
  ) {
210
- this._multisampleAutoChangeTime = this.context.time.realtimeSinceStartup;
211
- composer.multisampling = composer.multisampling <= 0 ? 1 : composer.multisampling * 2;
212
- composer.multisampling = Math.floor(composer.multisampling);
213
- if (debug) console.debug(`[PostProcessing] Increased multisampling from ${prev} to ${composer.multisampling}`);
207
+ const prev = this._postprocessing.multisampling;
208
+
209
+ if (this._postprocessing.multisampling > 0 && this.context.time.smoothedFps <= 50) {
210
+ this._multisampleAutoChangeTime = this.context.time.realtimeSinceStartup;
211
+ this._multisampleAutoDecreaseTime = this.context.time.realtimeSinceStartup;
212
+ let newMultiSample = this._postprocessing.multisampling * .5;
213
+ newMultiSample = Math.floor(newMultiSample);
214
+ if (newMultiSample != this._postprocessing.multisampling) {
215
+ this._postprocessing.multisampling = newMultiSample;
216
+ }
217
+ if (debug) console.debug(`[PostProcessing] Reduced multisampling from ${prev} to ${this._postprocessing.multisampling}`);
218
+ }
219
+ // if performance is good for a while try increasing multisampling again
220
+ else if (timeSinceLastChange > 1
221
+ && this.context.time.smoothedFps >= 59
222
+ && this._postprocessing.multisampling < this.context.renderer.capabilities.maxSamples
223
+ && this.context.time.realtimeSinceStartup - this._multisampleAutoDecreaseTime > 10
224
+ ) {
225
+ this._multisampleAutoChangeTime = this.context.time.realtimeSinceStartup;
226
+ let newMultiSample = this._postprocessing.multisampling <= 0 ? 1 : this._postprocessing.multisampling * 2;
227
+ newMultiSample = Math.floor(newMultiSample);
228
+ if (newMultiSample !== this._postprocessing.multisampling) {
229
+ this._postprocessing.multisampling = newMultiSample;
230
+ }
231
+ if (debug) console.debug(`[PostProcessing] Increased multisampling from ${prev} to ${this._postprocessing.multisampling}`);
232
+ }
214
233
  }
215
234
  }
216
235
  }
217
236
  else {
218
- composer.multisampling = Math.max(0, Math.min(this.multisampling, this.context.renderer.capabilities.maxSamples));
237
+ const newMultiSample = Math.max(0, Math.min(this.multisampling, this.context.renderer.capabilities.maxSamples));
238
+ if (newMultiSample !== this._postprocessing.multisampling)
239
+ this._postprocessing.multisampling = newMultiSample;
219
240
  }
220
241
 
221
242
  // only set the main camera if any pass has a different camera
@@ -244,7 +265,7 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
244
265
  private _isDirty: boolean = false;
245
266
 
246
267
  private apply() {
247
- if (debug) console.log(`Apply PostProcessing "${this.name}"`);
268
+ if (debug) console.log(`Apply PostProcessing "${this.name || "unnamed"}"`);
248
269
 
249
270
  if (isDevEnvironment()) {
250
271
  if (this._lastApplyTime !== undefined && Date.now() - this._lastApplyTime < 100) {
@@ -256,7 +277,6 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
256
277
  }
257
278
 
258
279
  this._isDirty = false;
259
- this.unapply();
260
280
 
261
281
  this._activeEffects.length = 0;
262
282
  // get from profile
@@ -283,32 +303,28 @@ export class Volume extends Behaviour implements IEditorModificationReceiver, IP
283
303
 
284
304
  this._applyPostQueue();
285
305
 
286
- const composer = this._postprocessing?.composer;
287
- if (composer) {
306
+ if (this._postprocessing) {
288
307
  if (this.multisampling === "auto") {
289
- composer.multisampling = DeviceUtilities.isMobileDevice()
308
+ this._postprocessing.multisampling = DeviceUtilities.isMobileDevice()
290
309
  ? 2
291
310
  : 4;
292
311
  }
293
312
  else {
294
- composer.multisampling = Math.max(0, Math.min(this.multisampling, this.context.renderer.capabilities.maxSamples));
313
+ this._postprocessing.multisampling = Math.max(0, Math.min(this.multisampling, this.context.renderer.capabilities.maxSamples));
295
314
  }
296
- if (debug) console.debug(`[PostProcessing] Set multisampling to ${composer.multisampling} (Is Mobile: ${DeviceUtilities.isMobileDevice()})`);
315
+ if (debug) console.debug(`[PostProcessing] Set multisampling to ${this._postprocessing.multisampling} (Is Mobile: ${DeviceUtilities.isMobileDevice()})`);
297
316
  }
298
317
  else if (debug) {
299
318
  console.warn(`[PostProcessing] No composer found`);
300
319
  }
301
320
  })
302
-
321
+ }
322
+ else {
323
+ this._postprocessing?.unapply(false);
303
324
  }
304
325
 
305
326
  }
306
327
 
307
- private unapply() {
308
- this._postprocessing?.unapply();
309
- }
310
-
311
-
312
328
  private _applyPostQueue() {
313
329
  if (this._modificationQueue) {
314
330
  for (const entry of this._modificationQueue.values()) this.onEditorModification(entry);
@@ -1,5 +1,6 @@
1
1
  export * from "./PostProcessingEffect.js";
2
2
  export * from "./PostProcessingHandler.js"
3
+ export { PostProcessingEffectOrder } from "./utils.js";
3
4
  export { PostProcessingManager } from "./Volume.js"
4
5
  export * from "./VolumeParameter.js"
5
- export * from "./VolumeProfile.js";
6
+ export * from "./VolumeProfile.js";
@@ -1,9 +1,11 @@
1
+ import type { Effect, Pass } from "postprocessing";
1
2
  import { Object3D } from "three";
2
3
 
3
4
  import { isDevEnvironment } from "../../engine/debug/index.js";
4
5
  import { addComponent } from "../../engine/engine_components.js";
5
6
  import { foreachComponentEnumerator } from "../../engine/engine_gameobject.js";
6
- import { ConstructorConcrete, IComponent } from "../../engine/engine_types.js";
7
+ import { MODULES } from "../../engine/engine_modules.js";
8
+ import { Constructor, ConstructorConcrete, IComponent } from "../../engine/engine_types.js";
7
9
  import { getParam } from "../../engine/engine_utils.js";
8
10
  import { type PostProcessingEffect } from "./PostProcessingEffect.js";
9
11
 
@@ -11,6 +13,8 @@ export const debug = getParam("debugpost");
11
13
 
12
14
  export type IPostProcessingManager = IComponent & {
13
15
  get isPostProcessingManager(): boolean;
16
+ get dirty(): boolean;
17
+ set dirty(value: boolean);
14
18
  addEffect(effect: PostProcessingEffect): void;
15
19
  removeEffect(effect: PostProcessingEffect): void;
16
20
  }
@@ -50,4 +54,101 @@ export function getPostProcessingManager(effect: PostProcessingEffect): IPostPro
50
54
  }
51
55
  }
52
56
  return manager;
53
- }
57
+ }
58
+
59
+
60
+
61
+ export type PostprocessingEffectData = {
62
+ effect: Effect | Pass;
63
+ priority?: number,
64
+ typeName?: string | null | undefined,
65
+ }
66
+
67
+ /**
68
+ * Default order for post-processing effects. This can be used to sort effects by their rendering order when creating custom effects.
69
+ * E.g. in your custom effect, you can set `order: PostProcessingEffectOrder.Bloom + 1;` to ensure it gets rendered after the bloom effect.
70
+ * OR `order: PostProcessingEffectOrder.Bloom - 1;` to ensure it gets rendered before the bloom effect.
71
+ * @example
72
+ * ```typescript
73
+ * import { PostProcessingEffectOrder } from "@needle-tools/engine"
74
+ *
75
+ * export class MyCustomEffect extends PostProcessingEffect {
76
+ * order: PostProcessingEffectPriority.Bloom + 1; // render after bloom
77
+ *
78
+ * // ... your effect code
79
+ * }
80
+ * ```
81
+ */
82
+ export const PostProcessingEffectOrder = {
83
+ /** Used to render effects at the start of the post-processing chain */
84
+ AT_START: -10_000,
85
+
86
+ NormalPass: 0,
87
+ DepthDownsamplingPass: 10,
88
+ SSAO: 20,
89
+ SMAA: 30,
90
+ TiltShift: 40,
91
+ DepthOfField: 50,
92
+ ChromaticAberration: 60,
93
+ Bloom: 70,
94
+ Vignette: 80,
95
+ Pixelation: 90,
96
+ ToneMapping: 100,
97
+ HueSaturation: 110,
98
+ BrightnessContrast: 120,
99
+ Sharpening: 130,
100
+
101
+ /** Used to render effects at the end of the post-processing chain, e.g. for final adjustments or overlays. */
102
+ AT_END: 10_000,
103
+ }
104
+ // let effectsOrder: Array<Constructor<Effect | Pass>> | null = null;
105
+
106
+ let builtinOrder: Map<Constructor<Effect | Pass>, number> | null = null;
107
+
108
+ export function orderEffects(effects: Array<PostprocessingEffectData>) {
109
+ if (debug === "verbose") console.debug("Before ordering effects", [...effects]);
110
+
111
+ if (!builtinOrder) {
112
+ builtinOrder = new Map<Constructor<Effect | Pass>, number>();
113
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.NormalPass, PostProcessingEffectOrder.NormalPass);
114
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.DepthDownsamplingPass, PostProcessingEffectOrder.DepthDownsamplingPass);
115
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SMAAEffect, PostProcessingEffectOrder.SMAA);
116
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SSAOEffect, PostProcessingEffectOrder.SSAO);
117
+ builtinOrder.set(MODULES.POSTPROCESSING_AO.MODULE.N8AOPostPass, PostProcessingEffectOrder.SSAO);
118
+ builtinOrder.set(MODULES.POSTPROCESSING_AO.MODULE.N8AOPass, PostProcessingEffectOrder.SSAO);
119
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.TiltShiftEffect, PostProcessingEffectOrder.TiltShift);
120
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.DepthOfFieldEffect, PostProcessingEffectOrder.DepthOfField);
121
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.ChromaticAberrationEffect, PostProcessingEffectOrder.ChromaticAberration);
122
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.BloomEffect, PostProcessingEffectOrder.Bloom);
123
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.SelectiveBloomEffect, PostProcessingEffectOrder.Bloom);
124
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.VignetteEffect, PostProcessingEffectOrder.Vignette);
125
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.PixelationEffect, PostProcessingEffectOrder.Pixelation);
126
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.ToneMappingEffect, PostProcessingEffectOrder.ToneMapping);
127
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.HueSaturationEffect, PostProcessingEffectOrder.HueSaturation);
128
+ builtinOrder.set(MODULES.POSTPROCESSING.MODULE.BrightnessContrastEffect, PostProcessingEffectOrder.BrightnessContrast);
129
+ }
130
+
131
+ // enforce correct order of effects (e.g. DOF before Bloom)
132
+ effects.sort((a, b) => {
133
+ // we use find index here because sometimes constructor names are prefixed with `_`
134
+ // TODO: find a more robust solution that isnt name based (not sure if that exists tho... maybe we must give effect TYPES some priority/index)
135
+ const aidx = typeof a.priority === "number" ? a.priority : builtinOrder!.get(a.effect.constructor as Constructor<Effect | Pass>) ?? Number.NEGATIVE_INFINITY;
136
+ const bidx = typeof b.priority === "number" ? b.priority : builtinOrder!.get(b.effect.constructor as Constructor<Effect | Pass>) ?? Number.NEGATIVE_INFINITY;
137
+
138
+ // Unknown effects should be rendered first
139
+ if (aidx === Number.NEGATIVE_INFINITY) {
140
+ if (debug) console.warn("Unknown effect found: ", a.constructor.name, a);
141
+ return 1;
142
+ }
143
+ else if (bidx === Number.NEGATIVE_INFINITY) {
144
+ if (debug) console.warn("Unknown effect found: ", b.constructor.name, b);
145
+ return -1;
146
+ }
147
+ return aidx - bidx;
148
+ });
149
+
150
+
151
+ if (debug === "verbose") console.debug("After ordering effects", [...effects]);
152
+ }
153
+
154
+