@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.
- package/CHANGELOG.md +118 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
- package/DOCS/CI_TESTING.md +38 -0
- package/DOCS/CLI_ONBOARDING.md +75 -0
- package/DOCS/CONTROL_REFERENCE.md +64 -0
- package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
- package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
- package/DOCS/ENV_SETUP.md +189 -0
- package/DOCS/EXPORT_FORMATS.md +417 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
- package/DOCS/LICENSING_TIERS.md +275 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
- package/DOCS/OBS_SETUP_GUIDE.md +98 -0
- package/DOCS/PROJECT_SETUP.md +66 -0
- package/DOCS/RENDERER_LIFECYCLE.md +40 -0
- package/DOCS/REPO_MANIFEST.md +121 -0
- package/DOCS/SESSION_014_PLAN.md +195 -0
- package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
- package/DOCS/SYSTEM_INVENTORY.md +520 -0
- package/DOCS/TELEMETRY_EXPORTS.md +34 -0
- package/DOCS/WEBGPU_STATUS.md +38 -0
- package/DOCS/XR_BENCHMARKS.md +608 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/docs/.nojekyll +0 -0
- package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/02-hyperspatial_ego_death.html +346 -0
- package/docs/03-post_cartesian_sublime.html +346 -0
- package/docs/04-crystalline_void_meditation.html +346 -0
- package/docs/05-quantum_decoherence_ballet.html +346 -0
- package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/07-hyperspatial_ego_death.html +346 -0
- package/docs/08-post_cartesian_sublime.html +346 -0
- package/docs/09-crystalline_void_meditation.html +346 -0
- package/docs/10-quantum_decoherence_ballet.html +346 -0
- package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/12-hyperspatial_ego_death.html +346 -0
- package/docs/13-post_cartesian_sublime.html +346 -0
- package/docs/index.html +794 -0
- package/docs/test-hub.html +441 -0
- package/docs/url-state.js +102 -0
- package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
- package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
- package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
- package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
- package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
- package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
- package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
- package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
- package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
- package/docs/vib3-exports/index.html +238 -0
- package/docs/webgpu-live.html +702 -0
- package/package.json +367 -0
- package/src/advanced/AIPresetGenerator.js +777 -0
- package/src/advanced/MIDIController.js +703 -0
- package/src/advanced/OffscreenWorker.js +1051 -0
- package/src/advanced/WebGPUCompute.js +1051 -0
- package/src/advanced/WebXRRenderer.js +680 -0
- package/src/agent/cli/AgentCLI.js +615 -0
- package/src/agent/cli/index.js +14 -0
- package/src/agent/index.js +73 -0
- package/src/agent/mcp/MCPServer.js +950 -0
- package/src/agent/mcp/index.js +9 -0
- package/src/agent/mcp/tools.js +548 -0
- package/src/agent/telemetry/EventStream.js +669 -0
- package/src/agent/telemetry/Instrumentation.js +618 -0
- package/src/agent/telemetry/TelemetryExporters.js +427 -0
- package/src/agent/telemetry/TelemetryService.js +464 -0
- package/src/agent/telemetry/index.js +52 -0
- package/src/benchmarks/BenchmarkRunner.js +381 -0
- package/src/benchmarks/MetricsCollector.js +299 -0
- package/src/benchmarks/index.js +9 -0
- package/src/benchmarks/scenes.js +259 -0
- package/src/cli/index.js +675 -0
- package/src/config/ApiConfig.js +88 -0
- package/src/core/CanvasManager.js +217 -0
- package/src/core/ErrorReporter.js +117 -0
- package/src/core/ParameterMapper.js +333 -0
- package/src/core/Parameters.js +396 -0
- package/src/core/RendererContracts.js +200 -0
- package/src/core/UnifiedResourceManager.js +370 -0
- package/src/core/VIB3Engine.js +636 -0
- package/src/core/renderers/FacetedRendererAdapter.js +32 -0
- package/src/core/renderers/HolographicRendererAdapter.js +29 -0
- package/src/core/renderers/QuantumRendererAdapter.js +29 -0
- package/src/core/renderers/RendererLifecycleManager.js +63 -0
- package/src/creative/ColorPresetsSystem.js +980 -0
- package/src/creative/ParameterTimeline.js +1061 -0
- package/src/creative/PostProcessingPipeline.js +1113 -0
- package/src/creative/TransitionAnimator.js +683 -0
- package/src/export/CSSExporter.js +226 -0
- package/src/export/CardGeneratorBase.js +279 -0
- package/src/export/ExportManager.js +580 -0
- package/src/export/FacetedCardGenerator.js +279 -0
- package/src/export/HolographicCardGenerator.js +543 -0
- package/src/export/LottieExporter.js +552 -0
- package/src/export/QuantumCardGenerator.js +315 -0
- package/src/export/SVGExporter.js +519 -0
- package/src/export/ShaderExporter.js +903 -0
- package/src/export/TradingCardGenerator.js +3055 -0
- package/src/export/TradingCardManager.js +181 -0
- package/src/export/VIB3PackageExporter.js +559 -0
- package/src/export/index.js +14 -0
- package/src/export/systems/TradingCardSystemFaceted.js +494 -0
- package/src/export/systems/TradingCardSystemHolographic.js +452 -0
- package/src/export/systems/TradingCardSystemQuantum.js +411 -0
- package/src/faceted/FacetedSystem.js +963 -0
- package/src/features/CollectionManager.js +433 -0
- package/src/gallery/CollectionManager.js +240 -0
- package/src/gallery/GallerySystem.js +485 -0
- package/src/geometry/GeometryFactory.js +314 -0
- package/src/geometry/GeometryLibrary.js +72 -0
- package/src/geometry/buffers/BufferBuilder.js +338 -0
- package/src/geometry/buffers/index.js +18 -0
- package/src/geometry/generators/Crystal.js +420 -0
- package/src/geometry/generators/Fractal.js +298 -0
- package/src/geometry/generators/KleinBottle.js +197 -0
- package/src/geometry/generators/Sphere.js +192 -0
- package/src/geometry/generators/Tesseract.js +160 -0
- package/src/geometry/generators/Tetrahedron.js +225 -0
- package/src/geometry/generators/Torus.js +304 -0
- package/src/geometry/generators/Wave.js +341 -0
- package/src/geometry/index.js +142 -0
- package/src/geometry/warp/HypersphereCore.js +211 -0
- package/src/geometry/warp/HypertetraCore.js +386 -0
- package/src/geometry/warp/index.js +57 -0
- package/src/holograms/HolographicVisualizer.js +1073 -0
- package/src/holograms/RealHolographicSystem.js +966 -0
- package/src/holograms/variantRegistry.js +69 -0
- package/src/integrations/FigmaPlugin.js +854 -0
- package/src/integrations/OBSMode.js +754 -0
- package/src/integrations/ThreeJsPackage.js +660 -0
- package/src/integrations/TouchDesignerExport.js +552 -0
- package/src/integrations/frameworks/Vib3React.js +591 -0
- package/src/integrations/frameworks/Vib3Svelte.js +654 -0
- package/src/integrations/frameworks/Vib3Vue.js +628 -0
- package/src/llm/LLMParameterInterface.js +240 -0
- package/src/llm/LLMParameterUI.js +577 -0
- package/src/math/Mat4x4.js +708 -0
- package/src/math/Projection.js +341 -0
- package/src/math/Rotor4D.js +637 -0
- package/src/math/Vec4.js +476 -0
- package/src/math/constants.js +164 -0
- package/src/math/index.js +68 -0
- package/src/math/projections.js +54 -0
- package/src/math/rotations.js +196 -0
- package/src/quantum/QuantumEngine.js +906 -0
- package/src/quantum/QuantumVisualizer.js +1103 -0
- package/src/reactivity/ReactivityConfig.js +499 -0
- package/src/reactivity/ReactivityManager.js +586 -0
- package/src/reactivity/SpatialInputSystem.js +1783 -0
- package/src/reactivity/index.js +93 -0
- package/src/render/CommandBuffer.js +465 -0
- package/src/render/MultiCanvasBridge.js +340 -0
- package/src/render/RenderCommand.js +514 -0
- package/src/render/RenderResourceRegistry.js +523 -0
- package/src/render/RenderState.js +552 -0
- package/src/render/RenderTarget.js +512 -0
- package/src/render/ShaderLoader.js +253 -0
- package/src/render/ShaderProgram.js +599 -0
- package/src/render/UnifiedRenderBridge.js +496 -0
- package/src/render/backends/WebGLBackend.js +1108 -0
- package/src/render/backends/WebGPUBackend.js +1409 -0
- package/src/render/commands/CommandBufferExecutor.js +607 -0
- package/src/render/commands/RenderCommandBuffer.js +661 -0
- package/src/render/commands/index.js +17 -0
- package/src/render/index.js +367 -0
- package/src/scene/Disposable.js +498 -0
- package/src/scene/MemoryPool.js +618 -0
- package/src/scene/Node4D.js +697 -0
- package/src/scene/ResourceManager.js +599 -0
- package/src/scene/Scene4D.js +540 -0
- package/src/scene/index.js +98 -0
- package/src/schemas/error.schema.json +84 -0
- package/src/schemas/extension.schema.json +88 -0
- package/src/schemas/index.js +214 -0
- package/src/schemas/parameters.schema.json +142 -0
- package/src/schemas/tool-pack.schema.json +44 -0
- package/src/schemas/tool-response.schema.json +127 -0
- package/src/shaders/common/fullscreen.vert.glsl +5 -0
- package/src/shaders/common/fullscreen.vert.wgsl +17 -0
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +85 -0
- package/src/shaders/common/rotation4d.wgsl +86 -0
- package/src/shaders/common/uniforms.glsl +44 -0
- package/src/shaders/common/uniforms.wgsl +48 -0
- package/src/shaders/faceted/faceted.frag.glsl +129 -0
- package/src/shaders/faceted/faceted.frag.wgsl +164 -0
- package/src/shaders/holographic/holographic.frag.glsl +406 -0
- package/src/shaders/holographic/holographic.frag.wgsl +185 -0
- package/src/shaders/quantum/quantum.frag.glsl +513 -0
- package/src/shaders/quantum/quantum.frag.wgsl +361 -0
- package/src/testing/ParallelTestFramework.js +519 -0
- package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
- package/src/testing/exportFormats.test.js +8 -0
- package/src/testing/projections.test.js +14 -0
- package/src/testing/rotations.test.js +37 -0
- package/src/ui/InteractivityMenu.js +516 -0
- package/src/ui/StatusManager.js +96 -0
- package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
- package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
- package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
- package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
- package/src/variations/VariationManager.js +431 -0
- package/src/viewer/AudioReactivity.js +505 -0
- package/src/viewer/CardBending.js +481 -0
- package/src/viewer/GalleryUI.js +832 -0
- package/src/viewer/ReactivityManager.js +590 -0
- package/src/viewer/TradingCardExporter.js +600 -0
- package/src/viewer/ViewerPortal.js +374 -0
- package/src/viewer/index.js +12 -0
- package/src/wasm/WasmLoader.js +296 -0
- package/src/wasm/index.js +132 -0
- package/tools/agentic/mcpTools.js +88 -0
- package/tools/cli/agent-cli.js +92 -0
- package/tools/export/formats.js +24 -0
- package/tools/math/rotation-baseline.mjs +64 -0
- package/tools/shader-sync-verify.js +937 -0
- package/tools/telemetry/manifestPipeline.js +141 -0
- package/tools/telemetry/telemetryEvents.js +35 -0
- package/types/adaptive-sdk.d.ts +185 -0
- package/types/advanced/AIPresetGenerator.d.ts +81 -0
- package/types/advanced/MIDIController.d.ts +100 -0
- package/types/advanced/OffscreenWorker.d.ts +82 -0
- package/types/advanced/WebGPUCompute.d.ts +52 -0
- package/types/advanced/WebXRRenderer.d.ts +77 -0
- package/types/advanced/index.d.ts +46 -0
- package/types/core/ErrorReporter.d.ts +50 -0
- package/types/core/VIB3Engine.d.ts +204 -0
- package/types/creative/ColorPresetsSystem.d.ts +91 -0
- package/types/creative/ParameterTimeline.d.ts +74 -0
- package/types/creative/PostProcessingPipeline.d.ts +109 -0
- package/types/creative/TransitionAnimator.d.ts +71 -0
- package/types/creative/index.d.ts +35 -0
- package/types/integrations/FigmaPlugin.d.ts +46 -0
- package/types/integrations/OBSMode.d.ts +74 -0
- package/types/integrations/ThreeJsPackage.d.ts +62 -0
- package/types/integrations/TouchDesignerExport.d.ts +36 -0
- package/types/integrations/Vib3React.d.ts +74 -0
- package/types/integrations/Vib3Svelte.d.ts +63 -0
- package/types/integrations/Vib3Vue.d.ts +55 -0
- package/types/integrations/index.d.ts +52 -0
- package/types/reactivity/SpatialInputSystem.d.ts +173 -0
- package/types/reactivity/index.d.ts +394 -0
- package/types/render/CommandBuffer.d.ts +169 -0
- package/types/render/RenderCommand.d.ts +312 -0
- package/types/render/RenderState.d.ts +279 -0
- package/types/render/RenderTarget.d.ts +254 -0
- package/types/render/ShaderProgram.d.ts +277 -0
- package/types/render/UnifiedRenderBridge.d.ts +143 -0
- package/types/render/WebGLBackend.d.ts +168 -0
- package/types/render/WebGPUBackend.d.ts +186 -0
- 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
|
+
}
|