@babylonjs/core 9.8.0 → 9.9.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 (103) hide show
  1. package/Audio/audioSceneComponent.pure.js +17 -9
  2. package/Bones/bone.pure.js +39 -29
  3. package/Cameras/arcRotateCamera.pure.d.ts +0 -8
  4. package/Cameras/arcRotateCamera.pure.js +0 -12
  5. package/Cameras/arcRotateCamera.pure.js.map +1 -1
  6. package/Cameras/inputMapper.d.ts +29 -8
  7. package/Cameras/inputMapper.js +63 -10
  8. package/Cameras/inputMapper.js.map +1 -1
  9. package/Cameras/targetCamera.pure.js +40 -27
  10. package/Culling/Helper/transformFeedbackBoundingHelper.pure.js +17 -23
  11. package/Engines/abstractEngine.pure.js +4 -4
  12. package/Engines/abstractEngine.pure.js.map +1 -1
  13. package/Engines/thinEngine.pure.js +234 -280
  14. package/Materials/Background/backgroundMaterial.pure.js +5 -4
  15. package/Materials/Background/backgroundMaterial.pure.js.map +1 -1
  16. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.d.ts +5 -0
  17. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js +8 -0
  18. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js.map +1 -0
  19. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.d.ts +278 -0
  20. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js +718 -0
  21. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js.map +1 -0
  22. package/Materials/GaussianSplatting/pure.d.ts +1 -0
  23. package/Materials/GaussianSplatting/pure.js +1 -0
  24. package/Materials/GaussianSplatting/pure.js.map +1 -1
  25. package/Materials/Node/Blocks/Dual/imageSourceBlock.pure.js +10 -14
  26. package/Materials/Node/Blocks/Dual/index.d.ts +0 -14
  27. package/Materials/Node/Blocks/Dual/index.js +0 -18
  28. package/Materials/Node/Blocks/Dual/index.js.map +1 -1
  29. package/Materials/Node/Blocks/Dual/textureBlock.pure.js +660 -662
  30. package/Materials/Node/Blocks/Fragment/index.d.ts +0 -10
  31. package/Materials/Node/Blocks/Fragment/index.js +0 -13
  32. package/Materials/Node/Blocks/Fragment/index.js.map +1 -1
  33. package/Materials/Node/Blocks/GaussianSplatting/index.d.ts +12 -0
  34. package/Materials/Node/Blocks/GaussianSplatting/index.js +14 -1
  35. package/Materials/Node/Blocks/GaussianSplatting/index.js.map +1 -1
  36. package/Materials/Node/Blocks/Vertex/index.d.ts +0 -8
  37. package/Materials/Node/Blocks/Vertex/index.js +0 -10
  38. package/Materials/Node/Blocks/Vertex/index.js.map +1 -1
  39. package/Materials/PBR/openpbrMaterial.pure.js +6 -5
  40. package/Materials/PBR/openpbrMaterial.pure.js.map +1 -1
  41. package/Materials/PBR/pbrBaseMaterial.pure.js +6 -5
  42. package/Materials/PBR/pbrBaseMaterial.pure.js.map +1 -1
  43. package/Materials/Textures/index.d.ts +1 -0
  44. package/Materials/Textures/index.js +1 -0
  45. package/Materials/Textures/index.js.map +1 -1
  46. package/Materials/Textures/internalTexture.js +7 -0
  47. package/Materials/Textures/internalTexture.js.map +1 -1
  48. package/Materials/Textures/texture.pure.js +157 -255
  49. package/Materials/index.d.ts +30 -0
  50. package/Materials/index.js +31 -0
  51. package/Materials/index.js.map +1 -1
  52. package/Materials/material.pure.js +128 -69
  53. package/Materials/pure.d.ts +1 -0
  54. package/Materials/pure.js +1 -0
  55. package/Materials/pure.js.map +1 -1
  56. package/Materials/standardMaterial.pure.js +6 -5
  57. package/Materials/standardMaterial.pure.js.map +1 -1
  58. package/Maths/math.color.pure.js +55 -47
  59. package/Maths/math.vector.pure.js +118 -242
  60. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.d.ts +7 -0
  61. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js +8 -0
  62. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js.map +1 -0
  63. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.d.ts +147 -0
  64. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js +257 -0
  65. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js.map +1 -0
  66. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +11 -0
  67. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +31 -0
  68. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
  69. package/Meshes/GaussianSplatting/pure.d.ts +1 -0
  70. package/Meshes/GaussianSplatting/pure.js +1 -0
  71. package/Meshes/GaussianSplatting/pure.js.map +1 -1
  72. package/Meshes/GreasedLine/greasedLineMesh.pure.js +9 -14
  73. package/Meshes/GreasedLine/greasedLineRibbonMesh.pure.js +26 -27
  74. package/Meshes/index.d.ts +1 -0
  75. package/Meshes/index.js +1 -0
  76. package/Meshes/index.js.map +1 -1
  77. package/Meshes/meshSimplification.common.d.ts +53 -0
  78. package/Meshes/meshSimplification.common.js +34 -0
  79. package/Meshes/meshSimplification.common.js.map +1 -0
  80. package/Meshes/meshSimplification.d.ts +3 -53
  81. package/Meshes/meshSimplification.js +1 -33
  82. package/Meshes/meshSimplification.js.map +1 -1
  83. package/Meshes/meshSimplificationSceneComponent.pure.js.map +1 -1
  84. package/Meshes/meshSimplificationSceneComponent.types.d.ts +2 -1
  85. package/Meshes/meshSimplificationSceneComponent.types.js.map +1 -1
  86. package/Meshes/pure.d.ts +1 -0
  87. package/Meshes/pure.js +1 -0
  88. package/Meshes/pure.js.map +1 -1
  89. package/Meshes/transformNode.pure.js +82 -44
  90. package/Misc/tools.pure.js +124 -186
  91. package/Misc/tools.pure.js.map +1 -1
  92. package/Physics/v1/physicsImpostor.pure.js +43 -37
  93. package/Shaders/ShadersInclude/gaussianSplatting.js +33 -10
  94. package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
  95. package/Shaders/gaussianSplatting.vertex.js +20 -1
  96. package/Shaders/gaussianSplatting.vertex.js.map +1 -1
  97. package/Shaders/picking.fragment.js +4 -1
  98. package/Shaders/picking.fragment.js.map +1 -1
  99. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +33 -10
  100. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
  101. package/ShadersWGSL/gaussianSplatting.vertex.js +21 -2
  102. package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
  103. package/package.json +3 -1
@@ -213,18 +213,39 @@ export declare class InputMapper<THandlers extends Record<string, unknown>> {
213
213
  */
214
214
  addEntry(entry: InputMapEntry<InteractionName<THandlers>>): void;
215
215
  /**
216
- * Changes the interaction for the first inputMap entry matching the given source and conditions.
217
- * This is the simplest way to remap a single input without rebuilding the entire inputMap.
216
+ * Sets the interaction for the input combination described by `conditions`. If an
217
+ * existing entry maps that exact combination, its `interaction` is updated in place;
218
+ * otherwise a new entry is inserted via {@link addEntry}.
218
219
  *
219
- * Note: only the first matching entry is updated. To update every matching entry use
220
- * {@link setInteractions}; to address an individual entry beyond the first, look it up via
221
- * {@link getEntries} and assign `entry.interaction` directly.
220
+ * To force an update on every matching entry use {@link setInteractions}; to address
221
+ * an individual entry beyond the first, look it up via {@link getEntries} and assign
222
+ * `entry.interaction` directly.
222
223
  * @param source - The physical input source to match
223
- * @param conditions - Conditions to match (button, modifiers, key, etc.)
224
- * @param interaction - The new interaction to assign to the matched entry
225
- * @returns true if a matching entry was found and updated, false otherwise
224
+ * @param conditions - Conditions describing the input combination (button, modifiers, key, etc.)
225
+ * @param interaction - The interaction to assign / insert
226
+ * @returns true (the mapping is always made effective)
226
227
  */
227
228
  setInteraction(source: InputSource, conditions: InputConditions | undefined, interaction: InteractionName<THandlers>): boolean;
229
+ /**
230
+ * Returns true when `entry` constrains every field that `conditions` specifies — i.e.
231
+ * `entry` covers all of the request's conditions. Used by {@link setInteraction} as one
232
+ * half of the "exactly as specific" check: combined with {@link resolveInteraction}'s
233
+ * guarantee that the returned entry is no *stricter* than the request, a true result
234
+ * here means `entry` and `conditions` constrain the same fields, and mutating
235
+ * `entry.interaction` is safe.
236
+ *
237
+ * On its own this predicate does not exclude entries that are stricter than `conditions`
238
+ * (those would also trivially cover every field present in `conditions`); callers must
239
+ * rely on the upstream resolve step to rule them out.
240
+ *
241
+ * `InputConditions` is a flat type covering all source-specific fields (`button`, `key`,
242
+ * `touchCount`, `modifiers`); for any given source the irrelevant fields are `undefined`
243
+ * on both `entry` and `conditions`, so checking them all is harmless.
244
+ * @param entry - The matched inputMap entry to test
245
+ * @param conditions - The conditions the caller supplied to `setInteraction`
246
+ * @returns true if `entry` covers every condition present in `conditions`
247
+ */
248
+ private _entryCoversAllConditionsOf;
228
249
  /**
229
250
  * Changes the interaction for every inputMap entry matching the given source and conditions.
230
251
  * Useful when more than one entry maps to the same physical input (e.g. duplicate bindings,
@@ -89,24 +89,77 @@ export class InputMapper {
89
89
  this.inputMap.splice(insertIndex, 0, entry);
90
90
  }
91
91
  /**
92
- * Changes the interaction for the first inputMap entry matching the given source and conditions.
93
- * This is the simplest way to remap a single input without rebuilding the entire inputMap.
92
+ * Sets the interaction for the input combination described by `conditions`. If an
93
+ * existing entry maps that exact combination, its `interaction` is updated in place;
94
+ * otherwise a new entry is inserted via {@link addEntry}.
94
95
  *
95
- * Note: only the first matching entry is updated. To update every matching entry use
96
- * {@link setInteractions}; to address an individual entry beyond the first, look it up via
97
- * {@link getEntries} and assign `entry.interaction` directly.
96
+ * To force an update on every matching entry use {@link setInteractions}; to address
97
+ * an individual entry beyond the first, look it up via {@link getEntries} and assign
98
+ * `entry.interaction` directly.
98
99
  * @param source - The physical input source to match
99
- * @param conditions - Conditions to match (button, modifiers, key, etc.)
100
- * @param interaction - The new interaction to assign to the matched entry
101
- * @returns true if a matching entry was found and updated, false otherwise
100
+ * @param conditions - Conditions describing the input combination (button, modifiers, key, etc.)
101
+ * @param interaction - The interaction to assign / insert
102
+ * @returns true (the mapping is always made effective)
102
103
  */
103
104
  setInteraction(source, conditions, interaction) {
105
+ // resolveInteraction returns the first entry that fires for `conditions` (so its
106
+ // conditions are no stricter than the request). If that entry also covers every
107
+ // condition present in the request, it's an exact match — mutate. Otherwise it's
108
+ // broader (or nothing matches): add a more-specific entry so we don't clobber the
109
+ // broader one.
104
110
  const entry = this.resolveInteraction(source, conditions);
105
- if (entry) {
111
+ if (entry && this._entryCoversAllConditionsOf(entry, conditions)) {
106
112
  entry.interaction = interaction;
107
113
  return true;
108
114
  }
109
- return false;
115
+ this.addEntry({ source, ...(conditions ?? {}), interaction });
116
+ return true;
117
+ }
118
+ /**
119
+ * Returns true when `entry` constrains every field that `conditions` specifies — i.e.
120
+ * `entry` covers all of the request's conditions. Used by {@link setInteraction} as one
121
+ * half of the "exactly as specific" check: combined with {@link resolveInteraction}'s
122
+ * guarantee that the returned entry is no *stricter* than the request, a true result
123
+ * here means `entry` and `conditions` constrain the same fields, and mutating
124
+ * `entry.interaction` is safe.
125
+ *
126
+ * On its own this predicate does not exclude entries that are stricter than `conditions`
127
+ * (those would also trivially cover every field present in `conditions`); callers must
128
+ * rely on the upstream resolve step to rule them out.
129
+ *
130
+ * `InputConditions` is a flat type covering all source-specific fields (`button`, `key`,
131
+ * `touchCount`, `modifiers`); for any given source the irrelevant fields are `undefined`
132
+ * on both `entry` and `conditions`, so checking them all is harmless.
133
+ * @param entry - The matched inputMap entry to test
134
+ * @param conditions - The conditions the caller supplied to `setInteraction`
135
+ * @returns true if `entry` covers every condition present in `conditions`
136
+ */
137
+ _entryCoversAllConditionsOf(entry, conditions) {
138
+ if (!conditions) {
139
+ return true;
140
+ }
141
+ // `as any` here because `entry` is a discriminated union and TypeScript can't narrow it
142
+ // from a string-keyed loop. The runtime check is harmless: irrelevant-for-this-source
143
+ // fields are undefined on both entry and conditions and skip the early return.
144
+ const e = entry;
145
+ for (const key of Object.keys(conditions)) {
146
+ const condValue = conditions[key];
147
+ if (condValue === undefined) {
148
+ continue;
149
+ }
150
+ if (key === "modifiers") {
151
+ const entryMods = (e.modifiers ?? {});
152
+ for (const modKey of Object.keys(condValue)) {
153
+ if (condValue[modKey] !== undefined && entryMods[modKey] === undefined) {
154
+ return false;
155
+ }
156
+ }
157
+ }
158
+ else if (e[key] === undefined) {
159
+ return false;
160
+ }
161
+ }
162
+ return true;
110
163
  }
111
164
  /**
112
165
  * Changes the interaction for every inputMap entry matching the given source and conditions.
@@ -1 +1 @@
1
- {"version":3,"file":"inputMapper.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/inputMapper.ts"],"names":[],"mappings":"AAAA,6DAA6D;AA6J7D;;;;;;;;;;;;;;;GAeG;AACH,gEAAgE;AAChE,MAAM,OAAO,WAAW;IAYpB;;;;;OAKG;IACH,YAAY,QAAmB,EAAE,oBAAwE;QAjBzG;;WAEG;QACI,aAAQ,GAAgD,EAAE,CAAC;QAe9D,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAClD,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAgBM,kBAAkB,CAAC,MAAmB,EAAE,iBAAmC;QAC9E,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAChC,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,iBAAiB,CAAC,EAAE,CAAC;gBAC1E,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;;OAGG;IACI,aAAa;QAChB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,CAAC;IACzD,CAAC;IAeM,QAAQ,CAAC,MAAmB,EAAE,WAAuC,EAAE,UAA4B;QACtG,sFAAsF;QACtF,+DAA+D;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACjB,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW,IAAI,IAAI,CAAC,qBAAqB,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC;gBACpG,OAAO,CAAC,CAAC;YACb,CAAC;QACL,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IAeM,UAAU,CAAC,MAAmB,EAAE,WAAuC,EAAE,UAA4B;QACxG,MAAM,OAAO,GAAgD,EAAE,CAAC;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACjB,IAAI,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,WAAW,KAAK,WAAW,IAAI,IAAI,CAAC,qBAAqB,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,CAAC;gBACpG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,CAAC;QACL,CAAC;QACD,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;;;;OAMG;IACI,QAAQ,CAAC,KAAgD;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC5C,IAAI,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC;gBACnD,WAAW,GAAG,CAAC,CAAC;gBAChB,MAAM;YACV,CAAC;QACL,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IAED;;;;;;;;;;;OAWG;IACI,cAAc,CAAC,MAAmB,EAAE,UAAuC,EAAE,WAAuC;QACvH,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC1D,IAAI,KAAK,EAAE,CAAC;YACR,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;YAChC,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAED;;;;;;;;;;OAUG;IACI,eAAe,CAAC,MAAmB,EAAE,UAAuC,EAAE,WAAuC;QACxH,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAClC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,IAAI,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC,EAAE,CAAC;gBACnE,KAAK,CAAC,WAAW,GAAG,WAAW,CAAC;gBAChC,KAAK,EAAE,CAAC;YACZ,CAAC;QACL,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,aAAa,CAAC,KAAgD,EAAE,iBAAmC;QACvG,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,SAAS;gBACV,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,iBAAiB,EAAE,MAAM,EAAE,CAAC;oBAC3E,OAAO,KAAK,CAAC;gBACjB,CAAC;gBACD,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;YAC/E,KAAK,OAAO;gBACR,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;YAC/E,KAAK,OAAO;gBACR,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,IAAI,KAAK,CAAC,UAAU,KAAK,iBAAiB,EAAE,UAAU,EAAE,CAAC;oBACvF,OAAO,KAAK,CAAC;gBACjB,CAAC;gBACD,OAAO,IAAI,CAAC;YAChB,KAAK,UAAU;gBACX,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;oBAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,iBAAiB,EAAE,GAAG,EAAE,CAAC;wBAC3H,OAAO,KAAK,CAAC;oBACjB,CAAC;gBACL,CAAC;gBACD,OAAO,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,SAAS,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;QACnF,CAAC;IACL,CAAC;IAEO,qBAAqB,CAAC,KAAgD,EAAE,UAA4B;QACxG,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,uFAAuF;QACvF,uEAAuE;QACvE,gFAAgF;QAChF,iFAAiF;QACjF,mFAAmF;QACnF,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;YACnB,KAAK,SAAS;gBACV,IAAI,QAAQ,IAAI,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,UAAU,CAAC,MAAM,EAAE,CAAC;oBAC/D,OAAO,KAAK,CAAC;gBACjB,CAAC;gBACD,OAAO,CAAC,CAAC,WAAW,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;YAC5G,KAAK,OAAO;gBACR,OAAO,CAAC,CAAC,WAAW,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;YAC5G,KAAK,OAAO;gBACR,OAAO,CAAC,CAAC,YAAY,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,UAAU,KAAK,UAAU,CAAC,UAAU,CAAC;YACvF,KAAK,UAAU;gBACX,IAAI,KAAK,IAAI,UAAU,EAAE,CAAC;oBACtB,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;wBAC1B,OAAO,UAAU,CAAC,GAAG,KAAK,SAAS,CAAC;oBACxC,CAAC;oBACD,IAAI,UAAU,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,KAAK,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;wBACvI,OAAO,KAAK,CAAC;oBACjB,CAAC;gBACL,CAAC;gBACD,OAAO,CAAC,CAAC,WAAW,IAAI,UAAU,CAAC,IAAI,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;QAChH,CAAC;IACL,CAAC;IAEO,iBAAiB,CAAC,KAAgD;QACtE,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,QAAQ,IAAI,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAClD,KAAK,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,KAAK,IAAI,KAAK,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YAC5C,KAAK,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,YAAY,IAAI,KAAK,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1D,KAAK,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,WAAW,IAAI,KAAK,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YAC1C,KAAK,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,KAAK,CAAC;IACjB,CAAC;IAEO,eAAe,CAAC,cAA+B,EAAE,gBAAiC;QACtF,IAAI,CAAC,cAAc,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,IAAI,cAAc,CAAC,IAAI,KAAK,SAAS,IAAI,cAAc,CAAC,IAAI,KAAK,CAAC,gBAAgB,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACjG,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,cAAc,CAAC,KAAK,KAAK,SAAS,IAAI,cAAc,CAAC,KAAK,KAAK,CAAC,gBAAgB,EAAE,KAAK,IAAI,KAAK,CAAC,EAAE,CAAC;YACpG,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,cAAc,CAAC,GAAG,KAAK,SAAS,IAAI,cAAc,CAAC,GAAG,KAAK,CAAC,gBAAgB,EAAE,GAAG,IAAI,KAAK,CAAC,EAAE,CAAC;YAC9F,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAEO,oBAAoB,CAAC,cAA+B,EAAE,mBAAoC;QAC9F,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACvB,OAAO,CAAC,cAAc,CAAC;QAC3B,CAAC;QAED,MAAM,qBAAqB,GAAG,mBAAmB,CAAC,IAAI,KAAK,SAAS,IAAI,mBAAmB,CAAC,KAAK,KAAK,SAAS,IAAI,mBAAmB,CAAC,GAAG,KAAK,SAAS,CAAC;QACzJ,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACzB,OAAO,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK,SAAS,IAAI,cAAc,CAAC,KAAK,KAAK,SAAS,IAAI,cAAc,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC;QAC5I,CAAC;QAED,IAAI,mBAAmB,CAAC,IAAI,KAAK,SAAS,IAAI,cAAc,EAAE,IAAI,KAAK,mBAAmB,CAAC,IAAI,EAAE,CAAC;YAC9F,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,mBAAmB,CAAC,KAAK,KAAK,SAAS,IAAI,cAAc,EAAE,KAAK,KAAK,mBAAmB,CAAC,KAAK,EAAE,CAAC;YACjG,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,mBAAmB,CAAC,GAAG,KAAK,SAAS,IAAI,cAAc,EAAE,GAAG,KAAK,mBAAmB,CAAC,GAAG,EAAE,CAAC;YAC3F,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ","sourcesContent":["/** This file must only contain pure code and pure imports */\r\n\r\n/**\r\n * Physical input source that generated an interaction.\r\n */\r\nexport type InputSource = \"pointer\" | \"wheel\" | \"touch\" | \"keyboard\";\r\n\r\n/**\r\n * Modifier key state, shared across input sources that support modifiers.\r\n */\r\nexport type InputModifiers = {\r\n /** Ctrl key pressed */\r\n ctrl?: boolean;\r\n /** Shift key pressed */\r\n shift?: boolean;\r\n /** Alt key pressed */\r\n alt?: boolean;\r\n};\r\n\r\n// ── Per-source condition shapes ────────────────────────────────────\r\n\r\n/**\r\n * Conditions for pointer inputs.\r\n */\r\nexport type PointerConditions = {\r\n /** Mouse button (0=left, 1=middle, 2=right). Omit to match any button. */\r\n button?: number;\r\n /** Modifier key state. Only specified keys are checked; omitted = don't-care. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n/**\r\n * Conditions for mouse wheel inputs.\r\n */\r\nexport type WheelConditions = {\r\n /** Modifier key state. Only specified keys are checked; omitted = don't-care. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n/**\r\n * Conditions for touch inputs.\r\n */\r\nexport type TouchConditions = {\r\n /** Number of active touch points. Omit to match any count. */\r\n touchCount?: number;\r\n};\r\n\r\n/**\r\n * Conditions for keyboard inputs.\r\n */\r\nexport type KeyboardConditions = {\r\n /** Key code of the current key being resolved. Omit to match any key. */\r\n key?: number;\r\n /** Modifier key state. Only specified keys are checked; omitted = don't-care. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n// ── Per-source inputMap entry types ────────────────────────────────\r\n\r\n/**\r\n * Mapping rule for pointer (mouse button) inputs.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type PointerInputMapEntry<TInteraction extends string = string> = {\r\n source: \"pointer\";\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n /** Optional per-axis override for the X (horizontal / yaw) component. Falls back to `sensitivity` if unset. */\r\n sensitivityX?: number;\r\n /** Optional per-axis override for the Y (vertical / pitch) component. Falls back to `sensitivity` if unset. */\r\n sensitivityY?: number;\r\n} & PointerConditions;\r\n\r\n/**\r\n * Mapping rule for mouse wheel inputs.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type WheelInputMapEntry<TInteraction extends string = string> = {\r\n source: \"wheel\";\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n} & WheelConditions;\r\n\r\n/**\r\n * Mapping rule for touch inputs.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type TouchInputMapEntry<TInteraction extends string = string> = {\r\n source: \"touch\";\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n /** Optional per-axis override for the X component. Falls back to `sensitivity` if unset. */\r\n sensitivityX?: number;\r\n /** Optional per-axis override for the Y component. Falls back to `sensitivity` if unset. */\r\n sensitivityY?: number;\r\n} & TouchConditions;\r\n\r\n/**\r\n * Mapping rule for keyboard inputs.\r\n * The `key` field on the entry supports a single key code or an array of key codes for matching.\r\n * When resolving, the condition's `key` is checked against the entry's `key` value(s).\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type KeyboardInputMapEntry<TInteraction extends string = string> = {\r\n /** Discriminator: keyboard input source */\r\n source: \"keyboard\";\r\n /** Interaction type to dispatch when this entry matches */\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n /** Key code filter(s). Supports a single code or an array. Omit to match any key. */\r\n key?: number | number[];\r\n /** Modifier keys that must be active for this entry to match. Omit to match regardless of modifiers. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n/**\r\n * A single mapping rule: source + optional conditions → interaction type.\r\n * The inputMap is an ordered array on the movement class; first matching entry wins.\r\n * The interaction string should match a handler property name on the camera's movement subclass.\r\n *\r\n * Discriminated union by `source` — only fields relevant to that source are available.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type InputMapEntry<TInteraction extends string = string> =\r\n | PointerInputMapEntry<TInteraction>\r\n | WheelInputMapEntry<TInteraction>\r\n | TouchInputMapEntry<TInteraction>\r\n | KeyboardInputMapEntry<TInteraction>;\r\n\r\n/**\r\n * Flat conditions object passed to resolveInteraction().\r\n * Only the fields relevant to the source type need to be set.\r\n * Per-source condition types (PointerConditions, KeyboardConditions, etc.) are subtypes\r\n * of this and should be used at call sites for clarity.\r\n */\r\nexport type InputConditions = {\r\n /** Mouse button (0=left, 1=middle, 2=right) */\r\n button?: number;\r\n /** Current modifier key state */\r\n modifiers?: InputModifiers;\r\n /** Number of active touch points */\r\n touchCount?: number;\r\n /** Key code of the current key being resolved */\r\n key?: number;\r\n};\r\n\r\n/**\r\n * Extracts the string-typed interaction names from a handlers object type.\r\n * Equivalent to `keyof THandlers & string` — filters out symbol/number keys.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type InteractionName<THandlers> = keyof THandlers & string;\r\n\r\n/**\r\n * Generic input-to-interaction mapper that resolves physical input events to semantic interaction types\r\n * and dispatches them to typed handlers.\r\n *\r\n * `InputMapper` is not tied to cameras — any object that needs a configurable, prioritized\r\n * mapping from physical inputs (pointer, keyboard, wheel, touch) to named interactions can use it.\r\n *\r\n * The mapper holds an ordered `inputMap` array. When `resolveInteraction` is called, the first\r\n * entry whose source and conditions match the current input wins. More specific entries (with more\r\n * conditions like button, key, modifiers) should be placed before less specific ones; use `addEntry`\r\n * to auto-insert based on specificity.\r\n *\r\n * @typeParam THandlers - Object type whose keys are the valid interaction type strings and values\r\n * are the handler functions/objects for each interaction (e.g. `ArcRotateHandlers`).\r\n * Interaction types are derived as `InteractionName<THandlers>`.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class InputMapper<THandlers extends Record<string, unknown>> {\r\n /**\r\n * Ordered list of input-to-interaction mapping rules. First matching entry wins.\r\n */\r\n public inputMap: InputMapEntry<InteractionName<THandlers>>[] = [];\r\n\r\n /**\r\n * Interaction handlers keyed by interaction type.\r\n * Override individual handlers to customize behavior without changing input mapping.\r\n */\r\n public readonly handlers: THandlers;\r\n\r\n /**\r\n * Creates a new InputMapper.\r\n * @param handlers - The interaction handlers, keyed by interaction type.\r\n * @param createDefaultEntries - Optional factory that returns the default inputMap entries.\r\n * Called by `resetInputMap()` and during construction. When omitted, the default map is empty.\r\n */\r\n constructor(handlers: THandlers, createDefaultEntries?: () => InputMapEntry<InteractionName<THandlers>>[]) {\r\n this.handlers = handlers;\r\n this._createDefaultEntries = createDefaultEntries;\r\n this.resetInputMap();\r\n }\r\n\r\n private _createDefaultEntries?: () => InputMapEntry<InteractionName<THandlers>>[];\r\n\r\n /**\r\n * Resolves a physical input event to a matching inputMap entry.\r\n * Iterates the inputMap in order; the first entry whose source and conditions match wins.\r\n * @param source - The physical input source (e.g. \"pointer\", \"keyboard\")\r\n * @param currentConditions - Conditions to match against, specific to the source type\r\n * @returns The matched InputMapEntry, or null if no entry matches\r\n */\r\n public resolveInteraction(source: \"pointer\", currentConditions?: InputConditions): PointerInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: \"wheel\", currentConditions?: InputConditions): WheelInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: \"touch\", currentConditions?: InputConditions): TouchInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: \"keyboard\", currentConditions?: InputConditions): KeyboardInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: InputSource, currentConditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: InputSource, currentConditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | null {\r\n for (const entry of this.inputMap) {\r\n if (entry.source === source && this._entryMatches(entry, currentConditions)) {\r\n return entry;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Restores the inputMap to the default entries provided at construction time.\r\n * If no factory was provided, resets to an empty array.\r\n */\r\n public resetInputMap(): void {\r\n this.inputMap = this._createDefaultEntries?.() ?? [];\r\n }\r\n\r\n /**\r\n * Finds the first inputMap entry matching the given source, interaction, and optional entry conditions.\r\n * Useful for modifying entry properties (e.g. sensitivity) without rebuilding the entire inputMap.\r\n * @param source - The physical input source to match\r\n * @param interaction - The interaction type to match\r\n * @param conditions - Optional entry conditions to match. Omitted condition fields are ignored.\r\n * @returns The matching entry, or undefined if not found\r\n */\r\n public getEntry(source: \"pointer\", interaction: InteractionName<THandlers>, conditions?: PointerConditions): PointerInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: \"wheel\", interaction: InteractionName<THandlers>, conditions?: WheelConditions): WheelInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: \"touch\", interaction: InteractionName<THandlers>, conditions?: TouchConditions): TouchInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: \"keyboard\", interaction: InteractionName<THandlers>, conditions?: KeyboardConditions): KeyboardInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | undefined {\r\n // Manual loop instead of `inputMap.find(arrow)` to avoid per-call closure allocation;\r\n // this is hit per pointer-move from multi-touch panning paths.\r\n const arr = this.inputMap;\r\n for (let i = 0; i < arr.length; i++) {\r\n const e = arr[i];\r\n if (e.source === source && e.interaction === interaction && this._entryConditionsMatch(e, conditions)) {\r\n return e;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Finds all inputMap entries matching the given source, interaction, and optional entry conditions.\r\n * Useful for bulk updates when more than one physical input maps to the same interaction.\r\n * @param source - The physical input source to match\r\n * @param interaction - The interaction type to match\r\n * @param conditions - Optional entry conditions to match. Omitted condition fields are ignored.\r\n * @returns All matching entries, in inputMap order\r\n */\r\n public getEntries(source: \"pointer\", interaction: InteractionName<THandlers>, conditions?: PointerConditions): PointerInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: \"wheel\", interaction: InteractionName<THandlers>, conditions?: WheelConditions): WheelInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: \"touch\", interaction: InteractionName<THandlers>, conditions?: TouchConditions): TouchInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: \"keyboard\", interaction: InteractionName<THandlers>, conditions?: KeyboardConditions): KeyboardInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>>[] {\r\n const matches: InputMapEntry<InteractionName<THandlers>>[] = [];\r\n const arr = this.inputMap;\r\n for (let i = 0; i < arr.length; i++) {\r\n const e = arr[i];\r\n if (e.source === source && e.interaction === interaction && this._entryConditionsMatch(e, conditions)) {\r\n matches.push(e);\r\n }\r\n }\r\n return matches;\r\n }\r\n\r\n /**\r\n * Adds an entry to the inputMap at the correct position based on specificity.\r\n * More specific entries (with more conditions like button, key, modifiers) are placed\r\n * before less specific ones, ensuring they match first. Among equally specific entries,\r\n * the new entry is placed after existing ones.\r\n * @param entry - The entry to add\r\n */\r\n public addEntry(entry: InputMapEntry<InteractionName<THandlers>>): void {\r\n const score = this._entrySpecificity(entry);\r\n let insertIndex = this.inputMap.length;\r\n for (let i = 0; i < this.inputMap.length; i++) {\r\n if (this._entrySpecificity(this.inputMap[i]) < score) {\r\n insertIndex = i;\r\n break;\r\n }\r\n }\r\n this.inputMap.splice(insertIndex, 0, entry);\r\n }\r\n\r\n /**\r\n * Changes the interaction for the first inputMap entry matching the given source and conditions.\r\n * This is the simplest way to remap a single input without rebuilding the entire inputMap.\r\n *\r\n * Note: only the first matching entry is updated. To update every matching entry use\r\n * {@link setInteractions}; to address an individual entry beyond the first, look it up via\r\n * {@link getEntries} and assign `entry.interaction` directly.\r\n * @param source - The physical input source to match\r\n * @param conditions - Conditions to match (button, modifiers, key, etc.)\r\n * @param interaction - The new interaction to assign to the matched entry\r\n * @returns true if a matching entry was found and updated, false otherwise\r\n */\r\n public setInteraction(source: InputSource, conditions: InputConditions | undefined, interaction: InteractionName<THandlers>): boolean {\r\n const entry = this.resolveInteraction(source, conditions);\r\n if (entry) {\r\n entry.interaction = interaction;\r\n return true;\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Changes the interaction for every inputMap entry matching the given source and conditions.\r\n * Useful when more than one entry maps to the same physical input (e.g. duplicate bindings,\r\n * or several keys aliased to the same action) and all of them should be remapped together.\r\n * @param source - The physical input source to match\r\n * @param conditions - Conditions to match (button, modifiers, key, etc.). Uses the same\r\n * event-resolution semantics as {@link resolveInteraction}: omitted entry\r\n * condition fields are treated as wildcards and will match.\r\n * @param interaction - The new interaction to assign to every matched entry\r\n * @returns The number of entries that were updated\r\n */\r\n public setInteractions(source: InputSource, conditions: InputConditions | undefined, interaction: InteractionName<THandlers>): number {\r\n let count = 0;\r\n const arr = this.inputMap;\r\n for (let i = 0; i < arr.length; i++) {\r\n const entry = arr[i];\r\n if (entry.source === source && this._entryMatches(entry, conditions)) {\r\n entry.interaction = interaction;\r\n count++;\r\n }\r\n }\r\n return count;\r\n }\r\n\r\n private _entryMatches(entry: InputMapEntry<InteractionName<THandlers>>, currentConditions?: InputConditions): boolean {\r\n switch (entry.source) {\r\n case \"pointer\":\r\n if (entry.button !== undefined && entry.button !== currentConditions?.button) {\r\n return false;\r\n }\r\n return this._matchModifiers(entry.modifiers, currentConditions?.modifiers);\r\n case \"wheel\":\r\n return this._matchModifiers(entry.modifiers, currentConditions?.modifiers);\r\n case \"touch\":\r\n if (entry.touchCount !== undefined && entry.touchCount !== currentConditions?.touchCount) {\r\n return false;\r\n }\r\n return true;\r\n case \"keyboard\":\r\n if (entry.key !== undefined) {\r\n if (Array.isArray(entry.key) ? entry.key.indexOf(currentConditions?.key ?? -1) === -1 : entry.key !== currentConditions?.key) {\r\n return false;\r\n }\r\n }\r\n return this._matchModifiers(entry.modifiers, currentConditions?.modifiers);\r\n }\r\n }\r\n\r\n private _entryConditionsMatch(entry: InputMapEntry<InteractionName<THandlers>>, conditions?: InputConditions): boolean {\r\n if (!conditions) {\r\n return true;\r\n }\r\n\r\n // NOTE: Uses the `\"key\" in conditions` form rather than `conditions.key !== undefined`\r\n // so that callers can explicitly target entries with no constraint via\r\n // `getEntries({ button: undefined })` — i.e. \"find catch-all entries that don't\r\n // require a specific button\". `!== undefined` would silently ignore a deliberate\r\n // `undefined` and behave like the property was omitted, which would be wrong here.\r\n switch (entry.source) {\r\n case \"pointer\":\r\n if (\"button\" in conditions && entry.button !== conditions.button) {\r\n return false;\r\n }\r\n return !(\"modifiers\" in conditions) || this._entryModifiersMatch(entry.modifiers, conditions.modifiers);\r\n case \"wheel\":\r\n return !(\"modifiers\" in conditions) || this._entryModifiersMatch(entry.modifiers, conditions.modifiers);\r\n case \"touch\":\r\n return !(\"touchCount\" in conditions) || entry.touchCount === conditions.touchCount;\r\n case \"keyboard\":\r\n if (\"key\" in conditions) {\r\n if (entry.key === undefined) {\r\n return conditions.key === undefined;\r\n }\r\n if (conditions.key === undefined || (Array.isArray(entry.key) ? entry.key.indexOf(conditions.key) === -1 : entry.key !== conditions.key)) {\r\n return false;\r\n }\r\n }\r\n return !(\"modifiers\" in conditions) || this._entryModifiersMatch(entry.modifiers, conditions.modifiers);\r\n }\r\n }\r\n\r\n private _entrySpecificity(entry: InputMapEntry<InteractionName<THandlers>>): number {\r\n let score = 0;\r\n if (\"button\" in entry && entry.button !== undefined) {\r\n score++;\r\n }\r\n if (\"key\" in entry && entry.key !== undefined) {\r\n score++;\r\n }\r\n if (\"touchCount\" in entry && entry.touchCount !== undefined) {\r\n score++;\r\n }\r\n if (\"modifiers\" in entry && entry.modifiers) {\r\n score++;\r\n }\r\n return score;\r\n }\r\n\r\n private _matchModifiers(entryModifiers?: InputModifiers, currentModifiers?: InputModifiers): boolean {\r\n if (!entryModifiers) {\r\n return true;\r\n }\r\n if (entryModifiers.ctrl !== undefined && entryModifiers.ctrl !== (currentModifiers?.ctrl ?? false)) {\r\n return false;\r\n }\r\n if (entryModifiers.shift !== undefined && entryModifiers.shift !== (currentModifiers?.shift ?? false)) {\r\n return false;\r\n }\r\n if (entryModifiers.alt !== undefined && entryModifiers.alt !== (currentModifiers?.alt ?? false)) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n private _entryModifiersMatch(entryModifiers?: InputModifiers, conditionsModifiers?: InputModifiers): boolean {\r\n if (!conditionsModifiers) {\r\n return !entryModifiers;\r\n }\r\n\r\n const hasModifierConditions = conditionsModifiers.ctrl !== undefined || conditionsModifiers.shift !== undefined || conditionsModifiers.alt !== undefined;\r\n if (!hasModifierConditions) {\r\n return !entryModifiers || (entryModifiers.ctrl === undefined && entryModifiers.shift === undefined && entryModifiers.alt === undefined);\r\n }\r\n\r\n if (conditionsModifiers.ctrl !== undefined && entryModifiers?.ctrl !== conditionsModifiers.ctrl) {\r\n return false;\r\n }\r\n if (conditionsModifiers.shift !== undefined && entryModifiers?.shift !== conditionsModifiers.shift) {\r\n return false;\r\n }\r\n if (conditionsModifiers.alt !== undefined && entryModifiers?.alt !== conditionsModifiers.alt) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"inputMapper.js","sourceRoot":"","sources":["../../../../dev/core/src/Cameras/inputMapper.ts"],"names":[],"mappings":"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","sourcesContent":["/** This file must only contain pure code and pure imports */\r\n\r\n/**\r\n * Physical input source that generated an interaction.\r\n */\r\nexport type InputSource = \"pointer\" | \"wheel\" | \"touch\" | \"keyboard\";\r\n\r\n/**\r\n * Modifier key state, shared across input sources that support modifiers.\r\n */\r\nexport type InputModifiers = {\r\n /** Ctrl key pressed */\r\n ctrl?: boolean;\r\n /** Shift key pressed */\r\n shift?: boolean;\r\n /** Alt key pressed */\r\n alt?: boolean;\r\n};\r\n\r\n// ── Per-source condition shapes ────────────────────────────────────\r\n\r\n/**\r\n * Conditions for pointer inputs.\r\n */\r\nexport type PointerConditions = {\r\n /** Mouse button (0=left, 1=middle, 2=right). Omit to match any button. */\r\n button?: number;\r\n /** Modifier key state. Only specified keys are checked; omitted = don't-care. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n/**\r\n * Conditions for mouse wheel inputs.\r\n */\r\nexport type WheelConditions = {\r\n /** Modifier key state. Only specified keys are checked; omitted = don't-care. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n/**\r\n * Conditions for touch inputs.\r\n */\r\nexport type TouchConditions = {\r\n /** Number of active touch points. Omit to match any count. */\r\n touchCount?: number;\r\n};\r\n\r\n/**\r\n * Conditions for keyboard inputs.\r\n */\r\nexport type KeyboardConditions = {\r\n /** Key code of the current key being resolved. Omit to match any key. */\r\n key?: number;\r\n /** Modifier key state. Only specified keys are checked; omitted = don't-care. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n// ── Per-source inputMap entry types ────────────────────────────────\r\n\r\n/**\r\n * Mapping rule for pointer (mouse button) inputs.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type PointerInputMapEntry<TInteraction extends string = string> = {\r\n source: \"pointer\";\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n /** Optional per-axis override for the X (horizontal / yaw) component. Falls back to `sensitivity` if unset. */\r\n sensitivityX?: number;\r\n /** Optional per-axis override for the Y (vertical / pitch) component. Falls back to `sensitivity` if unset. */\r\n sensitivityY?: number;\r\n} & PointerConditions;\r\n\r\n/**\r\n * Mapping rule for mouse wheel inputs.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type WheelInputMapEntry<TInteraction extends string = string> = {\r\n source: \"wheel\";\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n} & WheelConditions;\r\n\r\n/**\r\n * Mapping rule for touch inputs.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type TouchInputMapEntry<TInteraction extends string = string> = {\r\n source: \"touch\";\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n /** Optional per-axis override for the X component. Falls back to `sensitivity` if unset. */\r\n sensitivityX?: number;\r\n /** Optional per-axis override for the Y component. Falls back to `sensitivity` if unset. */\r\n sensitivityY?: number;\r\n} & TouchConditions;\r\n\r\n/**\r\n * Mapping rule for keyboard inputs.\r\n * The `key` field on the entry supports a single key code or an array of key codes for matching.\r\n * When resolving, the condition's `key` is checked against the entry's `key` value(s).\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type KeyboardInputMapEntry<TInteraction extends string = string> = {\r\n /** Discriminator: keyboard input source */\r\n source: \"keyboard\";\r\n /** Interaction type to dispatch when this entry matches */\r\n interaction: TInteraction;\r\n /** Multiplier applied to input deltas before passing to the handler. Default is 1. */\r\n sensitivity?: number;\r\n /** Key code filter(s). Supports a single code or an array. Omit to match any key. */\r\n key?: number | number[];\r\n /** Modifier keys that must be active for this entry to match. Omit to match regardless of modifiers. */\r\n modifiers?: InputModifiers;\r\n};\r\n\r\n/**\r\n * A single mapping rule: source + optional conditions → interaction type.\r\n * The inputMap is an ordered array on the movement class; first matching entry wins.\r\n * The interaction string should match a handler property name on the camera's movement subclass.\r\n *\r\n * Discriminated union by `source` — only fields relevant to that source are available.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type InputMapEntry<TInteraction extends string = string> =\r\n | PointerInputMapEntry<TInteraction>\r\n | WheelInputMapEntry<TInteraction>\r\n | TouchInputMapEntry<TInteraction>\r\n | KeyboardInputMapEntry<TInteraction>;\r\n\r\n/**\r\n * Flat conditions object passed to resolveInteraction().\r\n * Only the fields relevant to the source type need to be set.\r\n * Per-source condition types (PointerConditions, KeyboardConditions, etc.) are subtypes\r\n * of this and should be used at call sites for clarity.\r\n */\r\nexport type InputConditions = {\r\n /** Mouse button (0=left, 1=middle, 2=right) */\r\n button?: number;\r\n /** Current modifier key state */\r\n modifiers?: InputModifiers;\r\n /** Number of active touch points */\r\n touchCount?: number;\r\n /** Key code of the current key being resolved */\r\n key?: number;\r\n};\r\n\r\n/**\r\n * Extracts the string-typed interaction names from a handlers object type.\r\n * Equivalent to `keyof THandlers & string` — filters out symbol/number keys.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport type InteractionName<THandlers> = keyof THandlers & string;\r\n\r\n/**\r\n * Generic input-to-interaction mapper that resolves physical input events to semantic interaction types\r\n * and dispatches them to typed handlers.\r\n *\r\n * `InputMapper` is not tied to cameras — any object that needs a configurable, prioritized\r\n * mapping from physical inputs (pointer, keyboard, wheel, touch) to named interactions can use it.\r\n *\r\n * The mapper holds an ordered `inputMap` array. When `resolveInteraction` is called, the first\r\n * entry whose source and conditions match the current input wins. More specific entries (with more\r\n * conditions like button, key, modifiers) should be placed before less specific ones; use `addEntry`\r\n * to auto-insert based on specificity.\r\n *\r\n * @typeParam THandlers - Object type whose keys are the valid interaction type strings and values\r\n * are the handler functions/objects for each interaction (e.g. `ArcRotateHandlers`).\r\n * Interaction types are derived as `InteractionName<THandlers>`.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/naming-convention\r\nexport class InputMapper<THandlers extends Record<string, unknown>> {\r\n /**\r\n * Ordered list of input-to-interaction mapping rules. First matching entry wins.\r\n */\r\n public inputMap: InputMapEntry<InteractionName<THandlers>>[] = [];\r\n\r\n /**\r\n * Interaction handlers keyed by interaction type.\r\n * Override individual handlers to customize behavior without changing input mapping.\r\n */\r\n public readonly handlers: THandlers;\r\n\r\n /**\r\n * Creates a new InputMapper.\r\n * @param handlers - The interaction handlers, keyed by interaction type.\r\n * @param createDefaultEntries - Optional factory that returns the default inputMap entries.\r\n * Called by `resetInputMap()` and during construction. When omitted, the default map is empty.\r\n */\r\n constructor(handlers: THandlers, createDefaultEntries?: () => InputMapEntry<InteractionName<THandlers>>[]) {\r\n this.handlers = handlers;\r\n this._createDefaultEntries = createDefaultEntries;\r\n this.resetInputMap();\r\n }\r\n\r\n private _createDefaultEntries?: () => InputMapEntry<InteractionName<THandlers>>[];\r\n\r\n /**\r\n * Resolves a physical input event to a matching inputMap entry.\r\n * Iterates the inputMap in order; the first entry whose source and conditions match wins.\r\n * @param source - The physical input source (e.g. \"pointer\", \"keyboard\")\r\n * @param currentConditions - Conditions to match against, specific to the source type\r\n * @returns The matched InputMapEntry, or null if no entry matches\r\n */\r\n public resolveInteraction(source: \"pointer\", currentConditions?: InputConditions): PointerInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: \"wheel\", currentConditions?: InputConditions): WheelInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: \"touch\", currentConditions?: InputConditions): TouchInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: \"keyboard\", currentConditions?: InputConditions): KeyboardInputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: InputSource, currentConditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | null;\r\n public resolveInteraction(source: InputSource, currentConditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | null {\r\n for (const entry of this.inputMap) {\r\n if (entry.source === source && this._entryMatches(entry, currentConditions)) {\r\n return entry;\r\n }\r\n }\r\n return null;\r\n }\r\n\r\n /**\r\n * Restores the inputMap to the default entries provided at construction time.\r\n * If no factory was provided, resets to an empty array.\r\n */\r\n public resetInputMap(): void {\r\n this.inputMap = this._createDefaultEntries?.() ?? [];\r\n }\r\n\r\n /**\r\n * Finds the first inputMap entry matching the given source, interaction, and optional entry conditions.\r\n * Useful for modifying entry properties (e.g. sensitivity) without rebuilding the entire inputMap.\r\n * @param source - The physical input source to match\r\n * @param interaction - The interaction type to match\r\n * @param conditions - Optional entry conditions to match. Omitted condition fields are ignored.\r\n * @returns The matching entry, or undefined if not found\r\n */\r\n public getEntry(source: \"pointer\", interaction: InteractionName<THandlers>, conditions?: PointerConditions): PointerInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: \"wheel\", interaction: InteractionName<THandlers>, conditions?: WheelConditions): WheelInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: \"touch\", interaction: InteractionName<THandlers>, conditions?: TouchConditions): TouchInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: \"keyboard\", interaction: InteractionName<THandlers>, conditions?: KeyboardConditions): KeyboardInputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | undefined;\r\n public getEntry(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>> | undefined {\r\n // Manual loop instead of `inputMap.find(arrow)` to avoid per-call closure allocation;\r\n // this is hit per pointer-move from multi-touch panning paths.\r\n const arr = this.inputMap;\r\n for (let i = 0; i < arr.length; i++) {\r\n const e = arr[i];\r\n if (e.source === source && e.interaction === interaction && this._entryConditionsMatch(e, conditions)) {\r\n return e;\r\n }\r\n }\r\n return undefined;\r\n }\r\n\r\n /**\r\n * Finds all inputMap entries matching the given source, interaction, and optional entry conditions.\r\n * Useful for bulk updates when more than one physical input maps to the same interaction.\r\n * @param source - The physical input source to match\r\n * @param interaction - The interaction type to match\r\n * @param conditions - Optional entry conditions to match. Omitted condition fields are ignored.\r\n * @returns All matching entries, in inputMap order\r\n */\r\n public getEntries(source: \"pointer\", interaction: InteractionName<THandlers>, conditions?: PointerConditions): PointerInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: \"wheel\", interaction: InteractionName<THandlers>, conditions?: WheelConditions): WheelInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: \"touch\", interaction: InteractionName<THandlers>, conditions?: TouchConditions): TouchInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: \"keyboard\", interaction: InteractionName<THandlers>, conditions?: KeyboardConditions): KeyboardInputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>>[];\r\n public getEntries(source: InputSource, interaction: InteractionName<THandlers>, conditions?: InputConditions): InputMapEntry<InteractionName<THandlers>>[] {\r\n const matches: InputMapEntry<InteractionName<THandlers>>[] = [];\r\n const arr = this.inputMap;\r\n for (let i = 0; i < arr.length; i++) {\r\n const e = arr[i];\r\n if (e.source === source && e.interaction === interaction && this._entryConditionsMatch(e, conditions)) {\r\n matches.push(e);\r\n }\r\n }\r\n return matches;\r\n }\r\n\r\n /**\r\n * Adds an entry to the inputMap at the correct position based on specificity.\r\n * More specific entries (with more conditions like button, key, modifiers) are placed\r\n * before less specific ones, ensuring they match first. Among equally specific entries,\r\n * the new entry is placed after existing ones.\r\n * @param entry - The entry to add\r\n */\r\n public addEntry(entry: InputMapEntry<InteractionName<THandlers>>): void {\r\n const score = this._entrySpecificity(entry);\r\n let insertIndex = this.inputMap.length;\r\n for (let i = 0; i < this.inputMap.length; i++) {\r\n if (this._entrySpecificity(this.inputMap[i]) < score) {\r\n insertIndex = i;\r\n break;\r\n }\r\n }\r\n this.inputMap.splice(insertIndex, 0, entry);\r\n }\r\n\r\n /**\r\n * Sets the interaction for the input combination described by `conditions`. If an\r\n * existing entry maps that exact combination, its `interaction` is updated in place;\r\n * otherwise a new entry is inserted via {@link addEntry}.\r\n *\r\n * To force an update on every matching entry use {@link setInteractions}; to address\r\n * an individual entry beyond the first, look it up via {@link getEntries} and assign\r\n * `entry.interaction` directly.\r\n * @param source - The physical input source to match\r\n * @param conditions - Conditions describing the input combination (button, modifiers, key, etc.)\r\n * @param interaction - The interaction to assign / insert\r\n * @returns true (the mapping is always made effective)\r\n */\r\n public setInteraction(source: InputSource, conditions: InputConditions | undefined, interaction: InteractionName<THandlers>): boolean {\r\n // resolveInteraction returns the first entry that fires for `conditions` (so its\r\n // conditions are no stricter than the request). If that entry also covers every\r\n // condition present in the request, it's an exact match — mutate. Otherwise it's\r\n // broader (or nothing matches): add a more-specific entry so we don't clobber the\r\n // broader one.\r\n const entry = this.resolveInteraction(source, conditions);\r\n if (entry && this._entryCoversAllConditionsOf(entry, conditions)) {\r\n entry.interaction = interaction;\r\n return true;\r\n }\r\n this.addEntry({ source, ...(conditions ?? {}), interaction } as InputMapEntry<InteractionName<THandlers>>);\r\n return true;\r\n }\r\n\r\n /**\r\n * Returns true when `entry` constrains every field that `conditions` specifies — i.e.\r\n * `entry` covers all of the request's conditions. Used by {@link setInteraction} as one\r\n * half of the \"exactly as specific\" check: combined with {@link resolveInteraction}'s\r\n * guarantee that the returned entry is no *stricter* than the request, a true result\r\n * here means `entry` and `conditions` constrain the same fields, and mutating\r\n * `entry.interaction` is safe.\r\n *\r\n * On its own this predicate does not exclude entries that are stricter than `conditions`\r\n * (those would also trivially cover every field present in `conditions`); callers must\r\n * rely on the upstream resolve step to rule them out.\r\n *\r\n * `InputConditions` is a flat type covering all source-specific fields (`button`, `key`,\r\n * `touchCount`, `modifiers`); for any given source the irrelevant fields are `undefined`\r\n * on both `entry` and `conditions`, so checking them all is harmless.\r\n * @param entry - The matched inputMap entry to test\r\n * @param conditions - The conditions the caller supplied to `setInteraction`\r\n * @returns true if `entry` covers every condition present in `conditions`\r\n */\r\n private _entryCoversAllConditionsOf(entry: InputMapEntry<InteractionName<THandlers>>, conditions?: InputConditions): boolean {\r\n if (!conditions) {\r\n return true;\r\n }\r\n // `as any` here because `entry` is a discriminated union and TypeScript can't narrow it\r\n // from a string-keyed loop. The runtime check is harmless: irrelevant-for-this-source\r\n // fields are undefined on both entry and conditions and skip the early return.\r\n const e = entry as any;\r\n for (const key of Object.keys(conditions) as (keyof InputConditions)[]) {\r\n const condValue = conditions[key];\r\n if (condValue === undefined) {\r\n continue;\r\n }\r\n if (key === \"modifiers\") {\r\n const entryMods = (e.modifiers ?? {}) as InputModifiers;\r\n for (const modKey of Object.keys(condValue) as (keyof InputModifiers)[]) {\r\n if ((condValue as InputModifiers)[modKey] !== undefined && entryMods[modKey] === undefined) {\r\n return false;\r\n }\r\n }\r\n } else if (e[key] === undefined) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n }\r\n\r\n /**\r\n * Changes the interaction for every inputMap entry matching the given source and conditions.\r\n * Useful when more than one entry maps to the same physical input (e.g. duplicate bindings,\r\n * or several keys aliased to the same action) and all of them should be remapped together.\r\n * @param source - The physical input source to match\r\n * @param conditions - Conditions to match (button, modifiers, key, etc.). Uses the same\r\n * event-resolution semantics as {@link resolveInteraction}: omitted entry\r\n * condition fields are treated as wildcards and will match.\r\n * @param interaction - The new interaction to assign to every matched entry\r\n * @returns The number of entries that were updated\r\n */\r\n public setInteractions(source: InputSource, conditions: InputConditions | undefined, interaction: InteractionName<THandlers>): number {\r\n let count = 0;\r\n const arr = this.inputMap;\r\n for (let i = 0; i < arr.length; i++) {\r\n const entry = arr[i];\r\n if (entry.source === source && this._entryMatches(entry, conditions)) {\r\n entry.interaction = interaction;\r\n count++;\r\n }\r\n }\r\n return count;\r\n }\r\n\r\n private _entryMatches(entry: InputMapEntry<InteractionName<THandlers>>, currentConditions?: InputConditions): boolean {\r\n switch (entry.source) {\r\n case \"pointer\":\r\n if (entry.button !== undefined && entry.button !== currentConditions?.button) {\r\n return false;\r\n }\r\n return this._matchModifiers(entry.modifiers, currentConditions?.modifiers);\r\n case \"wheel\":\r\n return this._matchModifiers(entry.modifiers, currentConditions?.modifiers);\r\n case \"touch\":\r\n if (entry.touchCount !== undefined && entry.touchCount !== currentConditions?.touchCount) {\r\n return false;\r\n }\r\n return true;\r\n case \"keyboard\":\r\n if (entry.key !== undefined) {\r\n if (Array.isArray(entry.key) ? entry.key.indexOf(currentConditions?.key ?? -1) === -1 : entry.key !== currentConditions?.key) {\r\n return false;\r\n }\r\n }\r\n return this._matchModifiers(entry.modifiers, currentConditions?.modifiers);\r\n }\r\n }\r\n\r\n private _entryConditionsMatch(entry: InputMapEntry<InteractionName<THandlers>>, conditions?: InputConditions): boolean {\r\n if (!conditions) {\r\n return true;\r\n }\r\n\r\n // NOTE: Uses the `\"key\" in conditions` form rather than `conditions.key !== undefined`\r\n // so that callers can explicitly target entries with no constraint via\r\n // `getEntries({ button: undefined })` — i.e. \"find catch-all entries that don't\r\n // require a specific button\". `!== undefined` would silently ignore a deliberate\r\n // `undefined` and behave like the property was omitted, which would be wrong here.\r\n switch (entry.source) {\r\n case \"pointer\":\r\n if (\"button\" in conditions && entry.button !== conditions.button) {\r\n return false;\r\n }\r\n return !(\"modifiers\" in conditions) || this._entryModifiersMatch(entry.modifiers, conditions.modifiers);\r\n case \"wheel\":\r\n return !(\"modifiers\" in conditions) || this._entryModifiersMatch(entry.modifiers, conditions.modifiers);\r\n case \"touch\":\r\n return !(\"touchCount\" in conditions) || entry.touchCount === conditions.touchCount;\r\n case \"keyboard\":\r\n if (\"key\" in conditions) {\r\n if (entry.key === undefined) {\r\n return conditions.key === undefined;\r\n }\r\n if (conditions.key === undefined || (Array.isArray(entry.key) ? entry.key.indexOf(conditions.key) === -1 : entry.key !== conditions.key)) {\r\n return false;\r\n }\r\n }\r\n return !(\"modifiers\" in conditions) || this._entryModifiersMatch(entry.modifiers, conditions.modifiers);\r\n }\r\n }\r\n\r\n private _entrySpecificity(entry: InputMapEntry<InteractionName<THandlers>>): number {\r\n let score = 0;\r\n if (\"button\" in entry && entry.button !== undefined) {\r\n score++;\r\n }\r\n if (\"key\" in entry && entry.key !== undefined) {\r\n score++;\r\n }\r\n if (\"touchCount\" in entry && entry.touchCount !== undefined) {\r\n score++;\r\n }\r\n if (\"modifiers\" in entry && entry.modifiers) {\r\n score++;\r\n }\r\n return score;\r\n }\r\n\r\n private _matchModifiers(entryModifiers?: InputModifiers, currentModifiers?: InputModifiers): boolean {\r\n if (!entryModifiers) {\r\n return true;\r\n }\r\n if (entryModifiers.ctrl !== undefined && entryModifiers.ctrl !== (currentModifiers?.ctrl ?? false)) {\r\n return false;\r\n }\r\n if (entryModifiers.shift !== undefined && entryModifiers.shift !== (currentModifiers?.shift ?? false)) {\r\n return false;\r\n }\r\n if (entryModifiers.alt !== undefined && entryModifiers.alt !== (currentModifiers?.alt ?? false)) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n private _entryModifiersMatch(entryModifiers?: InputModifiers, conditionsModifiers?: InputModifiers): boolean {\r\n if (!conditionsModifiers) {\r\n return !entryModifiers;\r\n }\r\n\r\n const hasModifierConditions = conditionsModifiers.ctrl !== undefined || conditionsModifiers.shift !== undefined || conditionsModifiers.alt !== undefined;\r\n if (!hasModifierConditions) {\r\n return !entryModifiers || (entryModifiers.ctrl === undefined && entryModifiers.shift === undefined && entryModifiers.alt === undefined);\r\n }\r\n\r\n if (conditionsModifiers.ctrl !== undefined && entryModifiers?.ctrl !== conditionsModifiers.ctrl) {\r\n return false;\r\n }\r\n if (conditionsModifiers.shift !== undefined && entryModifiers?.shift !== conditionsModifiers.shift) {\r\n return false;\r\n }\r\n if (conditionsModifiers.alt !== undefined && entryModifiers?.alt !== conditionsModifiers.alt) {\r\n return false;\r\n }\r\n return true;\r\n }\r\n}\r\n"]}
@@ -166,10 +166,12 @@ export class TargetCamera extends Camera {
166
166
  const lockedTargetPosition = this._getLockedTargetPosition();
167
167
  if (!lockedTargetPosition) {
168
168
  this._cache.lockedTarget = null;
169
- } else {
169
+ }
170
+ else {
170
171
  if (!this._cache.lockedTarget) {
171
172
  this._cache.lockedTarget = lockedTargetPosition.clone();
172
- } else {
173
+ }
174
+ else {
173
175
  this._cache.lockedTarget.copyFrom(lockedTargetPosition);
174
176
  }
175
177
  }
@@ -185,10 +187,8 @@ export class TargetCamera extends Camera {
185
187
  return false;
186
188
  }
187
189
  const lockedTargetPosition = this._getLockedTargetPosition();
188
- return (
189
- (this._cache.lockedTarget ? this._cache.lockedTarget.equals(lockedTargetPosition) : !lockedTargetPosition) &&
190
- (this.rotationQuaternion ? this.rotationQuaternion.equals(this._cache.rotationQuaternion) : this._cache.rotation.equals(this.rotation))
191
- );
190
+ return ((this._cache.lockedTarget ? this._cache.lockedTarget.equals(lockedTargetPosition) : !lockedTargetPosition) &&
191
+ (this.rotationQuaternion ? this.rotationQuaternion.equals(this._cache.rotationQuaternion) : this._cache.rotation.equals(this.rotation)));
192
192
  }
193
193
  // Methods
194
194
  /** @internal */
@@ -210,7 +210,8 @@ export class TargetCamera extends Camera {
210
210
  this._referencePoint.normalize().scaleInPlace(this._initialFocalDistance);
211
211
  if (this.getScene().useRightHandedSystem) {
212
212
  Matrix.LookAtRHToRef(this.position, target, Vector3.UpReadOnly, TmpMatrix);
213
- } else {
213
+ }
214
+ else {
214
215
  Matrix.LookAtLHToRef(this.position, target, Vector3.UpReadOnly, TmpMatrix);
215
216
  }
216
217
  TmpMatrix.invert();
@@ -249,7 +250,8 @@ export class TargetCamera extends Camera {
249
250
  this._deferredPositionUpdate.addInPlace(TmpVectors.Vector3[0]);
250
251
  if (!this._deferOnly) {
251
252
  this.position.copyFrom(this._deferredPositionUpdate);
252
- } else {
253
+ }
254
+ else {
253
255
  this._deferredUpdated = true;
254
256
  }
255
257
  return;
@@ -257,7 +259,8 @@ export class TargetCamera extends Camera {
257
259
  this._deferredPositionUpdate.addInPlace(this.cameraDirection);
258
260
  if (!this._deferOnly) {
259
261
  this.position.copyFrom(this._deferredPositionUpdate);
260
- } else {
262
+ }
263
+ else {
261
264
  this._deferredUpdated = true;
262
265
  }
263
266
  }
@@ -296,22 +299,19 @@ export class TargetCamera extends Camera {
296
299
  }
297
300
  if (!this._deferOnly) {
298
301
  this.rotation.copyFrom(this._deferredRotationUpdate);
299
- } else {
302
+ }
303
+ else {
300
304
  this._deferredUpdated = true;
301
305
  }
302
306
  //rotate, if quaternion is set and rotation was used
303
307
  if (this.rotationQuaternion) {
304
308
  const len = this._deferredRotationUpdate.lengthSquared();
305
309
  if (len) {
306
- Quaternion.RotationYawPitchRollToRef(
307
- this._deferredRotationUpdate.y,
308
- this._deferredRotationUpdate.x,
309
- this._deferredRotationUpdate.z,
310
- this._deferredRotationQuaternionUpdate
311
- );
310
+ Quaternion.RotationYawPitchRollToRef(this._deferredRotationUpdate.y, this._deferredRotationUpdate.x, this._deferredRotationUpdate.z, this._deferredRotationQuaternionUpdate);
312
311
  if (!this._deferOnly) {
313
312
  this.rotationQuaternion.copyFrom(this._deferredRotationQuaternionUpdate);
314
- } else {
313
+ }
314
+ else {
315
315
  this._deferredUpdated = true;
316
316
  }
317
317
  }
@@ -346,7 +346,8 @@ export class TargetCamera extends Camera {
346
346
  _updateCameraRotationMatrix() {
347
347
  if (this.rotationQuaternion) {
348
348
  this.rotationQuaternion.toRotationMatrix(this._cameraRotationMatrix);
349
- } else {
349
+ }
350
+ else {
350
351
  Matrix.RotationYawPitchRollToRef(this.rotation.y, this.rotation.x, this.rotation.z, this._cameraRotationMatrix);
351
352
  }
352
353
  }
@@ -369,7 +370,8 @@ export class TargetCamera extends Camera {
369
370
  if (this.rotationQuaternion && this._cachedQuaternionRotationZ != this.rotationQuaternion.z) {
370
371
  this._rotateUpVectorWithCameraRotationMatrix();
371
372
  this._cachedQuaternionRotationZ = this.rotationQuaternion.z;
372
- } else if (this._cachedRotationZ !== this.rotation.z) {
373
+ }
374
+ else if (this._cachedRotationZ !== this.rotation.z) {
373
375
  this._rotateUpVectorWithCameraRotationMatrix();
374
376
  this._cachedRotationZ = this.rotation.z;
375
377
  }
@@ -379,7 +381,8 @@ export class TargetCamera extends Camera {
379
381
  if (this.updateUpVectorFromRotation) {
380
382
  if (this.rotationQuaternion) {
381
383
  Axis.Y.rotateByQuaternionToRef(this.rotationQuaternion, this.upVector);
382
- } else {
384
+ }
385
+ else {
383
386
  Quaternion.FromEulerVectorToRef(this.rotation, TmpQuaternion);
384
387
  Axis.Y.rotateByQuaternionToRef(TmpQuaternion, this.upVector);
385
388
  }
@@ -390,7 +393,8 @@ export class TargetCamera extends Camera {
390
393
  _computeViewMatrix(position, target, up) {
391
394
  if (this.getScene().useRightHandedSystem) {
392
395
  Matrix.LookAtRHToRef(position, target, up, this._viewMatrix);
393
- } else {
396
+ }
397
+ else {
394
398
  Matrix.LookAtLHToRef(position, target, up, this._viewMatrix);
395
399
  }
396
400
  if (this.parent) {
@@ -450,7 +454,8 @@ export class TargetCamera extends Camera {
450
454
  if (camLeft.rotationQuaternion && camRight.rotationQuaternion && this.rotationQuaternion) {
451
455
  camLeft.rotationQuaternion.copyFrom(this.rotationQuaternion);
452
456
  camRight.rotationQuaternion.copyFrom(this.rotationQuaternion);
453
- } else {
457
+ }
458
+ else {
454
459
  camLeft.rotation.copyFrom(this.rotation);
455
460
  camRight.rotation.copyFrom(this.rotation);
456
461
  }
@@ -483,10 +488,18 @@ export class TargetCamera extends Camera {
483
488
  TargetCamera._RigCamTransformMatrix = /*#__PURE__*/ new Matrix();
484
489
  TargetCamera._TargetTransformMatrix = /*#__PURE__*/ new Matrix();
485
490
  TargetCamera._TargetFocalPoint = /*#__PURE__*/ new Vector3();
486
- __decorate([serialize()], TargetCamera.prototype, "updateUpVectorFromRotation", void 0);
487
- __decorate([serializeAsVector3()], TargetCamera.prototype, "rotation", void 0);
488
- __decorate([serialize()], TargetCamera.prototype, "speed", void 0);
489
- __decorate([serializeAsMeshReference("lockedTargetId")], TargetCamera.prototype, "lockedTarget", void 0);
491
+ __decorate([
492
+ serialize()
493
+ ], TargetCamera.prototype, "updateUpVectorFromRotation", void 0);
494
+ __decorate([
495
+ serializeAsVector3()
496
+ ], TargetCamera.prototype, "rotation", void 0);
497
+ __decorate([
498
+ serialize()
499
+ ], TargetCamera.prototype, "speed", void 0);
500
+ __decorate([
501
+ serializeAsMeshReference("lockedTargetId")
502
+ ], TargetCamera.prototype, "lockedTarget", void 0);
490
503
  let _Registered = false;
491
504
  /**
492
505
  * Register side effects for targetCamera.
@@ -501,4 +514,4 @@ export function RegisterTargetCamera() {
501
514
  return () => new TargetCamera(name, Vector3.Zero(), scene);
502
515
  });
503
516
  }
504
- //# sourceMappingURL=targetCamera.pure.js.map
517
+ //# sourceMappingURL=targetCamera.pure.js.map
@@ -1,12 +1,7 @@
1
1
  /** This file must only contain pure code and pure imports */
2
2
  import { VertexBuffer, Buffer } from "../../Buffers/buffer.pure.js";
3
3
 
4
- import {
5
- BindBonesParameters,
6
- BindMorphTargetParameters,
7
- PrepareAttributesForBakedVertexAnimation,
8
- PrepareDefinesAndAttributesForMorphTargets,
9
- } from "../../Materials/materialHelper.functions.js";
4
+ import { BindBonesParameters, BindMorphTargetParameters, PrepareAttributesForBakedVertexAnimation, PrepareDefinesAndAttributesForMorphTargets, } from "../../Materials/materialHelper.functions.js";
10
5
  import { extractMinAndMax } from "../../Maths/math.functions.js";
11
6
  import { Vector3 } from "../../Maths/math.vector.pure.js";
12
7
  /** @internal */
@@ -55,23 +50,19 @@ export class TransformFeedbackBoundingHelper {
55
50
  defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
56
51
  defines.push("#define BONETEXTURE " + mesh.skeleton.isUsingTextureForMatrices);
57
52
  defines.push("#define BonesPerMesh " + (mesh.skeleton.bones.length + 1));
58
- } else {
53
+ }
54
+ else {
59
55
  defines.push("#define NUM_BONE_INFLUENCERS 0");
60
56
  }
61
57
  // Morph
62
58
  const numMorphInfluencers = mesh.morphTargetManager
63
- ? PrepareDefinesAndAttributesForMorphTargets(
64
- mesh.morphTargetManager,
65
- defines,
66
- attribs,
67
- mesh,
68
- true, // usePositionMorph
69
- false, // useNormalMorph
70
- false, // useTangentMorph
71
- false, // useUVMorph
72
- false, // useUV2Morph
73
- false // useColorMorph
74
- )
59
+ ? PrepareDefinesAndAttributesForMorphTargets(mesh.morphTargetManager, defines, attribs, mesh, true, // usePositionMorph
60
+ false, // useNormalMorph
61
+ false, // useTangentMorph
62
+ false, // useUVMorph
63
+ false, // useUV2Morph
64
+ false // useColorMorph
65
+ )
75
66
  : 0;
76
67
  // Baked Vertex Animation
77
68
  const bvaManager = mesh.bakedVertexAnimationManager;
@@ -108,7 +99,8 @@ export class TransformFeedbackBoundingHelper {
108
99
  };
109
100
  computeEffect = this._engine.createEffect("gpuTransform", computeEffectOptions, this._engine);
110
101
  this._effects[join] = computeEffect;
111
- } else {
102
+ }
103
+ else {
112
104
  computeEffect = this._effects[join];
113
105
  }
114
106
  this._compute(mesh, computeEffect);
@@ -124,7 +116,8 @@ export class TransformFeedbackBoundingHelper {
124
116
  const targetData = new Float32Array(vertexCount * 3);
125
117
  targetBuffer = new Buffer(mesh.getEngine(), targetData, true, 3);
126
118
  this._buffers[mesh.uniqueId] = targetBuffer;
127
- } else {
119
+ }
120
+ else {
128
121
  targetBuffer = this._buffers[mesh.uniqueId];
129
122
  }
130
123
  // Bind
@@ -155,7 +148,8 @@ export class TransformFeedbackBoundingHelper {
155
148
  // Update mesh
156
149
  if (this._meshListCounter === 0) {
157
150
  mesh._refreshBoundingInfo(arrayBuffer, null);
158
- } else {
151
+ }
152
+ else {
159
153
  const bb = mesh.getBoundingInfo().boundingBox;
160
154
  const extend = extractMinAndMax(arrayBuffer, 0, vertexCount);
161
155
  TransformFeedbackBoundingHelper._Min.copyFrom(bb.minimum).minimizeInPlace(extend.minimum);
@@ -199,4 +193,4 @@ export class TransformFeedbackBoundingHelper {
199
193
  }
200
194
  TransformFeedbackBoundingHelper._Min = /*#__PURE__*/ new Vector3();
201
195
  TransformFeedbackBoundingHelper._Max = /*#__PURE__*/ new Vector3();
202
- //# sourceMappingURL=transformFeedbackBoundingHelper.pure.js.map
196
+ //# sourceMappingURL=transformFeedbackBoundingHelper.pure.js.map
@@ -806,13 +806,13 @@ export class AbstractEngine {
806
806
  */
807
807
  // Not mixed with Version for tooling purpose.
808
808
  static get NpmPackage() {
809
- return "babylonjs@9.8.0";
809
+ return "babylonjs@9.9.0";
810
810
  }
811
811
  /**
812
812
  * Returns the current version of the framework
813
813
  */
814
814
  static get Version() {
815
- return "9.8.0";
815
+ return "9.9.0";
816
816
  }
817
817
  /**
818
818
  * Gets the HTML canvas attached with the current webGL context
@@ -1130,8 +1130,6 @@ export class AbstractEngine {
1130
1130
  // Detect if we are running on a faulty buggy desktop OS.
1131
1131
  this._badDesktopOS = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
1132
1132
  }
1133
- // Save this off for use in resize().
1134
- this.adaptToDeviceRatio = adaptToDeviceRatio ?? false;
1135
1133
  options.antialias = antialias ?? options.antialias;
1136
1134
  options.deterministicLockstep = options.deterministicLockstep ?? false;
1137
1135
  options.lockstepMaxSteps = options.lockstepMaxSteps ?? 4;
@@ -1147,6 +1145,8 @@ export class AbstractEngine {
1147
1145
  const limitDeviceRatio = options.limitDeviceRatio || devicePixelRatio;
1148
1146
  // Viewport
1149
1147
  adaptToDeviceRatio = adaptToDeviceRatio || options.adaptToDeviceRatio || false;
1148
+ // Save this off for use in resize().
1149
+ this.adaptToDeviceRatio = adaptToDeviceRatio;
1150
1150
  this._hardwareScalingLevel = adaptToDeviceRatio ? 1.0 / Math.min(limitDeviceRatio, devicePixelRatio) : 1.0;
1151
1151
  this._lastDevicePixelRatio = devicePixelRatio;
1152
1152
  this._creationOptions = options;