@vib3code/sdk 2.0.1

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 (258) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
  3. package/DOCS/CI_TESTING.md +38 -0
  4. package/DOCS/CLI_ONBOARDING.md +75 -0
  5. package/DOCS/CONTROL_REFERENCE.md +64 -0
  6. package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
  7. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
  8. package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
  9. package/DOCS/ENV_SETUP.md +189 -0
  10. package/DOCS/EXPORT_FORMATS.md +417 -0
  11. package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
  12. package/DOCS/LICENSING_TIERS.md +275 -0
  13. package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
  14. package/DOCS/OBS_SETUP_GUIDE.md +98 -0
  15. package/DOCS/PROJECT_SETUP.md +66 -0
  16. package/DOCS/RENDERER_LIFECYCLE.md +40 -0
  17. package/DOCS/REPO_MANIFEST.md +121 -0
  18. package/DOCS/SESSION_014_PLAN.md +195 -0
  19. package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
  20. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
  21. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
  22. package/DOCS/SYSTEM_INVENTORY.md +520 -0
  23. package/DOCS/TELEMETRY_EXPORTS.md +34 -0
  24. package/DOCS/WEBGPU_STATUS.md +38 -0
  25. package/DOCS/XR_BENCHMARKS.md +608 -0
  26. package/LICENSE +21 -0
  27. package/README.md +426 -0
  28. package/docs/.nojekyll +0 -0
  29. package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
  30. package/docs/02-hyperspatial_ego_death.html +346 -0
  31. package/docs/03-post_cartesian_sublime.html +346 -0
  32. package/docs/04-crystalline_void_meditation.html +346 -0
  33. package/docs/05-quantum_decoherence_ballet.html +346 -0
  34. package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
  35. package/docs/07-hyperspatial_ego_death.html +346 -0
  36. package/docs/08-post_cartesian_sublime.html +346 -0
  37. package/docs/09-crystalline_void_meditation.html +346 -0
  38. package/docs/10-quantum_decoherence_ballet.html +346 -0
  39. package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
  40. package/docs/12-hyperspatial_ego_death.html +346 -0
  41. package/docs/13-post_cartesian_sublime.html +346 -0
  42. package/docs/index.html +794 -0
  43. package/docs/test-hub.html +441 -0
  44. package/docs/url-state.js +102 -0
  45. package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
  46. package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
  47. package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
  48. package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
  49. package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
  50. package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
  51. package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
  52. package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
  53. package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
  54. package/docs/vib3-exports/index.html +238 -0
  55. package/docs/webgpu-live.html +702 -0
  56. package/package.json +367 -0
  57. package/src/advanced/AIPresetGenerator.js +777 -0
  58. package/src/advanced/MIDIController.js +703 -0
  59. package/src/advanced/OffscreenWorker.js +1051 -0
  60. package/src/advanced/WebGPUCompute.js +1051 -0
  61. package/src/advanced/WebXRRenderer.js +680 -0
  62. package/src/agent/cli/AgentCLI.js +615 -0
  63. package/src/agent/cli/index.js +14 -0
  64. package/src/agent/index.js +73 -0
  65. package/src/agent/mcp/MCPServer.js +950 -0
  66. package/src/agent/mcp/index.js +9 -0
  67. package/src/agent/mcp/tools.js +548 -0
  68. package/src/agent/telemetry/EventStream.js +669 -0
  69. package/src/agent/telemetry/Instrumentation.js +618 -0
  70. package/src/agent/telemetry/TelemetryExporters.js +427 -0
  71. package/src/agent/telemetry/TelemetryService.js +464 -0
  72. package/src/agent/telemetry/index.js +52 -0
  73. package/src/benchmarks/BenchmarkRunner.js +381 -0
  74. package/src/benchmarks/MetricsCollector.js +299 -0
  75. package/src/benchmarks/index.js +9 -0
  76. package/src/benchmarks/scenes.js +259 -0
  77. package/src/cli/index.js +675 -0
  78. package/src/config/ApiConfig.js +88 -0
  79. package/src/core/CanvasManager.js +217 -0
  80. package/src/core/ErrorReporter.js +117 -0
  81. package/src/core/ParameterMapper.js +333 -0
  82. package/src/core/Parameters.js +396 -0
  83. package/src/core/RendererContracts.js +200 -0
  84. package/src/core/UnifiedResourceManager.js +370 -0
  85. package/src/core/VIB3Engine.js +636 -0
  86. package/src/core/renderers/FacetedRendererAdapter.js +32 -0
  87. package/src/core/renderers/HolographicRendererAdapter.js +29 -0
  88. package/src/core/renderers/QuantumRendererAdapter.js +29 -0
  89. package/src/core/renderers/RendererLifecycleManager.js +63 -0
  90. package/src/creative/ColorPresetsSystem.js +980 -0
  91. package/src/creative/ParameterTimeline.js +1061 -0
  92. package/src/creative/PostProcessingPipeline.js +1113 -0
  93. package/src/creative/TransitionAnimator.js +683 -0
  94. package/src/export/CSSExporter.js +226 -0
  95. package/src/export/CardGeneratorBase.js +279 -0
  96. package/src/export/ExportManager.js +580 -0
  97. package/src/export/FacetedCardGenerator.js +279 -0
  98. package/src/export/HolographicCardGenerator.js +543 -0
  99. package/src/export/LottieExporter.js +552 -0
  100. package/src/export/QuantumCardGenerator.js +315 -0
  101. package/src/export/SVGExporter.js +519 -0
  102. package/src/export/ShaderExporter.js +903 -0
  103. package/src/export/TradingCardGenerator.js +3055 -0
  104. package/src/export/TradingCardManager.js +181 -0
  105. package/src/export/VIB3PackageExporter.js +559 -0
  106. package/src/export/index.js +14 -0
  107. package/src/export/systems/TradingCardSystemFaceted.js +494 -0
  108. package/src/export/systems/TradingCardSystemHolographic.js +452 -0
  109. package/src/export/systems/TradingCardSystemQuantum.js +411 -0
  110. package/src/faceted/FacetedSystem.js +963 -0
  111. package/src/features/CollectionManager.js +433 -0
  112. package/src/gallery/CollectionManager.js +240 -0
  113. package/src/gallery/GallerySystem.js +485 -0
  114. package/src/geometry/GeometryFactory.js +314 -0
  115. package/src/geometry/GeometryLibrary.js +72 -0
  116. package/src/geometry/buffers/BufferBuilder.js +338 -0
  117. package/src/geometry/buffers/index.js +18 -0
  118. package/src/geometry/generators/Crystal.js +420 -0
  119. package/src/geometry/generators/Fractal.js +298 -0
  120. package/src/geometry/generators/KleinBottle.js +197 -0
  121. package/src/geometry/generators/Sphere.js +192 -0
  122. package/src/geometry/generators/Tesseract.js +160 -0
  123. package/src/geometry/generators/Tetrahedron.js +225 -0
  124. package/src/geometry/generators/Torus.js +304 -0
  125. package/src/geometry/generators/Wave.js +341 -0
  126. package/src/geometry/index.js +142 -0
  127. package/src/geometry/warp/HypersphereCore.js +211 -0
  128. package/src/geometry/warp/HypertetraCore.js +386 -0
  129. package/src/geometry/warp/index.js +57 -0
  130. package/src/holograms/HolographicVisualizer.js +1073 -0
  131. package/src/holograms/RealHolographicSystem.js +966 -0
  132. package/src/holograms/variantRegistry.js +69 -0
  133. package/src/integrations/FigmaPlugin.js +854 -0
  134. package/src/integrations/OBSMode.js +754 -0
  135. package/src/integrations/ThreeJsPackage.js +660 -0
  136. package/src/integrations/TouchDesignerExport.js +552 -0
  137. package/src/integrations/frameworks/Vib3React.js +591 -0
  138. package/src/integrations/frameworks/Vib3Svelte.js +654 -0
  139. package/src/integrations/frameworks/Vib3Vue.js +628 -0
  140. package/src/llm/LLMParameterInterface.js +240 -0
  141. package/src/llm/LLMParameterUI.js +577 -0
  142. package/src/math/Mat4x4.js +708 -0
  143. package/src/math/Projection.js +341 -0
  144. package/src/math/Rotor4D.js +637 -0
  145. package/src/math/Vec4.js +476 -0
  146. package/src/math/constants.js +164 -0
  147. package/src/math/index.js +68 -0
  148. package/src/math/projections.js +54 -0
  149. package/src/math/rotations.js +196 -0
  150. package/src/quantum/QuantumEngine.js +906 -0
  151. package/src/quantum/QuantumVisualizer.js +1103 -0
  152. package/src/reactivity/ReactivityConfig.js +499 -0
  153. package/src/reactivity/ReactivityManager.js +586 -0
  154. package/src/reactivity/SpatialInputSystem.js +1783 -0
  155. package/src/reactivity/index.js +93 -0
  156. package/src/render/CommandBuffer.js +465 -0
  157. package/src/render/MultiCanvasBridge.js +340 -0
  158. package/src/render/RenderCommand.js +514 -0
  159. package/src/render/RenderResourceRegistry.js +523 -0
  160. package/src/render/RenderState.js +552 -0
  161. package/src/render/RenderTarget.js +512 -0
  162. package/src/render/ShaderLoader.js +253 -0
  163. package/src/render/ShaderProgram.js +599 -0
  164. package/src/render/UnifiedRenderBridge.js +496 -0
  165. package/src/render/backends/WebGLBackend.js +1108 -0
  166. package/src/render/backends/WebGPUBackend.js +1409 -0
  167. package/src/render/commands/CommandBufferExecutor.js +607 -0
  168. package/src/render/commands/RenderCommandBuffer.js +661 -0
  169. package/src/render/commands/index.js +17 -0
  170. package/src/render/index.js +367 -0
  171. package/src/scene/Disposable.js +498 -0
  172. package/src/scene/MemoryPool.js +618 -0
  173. package/src/scene/Node4D.js +697 -0
  174. package/src/scene/ResourceManager.js +599 -0
  175. package/src/scene/Scene4D.js +540 -0
  176. package/src/scene/index.js +98 -0
  177. package/src/schemas/error.schema.json +84 -0
  178. package/src/schemas/extension.schema.json +88 -0
  179. package/src/schemas/index.js +214 -0
  180. package/src/schemas/parameters.schema.json +142 -0
  181. package/src/schemas/tool-pack.schema.json +44 -0
  182. package/src/schemas/tool-response.schema.json +127 -0
  183. package/src/shaders/common/fullscreen.vert.glsl +5 -0
  184. package/src/shaders/common/fullscreen.vert.wgsl +17 -0
  185. package/src/shaders/common/geometry24.glsl +65 -0
  186. package/src/shaders/common/geometry24.wgsl +54 -0
  187. package/src/shaders/common/rotation4d.glsl +85 -0
  188. package/src/shaders/common/rotation4d.wgsl +86 -0
  189. package/src/shaders/common/uniforms.glsl +44 -0
  190. package/src/shaders/common/uniforms.wgsl +48 -0
  191. package/src/shaders/faceted/faceted.frag.glsl +129 -0
  192. package/src/shaders/faceted/faceted.frag.wgsl +164 -0
  193. package/src/shaders/holographic/holographic.frag.glsl +406 -0
  194. package/src/shaders/holographic/holographic.frag.wgsl +185 -0
  195. package/src/shaders/quantum/quantum.frag.glsl +513 -0
  196. package/src/shaders/quantum/quantum.frag.wgsl +361 -0
  197. package/src/testing/ParallelTestFramework.js +519 -0
  198. package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
  199. package/src/testing/exportFormats.test.js +8 -0
  200. package/src/testing/projections.test.js +14 -0
  201. package/src/testing/rotations.test.js +37 -0
  202. package/src/ui/InteractivityMenu.js +516 -0
  203. package/src/ui/StatusManager.js +96 -0
  204. package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
  205. package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
  206. package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
  207. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
  208. package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
  209. package/src/variations/VariationManager.js +431 -0
  210. package/src/viewer/AudioReactivity.js +505 -0
  211. package/src/viewer/CardBending.js +481 -0
  212. package/src/viewer/GalleryUI.js +832 -0
  213. package/src/viewer/ReactivityManager.js +590 -0
  214. package/src/viewer/TradingCardExporter.js +600 -0
  215. package/src/viewer/ViewerPortal.js +374 -0
  216. package/src/viewer/index.js +12 -0
  217. package/src/wasm/WasmLoader.js +296 -0
  218. package/src/wasm/index.js +132 -0
  219. package/tools/agentic/mcpTools.js +88 -0
  220. package/tools/cli/agent-cli.js +92 -0
  221. package/tools/export/formats.js +24 -0
  222. package/tools/math/rotation-baseline.mjs +64 -0
  223. package/tools/shader-sync-verify.js +937 -0
  224. package/tools/telemetry/manifestPipeline.js +141 -0
  225. package/tools/telemetry/telemetryEvents.js +35 -0
  226. package/types/adaptive-sdk.d.ts +185 -0
  227. package/types/advanced/AIPresetGenerator.d.ts +81 -0
  228. package/types/advanced/MIDIController.d.ts +100 -0
  229. package/types/advanced/OffscreenWorker.d.ts +82 -0
  230. package/types/advanced/WebGPUCompute.d.ts +52 -0
  231. package/types/advanced/WebXRRenderer.d.ts +77 -0
  232. package/types/advanced/index.d.ts +46 -0
  233. package/types/core/ErrorReporter.d.ts +50 -0
  234. package/types/core/VIB3Engine.d.ts +204 -0
  235. package/types/creative/ColorPresetsSystem.d.ts +91 -0
  236. package/types/creative/ParameterTimeline.d.ts +74 -0
  237. package/types/creative/PostProcessingPipeline.d.ts +109 -0
  238. package/types/creative/TransitionAnimator.d.ts +71 -0
  239. package/types/creative/index.d.ts +35 -0
  240. package/types/integrations/FigmaPlugin.d.ts +46 -0
  241. package/types/integrations/OBSMode.d.ts +74 -0
  242. package/types/integrations/ThreeJsPackage.d.ts +62 -0
  243. package/types/integrations/TouchDesignerExport.d.ts +36 -0
  244. package/types/integrations/Vib3React.d.ts +74 -0
  245. package/types/integrations/Vib3Svelte.d.ts +63 -0
  246. package/types/integrations/Vib3Vue.d.ts +55 -0
  247. package/types/integrations/index.d.ts +52 -0
  248. package/types/reactivity/SpatialInputSystem.d.ts +173 -0
  249. package/types/reactivity/index.d.ts +394 -0
  250. package/types/render/CommandBuffer.d.ts +169 -0
  251. package/types/render/RenderCommand.d.ts +312 -0
  252. package/types/render/RenderState.d.ts +279 -0
  253. package/types/render/RenderTarget.d.ts +254 -0
  254. package/types/render/ShaderProgram.d.ts +277 -0
  255. package/types/render/UnifiedRenderBridge.d.ts +143 -0
  256. package/types/render/WebGLBackend.d.ts +168 -0
  257. package/types/render/WebGPUBackend.d.ts +186 -0
  258. package/types/render/index.d.ts +141 -0
@@ -0,0 +1,590 @@
1
+ /**
2
+ * ReactivityManager.js - Unified Input Handler for 4D Visualization
3
+ *
4
+ * Manages multiple input sources and maps them to 4D rotation:
5
+ * - Mouse movement and drag
6
+ * - Touch gestures (pan, pinch, rotate)
7
+ * - Device orientation (gyroscope/accelerometer)
8
+ * - Keyboard shortcuts
9
+ * - Gamepad input
10
+ */
11
+
12
+ import { EventEmitter } from 'events';
13
+
14
+ /**
15
+ * Input source types
16
+ */
17
+ export const InputSource = {
18
+ MOUSE: 'mouse',
19
+ TOUCH: 'touch',
20
+ GYROSCOPE: 'gyroscope',
21
+ KEYBOARD: 'keyboard',
22
+ GAMEPAD: 'gamepad'
23
+ };
24
+
25
+ /**
26
+ * Input mapping presets
27
+ */
28
+ export const InputPreset = {
29
+ DEFAULT: 'default',
30
+ MOBILE: 'mobile',
31
+ DESKTOP: 'desktop',
32
+ VR: 'vr'
33
+ };
34
+
35
+ /**
36
+ * ReactivityManager - Unified input handling
37
+ */
38
+ export class ReactivityManager extends EventEmitter {
39
+ constructor(options = {}) {
40
+ super();
41
+
42
+ /** @type {HTMLElement|null} */
43
+ this.element = null;
44
+
45
+ /** @type {Set<string>} Active input sources */
46
+ this.activeSources = new Set();
47
+
48
+ /** @type {object} Current input state */
49
+ this.state = {
50
+ // Mouse/touch position (normalized -1 to 1)
51
+ pointerX: 0,
52
+ pointerY: 0,
53
+ // Pointer delta
54
+ deltaX: 0,
55
+ deltaY: 0,
56
+ // Multi-touch
57
+ pinchScale: 1,
58
+ rotationAngle: 0,
59
+ // Device orientation
60
+ alpha: 0, // Compass direction (0-360)
61
+ beta: 0, // Front/back tilt (-180 to 180)
62
+ gamma: 0, // Left/right tilt (-90 to 90)
63
+ // Keyboard
64
+ keys: new Set(),
65
+ // Gamepad axes
66
+ gamepadAxes: [0, 0, 0, 0]
67
+ };
68
+
69
+ /** @type {object} Rotation output (6 planes) */
70
+ this.rotation = {
71
+ xy: 0, xz: 0, yz: 0,
72
+ xw: 0, yw: 0, zw: 0
73
+ };
74
+
75
+ /** @type {object} Configuration */
76
+ this.config = {
77
+ // Sensitivity multipliers
78
+ mouseSensitivity: options.mouseSensitivity || 0.005,
79
+ touchSensitivity: options.touchSensitivity || 0.008,
80
+ gyroSensitivity: options.gyroSensitivity || 0.02,
81
+ keyboardSpeed: options.keyboardSpeed || 0.02,
82
+ gamepadSensitivity: options.gamepadSensitivity || 0.03,
83
+ // Damping
84
+ damping: options.damping || 0.92,
85
+ // Deadzone for gamepad
86
+ deadzone: options.deadzone || 0.1,
87
+ // Input mapping
88
+ mapping: options.mapping || this._getDefaultMapping()
89
+ };
90
+
91
+ /** @type {object} Velocity for momentum */
92
+ this._velocity = {
93
+ xy: 0, xz: 0, yz: 0,
94
+ xw: 0, yw: 0, zw: 0
95
+ };
96
+
97
+ /** @type {object} Touch tracking */
98
+ this._touches = new Map();
99
+ this._initialPinchDistance = 0;
100
+ this._initialRotationAngle = 0;
101
+
102
+ /** @type {number|null} Gamepad polling interval */
103
+ this._gamepadInterval = null;
104
+
105
+ /** @type {number|null} Animation frame */
106
+ this._animationFrame = null;
107
+
108
+ // Bind methods
109
+ this._onMouseMove = this._onMouseMove.bind(this);
110
+ this._onMouseDown = this._onMouseDown.bind(this);
111
+ this._onMouseUp = this._onMouseUp.bind(this);
112
+ this._onWheel = this._onWheel.bind(this);
113
+ this._onTouchStart = this._onTouchStart.bind(this);
114
+ this._onTouchMove = this._onTouchMove.bind(this);
115
+ this._onTouchEnd = this._onTouchEnd.bind(this);
116
+ this._onDeviceOrientation = this._onDeviceOrientation.bind(this);
117
+ this._onKeyDown = this._onKeyDown.bind(this);
118
+ this._onKeyUp = this._onKeyUp.bind(this);
119
+ this._pollGamepad = this._pollGamepad.bind(this);
120
+ this._update = this._update.bind(this);
121
+ }
122
+
123
+ /**
124
+ * Initialize with target element
125
+ * @param {HTMLElement} element
126
+ */
127
+ initialize(element) {
128
+ this.element = element;
129
+ this._addEventListeners();
130
+ this._startUpdateLoop();
131
+ this.emit('initialized');
132
+ return this;
133
+ }
134
+
135
+ /**
136
+ * Dispose and cleanup
137
+ */
138
+ dispose() {
139
+ this._stopUpdateLoop();
140
+ this._removeEventListeners();
141
+ this.emit('disposed');
142
+ }
143
+
144
+ /**
145
+ * Enable specific input source
146
+ * @param {string} source - Input source type
147
+ */
148
+ async enableSource(source) {
149
+ switch (source) {
150
+ case InputSource.MOUSE:
151
+ this.activeSources.add(source);
152
+ break;
153
+
154
+ case InputSource.TOUCH:
155
+ this.activeSources.add(source);
156
+ break;
157
+
158
+ case InputSource.GYROSCOPE:
159
+ const granted = await this._requestGyroscopePermission();
160
+ if (granted) {
161
+ window.addEventListener('deviceorientation', this._onDeviceOrientation);
162
+ this.activeSources.add(source);
163
+ }
164
+ break;
165
+
166
+ case InputSource.KEYBOARD:
167
+ this.activeSources.add(source);
168
+ break;
169
+
170
+ case InputSource.GAMEPAD:
171
+ this._startGamepadPolling();
172
+ this.activeSources.add(source);
173
+ break;
174
+ }
175
+
176
+ this.emit('sourceEnabled', source);
177
+ return this.activeSources.has(source);
178
+ }
179
+
180
+ /**
181
+ * Disable specific input source
182
+ * @param {string} source
183
+ */
184
+ disableSource(source) {
185
+ switch (source) {
186
+ case InputSource.GYROSCOPE:
187
+ window.removeEventListener('deviceorientation', this._onDeviceOrientation);
188
+ break;
189
+ case InputSource.GAMEPAD:
190
+ this._stopGamepadPolling();
191
+ break;
192
+ }
193
+
194
+ this.activeSources.delete(source);
195
+ this.emit('sourceDisabled', source);
196
+ }
197
+
198
+ /**
199
+ * Set input preset
200
+ * @param {string} preset
201
+ */
202
+ setPreset(preset) {
203
+ switch (preset) {
204
+ case InputPreset.MOBILE:
205
+ this.config.mapping = this._getMobileMapping();
206
+ break;
207
+ case InputPreset.DESKTOP:
208
+ this.config.mapping = this._getDesktopMapping();
209
+ break;
210
+ case InputPreset.VR:
211
+ this.config.mapping = this._getVRMapping();
212
+ break;
213
+ default:
214
+ this.config.mapping = this._getDefaultMapping();
215
+ }
216
+ this.emit('presetChanged', preset);
217
+ }
218
+
219
+ /**
220
+ * Get current rotation values
221
+ */
222
+ getRotation() {
223
+ return { ...this.rotation };
224
+ }
225
+
226
+ /**
227
+ * Reset all input state
228
+ */
229
+ reset() {
230
+ this.rotation = { xy: 0, xz: 0, yz: 0, xw: 0, yw: 0, zw: 0 };
231
+ this._velocity = { xy: 0, xz: 0, yz: 0, xw: 0, yw: 0, zw: 0 };
232
+ this.state.keys.clear();
233
+ this.emit('reset');
234
+ }
235
+
236
+ /**
237
+ * Default input mapping
238
+ * @private
239
+ */
240
+ _getDefaultMapping() {
241
+ return {
242
+ mouse: {
243
+ dragX: 'xw', // Horizontal drag -> XW rotation
244
+ dragY: 'yw', // Vertical drag -> YW rotation
245
+ wheel: 'zw' // Scroll -> ZW rotation
246
+ },
247
+ touch: {
248
+ panX: 'xw',
249
+ panY: 'yw',
250
+ pinch: 'zw',
251
+ rotate: 'xy'
252
+ },
253
+ gyro: {
254
+ alpha: 'xy', // Compass -> XY rotation
255
+ beta: 'yw', // Front/back -> YW rotation
256
+ gamma: 'xw' // Left/right -> XW rotation
257
+ },
258
+ keyboard: {
259
+ 'ArrowLeft': { plane: 'xw', direction: -1 },
260
+ 'ArrowRight': { plane: 'xw', direction: 1 },
261
+ 'ArrowUp': { plane: 'yw', direction: -1 },
262
+ 'ArrowDown': { plane: 'yw', direction: 1 },
263
+ 'KeyQ': { plane: 'xy', direction: -1 },
264
+ 'KeyE': { plane: 'xy', direction: 1 },
265
+ 'KeyA': { plane: 'xz', direction: -1 },
266
+ 'KeyD': { plane: 'xz', direction: 1 },
267
+ 'KeyW': { plane: 'yz', direction: -1 },
268
+ 'KeyS': { plane: 'yz', direction: 1 },
269
+ 'KeyZ': { plane: 'zw', direction: -1 },
270
+ 'KeyX': { plane: 'zw', direction: 1 }
271
+ },
272
+ gamepad: {
273
+ leftStickX: 'xw',
274
+ leftStickY: 'yw',
275
+ rightStickX: 'xy',
276
+ rightStickY: 'zw'
277
+ }
278
+ };
279
+ }
280
+
281
+ _getMobileMapping() {
282
+ return {
283
+ ...this._getDefaultMapping(),
284
+ touch: {
285
+ panX: 'xw',
286
+ panY: 'yw',
287
+ pinch: 'zw',
288
+ rotate: 'xy'
289
+ }
290
+ };
291
+ }
292
+
293
+ _getDesktopMapping() {
294
+ return this._getDefaultMapping();
295
+ }
296
+
297
+ _getVRMapping() {
298
+ return {
299
+ ...this._getDefaultMapping(),
300
+ gyro: {
301
+ alpha: 'xy',
302
+ beta: 'xw',
303
+ gamma: 'yw'
304
+ }
305
+ };
306
+ }
307
+
308
+ _addEventListeners() {
309
+ if (!this.element) return;
310
+
311
+ // Mouse
312
+ this.element.addEventListener('mousedown', this._onMouseDown);
313
+ this.element.addEventListener('wheel', this._onWheel, { passive: false });
314
+
315
+ // Touch
316
+ this.element.addEventListener('touchstart', this._onTouchStart, { passive: false });
317
+
318
+ // Keyboard
319
+ document.addEventListener('keydown', this._onKeyDown);
320
+ document.addEventListener('keyup', this._onKeyUp);
321
+ }
322
+
323
+ _removeEventListeners() {
324
+ if (this.element) {
325
+ this.element.removeEventListener('mousedown', this._onMouseDown);
326
+ this.element.removeEventListener('wheel', this._onWheel);
327
+ this.element.removeEventListener('touchstart', this._onTouchStart);
328
+ }
329
+
330
+ document.removeEventListener('mousemove', this._onMouseMove);
331
+ document.removeEventListener('mouseup', this._onMouseUp);
332
+ document.removeEventListener('touchmove', this._onTouchMove);
333
+ document.removeEventListener('touchend', this._onTouchEnd);
334
+ document.removeEventListener('keydown', this._onKeyDown);
335
+ document.removeEventListener('keyup', this._onKeyUp);
336
+ window.removeEventListener('deviceorientation', this._onDeviceOrientation);
337
+
338
+ this._stopGamepadPolling();
339
+ }
340
+
341
+ _onMouseDown(event) {
342
+ if (!this.activeSources.has(InputSource.MOUSE)) {
343
+ this.activeSources.add(InputSource.MOUSE);
344
+ }
345
+
346
+ this.state.pointerX = event.clientX;
347
+ this.state.pointerY = event.clientY;
348
+
349
+ document.addEventListener('mousemove', this._onMouseMove);
350
+ document.addEventListener('mouseup', this._onMouseUp);
351
+
352
+ this.emit('pointerDown', { x: event.clientX, y: event.clientY });
353
+ }
354
+
355
+ _onMouseMove(event) {
356
+ const deltaX = event.clientX - this.state.pointerX;
357
+ const deltaY = event.clientY - this.state.pointerY;
358
+
359
+ this.state.pointerX = event.clientX;
360
+ this.state.pointerY = event.clientY;
361
+ this.state.deltaX = deltaX;
362
+ this.state.deltaY = deltaY;
363
+
364
+ const mapping = this.config.mapping.mouse;
365
+ this._velocity[mapping.dragX] += deltaX * this.config.mouseSensitivity;
366
+ this._velocity[mapping.dragY] += deltaY * this.config.mouseSensitivity;
367
+
368
+ this.emit('pointerMove', { x: event.clientX, y: event.clientY, deltaX, deltaY });
369
+ }
370
+
371
+ _onMouseUp() {
372
+ document.removeEventListener('mousemove', this._onMouseMove);
373
+ document.removeEventListener('mouseup', this._onMouseUp);
374
+ this.emit('pointerUp');
375
+ }
376
+
377
+ _onWheel(event) {
378
+ event.preventDefault();
379
+ const mapping = this.config.mapping.mouse;
380
+ this._velocity[mapping.wheel] += event.deltaY * 0.001;
381
+ this.emit('wheel', event.deltaY);
382
+ }
383
+
384
+ _onTouchStart(event) {
385
+ event.preventDefault();
386
+
387
+ for (const touch of event.changedTouches) {
388
+ this._touches.set(touch.identifier, {
389
+ startX: touch.clientX,
390
+ startY: touch.clientY,
391
+ currentX: touch.clientX,
392
+ currentY: touch.clientY
393
+ });
394
+ }
395
+
396
+ if (this._touches.size === 2) {
397
+ const [t1, t2] = Array.from(this._touches.values());
398
+ this._initialPinchDistance = Math.hypot(
399
+ t2.currentX - t1.currentX,
400
+ t2.currentY - t1.currentY
401
+ );
402
+ this._initialRotationAngle = Math.atan2(
403
+ t2.currentY - t1.currentY,
404
+ t2.currentX - t1.currentX
405
+ );
406
+ }
407
+
408
+ document.addEventListener('touchmove', this._onTouchMove, { passive: false });
409
+ document.addEventListener('touchend', this._onTouchEnd);
410
+
411
+ this.emit('touchStart', { count: this._touches.size });
412
+ }
413
+
414
+ _onTouchMove(event) {
415
+ event.preventDefault();
416
+
417
+ for (const touch of event.changedTouches) {
418
+ const tracked = this._touches.get(touch.identifier);
419
+ if (tracked) {
420
+ tracked.currentX = touch.clientX;
421
+ tracked.currentY = touch.clientY;
422
+ }
423
+ }
424
+
425
+ const mapping = this.config.mapping.touch;
426
+
427
+ if (this._touches.size === 1) {
428
+ // Single finger pan
429
+ const [t] = Array.from(this._touches.values());
430
+ const deltaX = t.currentX - t.startX;
431
+ const deltaY = t.currentY - t.startY;
432
+ t.startX = t.currentX;
433
+ t.startY = t.currentY;
434
+
435
+ this._velocity[mapping.panX] += deltaX * this.config.touchSensitivity;
436
+ this._velocity[mapping.panY] += deltaY * this.config.touchSensitivity;
437
+ } else if (this._touches.size === 2) {
438
+ // Two finger pinch/rotate
439
+ const [t1, t2] = Array.from(this._touches.values());
440
+
441
+ const distance = Math.hypot(
442
+ t2.currentX - t1.currentX,
443
+ t2.currentY - t1.currentY
444
+ );
445
+ const scale = distance / this._initialPinchDistance;
446
+ this.state.pinchScale = scale;
447
+
448
+ const angle = Math.atan2(
449
+ t2.currentY - t1.currentY,
450
+ t2.currentX - t1.currentX
451
+ );
452
+ const deltaAngle = angle - this._initialRotationAngle;
453
+ this.state.rotationAngle = deltaAngle;
454
+
455
+ this._velocity[mapping.pinch] += (scale - 1) * 0.1;
456
+ this._velocity[mapping.rotate] += deltaAngle * 0.5;
457
+
458
+ this._initialPinchDistance = distance;
459
+ this._initialRotationAngle = angle;
460
+ }
461
+
462
+ this.emit('touchMove', { count: this._touches.size });
463
+ }
464
+
465
+ _onTouchEnd(event) {
466
+ for (const touch of event.changedTouches) {
467
+ this._touches.delete(touch.identifier);
468
+ }
469
+
470
+ if (this._touches.size === 0) {
471
+ document.removeEventListener('touchmove', this._onTouchMove);
472
+ document.removeEventListener('touchend', this._onTouchEnd);
473
+ }
474
+
475
+ this.emit('touchEnd', { count: this._touches.size });
476
+ }
477
+
478
+ _onDeviceOrientation(event) {
479
+ const { alpha, beta, gamma } = event;
480
+
481
+ this.state.alpha = alpha || 0;
482
+ this.state.beta = beta || 0;
483
+ this.state.gamma = gamma || 0;
484
+
485
+ const mapping = this.config.mapping.gyro;
486
+ const sens = this.config.gyroSensitivity;
487
+
488
+ // Smooth rotation from device orientation
489
+ const targetXY = (alpha || 0) * Math.PI / 180 * sens;
490
+ const targetYW = (beta || 0) * Math.PI / 180 * sens;
491
+ const targetXW = (gamma || 0) * Math.PI / 180 * sens;
492
+
493
+ this._velocity[mapping.alpha] += (targetXY - this.rotation[mapping.alpha]) * 0.1;
494
+ this._velocity[mapping.beta] += (targetYW - this.rotation[mapping.beta]) * 0.1;
495
+ this._velocity[mapping.gamma] += (targetXW - this.rotation[mapping.gamma]) * 0.1;
496
+
497
+ this.emit('deviceOrientation', { alpha, beta, gamma });
498
+ }
499
+
500
+ _onKeyDown(event) {
501
+ this.state.keys.add(event.code);
502
+ this.emit('keyDown', event.code);
503
+ }
504
+
505
+ _onKeyUp(event) {
506
+ this.state.keys.delete(event.code);
507
+ this.emit('keyUp', event.code);
508
+ }
509
+
510
+ async _requestGyroscopePermission() {
511
+ if (typeof DeviceOrientationEvent !== 'undefined' &&
512
+ typeof DeviceOrientationEvent.requestPermission === 'function') {
513
+ try {
514
+ const permission = await DeviceOrientationEvent.requestPermission();
515
+ return permission === 'granted';
516
+ } catch {
517
+ return false;
518
+ }
519
+ }
520
+ return true;
521
+ }
522
+
523
+ _startGamepadPolling() {
524
+ this._gamepadInterval = setInterval(this._pollGamepad, 16);
525
+ }
526
+
527
+ _stopGamepadPolling() {
528
+ if (this._gamepadInterval) {
529
+ clearInterval(this._gamepadInterval);
530
+ this._gamepadInterval = null;
531
+ }
532
+ }
533
+
534
+ _pollGamepad() {
535
+ const gamepads = navigator.getGamepads?.() || [];
536
+ const gamepad = gamepads[0];
537
+
538
+ if (gamepad) {
539
+ const [lx, ly, rx, ry] = gamepad.axes;
540
+ const mapping = this.config.mapping.gamepad;
541
+ const sens = this.config.gamepadSensitivity;
542
+ const dz = this.config.deadzone;
543
+
544
+ const applyDeadzone = (v) => Math.abs(v) < dz ? 0 : v;
545
+
546
+ this._velocity[mapping.leftStickX] += applyDeadzone(lx) * sens;
547
+ this._velocity[mapping.leftStickY] += applyDeadzone(ly) * sens;
548
+ this._velocity[mapping.rightStickX] += applyDeadzone(rx) * sens;
549
+ this._velocity[mapping.rightStickY] += applyDeadzone(ry) * sens;
550
+
551
+ this.state.gamepadAxes = [lx, ly, rx, ry];
552
+ }
553
+ }
554
+
555
+ _startUpdateLoop() {
556
+ this._update();
557
+ }
558
+
559
+ _stopUpdateLoop() {
560
+ if (this._animationFrame) {
561
+ cancelAnimationFrame(this._animationFrame);
562
+ this._animationFrame = null;
563
+ }
564
+ }
565
+
566
+ _update() {
567
+ // Apply keyboard input
568
+ const keyMapping = this.config.mapping.keyboard;
569
+ for (const [code, action] of Object.entries(keyMapping)) {
570
+ if (this.state.keys.has(code)) {
571
+ this._velocity[action.plane] += action.direction * this.config.keyboardSpeed;
572
+ }
573
+ }
574
+
575
+ // Apply velocity with damping
576
+ for (const plane of Object.keys(this._velocity)) {
577
+ this.rotation[plane] += this._velocity[plane];
578
+ this._velocity[plane] *= this.config.damping;
579
+
580
+ if (Math.abs(this._velocity[plane]) < 0.0001) {
581
+ this._velocity[plane] = 0;
582
+ }
583
+ }
584
+
585
+ this.emit('update', this.rotation);
586
+ this._animationFrame = requestAnimationFrame(this._update);
587
+ }
588
+ }
589
+
590
+ export default ReactivityManager;