@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,112 @@
1
+ /**
2
+ * VIB3+ WebGPU Module
3
+ * Experimental WebGPU backend for 4D visualization
4
+ *
5
+ * @fileoverview WebGPU feature flags and exports
6
+ *
7
+ * Usage:
8
+ * import { WebGPURenderer, enableWebGPU } from './webgpu';
9
+ *
10
+ * // Check and enable WebGPU
11
+ * if (await WebGPURenderer.isAvailable()) {
12
+ * enableWebGPU();
13
+ * const renderer = new WebGPURenderer();
14
+ * await renderer.init({ canvas: myCanvas });
15
+ * }
16
+ */
17
+
18
+ // Re-export components
19
+ export { BufferLayout, createStd140Layout, createStd430Layout, GlassUniformLayout } from './BufferLayout.ts';
20
+ export { TripleBufferedUniform } from './TripleBufferedUniform.ts';
21
+ export { PolytopeInstanceBuffer } from './PolytopeInstanceBuffer.ts';
22
+ export { WebGPURenderer } from './WebGPURenderer.ts';
23
+
24
+ /**
25
+ * WebGPU feature flags
26
+ * Set enabled=true to activate WebGPU backend
27
+ */
28
+ export const WEBGPU_FEATURE_FLAGS = {
29
+ enabled: false,
30
+ reason: 'WebGPU backend is experimental; enable explicitly in host apps.',
31
+ fallback: 'webgl2' as 'webgl' | 'webgl2' | 'canvas2d',
32
+ debug: false
33
+ };
34
+
35
+ /**
36
+ * Check if WebGPU is currently enabled
37
+ */
38
+ export function isWebGPUEnabled(): boolean {
39
+ return WEBGPU_FEATURE_FLAGS.enabled;
40
+ }
41
+
42
+ /**
43
+ * Enable WebGPU backend
44
+ * @param options - Optional configuration
45
+ */
46
+ export function enableWebGPU(options?: {
47
+ fallback?: 'webgl' | 'webgl2' | 'canvas2d';
48
+ debug?: boolean;
49
+ }): void {
50
+ WEBGPU_FEATURE_FLAGS.enabled = true;
51
+ WEBGPU_FEATURE_FLAGS.reason = 'Enabled by application';
52
+ if (options?.fallback) {
53
+ WEBGPU_FEATURE_FLAGS.fallback = options.fallback;
54
+ }
55
+ if (options?.debug !== undefined) {
56
+ WEBGPU_FEATURE_FLAGS.debug = options.debug;
57
+ }
58
+ }
59
+
60
+ /**
61
+ * Disable WebGPU backend
62
+ */
63
+ export function disableWebGPU(): void {
64
+ WEBGPU_FEATURE_FLAGS.enabled = false;
65
+ WEBGPU_FEATURE_FLAGS.reason = 'Disabled by application';
66
+ }
67
+
68
+ /**
69
+ * Check WebGPU support in current environment
70
+ * @returns Promise<boolean> true if WebGPU is supported
71
+ */
72
+ export async function checkWebGPUSupport(): Promise<{
73
+ supported: boolean;
74
+ reason: string;
75
+ adapter?: unknown;
76
+ }> {
77
+ if (typeof navigator === 'undefined') {
78
+ return { supported: false, reason: 'Not in browser environment' };
79
+ }
80
+
81
+ if (!navigator.gpu) {
82
+ return { supported: false, reason: 'WebGPU API not available' };
83
+ }
84
+
85
+ try {
86
+ const adapter = await navigator.gpu.requestAdapter();
87
+ if (!adapter) {
88
+ return { supported: false, reason: 'No GPU adapter available' };
89
+ }
90
+ return { supported: true, reason: 'WebGPU available', adapter };
91
+ } catch (error) {
92
+ return {
93
+ supported: false,
94
+ reason: `WebGPU initialization failed: ${error instanceof Error ? error.message : 'Unknown error'}`
95
+ };
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Get the appropriate renderer based on feature flags and support
101
+ * @returns 'webgpu' | 'webgl2' | 'webgl' | 'canvas2d'
102
+ */
103
+ export async function getPreferredRenderer(): Promise<'webgpu' | 'webgl2' | 'webgl' | 'canvas2d'> {
104
+ if (WEBGPU_FEATURE_FLAGS.enabled) {
105
+ const support = await checkWebGPUSupport();
106
+ if (support.supported) {
107
+ return 'webgpu';
108
+ }
109
+ console.warn(`WebGPU not available: ${support.reason}. Falling back to ${WEBGPU_FEATURE_FLAGS.fallback}`);
110
+ }
111
+ return WEBGPU_FEATURE_FLAGS.fallback;
112
+ }
@@ -0,0 +1,431 @@
1
+ /**
2
+ * VIB34D Variation Management System
3
+ * Manages 100 total variations: 30 default + 70 custom
4
+ */
5
+
6
+ import { GeometryLibrary } from '../geometry/GeometryLibrary.js';
7
+
8
+ export class VariationManager {
9
+ /**
10
+ * Sanitize a variation name to prevent XSS and enforce limits.
11
+ * @param {*} name
12
+ * @param {string} fallback
13
+ * @returns {string}
14
+ */
15
+ static sanitizeName(name, fallback = 'Unnamed') {
16
+ if (typeof name !== 'string') return fallback;
17
+ // Strip HTML tags and limit length
18
+ const clean = name.replace(/<[^>]*>/g, '').trim();
19
+ if (clean.length === 0) return fallback;
20
+ return clean.slice(0, 100);
21
+ }
22
+
23
+ constructor(engine) {
24
+ this.engine = engine;
25
+
26
+ // Default variation names (30 total)
27
+ this.variationNames = [
28
+ // Tetrahedron Lattice (0-3)
29
+ 'TETRAHEDRON LATTICE 1', 'TETRAHEDRON LATTICE 2', 'TETRAHEDRON LATTICE 3', 'TETRAHEDRON LATTICE 4',
30
+
31
+ // Hypercube Lattice (4-7)
32
+ 'HYPERCUBE LATTICE 1', 'HYPERCUBE LATTICE 2', 'HYPERCUBE LATTICE 3', 'HYPERCUBE LATTICE 4',
33
+
34
+ // Sphere Lattice (8-11)
35
+ 'SPHERE LATTICE 1', 'SPHERE LATTICE 2', 'SPHERE LATTICE 3', 'SPHERE LATTICE 4',
36
+
37
+ // Torus Lattice (12-15)
38
+ 'TORUS LATTICE 1', 'TORUS LATTICE 2', 'TORUS LATTICE 3', 'TORUS LATTICE 4',
39
+
40
+ // Klein Bottle Lattice (16-19)
41
+ 'KLEIN BOTTLE LATTICE 1', 'KLEIN BOTTLE LATTICE 2', 'KLEIN BOTTLE LATTICE 3', 'KLEIN BOTTLE LATTICE 4',
42
+
43
+ // Fractal Lattice (20-22)
44
+ 'FRACTAL LATTICE 1', 'FRACTAL LATTICE 2', 'FRACTAL LATTICE 3',
45
+
46
+ // Wave Lattice (23-25)
47
+ 'WAVE LATTICE 1', 'WAVE LATTICE 2', 'WAVE LATTICE 3',
48
+
49
+ // Crystal Lattice (26-29)
50
+ 'CRYSTAL LATTICE 1', 'CRYSTAL LATTICE 2', 'CRYSTAL LATTICE 3', 'CRYSTAL LATTICE 4'
51
+ ];
52
+
53
+ // Custom variations storage (70 slots)
54
+ this.customVariations = new Array(70).fill(null);
55
+
56
+ // Total variation count
57
+ this.totalVariations = 100;
58
+ }
59
+
60
+ /**
61
+ * Get variation name for display
62
+ */
63
+ getVariationName(index) {
64
+ if (index < 30) {
65
+ return this.variationNames[index];
66
+ } else {
67
+ const customIndex = index - 30;
68
+ const customVar = this.customVariations[customIndex];
69
+ return customVar ? customVar.name : `CUSTOM ${customIndex + 1}`;
70
+ }
71
+ }
72
+
73
+ /**
74
+ * Generate default variation parameters
75
+ */
76
+ generateDefaultVariation(index) {
77
+ if (index >= 30) return null;
78
+
79
+ const geometryType = Math.floor(index / 4);
80
+ let level = index % 4;
81
+
82
+ // Special handling for reduced geometry sets
83
+ let adjustedGeometryType = geometryType;
84
+ if (geometryType === 5 && level > 2) { // Fractal only has 3 levels
85
+ adjustedGeometryType = 5;
86
+ level = 2;
87
+ }
88
+ if (geometryType === 6 && level > 2) { // Wave only has 3 levels
89
+ adjustedGeometryType = 6;
90
+ level = 2;
91
+ }
92
+
93
+ return {
94
+ variation: index,
95
+ geometry: adjustedGeometryType,
96
+ gridDensity: 8 + adjustedGeometryType * 2 + level * 1.5,
97
+ morphFactor: 0.2 + level * 0.2,
98
+ chaos: level * 0.2,
99
+ speed: 0.8 + level * 0.2,
100
+ hue: (index * 12.27) % 360,
101
+ rot4dXW: (level - 1.5) * 0.3,
102
+ rot4dYW: (adjustedGeometryType % 2) * 0.2,
103
+ rot4dZW: ((adjustedGeometryType + level) % 3) * 0.15,
104
+ dimension: 3.2 + level * 0.2
105
+ };
106
+ }
107
+
108
+ /**
109
+ * Apply specific variation to the engine
110
+ */
111
+ applyVariation(index) {
112
+ if (index < 0 || index >= this.totalVariations) return false;
113
+
114
+ let params;
115
+
116
+ if (index < 30) {
117
+ // Default variation
118
+ params = this.generateDefaultVariation(index);
119
+ } else {
120
+ // Custom variation
121
+ const customIndex = index - 30;
122
+ const customVar = this.customVariations[customIndex];
123
+
124
+ if (customVar) {
125
+ params = { ...customVar.parameters, variation: index };
126
+ } else {
127
+ // Empty slot - use current parameters
128
+ params = { ...this.engine.parameterManager.getAllParameters(), variation: index };
129
+ }
130
+ }
131
+
132
+ if (params) {
133
+ this.engine.parameterManager.setParameters(params);
134
+ this.engine.currentVariation = index;
135
+ return true;
136
+ }
137
+
138
+ return false;
139
+ }
140
+
141
+ /**
142
+ * Save current state as custom variation
143
+ */
144
+ saveCurrentAsCustom() {
145
+ // Find first empty custom slot
146
+ const emptyIndex = this.customVariations.findIndex(slot => slot === null);
147
+
148
+ if (emptyIndex === -1) {
149
+ return -1; // No empty slots
150
+ }
151
+
152
+ const currentParams = this.engine.parameterManager.getAllParameters();
153
+ const currentGeometry = GeometryLibrary.getGeometryName(currentParams.geometry);
154
+
155
+ const customVariation = {
156
+ name: `${currentGeometry} CUSTOM ${emptyIndex + 1}`,
157
+ timestamp: new Date().toISOString(),
158
+ parameters: { ...currentParams },
159
+ metadata: {
160
+ basedOnVariation: this.engine.currentVariation,
161
+ createdFrom: 'current-state'
162
+ }
163
+ };
164
+
165
+ this.customVariations[emptyIndex] = customVariation;
166
+ this.saveCustomVariations();
167
+
168
+ return 30 + emptyIndex; // Return absolute variation index
169
+ }
170
+
171
+ /**
172
+ * Delete custom variation
173
+ */
174
+ deleteCustomVariation(customIndex) {
175
+ if (customIndex >= 0 && customIndex < 70) {
176
+ this.customVariations[customIndex] = null;
177
+ this.saveCustomVariations();
178
+ return true;
179
+ }
180
+ return false;
181
+ }
182
+
183
+ /**
184
+ * Populate the variation grid UI
185
+ */
186
+ populateGrid() {
187
+ const gridContainer = document.getElementById('variationGrid');
188
+ if (!gridContainer) return;
189
+
190
+ gridContainer.innerHTML = '';
191
+
192
+ // Create sections for different geometry types
193
+ const sections = [
194
+ { name: 'Tetrahedron', range: [0, 3], class: 'tetrahedron' },
195
+ { name: 'Hypercube', range: [4, 7], class: 'hypercube' },
196
+ { name: 'Sphere', range: [8, 11], class: 'sphere' },
197
+ { name: 'Torus', range: [12, 15], class: 'torus' },
198
+ { name: 'Klein Bottle', range: [16, 19], class: 'klein' },
199
+ { name: 'Fractal', range: [20, 22], class: 'fractal' },
200
+ { name: 'Wave', range: [23, 25], class: 'wave' },
201
+ { name: 'Crystal', range: [26, 29], class: 'crystal' }
202
+ ];
203
+
204
+ // Add default variations
205
+ sections.forEach(section => {
206
+ const sectionDiv = document.createElement('div');
207
+ sectionDiv.className = 'variation-section';
208
+ const sectionHeader = document.createElement('h3');
209
+ sectionHeader.textContent = `${section.name} Lattice`;
210
+ sectionDiv.appendChild(sectionHeader);
211
+
212
+ const buttonContainer = document.createElement('div');
213
+ buttonContainer.className = 'variation-buttons';
214
+
215
+ for (let i = section.range[0]; i <= section.range[1]; i++) {
216
+ if (i < this.variationNames.length) {
217
+ const button = this.createVariationButton(i, true, section.class);
218
+ buttonContainer.appendChild(button);
219
+ }
220
+ }
221
+
222
+ sectionDiv.appendChild(buttonContainer);
223
+ gridContainer.appendChild(sectionDiv);
224
+ });
225
+
226
+ // Add custom variations section
227
+ const customSection = document.createElement('div');
228
+ customSection.className = 'variation-section custom-section';
229
+ const customHeader = document.createElement('h3');
230
+ customHeader.textContent = 'Custom Variations';
231
+ customSection.appendChild(customHeader);
232
+
233
+ const customContainer = document.createElement('div');
234
+ customContainer.className = 'variation-buttons custom-grid';
235
+
236
+ for (let i = 0; i < 70; i++) {
237
+ const button = this.createVariationButton(30 + i, false, 'custom');
238
+ customContainer.appendChild(button);
239
+ }
240
+
241
+ customSection.appendChild(customContainer);
242
+ gridContainer.appendChild(customSection);
243
+ }
244
+
245
+ /**
246
+ * Create individual variation button
247
+ */
248
+ createVariationButton(variationIndex, isDefault, geomClass) {
249
+ const button = document.createElement('button');
250
+ const name = this.getVariationName(variationIndex);
251
+
252
+ button.className = `preset-btn ${geomClass} ${isDefault ? 'default-variation' : 'custom-variation'}`;
253
+ button.dataset.variation = variationIndex;
254
+ button.title = `${variationIndex + 1}. ${name}`;
255
+
256
+ // Button content
257
+ if (isDefault) {
258
+ button.innerHTML = `
259
+ <div class="variation-number">${(variationIndex + 1).toString().padStart(2, '0')}</div>
260
+ <div class="variation-level">Level ${(variationIndex % 4) + 1}</div>
261
+ `;
262
+ } else {
263
+ const customIndex = variationIndex - 30;
264
+ const hasCustom = this.customVariations[customIndex] !== null;
265
+
266
+ button.innerHTML = `
267
+ <div class="variation-number">${(variationIndex + 1).toString()}</div>
268
+ <div class="variation-type">${hasCustom ? 'CUSTOM' : 'EMPTY'}</div>
269
+ `;
270
+
271
+ if (!hasCustom) {
272
+ button.classList.add('empty-slot');
273
+ }
274
+ }
275
+
276
+ // Click handler
277
+ button.addEventListener('click', () => {
278
+ if (isDefault || this.customVariations[variationIndex - 30] !== null) {
279
+ this.engine.setVariation(variationIndex);
280
+ this.updateVariationGrid();
281
+ }
282
+ });
283
+
284
+ // Right-click for custom variations (delete)
285
+ if (!isDefault) {
286
+ button.addEventListener('contextmenu', (e) => {
287
+ e.preventDefault();
288
+ const customIndex = variationIndex - 30;
289
+ if (this.customVariations[customIndex] !== null) {
290
+ if (confirm(`Delete custom variation ${variationIndex + 1}?`)) {
291
+ this.deleteCustomVariation(customIndex);
292
+ this.populateGrid();
293
+ }
294
+ }
295
+ });
296
+ }
297
+
298
+ return button;
299
+ }
300
+
301
+ /**
302
+ * Update variation grid to show current selection
303
+ */
304
+ updateVariationGrid() {
305
+ const buttons = document.querySelectorAll('.preset-btn');
306
+ buttons.forEach(btn => {
307
+ btn.classList.remove('active');
308
+ if (parseInt(btn.dataset.variation) === this.engine.currentVariation) {
309
+ btn.classList.add('active');
310
+ }
311
+ });
312
+ }
313
+
314
+ /**
315
+ * Load custom variations from localStorage
316
+ */
317
+ loadCustomVariations() {
318
+ try {
319
+ const stored = localStorage.getItem('vib34d-custom-variations');
320
+ if (stored) {
321
+ // Limit stored data size (1 MB) to prevent DoS from bloated localStorage
322
+ if (stored.length > 1024 * 1024) {
323
+ console.warn('Custom variations data exceeds 1 MB, ignoring');
324
+ return;
325
+ }
326
+ const parsed = JSON.parse(stored);
327
+ if (Array.isArray(parsed) && parsed.length === 70) {
328
+ // Sanitize all variation names loaded from storage
329
+ this.customVariations = parsed.map(v => {
330
+ if (v && typeof v === 'object') {
331
+ return { ...v, name: VariationManager.sanitizeName(v.name, 'Custom') };
332
+ }
333
+ return v;
334
+ });
335
+ }
336
+ }
337
+ } catch (error) {
338
+ console.warn('Failed to load custom variations:', error);
339
+ }
340
+ }
341
+
342
+ /**
343
+ * Save custom variations to localStorage
344
+ */
345
+ saveCustomVariations() {
346
+ try {
347
+ localStorage.setItem('vib34d-custom-variations', JSON.stringify(this.customVariations));
348
+ } catch (error) {
349
+ console.warn('Failed to save custom variations:', error);
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Export all custom variations as JSON
355
+ */
356
+ exportCustomVariations() {
357
+ const exportData = {
358
+ type: 'vib34d-custom-variations',
359
+ version: '1.0.0',
360
+ timestamp: new Date().toISOString(),
361
+ variations: this.customVariations.filter(v => v !== null)
362
+ };
363
+
364
+ const json = JSON.stringify(exportData, null, 2);
365
+ const blob = new Blob([json], { type: 'application/json' });
366
+ const url = URL.createObjectURL(blob);
367
+
368
+ const link = document.createElement('a');
369
+ link.href = url;
370
+ link.download = 'vib34d-custom-variations.json';
371
+ link.click();
372
+
373
+ URL.revokeObjectURL(url);
374
+ }
375
+
376
+ /**
377
+ * Import custom variations from JSON
378
+ */
379
+ async importCustomVariations(file) {
380
+ try {
381
+ const text = await file.text();
382
+ // Limit import file size (2 MB)
383
+ if (text.length > 2 * 1024 * 1024) {
384
+ console.warn('Import file exceeds 2 MB, rejecting');
385
+ return 0;
386
+ }
387
+ const data = JSON.parse(text);
388
+
389
+ if (data.type === 'vib34d-custom-variations' && Array.isArray(data.variations)) {
390
+ // Merge imported variations (sanitize names)
391
+ let importCount = 0;
392
+
393
+ data.variations.forEach(variation => {
394
+ if (!variation || typeof variation !== 'object') return;
395
+ const emptyIndex = this.customVariations.findIndex(slot => slot === null);
396
+ if (emptyIndex !== -1) {
397
+ // Sanitize name from imported data
398
+ variation.name = VariationManager.sanitizeName(variation.name, `Imported ${emptyIndex + 1}`);
399
+ this.customVariations[emptyIndex] = variation;
400
+ importCount++;
401
+ }
402
+ });
403
+
404
+ this.saveCustomVariations();
405
+ this.populateGrid();
406
+
407
+ return importCount;
408
+ }
409
+ } catch (error) {
410
+ console.error('Failed to import custom variations:', error);
411
+ }
412
+
413
+ return 0;
414
+ }
415
+
416
+ /**
417
+ * Get variation statistics
418
+ */
419
+ getStatistics() {
420
+ const customCount = this.customVariations.filter(v => v !== null).length;
421
+
422
+ return {
423
+ totalVariations: this.totalVariations,
424
+ defaultVariations: 30,
425
+ customVariations: customCount,
426
+ emptySlots: 70 - customCount,
427
+ currentVariation: this.engine.currentVariation,
428
+ isCustom: this.engine.currentVariation >= 30
429
+ };
430
+ }
431
+ }