@onerjs/core 8.51.6 → 8.51.7

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 (54) hide show
  1. package/Cameras/inputMapper.js +13 -9
  2. package/Cameras/inputMapper.js.map +1 -1
  3. package/Engines/AbstractEngine/abstractEngine.views.pure.js.map +1 -1
  4. package/Engines/AbstractEngine/abstractEngine.views.types.d.ts +2 -1
  5. package/Engines/AbstractEngine/abstractEngine.views.types.js.map +1 -1
  6. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.d.ts +5 -0
  7. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js +8 -0
  8. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.js.map +1 -0
  9. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.d.ts +278 -0
  10. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js +718 -0
  11. package/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.pure.js.map +1 -0
  12. package/Materials/GaussianSplatting/pure.d.ts +1 -0
  13. package/Materials/GaussianSplatting/pure.js +1 -0
  14. package/Materials/GaussianSplatting/pure.js.map +1 -1
  15. package/Materials/Textures/internalTexture.js +7 -0
  16. package/Materials/Textures/internalTexture.js.map +1 -1
  17. package/Materials/index.d.ts +1 -0
  18. package/Materials/index.js +1 -0
  19. package/Materials/index.js.map +1 -1
  20. package/Materials/pure.d.ts +1 -0
  21. package/Materials/pure.js +1 -0
  22. package/Materials/pure.js.map +1 -1
  23. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.d.ts +7 -0
  24. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js +8 -0
  25. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.js.map +1 -0
  26. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.d.ts +147 -0
  27. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js +257 -0
  28. package/Meshes/GaussianSplatting/gaussianSplattingDebugger.pure.js.map +1 -0
  29. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.d.ts +11 -0
  30. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js +31 -0
  31. package/Meshes/GaussianSplatting/gaussianSplattingMeshBase.pure.js.map +1 -1
  32. package/Meshes/GaussianSplatting/pure.d.ts +1 -0
  33. package/Meshes/GaussianSplatting/pure.js +1 -0
  34. package/Meshes/GaussianSplatting/pure.js.map +1 -1
  35. package/Meshes/abstractMesh.pure.js +3 -0
  36. package/Meshes/abstractMesh.pure.js.map +1 -1
  37. package/Meshes/index.d.ts +1 -0
  38. package/Meshes/index.js +1 -0
  39. package/Meshes/index.js.map +1 -1
  40. package/Meshes/pure.d.ts +1 -0
  41. package/Meshes/pure.js +1 -0
  42. package/Meshes/pure.js.map +1 -1
  43. package/Shaders/ShadersInclude/gaussianSplatting.js +33 -10
  44. package/Shaders/ShadersInclude/gaussianSplatting.js.map +1 -1
  45. package/Shaders/gaussianSplatting.vertex.js +20 -1
  46. package/Shaders/gaussianSplatting.vertex.js.map +1 -1
  47. package/Shaders/picking.fragment.js +4 -1
  48. package/Shaders/picking.fragment.js.map +1 -1
  49. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js +33 -10
  50. package/ShadersWGSL/ShadersInclude/gaussianSplatting.js.map +1 -1
  51. package/ShadersWGSL/gaussianSplatting.vertex.js +21 -2
  52. package/ShadersWGSL/gaussianSplatting.vertex.js.map +1 -1
  53. package/package.json +1 -1
  54. package/scene.pure.js.map +1 -1
@@ -142,18 +142,22 @@ export class InputMapper {
142
142
  // from a string-keyed loop. The runtime check is harmless: irrelevant-for-this-source
143
143
  // fields are undefined on both entry and conditions and skip the early return.
144
144
  const e = entry;
145
- for (const field of ["button", "key", "touchCount"]) {
146
- if (conditions[field] !== undefined && e[field] === undefined) {
147
- return false;
145
+ for (const key of Object.keys(conditions)) {
146
+ const condValue = conditions[key];
147
+ if (condValue === undefined) {
148
+ continue;
148
149
  }
149
- }
150
- if (conditions.modifiers) {
151
- const entryMods = e.modifiers ?? {};
152
- for (const key of Object.keys(conditions.modifiers)) {
153
- if (conditions.modifiers[key] !== undefined && entryMods[key] === undefined) {
154
- return false;
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
+ }
155
156
  }
156
157
  }
158
+ else if (e[key] === undefined) {
159
+ return false;
160
+ }
157
161
  }
158
162
  return true;
159
163
  }
@@ -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 * 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 field of [\"button\", \"key\", \"touchCount\"] as const) {\r\n if (conditions[field] !== undefined && e[field] === undefined) {\r\n return false;\r\n }\r\n }\r\n if (conditions.modifiers) {\r\n const entryMods = e.modifiers ?? {};\r\n for (const key of Object.keys(conditions.modifiers) as (keyof InputModifiers)[]) {\r\n if (conditions.modifiers[key] !== undefined && entryMods[key] === undefined) {\r\n return false;\r\n }\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"]}
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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"abstractEngine.views.pure.js","sourceRoot":"","sources":["../../../../../dev/core/src/Engines/AbstractEngine/abstractEngine.views.pure.ts"],"names":[],"mappings":"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","sourcesContent":["/** This file must only contain pure code and pure imports */\r\n\r\nimport { type Camera } from \"../../Cameras/camera.pure\";\r\nimport { type Nullable } from \"../../types\";\r\nimport { type Scene } from \"../../scene.pure\";\r\nimport { Observable } from \"../../Misc/observable.pure\";\r\nimport { AbstractEngine } from \"../abstractEngine.pure\";\r\n\r\n/**\r\n * Class used to define an additional view for the engine\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/multiCanvas\r\n */\r\nexport class EngineView {\r\n /**\r\n * A randomly generated unique id\r\n */\r\n readonly id: string;\r\n /** Defines the canvas where to render the view */\r\n target: HTMLCanvasElement;\r\n /**\r\n * Defines an optional camera or array of cameras used to render the view (will use active camera / cameras else)\r\n * Support for array of cameras @since\r\n */\r\n camera?: Camera | Camera[];\r\n /** Indicates if the destination view canvas should be cleared before copying the parent canvas. Can help if the scene clear color has alpha < 1 */\r\n clearBeforeCopy?: boolean;\r\n /** Indicates if the view is enabled (true by default) */\r\n enabled: boolean;\r\n /** Defines a custom function to handle canvas size changes. (the canvas to render into is provided to the callback) */\r\n customResize?: (canvas: HTMLCanvasElement) => void;\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Register side effects for abstractEngineViews.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterAbstractEngineViews(): void {\r\n if (_Registered) {\r\n return;\r\n }\r\n _Registered = true;\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const OnBeforeViewRenderObservable = new Observable<EngineView>();\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const OnAfterViewRenderObservable = new Observable<EngineView>();\r\n\r\n Object.defineProperty(AbstractEngine.prototype, \"onBeforeViewRenderObservable\", {\r\n get: function (this: AbstractEngine) {\r\n return OnBeforeViewRenderObservable;\r\n },\r\n });\r\n\r\n Object.defineProperty(AbstractEngine.prototype, \"onAfterViewRenderObservable\", {\r\n get: function (this: AbstractEngine) {\r\n return OnAfterViewRenderObservable;\r\n },\r\n });\r\n\r\n Object.defineProperty(AbstractEngine.prototype, \"inputElement\", {\r\n get: function (this: AbstractEngine) {\r\n return this._inputElement;\r\n },\r\n set: function (this: AbstractEngine, value: HTMLElement) {\r\n if (this._inputElement !== value) {\r\n this._inputElement = value;\r\n this._onEngineViewChanged?.();\r\n }\r\n },\r\n });\r\n\r\n AbstractEngine.prototype.getInputElement = function (): Nullable<HTMLElement> {\r\n return this.inputElement || this.getRenderingCanvas();\r\n };\r\n\r\nAbstractEngine.prototype.registerView = function (\r\n canvas: HTMLCanvasElement,\r\n camera?: Camera | Camera[],\r\n clearBeforeCopy?: boolean,\r\n customResize?: EngineView[\"customResize\"]\r\n): EngineView {\r\n if (!this.views) {\r\n this.views = [];\r\n }\r\n\r\n for (const view of this.views) {\r\n if (view.target === canvas) {\r\n return view;\r\n }\r\n }\r\n\r\n const masterCanvas = this.getRenderingCanvas();\r\n if (masterCanvas) {\r\n canvas.width = masterCanvas.width;\r\n canvas.height = masterCanvas.height;\r\n }\r\n\r\n const newView = { target: canvas, camera, clearBeforeCopy, enabled: true, id: (Math.random() * 100000).toFixed(), customResize };\r\n this.views.push(newView);\r\n if (customResize) {\r\n customResize(canvas);\r\n }\r\n if (camera && !Array.isArray(camera)) {\r\n camera.onDisposeObservable.add(() => {\r\n this.unRegisterView(canvas);\r\n });\r\n }\r\n\r\n return newView;\r\n };\r\n\r\n AbstractEngine.prototype.unRegisterView = function (canvas: HTMLCanvasElement): AbstractEngine {\r\n if (!this.views || this.views.length === 0) {\r\n return this;\r\n }\r\n\r\n for (const view of this.views) {\r\n if (view.target === canvas) {\r\n const index = this.views.indexOf(view);\r\n\r\n if (index !== -1) {\r\n this.views.splice(index, 1);\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return this;\r\n };\r\n\r\n AbstractEngine.prototype._renderViewStep = function (view: EngineView): boolean {\r\n const canvas = view.target;\r\n const context = canvas.getContext(\"2d\");\r\n if (!context) {\r\n return true;\r\n }\r\n const parent = this.getRenderingCanvas()!;\r\n\r\n OnBeforeViewRenderObservable.notifyObservers(view);\r\n const camera = view.camera;\r\n let previewCamera: Nullable<Camera> = null;\r\n let previewCameras: Nullable<Camera[]> = null;\r\n let scene: Nullable<Scene> = null;\r\n if (camera) {\r\n scene = Array.isArray(camera) ? camera[0].getScene() : camera.getScene();\r\n\r\n previewCamera = scene.activeCamera;\r\n previewCameras = scene.activeCameras;\r\n\r\n if (Array.isArray(camera)) {\r\n scene.activeCameras = camera;\r\n } else {\r\n scene.activeCamera = camera;\r\n scene.activeCameras = null;\r\n }\r\n }\r\n this.activeView = view;\r\n\r\n if (view.customResize) {\r\n view.customResize(canvas);\r\n } else {\r\n // Set sizes\r\n const width = Math.floor(canvas.clientWidth / this._hardwareScalingLevel);\r\n const height = Math.floor(canvas.clientHeight / this._hardwareScalingLevel);\r\n\r\n const dimsChanged = width !== canvas.width || parent.width !== canvas.width || height !== canvas.height || parent.height !== canvas.height;\r\n if (canvas.clientWidth && canvas.clientHeight && dimsChanged) {\r\n canvas.width = width;\r\n canvas.height = height;\r\n this.setSize(width, height);\r\n }\r\n }\r\n\r\n if (!parent.width || !parent.height) {\r\n return false;\r\n }\r\n\r\n // Render the frame\r\n this._renderFrame();\r\n\r\n this.flushFramebuffer();\r\n\r\n // Copy to target\r\n if (view.clearBeforeCopy) {\r\n context.clearRect(0, 0, parent.width, parent.height);\r\n }\r\n context.drawImage(parent, 0, 0);\r\n\r\n // Restore\r\n if (scene) {\r\n scene.activeCameras = previewCameras;\r\n scene.activeCamera = previewCamera;\r\n }\r\n OnAfterViewRenderObservable.notifyObservers(view);\r\n return true;\r\n };\r\n\r\n AbstractEngine.prototype._renderViews = function () {\r\n if (!this.views || this.views.length === 0) {\r\n return false;\r\n }\r\n\r\n const parent = this.getRenderingCanvas();\r\n\r\n if (!parent) {\r\n return false;\r\n }\r\n\r\n let inputElementView;\r\n for (const view of this.views) {\r\n if (!view.enabled) {\r\n continue;\r\n }\r\n const canvas = view.target;\r\n // Always render the view correspondent to the inputElement for last\r\n if (canvas === this.inputElement) {\r\n inputElementView = view;\r\n continue;\r\n }\r\n\r\n if (!this._renderViewStep(view)) {\r\n return false;\r\n }\r\n }\r\n\r\n if (inputElementView) {\r\n if (!this._renderViewStep(inputElementView)) {\r\n return false;\r\n }\r\n }\r\n\r\n this.activeView = null;\r\n\r\n return true;\r\n };\r\n}\r\n"]}
1
+ {"version":3,"file":"abstractEngine.views.pure.js","sourceRoot":"","sources":["../../../../../dev/core/src/Engines/AbstractEngine/abstractEngine.views.pure.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAK7D,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD;;;GAGG;AACH,MAAM,OAAO,UAAU;CAkBtB;AAED,IAAI,WAAW,GAAG,KAAK,CAAC;AACxB;;;GAGG;AACH,MAAM,UAAU,2BAA2B;IACvC,IAAI,WAAW,EAAE,CAAC;QACd,OAAO;IACX,CAAC;IACD,WAAW,GAAG,IAAI,CAAC;IAEnB,gEAAgE;IAChE,MAAM,4BAA4B,GAAG,IAAI,UAAU,EAAc,CAAC;IAElE,gEAAgE;IAChE,MAAM,2BAA2B,GAAG,IAAI,UAAU,EAAc,CAAC;IAEjE,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,SAAS,EAAE,8BAA8B,EAAE;QAC5E,GAAG,EAAE;YACD,OAAO,4BAA4B,CAAC;QACxC,CAAC;KACJ,CAAC,CAAC;IAEH,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,SAAS,EAAE,6BAA6B,EAAE;QAC3E,GAAG,EAAE;YACD,OAAO,2BAA2B,CAAC;QACvC,CAAC;KACJ,CAAC,CAAC;IAEH,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,SAAS,EAAE,cAAc,EAAE;QAC5D,GAAG,EAAE;YACD,OAAO,IAAI,CAAC,aAAa,CAAC;QAC9B,CAAC;QACD,GAAG,EAAE,UAAgC,KAAkB;YACnD,IAAI,IAAI,CAAC,aAAa,KAAK,KAAK,EAAE,CAAC;gBAC/B,IAAI,CAAC,aAAa,GAAG,KAAK,CAAC;gBAC3B,IAAI,CAAC,oBAAoB,EAAE,EAAE,CAAC;YAClC,CAAC;QACL,CAAC;KACJ,CAAC,CAAC;IAEH,cAAc,CAAC,SAAS,CAAC,eAAe,GAAG;QACvC,OAAO,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAC1D,CAAC,CAAC;IAEF,cAAc,CAAC,SAAS,CAAC,YAAY,GAAG,UACpC,MAAyB,EACzB,MAA0B,EAC1B,eAAyB,EACzB,YAAyC;QAEzC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QACpB,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACzB,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAC/C,IAAI,YAAY,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC;YAClC,MAAM,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;QACxC,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,CAAC;QACjI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,IAAI,YAAY,EAAE,CAAC;YACf,YAAY,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,MAAM,CAAC,mBAAmB,CAAC,GAAG,CAAC,GAAG,EAAE;gBAChC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACP,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC,CAAC;IAEF,cAAc,CAAC,SAAS,CAAC,cAAc,GAAG,UAAU,MAAyB;QACzE,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,IAAI,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBAEvC,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;oBACf,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;gBAChC,CAAC;gBACD,MAAM;YACV,CAAC;QACL,CAAC;QAED,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;IAEF,cAAc,CAAC,SAAS,CAAC,eAAe,GAAG,UAAU,IAAgB;QACjE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAG,CAAC;QAE1C,4BAA4B,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,IAAI,aAAa,GAAqB,IAAI,CAAC;QAC3C,IAAI,cAAc,GAAuB,IAAI,CAAC;QAC9C,IAAI,KAAK,GAAoB,IAAI,CAAC;QAClC,IAAI,MAAM,EAAE,CAAC;YACT,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YAEzE,aAAa,GAAG,KAAK,CAAC,YAAY,CAAC;YACnC,cAAc,GAAG,KAAK,CAAC,aAAa,CAAC;YAErC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBACxB,KAAK,CAAC,aAAa,GAAG,MAAM,CAAC;YACjC,CAAC;iBAAM,CAAC;gBACJ,KAAK,CAAC,YAAY,GAAG,MAAM,CAAC;gBAC5B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;YAC/B,CAAC;QACL,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC;aAAM,CAAC;YACJ,YAAY;YACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC;YAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC;YAE5E,MAAM,WAAW,GAAG,KAAK,KAAK,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,IAAI,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC;YAC3I,IAAI,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,YAAY,IAAI,WAAW,EAAE,CAAC;gBAC3D,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;gBACrB,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;gBACvB,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAChC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAClC,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,mBAAmB;QACnB,IAAI,CAAC,YAAY,EAAE,CAAC;QAEpB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAExB,iBAAiB;QACjB,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACvB,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAEhC,UAAU;QACV,IAAI,KAAK,EAAE,CAAC;YACR,KAAK,CAAC,aAAa,GAAG,cAAc,CAAC;YACrC,KAAK,CAAC,YAAY,GAAG,aAAa,CAAC;QACvC,CAAC;QACD,2BAA2B,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;IAEF,cAAc,CAAC,SAAS,CAAC,YAAY,GAAG;QACpC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;QAEzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACV,OAAO,KAAK,CAAC;QACjB,CAAC;QAED,IAAI,gBAAgB,CAAC;QACrB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAChB,SAAS;YACb,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;YAC3B,oEAAoE;YACpE,IAAI,MAAM,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC/B,gBAAgB,GAAG,IAAI,CAAC;gBACxB,SAAS;YACb,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC9B,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QAED,IAAI,gBAAgB,EAAE,CAAC;YACnB,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE,CAAC;gBAC1C,OAAO,KAAK,CAAC;YACjB,CAAC;QACL,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC;AACN,CAAC","sourcesContent":["/** This file must only contain pure code and pure imports */\r\n\r\nimport { type Camera } from \"../../Cameras/camera.pure\";\r\nimport { type Nullable } from \"../../types\";\r\nimport { type Scene } from \"../../scene.pure\";\r\nimport { Observable } from \"../../Misc/observable.pure\";\r\nimport { AbstractEngine } from \"../abstractEngine.pure\";\r\n\r\n/**\r\n * Class used to define an additional view for the engine\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/multiCanvas\r\n */\r\nexport class EngineView {\r\n /**\r\n * A randomly generated unique id\r\n */\r\n readonly id: string;\r\n /** Defines the canvas where to render the view */\r\n target: HTMLCanvasElement;\r\n /**\r\n * Defines an optional camera or array of cameras used to render the view (will use active camera / cameras else)\r\n * Support for array of cameras @since\r\n */\r\n camera?: Camera | Camera[];\r\n /** Indicates if the destination view canvas should be cleared before copying the parent canvas. Can help if the scene clear color has alpha < 1 */\r\n clearBeforeCopy?: boolean;\r\n /** Indicates if the view is enabled (true by default) */\r\n enabled: boolean;\r\n /** Defines a custom function to handle canvas size changes. (the canvas to render into is provided to the callback) */\r\n customResize?: (canvas: HTMLCanvasElement) => void;\r\n}\r\n\r\nlet _Registered = false;\r\n/**\r\n * Register side effects for abstractEngineViews.\r\n * Safe to call multiple times; only the first call has an effect.\r\n */\r\nexport function RegisterAbstractEngineViews(): void {\r\n if (_Registered) {\r\n return;\r\n }\r\n _Registered = true;\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const OnBeforeViewRenderObservable = new Observable<EngineView>();\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n const OnAfterViewRenderObservable = new Observable<EngineView>();\r\n\r\n Object.defineProperty(AbstractEngine.prototype, \"onBeforeViewRenderObservable\", {\r\n get: function (this: AbstractEngine) {\r\n return OnBeforeViewRenderObservable;\r\n },\r\n });\r\n\r\n Object.defineProperty(AbstractEngine.prototype, \"onAfterViewRenderObservable\", {\r\n get: function (this: AbstractEngine) {\r\n return OnAfterViewRenderObservable;\r\n },\r\n });\r\n\r\n Object.defineProperty(AbstractEngine.prototype, \"inputElement\", {\r\n get: function (this: AbstractEngine) {\r\n return this._inputElement;\r\n },\r\n set: function (this: AbstractEngine, value: HTMLElement) {\r\n if (this._inputElement !== value) {\r\n this._inputElement = value;\r\n this._onEngineViewChanged?.();\r\n }\r\n },\r\n });\r\n\r\n AbstractEngine.prototype.getInputElement = function (): Nullable<HTMLElement> {\r\n return this.inputElement || this.getRenderingCanvas();\r\n };\r\n\r\n AbstractEngine.prototype.registerView = function (\r\n canvas: HTMLCanvasElement,\r\n camera?: Camera | Camera[],\r\n clearBeforeCopy?: boolean,\r\n customResize?: EngineView[\"customResize\"]\r\n ): EngineView {\r\n if (!this.views) {\r\n this.views = [];\r\n }\r\n\r\n for (const view of this.views) {\r\n if (view.target === canvas) {\r\n return view;\r\n }\r\n }\r\n\r\n const masterCanvas = this.getRenderingCanvas();\r\n if (masterCanvas) {\r\n canvas.width = masterCanvas.width;\r\n canvas.height = masterCanvas.height;\r\n }\r\n\r\n const newView = { target: canvas, camera, clearBeforeCopy, enabled: true, id: (Math.random() * 100000).toFixed(), customResize };\r\n this.views.push(newView);\r\n if (customResize) {\r\n customResize(canvas);\r\n }\r\n if (camera && !Array.isArray(camera)) {\r\n camera.onDisposeObservable.add(() => {\r\n this.unRegisterView(canvas);\r\n });\r\n }\r\n\r\n return newView;\r\n };\r\n\r\n AbstractEngine.prototype.unRegisterView = function (canvas: HTMLCanvasElement): AbstractEngine {\r\n if (!this.views || this.views.length === 0) {\r\n return this;\r\n }\r\n\r\n for (const view of this.views) {\r\n if (view.target === canvas) {\r\n const index = this.views.indexOf(view);\r\n\r\n if (index !== -1) {\r\n this.views.splice(index, 1);\r\n }\r\n break;\r\n }\r\n }\r\n\r\n return this;\r\n };\r\n\r\n AbstractEngine.prototype._renderViewStep = function (view: EngineView): boolean {\r\n const canvas = view.target;\r\n const context = canvas.getContext(\"2d\");\r\n if (!context) {\r\n return true;\r\n }\r\n const parent = this.getRenderingCanvas()!;\r\n\r\n OnBeforeViewRenderObservable.notifyObservers(view);\r\n const camera = view.camera;\r\n let previewCamera: Nullable<Camera> = null;\r\n let previewCameras: Nullable<Camera[]> = null;\r\n let scene: Nullable<Scene> = null;\r\n if (camera) {\r\n scene = Array.isArray(camera) ? camera[0].getScene() : camera.getScene();\r\n\r\n previewCamera = scene.activeCamera;\r\n previewCameras = scene.activeCameras;\r\n\r\n if (Array.isArray(camera)) {\r\n scene.activeCameras = camera;\r\n } else {\r\n scene.activeCamera = camera;\r\n scene.activeCameras = null;\r\n }\r\n }\r\n this.activeView = view;\r\n\r\n if (view.customResize) {\r\n view.customResize(canvas);\r\n } else {\r\n // Set sizes\r\n const width = Math.floor(canvas.clientWidth / this._hardwareScalingLevel);\r\n const height = Math.floor(canvas.clientHeight / this._hardwareScalingLevel);\r\n\r\n const dimsChanged = width !== canvas.width || parent.width !== canvas.width || height !== canvas.height || parent.height !== canvas.height;\r\n if (canvas.clientWidth && canvas.clientHeight && dimsChanged) {\r\n canvas.width = width;\r\n canvas.height = height;\r\n this.setSize(width, height);\r\n }\r\n }\r\n\r\n if (!parent.width || !parent.height) {\r\n return false;\r\n }\r\n\r\n // Render the frame\r\n this._renderFrame();\r\n\r\n this.flushFramebuffer();\r\n\r\n // Copy to target\r\n if (view.clearBeforeCopy) {\r\n context.clearRect(0, 0, parent.width, parent.height);\r\n }\r\n context.drawImage(parent, 0, 0);\r\n\r\n // Restore\r\n if (scene) {\r\n scene.activeCameras = previewCameras;\r\n scene.activeCamera = previewCamera;\r\n }\r\n OnAfterViewRenderObservable.notifyObservers(view);\r\n return true;\r\n };\r\n\r\n AbstractEngine.prototype._renderViews = function () {\r\n if (!this.views || this.views.length === 0) {\r\n return false;\r\n }\r\n\r\n const parent = this.getRenderingCanvas();\r\n\r\n if (!parent) {\r\n return false;\r\n }\r\n\r\n let inputElementView;\r\n for (const view of this.views) {\r\n if (!view.enabled) {\r\n continue;\r\n }\r\n const canvas = view.target;\r\n // Always render the view correspondent to the inputElement for last\r\n if (canvas === this.inputElement) {\r\n inputElementView = view;\r\n continue;\r\n }\r\n\r\n if (!this._renderViewStep(view)) {\r\n return false;\r\n }\r\n }\r\n\r\n if (inputElementView) {\r\n if (!this._renderViewStep(inputElementView)) {\r\n return false;\r\n }\r\n }\r\n\r\n this.activeView = null;\r\n\r\n return true;\r\n };\r\n}\r\n"]}
@@ -35,9 +35,10 @@ declare module "../../Engines/abstractEngine.pure.js" {
35
35
  * @param canvas defines the canvas to register
36
36
  * @param camera defines an optional camera or array of cameras to use with this canvas (it will overwrite the scene.activeCamera / scene.activeCameras for this view). Support for array of cameras @since
37
37
  * @param clearBeforeCopy Indicates if the destination view canvas should be cleared before copying the parent canvas. Can help if the scene clear color has alpha \< 1
38
+ * @param customResize defines the canvas custom resize handle
38
39
  * @returns the associated view
39
40
  */
40
- registerView(canvas: HTMLCanvasElement, camera?: Camera | Camera[], clearBeforeCopy?: boolean): EngineView;
41
+ registerView(canvas: HTMLCanvasElement, camera?: Camera | Camera[], clearBeforeCopy?: boolean, customResize?: EngineView["customResize"]): EngineView;
41
42
  /**
42
43
  * Remove a registered child canvas
43
44
  * @param canvas defines the canvas to remove
@@ -1 +1 @@
1
- {"version":3,"file":"abstractEngine.views.types.js","sourceRoot":"","sources":["../../../../../dev/core/src/Engines/AbstractEngine/abstractEngine.views.types.ts"],"names":[],"mappings":"","sourcesContent":["import { type Camera } from \"../../Cameras/camera\";\r\nimport { type Nullable } from \"../../types\";\r\nimport { type Observable } from \"../../Misc/observable\";\r\nimport { type EngineView } from \"./abstractEngine.views.pure\";\r\ndeclare module \"../../Engines/abstractEngine.pure\" {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n export interface AbstractEngine {\r\n /** @internal */\r\n _inputElement: Nullable<HTMLElement>;\r\n\r\n /**\r\n * Gets or sets the HTML element to use for attaching events\r\n */\r\n inputElement: Nullable<HTMLElement>;\r\n\r\n /**\r\n * Observable to handle when a change to inputElement occurs\r\n * @internal\r\n */\r\n _onEngineViewChanged?: () => void;\r\n\r\n /**\r\n * Will be triggered before the view renders\r\n */\r\n readonly onBeforeViewRenderObservable: Observable<EngineView>;\r\n /**\r\n * Will be triggered after the view rendered\r\n */\r\n readonly onAfterViewRenderObservable: Observable<EngineView>;\r\n\r\n /**\r\n * Gets the current engine view\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/multiCanvas\r\n */\r\n activeView: Nullable<EngineView>;\r\n\r\n /** Gets or sets the list of views */\r\n views: EngineView[];\r\n\r\n /**\r\n * Register a new child canvas\r\n * @param canvas defines the canvas to register\r\n * @param camera defines an optional camera or array of cameras to use with this canvas (it will overwrite the scene.activeCamera / scene.activeCameras for this view). Support for array of cameras @since\r\n * @param clearBeforeCopy Indicates if the destination view canvas should be cleared before copying the parent canvas. Can help if the scene clear color has alpha \\< 1\r\n * @returns the associated view\r\n */\r\n registerView(canvas: HTMLCanvasElement, camera?: Camera | Camera[], clearBeforeCopy?: boolean): EngineView;\r\n\r\n /**\r\n * Remove a registered child canvas\r\n * @param canvas defines the canvas to remove\r\n * @returns the current engine\r\n */\r\n unRegisterView(canvas: HTMLCanvasElement): AbstractEngine;\r\n\r\n /**\r\n * @internal\r\n */\r\n _renderViewStep(view: EngineView): boolean;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"abstractEngine.views.types.js","sourceRoot":"","sources":["../../../../../dev/core/src/Engines/AbstractEngine/abstractEngine.views.types.ts"],"names":[],"mappings":"","sourcesContent":["import { type Camera } from \"../../Cameras/camera\";\r\nimport { type Nullable } from \"../../types\";\r\nimport { type Observable } from \"../../Misc/observable\";\r\nimport { type EngineView } from \"./abstractEngine.views.pure\";\r\ndeclare module \"../../Engines/abstractEngine.pure\" {\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n export interface AbstractEngine {\r\n /** @internal */\r\n _inputElement: Nullable<HTMLElement>;\r\n\r\n /**\r\n * Gets or sets the HTML element to use for attaching events\r\n */\r\n inputElement: Nullable<HTMLElement>;\r\n\r\n /**\r\n * Observable to handle when a change to inputElement occurs\r\n * @internal\r\n */\r\n _onEngineViewChanged?: () => void;\r\n\r\n /**\r\n * Will be triggered before the view renders\r\n */\r\n readonly onBeforeViewRenderObservable: Observable<EngineView>;\r\n /**\r\n * Will be triggered after the view rendered\r\n */\r\n readonly onAfterViewRenderObservable: Observable<EngineView>;\r\n\r\n /**\r\n * Gets the current engine view\r\n * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/multiCanvas\r\n */\r\n activeView: Nullable<EngineView>;\r\n\r\n /** Gets or sets the list of views */\r\n views: EngineView[];\r\n\r\n /**\r\n * Register a new child canvas\r\n * @param canvas defines the canvas to register\r\n * @param camera defines an optional camera or array of cameras to use with this canvas (it will overwrite the scene.activeCamera / scene.activeCameras for this view). Support for array of cameras @since\r\n * @param clearBeforeCopy Indicates if the destination view canvas should be cleared before copying the parent canvas. Can help if the scene clear color has alpha \\< 1\r\n * @param customResize defines the canvas custom resize handle\r\n * @returns the associated view\r\n */\r\n registerView(canvas: HTMLCanvasElement, camera?: Camera | Camera[], clearBeforeCopy?: boolean, customResize?: EngineView[\"customResize\"]): EngineView;\r\n\r\n /**\r\n * Remove a registered child canvas\r\n * @param canvas defines the canvas to remove\r\n * @returns the current engine\r\n */\r\n unRegisterView(canvas: HTMLCanvasElement): AbstractEngine;\r\n\r\n /**\r\n * @internal\r\n */\r\n _renderViewStep(view: EngineView): boolean;\r\n }\r\n}\r\n"]}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Re-exports pure implementation and applies runtime side effects.
3
+ * Import gaussianSplattingDebugMaterialPlugin.pure for tree-shakeable, side-effect-free usage.
4
+ */
5
+ export * from "./gaussianSplattingDebugMaterialPlugin.pure.js";
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Re-exports pure implementation and applies runtime side effects.
3
+ * Import gaussianSplattingDebugMaterialPlugin.pure for tree-shakeable, side-effect-free usage.
4
+ */
5
+ export * from "./gaussianSplattingDebugMaterialPlugin.pure.js";
6
+ import { RegisterGaussianSplattingDebugMaterialPlugin } from "./gaussianSplattingDebugMaterialPlugin.pure.js";
7
+ RegisterGaussianSplattingDebugMaterialPlugin();
8
+ //# sourceMappingURL=gaussianSplattingDebugMaterialPlugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gaussianSplattingDebugMaterialPlugin.js","sourceRoot":"","sources":["../../../../../dev/core/src/Materials/GaussianSplatting/gaussianSplattingDebugMaterialPlugin.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,cAAc,6CAA6C,CAAC;AAE5D,OAAO,EAAE,4CAA4C,EAAE,MAAM,6CAA6C,CAAC;AAC3G,4CAA4C,EAAE,CAAC","sourcesContent":["/**\n * Re-exports pure implementation and applies runtime side effects.\n * Import gaussianSplattingDebugMaterialPlugin.pure for tree-shakeable, side-effect-free usage.\n */\nexport * from \"./gaussianSplattingDebugMaterialPlugin.pure\";\n\nimport { RegisterGaussianSplattingDebugMaterialPlugin } from \"./gaussianSplattingDebugMaterialPlugin.pure\";\nRegisterGaussianSplattingDebugMaterialPlugin();\n"]}
@@ -0,0 +1,278 @@
1
+ /** This file must only contain pure code and pure imports */
2
+ import { type Nullable } from "../../types.js";
3
+ import { type Scene } from "../../scene.js";
4
+ import { type AbstractEngine } from "../../Engines/abstractEngine.js";
5
+ import { type SubMesh } from "../../Meshes/subMesh.js";
6
+ import { type UniformBuffer } from "../uniformBuffer.js";
7
+ import { MaterialDefines } from "../materialDefines.js";
8
+ import { MaterialPluginBase } from "../materialPluginBase.pure.js";
9
+ import { ShaderLanguage } from "../shaderLanguage.js";
10
+ import { type Vector3 } from "../../Maths/math.vector.js";
11
+ import { type GaussianSplattingMaterial } from "./gaussianSplattingMaterial.pure.js";
12
+ /** @internal */
13
+ declare class GaussianSplattingDebugDefines extends MaterialDefines {
14
+ /** Defines whether any debug feature is active */
15
+ GS_DBG_ENABLED: boolean;
16
+ /** Defines whether world-space clipping box is enabled (0: off, 1: on) */
17
+ GS_DBG_CLIP: number;
18
+ /** Defines whether opacity culling is enabled (0: off, 1: on) */
19
+ GS_DBG_CULL_OPACITY: number;
20
+ /** Defines whether size culling is enabled (0: off, 1: on) */
21
+ GS_DBG_CULL_SIZE: number;
22
+ /** Defines whether per-splat opacity scaling is enabled (0: off, 1: on) */
23
+ GS_DBG_OPACITY_SCALE: number;
24
+ /** Defines whether opacity saturation (flat disk) is enabled (0: off, 1: on) */
25
+ GS_DBG_OPACITY_SATURATE: number;
26
+ /** Defines whether the DC (base) SH color is included (0: off, 1: on) */
27
+ GS_DBG_SH_DC: number;
28
+ /** Defines whether SH band 1 contribution is included (0: off, 1: on) */
29
+ GS_DBG_SH_ORDER1: number;
30
+ /** Defines whether SH band 2 contribution is included (0: off, 1: on) */
31
+ GS_DBG_SH_ORDER2: number;
32
+ /** Defines whether SH band 3 contribution is included (0: off, 1: on) */
33
+ GS_DBG_SH_ORDER3: number;
34
+ /** Defines whether SH band 4 contribution is included (0: off, 1: on) */
35
+ GS_DBG_SH_ORDER4: number;
36
+ }
37
+ /**
38
+ * Per-part debug options for compound Gaussian splat meshes.
39
+ * Each field is optional; unset fields fall back to the global setting on the plugin,
40
+ * and if that is also unset, a neutral value is used (no culling, full SH, etc.).
41
+ */
42
+ export interface IGaussianSplattingDebugOptions {
43
+ /** World-space axis-aligned clipping box, or null to disable. */
44
+ clippingBox: Nullable<{
45
+ min: Vector3;
46
+ max: Vector3;
47
+ }>;
48
+ /** Opacity culling range [0..1], or null to disable. */
49
+ opacityCulling: Nullable<{
50
+ min: number;
51
+ max: number;
52
+ }>;
53
+ /** Size culling range, or null to disable. */
54
+ sizeCulling: Nullable<{
55
+ min: number;
56
+ max: number;
57
+ }>;
58
+ /** Scalar opacity multiplier. 1.0 = no change. */
59
+ opacityScale: number;
60
+ /** When true, replaces Gaussian falloff with flat disk opacity. */
61
+ opacitySaturate: boolean;
62
+ /** Include the DC (base) SH color. */
63
+ shDc: boolean;
64
+ /** Include SH band 1 contribution. */
65
+ shOrder1: boolean;
66
+ /** Include SH band 2 contribution. */
67
+ shOrder2: boolean;
68
+ /** Include SH band 3 contribution. */
69
+ shOrder3: boolean;
70
+ /** Include SH band 4 contribution. */
71
+ shOrder4: boolean;
72
+ }
73
+ /**
74
+ * Debug plugin for GaussianSplattingMaterial.
75
+ * Provides runtime controls for clipping, opacity/size culling, opacity scaling,
76
+ * opacity saturation, and per-SH-order toggling. All features are gated behind
77
+ * the GS_DBG_ENABLED shader define — when every option is at its default value
78
+ * the define is absent and the shader compiles to identical code as without the plugin.
79
+ *
80
+ * In compound mode (partCount \> 0), per-part overrides can be set via setPartOptions().
81
+ * Global settings act as defaults; per-part settings override them for that part index.
82
+ */
83
+ export declare class GaussianSplattingDebugMaterialPlugin extends MaterialPluginBase {
84
+ private _clippingBox;
85
+ private _opacityCulling;
86
+ private _sizeCulling;
87
+ private _opacityScale;
88
+ private _opacitySaturate;
89
+ private _shDc;
90
+ private _shOrder1;
91
+ private _shOrder2;
92
+ private _shOrder3;
93
+ private _shOrder4;
94
+ private _partCount;
95
+ private _partClippingBoxes;
96
+ private _partOpacityCullings;
97
+ private _partSizeCullings;
98
+ private _partOpacityScales;
99
+ private _partOpacitySaturates;
100
+ private _partShDcs;
101
+ private _partShOrder1s;
102
+ private _partShOrder2s;
103
+ private _partShOrder3s;
104
+ private _partShOrder4s;
105
+ private _dbgPartDataTexture;
106
+ private _textureDirty;
107
+ private _maxPartCount;
108
+ /**
109
+ * Creates a new GaussianSplattingDebugMaterialPlugin.
110
+ * @param material The GaussianSplattingMaterial to attach the plugin to.
111
+ */
112
+ constructor(material: GaussianSplattingMaterial);
113
+ private _isAnyFeatureActive;
114
+ private _markDirty;
115
+ /**
116
+ * Number of parts in compound mode. Set automatically by GaussianSplattingDebugger.addMesh().
117
+ * When 0 (non-compound), setPartOptions() logs an error.
118
+ * @returns the part count
119
+ */
120
+ get partCount(): number;
121
+ set partCount(count: number);
122
+ /**
123
+ * Sets per-part debug overrides for the given part index.
124
+ * Only valid on compound meshes (partCount \> 0); logs an error otherwise.
125
+ * @param partIndex The zero-based part index.
126
+ * @param options Partial set of debug options to override for this part.
127
+ */
128
+ setPartOptions(partIndex: number, options: Partial<IGaussianSplattingDebugOptions>): void;
129
+ /**
130
+ * Clears all per-part debug overrides for the given part index,
131
+ * falling back to global settings.
132
+ * @param partIndex The zero-based part index.
133
+ */
134
+ clearPartOptions(partIndex: number): void;
135
+ /**
136
+ * World-space axis-aligned clipping box. Splats outside are not rendered.
137
+ * Set to null to disable clipping.
138
+ * Example: `{ min: new Vector3(-2,-2,-2), max: new Vector3(2,2,2) }`
139
+ */
140
+ get clippingBox(): Nullable<{
141
+ min: Vector3;
142
+ max: Vector3;
143
+ }>;
144
+ set clippingBox(value: Nullable<{
145
+ min: Vector3;
146
+ max: Vector3;
147
+ }>);
148
+ /**
149
+ * Opacity culling range [0..1]. Splats whose stored opacity falls outside this
150
+ * range are not rendered. Set to null to disable.
151
+ */
152
+ get opacityCulling(): Nullable<{
153
+ min: number;
154
+ max: number;
155
+ }>;
156
+ set opacityCulling(value: Nullable<{
157
+ min: number;
158
+ max: number;
159
+ }>);
160
+ /**
161
+ * Size culling range. Size is pow(|det(Σ)|, 1/6) of the 3D covariance matrix,
162
+ * equal to the geometric mean of the principal radii. Use GaussianSplattingMeshBase.splatSizeRange
163
+ * to find the asset's range. Set to null to disable.
164
+ */
165
+ get sizeCulling(): Nullable<{
166
+ min: number;
167
+ max: number;
168
+ }>;
169
+ set sizeCulling(value: Nullable<{
170
+ min: number;
171
+ max: number;
172
+ }>);
173
+ /**
174
+ * Scalar multiplier applied to every splat's opacity after all other modifiers.
175
+ * 1.0 (default) = no change.
176
+ */
177
+ get opacityScale(): number;
178
+ set opacityScale(value: number);
179
+ /**
180
+ * When true, replaces the Gaussian spatial falloff with a flat uniform opacity,
181
+ * making each splat appear as a solid disk with its raw alpha value.
182
+ */
183
+ get opacitySaturate(): boolean;
184
+ set opacitySaturate(value: boolean);
185
+ /** Include the DC (base) color from colorsTexture. Default: true. */
186
+ get shDc(): boolean;
187
+ set shDc(value: boolean);
188
+ /** Include SH band 1 contribution. Default: true. */
189
+ get shOrder1(): boolean;
190
+ set shOrder1(value: boolean);
191
+ /** Include SH band 2 contribution. Default: true. */
192
+ get shOrder2(): boolean;
193
+ set shOrder2(value: boolean);
194
+ /** Include SH band 3 contribution. Default: true. */
195
+ get shOrder3(): boolean;
196
+ set shOrder3(value: boolean);
197
+ /** Include SH band 4 contribution. Default: true. */
198
+ get shOrder4(): boolean;
199
+ set shOrder4(value: boolean);
200
+ /**
201
+ * Adds the per-part debug data texture name to the sampler list so the effect can bind it.
202
+ * @param samplers the sampler list to populate
203
+ */
204
+ getSamplers(samplers: string[]): void;
205
+ /** @returns the class name of this plugin */
206
+ getClassName(): string;
207
+ /**
208
+ * @param shaderLanguage the shader language to check
209
+ * @returns true for GLSL and WGSL
210
+ */
211
+ isCompatible(shaderLanguage: ShaderLanguage): boolean;
212
+ /**
213
+ * Always ready — no async resources.
214
+ * @param _defines unused
215
+ * @param _scene unused
216
+ * @param _engine unused
217
+ * @param _subMesh unused
218
+ * @returns true
219
+ */
220
+ isReadyForSubMesh(_defines: MaterialDefines, _scene: Scene, _engine: AbstractEngine, _subMesh: SubMesh): boolean;
221
+ /**
222
+ * Sets shader defines from current property state. GS_DBG_ENABLED is set to true
223
+ * only when at least one feature is non-default, ensuring zero overhead otherwise.
224
+ * Sub-flags also check per-part arrays so compound-only overrides activate the correct
225
+ * code paths even when the global setting is at its default.
226
+ * @param defines the defines object
227
+ */
228
+ prepareDefines(defines: GaussianSplattingDebugDefines): void;
229
+ /**
230
+ * Returns shader code injections for the debug features.
231
+ * @param shaderType "vertex" or "fragment"
232
+ * @param shaderLanguage GLSL or WGSL
233
+ * @returns map of injection-point name to injected code, or null
234
+ */
235
+ getCustomCode(shaderType: string, shaderLanguage?: ShaderLanguage): Nullable<{
236
+ [pointName: string]: string;
237
+ }>;
238
+ private _getCustomCodeGLSL;
239
+ private _getCustomCodeWGSL;
240
+ /**
241
+ * Declares the non-compound scalar debug uniform names as external so the Effect can
242
+ * resolve their locations. WGSL uniforms are declared inline in getCustomCode() injections.
243
+ * @returns uniform descriptor with externalUniforms list
244
+ */
245
+ getUniforms(): {
246
+ ubo?: Array<{
247
+ name: string;
248
+ size?: number;
249
+ type?: string;
250
+ arraySize?: number;
251
+ }>;
252
+ vertex?: string;
253
+ fragment?: string;
254
+ externalUniforms?: string[];
255
+ };
256
+ private _buildTextureData;
257
+ private _updateOrCreateTexture;
258
+ /**
259
+ * Binds uniform values each frame. Scalar uniforms are uploaded for non-compound mode;
260
+ * the per-part data texture is updated and bound for compound mode.
261
+ * @param _uniformBuffer unused
262
+ * @param _scene the current scene
263
+ * @param _engine unused
264
+ * @param subMesh the submesh being rendered
265
+ */
266
+ bindForSubMesh(_uniformBuffer: UniformBuffer, _scene: Scene, _engine: AbstractEngine, subMesh: SubMesh): void;
267
+ /**
268
+ * Disposes the per-part data texture.
269
+ * @param _forceDisposeTextures unused; the LUT texture is always disposed as it is owned by this plugin
270
+ */
271
+ dispose(_forceDisposeTextures?: boolean): void;
272
+ }
273
+ /**
274
+ * Register side effects for GaussianSplattingDebugMaterialPlugin.
275
+ * Safe to call multiple times; only the first call has an effect.
276
+ */
277
+ export declare function RegisterGaussianSplattingDebugMaterialPlugin(): void;
278
+ export {};