@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.
- package/Audio/audioSceneComponent.pure.js +17 -9
- package/Bones/bone.pure.js +39 -29
- package/Cameras/arcRotateCamera.pure.d.ts +0 -8
- package/Cameras/arcRotateCamera.pure.js +0 -12
- package/Cameras/arcRotateCamera.pure.js.map +1 -1
- package/Cameras/inputMapper.d.ts +29 -8
- package/Cameras/inputMapper.js +63 -10
- package/Cameras/inputMapper.js.map +1 -1
- package/Cameras/targetCamera.pure.js +40 -27
- package/Culling/Helper/transformFeedbackBoundingHelper.pure.js +17 -23
- package/Engines/abstractEngine.pure.js +4 -4
- package/Engines/abstractEngine.pure.js.map +1 -1
- package/Engines/thinEngine.pure.js +234 -280
- package/Materials/Background/backgroundMaterial.pure.js +5 -4
- package/Materials/Background/backgroundMaterial.pure.js.map +1 -1
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.d.ts +5 -0
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js +8 -0
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js.map +1 -0
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.d.ts +278 -0
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js +718 -0
- package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js.map +1 -0
- package/Materials/GaussianSplatting/pure.d.ts +1 -0
- package/Materials/GaussianSplatting/pure.js +1 -0
- package/Materials/GaussianSplatting/pure.js.map +1 -1
- package/Materials/Node/Blocks/Dual/imageSourceBlock.pure.js +10 -14
- package/Materials/Node/Blocks/Dual/index.d.ts +0 -14
- package/Materials/Node/Blocks/Dual/index.js +0 -18
- package/Materials/Node/Blocks/Dual/index.js.map +1 -1
- package/Materials/Node/Blocks/Dual/textureBlock.pure.js +660 -662
- package/Materials/Node/Blocks/Fragment/index.d.ts +0 -10
- package/Materials/Node/Blocks/Fragment/index.js +0 -13
- package/Materials/Node/Blocks/Fragment/index.js.map +1 -1
- package/Materials/Node/Blocks/GaussianSplatting/index.d.ts +12 -0
- package/Materials/Node/Blocks/GaussianSplatting/index.js +14 -1
- package/Materials/Node/Blocks/GaussianSplatting/index.js.map +1 -1
- package/Materials/Node/Blocks/Vertex/index.d.ts +0 -8
- package/Materials/Node/Blocks/Vertex/index.js +0 -10
- package/Materials/Node/Blocks/Vertex/index.js.map +1 -1
- package/Materials/PBR/openpbrMaterial.pure.js +6 -5
- package/Materials/PBR/openpbrMaterial.pure.js.map +1 -1
- package/Materials/PBR/pbrBaseMaterial.pure.js +6 -5
- package/Materials/PBR/pbrBaseMaterial.pure.js.map +1 -1
- package/Materials/Textures/index.d.ts +1 -0
- package/Materials/Textures/index.js +1 -0
- package/Materials/Textures/index.js.map +1 -1
- package/Materials/Textures/internalTexture.js +7 -0
- package/Materials/Textures/internalTexture.js.map +1 -1
- package/Materials/Textures/texture.pure.js +157 -255
- package/Materials/index.d.ts +30 -0
- package/Materials/index.js +31 -0
- package/Materials/index.js.map +1 -1
- package/Materials/material.pure.js +128 -69
- package/Materials/pure.d.ts +1 -0
- package/Materials/pure.js +1 -0
- package/Materials/pure.js.map +1 -1
- package/Materials/standardMaterial.pure.js +6 -5
- package/Materials/standardMaterial.pure.js.map +1 -1
- package/Maths/math.color.pure.js +55 -47
- package/Maths/math.vector.pure.js +118 -242
- package/Meshes/GaussianSplatting/gaussianSplattingDebugger.d.ts +7 -0
- package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js +8 -0
- package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js.map +1 -0
- package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.d.ts +147 -0
- package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js +257 -0
- package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js.map +1 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +11 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +31 -0
- package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
- package/Meshes/GaussianSplatting/pure.d.ts +1 -0
- package/Meshes/GaussianSplatting/pure.js +1 -0
- package/Meshes/GaussianSplatting/pure.js.map +1 -1
- package/Meshes/GreasedLine/greasedLineMesh.pure.js +9 -14
- package/Meshes/GreasedLine/greasedLineRibbonMesh.pure.js +26 -27
- package/Meshes/index.d.ts +1 -0
- package/Meshes/index.js +1 -0
- package/Meshes/index.js.map +1 -1
- package/Meshes/meshSimplification.common.d.ts +53 -0
- package/Meshes/meshSimplification.common.js +34 -0
- package/Meshes/meshSimplification.common.js.map +1 -0
- package/Meshes/meshSimplification.d.ts +3 -53
- package/Meshes/meshSimplification.js +1 -33
- package/Meshes/meshSimplification.js.map +1 -1
- package/Meshes/meshSimplificationSceneComponent.pure.js.map +1 -1
- package/Meshes/meshSimplificationSceneComponent.types.d.ts +2 -1
- package/Meshes/meshSimplificationSceneComponent.types.js.map +1 -1
- package/Meshes/pure.d.ts +1 -0
- package/Meshes/pure.js +1 -0
- package/Meshes/pure.js.map +1 -1
- package/Meshes/transformNode.pure.js +82 -44
- package/Misc/tools.pure.js +124 -186
- package/Misc/tools.pure.js.map +1 -1
- package/Physics/v1/physicsImpostor.pure.js +43 -37
- package/Shaders/ShadersInclude/gaussianSplatting.js +33 -10
- package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/Shaders/gaussianSplatting.vertex.js +20 -1
- package/Shaders/gaussianSplatting.vertex.js.map +1 -1
- package/Shaders/picking.fragment.js +4 -1
- package/Shaders/picking.fragment.js.map +1 -1
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +33 -10
- package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
- package/ShadersWGSL/gaussianSplatting.vertex.js +21 -2
- package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
- package/package.json +3 -1
package/Cameras/inputMapper.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
217
|
-
*
|
|
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
|
-
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
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
|
|
224
|
-
* @param interaction - The
|
|
225
|
-
* @returns true
|
|
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,
|
package/Cameras/inputMapper.js
CHANGED
|
@@ -89,24 +89,77 @@ export class InputMapper {
|
|
|
89
89
|
this.inputMap.splice(insertIndex, 0, entry);
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
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
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
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
|
|
100
|
-
* @param interaction - The
|
|
101
|
-
* @returns true
|
|
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
|
-
|
|
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":"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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 * 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
|
-
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
170
171
|
if (!this._cache.lockedTarget) {
|
|
171
172
|
this._cache.lockedTarget = lockedTargetPosition.clone();
|
|
172
|
-
}
|
|
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.
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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([
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
__decorate([
|
|
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
|
-
}
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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
|
-
}
|
|
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.
|
|
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.
|
|
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;
|