@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,683 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TransitionAnimator.js - VIB3+ Smooth Parameter Transition System
|
|
3
|
+
*
|
|
4
|
+
* Provides smooth animated transitions between arbitrary sets of VIB3+
|
|
5
|
+
* parameters. Supports multiple concurrent transitions, a rich library of
|
|
6
|
+
* easing functions, chainable sequences, cancellation, and completion
|
|
7
|
+
* callbacks.
|
|
8
|
+
*
|
|
9
|
+
* @module creative/TransitionAnimator
|
|
10
|
+
* @version 1.0.0
|
|
11
|
+
* @author VIB3+ Creative Tooling - Phase B
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} TransitionOptions
|
|
16
|
+
* @property {Object<string, number>} params - Target parameter values keyed by name
|
|
17
|
+
* @property {number} [duration=1000] - Transition duration in milliseconds
|
|
18
|
+
* @property {string} [easing='easeInOut'] - Easing function name
|
|
19
|
+
* @property {number} [delay=0] - Delay before starting (ms)
|
|
20
|
+
* @property {Function} [onComplete] - Callback when this transition completes
|
|
21
|
+
* @property {Function} [onUpdate] - Callback on each frame with progress (0-1)
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {Object} SequenceStep
|
|
26
|
+
* @property {Object<string, number>} params - Target parameter values
|
|
27
|
+
* @property {number} [duration=1000] - Step duration in milliseconds
|
|
28
|
+
* @property {string} [easing='easeInOut'] - Easing function name
|
|
29
|
+
* @property {number} [delay=0] - Delay before this step starts
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @typedef {Object} ActiveTransition
|
|
34
|
+
* @property {string} id - Unique transition identifier
|
|
35
|
+
* @property {Object<string, number>} fromValues - Starting parameter values
|
|
36
|
+
* @property {Object<string, number>} toValues - Target parameter values
|
|
37
|
+
* @property {number} startTime - Timestamp when the transition started (ms)
|
|
38
|
+
* @property {number} duration - Total duration (ms)
|
|
39
|
+
* @property {string} easing - Easing function name
|
|
40
|
+
* @property {Function|null} onComplete - Completion callback
|
|
41
|
+
* @property {Function|null} onUpdate - Per-frame callback
|
|
42
|
+
* @property {boolean} cancelled - Whether this transition has been cancelled
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
let _nextTransitionId = 0;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Smooth parameter transition animator for the VIB3+ engine.
|
|
49
|
+
*
|
|
50
|
+
* Transitions any set of VIB3+ parameters simultaneously from their current
|
|
51
|
+
* values to target values over a configurable duration with configurable
|
|
52
|
+
* easing. Multiple transitions can run concurrently, and transitions can
|
|
53
|
+
* be chained into sequences.
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* const animator = new TransitionAnimator((name, value) => {
|
|
57
|
+
* engine.setParameter(name, value);
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* // Simple transition
|
|
61
|
+
* animator.transition({ hue: 120, intensity: 0.9 }, 1500, 'easeOut');
|
|
62
|
+
*
|
|
63
|
+
* // Sequence of transitions
|
|
64
|
+
* animator.sequence([
|
|
65
|
+
* { params: { hue: 0, chaos: 0.8 }, duration: 1000, easing: 'elastic' },
|
|
66
|
+
* { params: { hue: 180, chaos: 0.1 }, duration: 2000, easing: 'easeInOut' },
|
|
67
|
+
* { params: { hue: 360, chaos: 0.5 }, duration: 1000, easing: 'bounce' }
|
|
68
|
+
* ]);
|
|
69
|
+
*/
|
|
70
|
+
export class TransitionAnimator {
|
|
71
|
+
/**
|
|
72
|
+
* Create a new TransitionAnimator.
|
|
73
|
+
*
|
|
74
|
+
* @param {Function} parameterUpdateFn - Callback invoked as (paramName, value)
|
|
75
|
+
* whenever a VIB3+ parameter should be updated.
|
|
76
|
+
* @param {Function} [parameterGetFn] - Optional callback to read current
|
|
77
|
+
* parameter values, invoked as (paramName) => number. If not provided,
|
|
78
|
+
* transitions will use the target values of any currently running
|
|
79
|
+
* transition or fall back to VIB3+ defaults.
|
|
80
|
+
*/
|
|
81
|
+
constructor(parameterUpdateFn, parameterGetFn = null) {
|
|
82
|
+
if (typeof parameterUpdateFn !== 'function') {
|
|
83
|
+
throw new Error('TransitionAnimator requires a parameterUpdateFn callback');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** @type {Function} */
|
|
87
|
+
this.updateParameter = parameterUpdateFn;
|
|
88
|
+
|
|
89
|
+
/** @type {Function|null} */
|
|
90
|
+
this.getParameter = typeof parameterGetFn === 'function' ? parameterGetFn : null;
|
|
91
|
+
|
|
92
|
+
/** @type {Map<string, ActiveTransition>} Active transitions keyed by ID */
|
|
93
|
+
this.activeTransitions = new Map();
|
|
94
|
+
|
|
95
|
+
/** @type {Array<{steps: SequenceStep[], currentIndex: number, id: string, onComplete: Function|null}>} */
|
|
96
|
+
this.sequences = [];
|
|
97
|
+
|
|
98
|
+
/** @type {number|null} requestAnimationFrame ID */
|
|
99
|
+
this._frameId = null;
|
|
100
|
+
|
|
101
|
+
/** @type {Object<string, number>} Snapshot of last-known parameter values */
|
|
102
|
+
this._knownValues = {};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Map of all available easing functions.
|
|
106
|
+
* @type {Object<string, Function>}
|
|
107
|
+
*/
|
|
108
|
+
this.easingFunctions = this._buildEasingFunctions();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// -------------------------------------------------------------------------
|
|
112
|
+
// Public API - Transitions
|
|
113
|
+
// -------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Start a transition to the given parameter values.
|
|
117
|
+
*
|
|
118
|
+
* @param {Object<string, number>} params - Target parameter values
|
|
119
|
+
* @param {number} [duration=1000] - Duration in milliseconds
|
|
120
|
+
* @param {string} [easing='easeInOut'] - Easing function name
|
|
121
|
+
* @param {Function} [onComplete] - Callback when complete
|
|
122
|
+
* @param {Function} [onUpdate] - Callback on each frame with progress (0-1)
|
|
123
|
+
* @returns {string} Transition ID (can be used to cancel)
|
|
124
|
+
*/
|
|
125
|
+
transition(params, duration = 1000, easing = 'easeInOut', onComplete = null, onUpdate = null) {
|
|
126
|
+
if (!params || typeof params !== 'object') {
|
|
127
|
+
console.warn('TransitionAnimator: params must be an object');
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const id = `transition_${++_nextTransitionId}`;
|
|
132
|
+
const fromValues = {};
|
|
133
|
+
|
|
134
|
+
// Capture starting values for each parameter
|
|
135
|
+
for (const paramName of Object.keys(params)) {
|
|
136
|
+
fromValues[paramName] = this._getCurrentValue(paramName);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** @type {ActiveTransition} */
|
|
140
|
+
const record = {
|
|
141
|
+
id,
|
|
142
|
+
fromValues,
|
|
143
|
+
toValues: { ...params },
|
|
144
|
+
startTime: performance.now(),
|
|
145
|
+
duration: Math.max(0, duration),
|
|
146
|
+
easing: this.easingFunctions[easing] ? easing : 'easeInOut',
|
|
147
|
+
onComplete: typeof onComplete === 'function' ? onComplete : null,
|
|
148
|
+
onUpdate: typeof onUpdate === 'function' ? onUpdate : null,
|
|
149
|
+
cancelled: false
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
this.activeTransitions.set(id, record);
|
|
153
|
+
this._ensureAnimating();
|
|
154
|
+
|
|
155
|
+
return id;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Transition to a full target state (shorthand for `transition`).
|
|
160
|
+
*
|
|
161
|
+
* @param {Object<string, number>} targetState - Target parameter state
|
|
162
|
+
* @param {number} [duration=1000] - Duration in ms
|
|
163
|
+
* @param {string} [easing='easeInOut'] - Easing function name
|
|
164
|
+
* @param {Function} [onComplete] - Completion callback
|
|
165
|
+
* @returns {string} Transition ID
|
|
166
|
+
*/
|
|
167
|
+
transitionTo(targetState, duration = 1000, easing = 'easeInOut', onComplete = null) {
|
|
168
|
+
return this.transition(targetState, duration, easing, onComplete);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Execute a sequence of transitions one after another.
|
|
173
|
+
*
|
|
174
|
+
* @param {SequenceStep[]} steps - Array of transition steps
|
|
175
|
+
* @param {Function} [onComplete] - Callback when the entire sequence finishes
|
|
176
|
+
* @returns {string} Sequence ID (can be used to cancel)
|
|
177
|
+
*/
|
|
178
|
+
sequence(steps, onComplete = null) {
|
|
179
|
+
if (!Array.isArray(steps) || steps.length === 0) {
|
|
180
|
+
console.warn('TransitionAnimator: sequence requires a non-empty array of steps');
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const seqId = `sequence_${++_nextTransitionId}`;
|
|
185
|
+
|
|
186
|
+
const seq = {
|
|
187
|
+
id: seqId,
|
|
188
|
+
steps: steps.map(step => ({
|
|
189
|
+
params: { ...step.params },
|
|
190
|
+
duration: step.duration != null ? step.duration : 1000,
|
|
191
|
+
easing: step.easing || 'easeInOut',
|
|
192
|
+
delay: step.delay || 0
|
|
193
|
+
})),
|
|
194
|
+
currentIndex: 0,
|
|
195
|
+
onComplete: typeof onComplete === 'function' ? onComplete : null
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
this.sequences.push(seq);
|
|
199
|
+
this._runNextSequenceStep(seq);
|
|
200
|
+
|
|
201
|
+
return seqId;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// -------------------------------------------------------------------------
|
|
205
|
+
// Public API - Cancellation
|
|
206
|
+
// -------------------------------------------------------------------------
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Cancel a specific transition or sequence by ID.
|
|
210
|
+
*
|
|
211
|
+
* @param {string} id - Transition or sequence ID
|
|
212
|
+
* @returns {boolean} true if something was cancelled
|
|
213
|
+
*/
|
|
214
|
+
cancel(id) {
|
|
215
|
+
// Try transitions first
|
|
216
|
+
const transition = this.activeTransitions.get(id);
|
|
217
|
+
if (transition) {
|
|
218
|
+
transition.cancelled = true;
|
|
219
|
+
this.activeTransitions.delete(id);
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Try sequences
|
|
224
|
+
const seqIndex = this.sequences.findIndex(s => s.id === id);
|
|
225
|
+
if (seqIndex >= 0) {
|
|
226
|
+
const seq = this.sequences[seqIndex];
|
|
227
|
+
// Cancel any active transition belonging to this sequence
|
|
228
|
+
for (const [tId, t] of this.activeTransitions) {
|
|
229
|
+
if (tId.startsWith(id + '_step_')) {
|
|
230
|
+
t.cancelled = true;
|
|
231
|
+
this.activeTransitions.delete(tId);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
this.sequences.splice(seqIndex, 1);
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Cancel all active transitions and sequences immediately.
|
|
243
|
+
*/
|
|
244
|
+
cancelAll() {
|
|
245
|
+
for (const [, transition] of this.activeTransitions) {
|
|
246
|
+
transition.cancelled = true;
|
|
247
|
+
}
|
|
248
|
+
this.activeTransitions.clear();
|
|
249
|
+
this.sequences.length = 0;
|
|
250
|
+
|
|
251
|
+
if (this._frameId !== null) {
|
|
252
|
+
cancelAnimationFrame(this._frameId);
|
|
253
|
+
this._frameId = null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// -------------------------------------------------------------------------
|
|
258
|
+
// Public API - Queries
|
|
259
|
+
// -------------------------------------------------------------------------
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Check if any transitions are currently active.
|
|
263
|
+
*
|
|
264
|
+
* @returns {boolean}
|
|
265
|
+
*/
|
|
266
|
+
isAnimating() {
|
|
267
|
+
return this.activeTransitions.size > 0 || this.sequences.length > 0;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Get the number of active transitions.
|
|
272
|
+
*
|
|
273
|
+
* @returns {number}
|
|
274
|
+
*/
|
|
275
|
+
getActiveCount() {
|
|
276
|
+
return this.activeTransitions.size;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Get the list of available easing function names.
|
|
281
|
+
*
|
|
282
|
+
* @returns {string[]}
|
|
283
|
+
*/
|
|
284
|
+
getEasingNames() {
|
|
285
|
+
return Object.keys(this.easingFunctions);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// -------------------------------------------------------------------------
|
|
289
|
+
// Public API - Lifecycle
|
|
290
|
+
// -------------------------------------------------------------------------
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Clean up resources and cancel all animations.
|
|
294
|
+
*/
|
|
295
|
+
dispose() {
|
|
296
|
+
this.cancelAll();
|
|
297
|
+
this._knownValues = {};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// -------------------------------------------------------------------------
|
|
301
|
+
// Private - Animation Loop
|
|
302
|
+
// -------------------------------------------------------------------------
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Ensure the animation loop is running.
|
|
306
|
+
* @private
|
|
307
|
+
*/
|
|
308
|
+
_ensureAnimating() {
|
|
309
|
+
if (this._frameId === null) {
|
|
310
|
+
this._frameId = requestAnimationFrame(() => this._tick());
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Main animation tick. Evaluates all active transitions.
|
|
316
|
+
* @private
|
|
317
|
+
*/
|
|
318
|
+
_tick() {
|
|
319
|
+
this._frameId = null;
|
|
320
|
+
const now = performance.now();
|
|
321
|
+
const completed = [];
|
|
322
|
+
|
|
323
|
+
for (const [id, t] of this.activeTransitions) {
|
|
324
|
+
if (t.cancelled) {
|
|
325
|
+
completed.push(id);
|
|
326
|
+
continue;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
const elapsed = now - t.startTime;
|
|
330
|
+
const rawProgress = t.duration > 0 ? Math.min(elapsed / t.duration, 1) : 1;
|
|
331
|
+
const easeFn = this.easingFunctions[t.easing] || this.easingFunctions.linear;
|
|
332
|
+
const eased = easeFn(rawProgress);
|
|
333
|
+
|
|
334
|
+
// Apply interpolated values
|
|
335
|
+
for (const paramName of Object.keys(t.toValues)) {
|
|
336
|
+
const from = t.fromValues[paramName];
|
|
337
|
+
const to = t.toValues[paramName];
|
|
338
|
+
|
|
339
|
+
// Special circular interpolation for hue
|
|
340
|
+
let value;
|
|
341
|
+
if (paramName === 'hue') {
|
|
342
|
+
value = this._lerpHue(from, to, eased);
|
|
343
|
+
} else {
|
|
344
|
+
value = from + (to - from) * eased;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
this.updateParameter(paramName, value);
|
|
348
|
+
this._knownValues[paramName] = value;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Per-frame callback
|
|
352
|
+
if (t.onUpdate) {
|
|
353
|
+
t.onUpdate(rawProgress);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Check completion
|
|
357
|
+
if (rawProgress >= 1) {
|
|
358
|
+
completed.push(id);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Process completions
|
|
363
|
+
for (const id of completed) {
|
|
364
|
+
const t = this.activeTransitions.get(id);
|
|
365
|
+
this.activeTransitions.delete(id);
|
|
366
|
+
if (t && !t.cancelled && t.onComplete) {
|
|
367
|
+
t.onComplete();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Continue loop if there is still work
|
|
372
|
+
if (this.activeTransitions.size > 0) {
|
|
373
|
+
this._frameId = requestAnimationFrame(() => this._tick());
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// -------------------------------------------------------------------------
|
|
378
|
+
// Private - Sequence Runner
|
|
379
|
+
// -------------------------------------------------------------------------
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Run the next step in a sequence.
|
|
383
|
+
*
|
|
384
|
+
* @param {Object} seq - The sequence record
|
|
385
|
+
* @private
|
|
386
|
+
*/
|
|
387
|
+
_runNextSequenceStep(seq) {
|
|
388
|
+
if (seq.currentIndex >= seq.steps.length) {
|
|
389
|
+
// Sequence complete
|
|
390
|
+
const idx = this.sequences.indexOf(seq);
|
|
391
|
+
if (idx >= 0) {
|
|
392
|
+
this.sequences.splice(idx, 1);
|
|
393
|
+
}
|
|
394
|
+
if (seq.onComplete) {
|
|
395
|
+
seq.onComplete();
|
|
396
|
+
}
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const step = seq.steps[seq.currentIndex];
|
|
401
|
+
const stepId = `${seq.id}_step_${seq.currentIndex}`;
|
|
402
|
+
|
|
403
|
+
const startStep = () => {
|
|
404
|
+
const fromValues = {};
|
|
405
|
+
for (const paramName of Object.keys(step.params)) {
|
|
406
|
+
fromValues[paramName] = this._getCurrentValue(paramName);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const record = {
|
|
410
|
+
id: stepId,
|
|
411
|
+
fromValues,
|
|
412
|
+
toValues: { ...step.params },
|
|
413
|
+
startTime: performance.now(),
|
|
414
|
+
duration: Math.max(0, step.duration),
|
|
415
|
+
easing: this.easingFunctions[step.easing] ? step.easing : 'easeInOut',
|
|
416
|
+
onComplete: () => {
|
|
417
|
+
seq.currentIndex++;
|
|
418
|
+
this._runNextSequenceStep(seq);
|
|
419
|
+
},
|
|
420
|
+
onUpdate: null,
|
|
421
|
+
cancelled: false
|
|
422
|
+
};
|
|
423
|
+
|
|
424
|
+
this.activeTransitions.set(stepId, record);
|
|
425
|
+
this._ensureAnimating();
|
|
426
|
+
};
|
|
427
|
+
|
|
428
|
+
if (step.delay > 0) {
|
|
429
|
+
setTimeout(startStep, step.delay);
|
|
430
|
+
} else {
|
|
431
|
+
startStep();
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// -------------------------------------------------------------------------
|
|
436
|
+
// Private - Value Resolution
|
|
437
|
+
// -------------------------------------------------------------------------
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Get the current value for a parameter.
|
|
441
|
+
*
|
|
442
|
+
* Priority:
|
|
443
|
+
* 1. External getter function (if provided)
|
|
444
|
+
* 2. Last known value from a transition
|
|
445
|
+
* 3. VIB3+ parameter defaults
|
|
446
|
+
*
|
|
447
|
+
* @param {string} paramName
|
|
448
|
+
* @returns {number}
|
|
449
|
+
* @private
|
|
450
|
+
*/
|
|
451
|
+
_getCurrentValue(paramName) {
|
|
452
|
+
// Try external getter first
|
|
453
|
+
if (this.getParameter) {
|
|
454
|
+
const val = this.getParameter(paramName);
|
|
455
|
+
if (typeof val === 'number' && Number.isFinite(val)) {
|
|
456
|
+
return val;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Check last known value from a completed/in-progress transition
|
|
461
|
+
if (paramName in this._knownValues) {
|
|
462
|
+
return this._knownValues[paramName];
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Check in-flight transitions for target value
|
|
466
|
+
for (const [, t] of this.activeTransitions) {
|
|
467
|
+
if (paramName in t.toValues) {
|
|
468
|
+
return t.toValues[paramName];
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// Fall back to VIB3+ defaults
|
|
473
|
+
return this._getDefaultValue(paramName);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* VIB3+ default parameter values as defined in Parameters.js.
|
|
478
|
+
*
|
|
479
|
+
* @param {string} paramName
|
|
480
|
+
* @returns {number}
|
|
481
|
+
* @private
|
|
482
|
+
*/
|
|
483
|
+
_getDefaultValue(paramName) {
|
|
484
|
+
const defaults = {
|
|
485
|
+
hue: 200,
|
|
486
|
+
saturation: 0.8,
|
|
487
|
+
intensity: 0.5,
|
|
488
|
+
speed: 1.0,
|
|
489
|
+
chaos: 0.2,
|
|
490
|
+
morphFactor: 1.0,
|
|
491
|
+
gridDensity: 15,
|
|
492
|
+
dimension: 3.5,
|
|
493
|
+
geometry: 0,
|
|
494
|
+
rot4dXY: 0,
|
|
495
|
+
rot4dXZ: 0,
|
|
496
|
+
rot4dYZ: 0,
|
|
497
|
+
rot4dXW: 0,
|
|
498
|
+
rot4dYW: 0,
|
|
499
|
+
rot4dZW: 0
|
|
500
|
+
};
|
|
501
|
+
return defaults[paramName] !== undefined ? defaults[paramName] : 0;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// -------------------------------------------------------------------------
|
|
505
|
+
// Private - Math Utilities
|
|
506
|
+
// -------------------------------------------------------------------------
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Circular hue interpolation (shortest path around 360-degree wheel).
|
|
510
|
+
*
|
|
511
|
+
* @param {number} a - Start hue (0-360)
|
|
512
|
+
* @param {number} b - End hue (0-360)
|
|
513
|
+
* @param {number} t - Progress (0-1)
|
|
514
|
+
* @returns {number}
|
|
515
|
+
* @private
|
|
516
|
+
*/
|
|
517
|
+
_lerpHue(a, b, t) {
|
|
518
|
+
let diff = b - a;
|
|
519
|
+
if (diff > 180) diff -= 360;
|
|
520
|
+
if (diff < -180) diff += 360;
|
|
521
|
+
let result = a + diff * t;
|
|
522
|
+
if (result < 0) result += 360;
|
|
523
|
+
if (result >= 360) result -= 360;
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/**
|
|
528
|
+
* Build the complete set of easing functions.
|
|
529
|
+
*
|
|
530
|
+
* @returns {Object<string, Function>}
|
|
531
|
+
* @private
|
|
532
|
+
*/
|
|
533
|
+
_buildEasingFunctions() {
|
|
534
|
+
return {
|
|
535
|
+
/**
|
|
536
|
+
* No easing, constant velocity.
|
|
537
|
+
* @param {number} t
|
|
538
|
+
* @returns {number}
|
|
539
|
+
*/
|
|
540
|
+
linear(t) {
|
|
541
|
+
return t;
|
|
542
|
+
},
|
|
543
|
+
|
|
544
|
+
/**
|
|
545
|
+
* Cubic acceleration from zero velocity.
|
|
546
|
+
* @param {number} t
|
|
547
|
+
* @returns {number}
|
|
548
|
+
*/
|
|
549
|
+
easeIn(t) {
|
|
550
|
+
return t * t * t;
|
|
551
|
+
},
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Cubic deceleration to zero velocity.
|
|
555
|
+
* @param {number} t
|
|
556
|
+
* @returns {number}
|
|
557
|
+
*/
|
|
558
|
+
easeOut(t) {
|
|
559
|
+
return 1 - Math.pow(1 - t, 3);
|
|
560
|
+
},
|
|
561
|
+
|
|
562
|
+
/**
|
|
563
|
+
* Cubic acceleration then deceleration.
|
|
564
|
+
* @param {number} t
|
|
565
|
+
* @returns {number}
|
|
566
|
+
*/
|
|
567
|
+
easeInOut(t) {
|
|
568
|
+
return t < 0.5
|
|
569
|
+
? 4 * t * t * t
|
|
570
|
+
: 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
571
|
+
},
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Quadratic ease-in.
|
|
575
|
+
* @param {number} t
|
|
576
|
+
* @returns {number}
|
|
577
|
+
*/
|
|
578
|
+
easeInQuad(t) {
|
|
579
|
+
return t * t;
|
|
580
|
+
},
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Quadratic ease-out.
|
|
584
|
+
* @param {number} t
|
|
585
|
+
* @returns {number}
|
|
586
|
+
*/
|
|
587
|
+
easeOutQuad(t) {
|
|
588
|
+
return 1 - (1 - t) * (1 - t);
|
|
589
|
+
},
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Bounce effect that simulates a ball bouncing to rest.
|
|
593
|
+
* @param {number} t
|
|
594
|
+
* @returns {number}
|
|
595
|
+
*/
|
|
596
|
+
bounce(t) {
|
|
597
|
+
const n1 = 7.5625;
|
|
598
|
+
const d1 = 2.75;
|
|
599
|
+
|
|
600
|
+
if (t < 1 / d1) {
|
|
601
|
+
return n1 * t * t;
|
|
602
|
+
} else if (t < 2 / d1) {
|
|
603
|
+
return n1 * (t -= 1.5 / d1) * t + 0.75;
|
|
604
|
+
} else if (t < 2.5 / d1) {
|
|
605
|
+
return n1 * (t -= 2.25 / d1) * t + 0.9375;
|
|
606
|
+
} else {
|
|
607
|
+
return n1 * (t -= 2.625 / d1) * t + 0.984375;
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* Elastic oscillation that overshoots then settles.
|
|
613
|
+
* @param {number} t
|
|
614
|
+
* @returns {number}
|
|
615
|
+
*/
|
|
616
|
+
elastic(t) {
|
|
617
|
+
if (t === 0 || t === 1) return t;
|
|
618
|
+
const c4 = (2 * Math.PI) / 3;
|
|
619
|
+
return Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
|
|
620
|
+
},
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Smooth cubic Bezier-style ease.
|
|
624
|
+
* @param {number} t
|
|
625
|
+
* @returns {number}
|
|
626
|
+
*/
|
|
627
|
+
cubic(t) {
|
|
628
|
+
return t < 0.5
|
|
629
|
+
? 4 * t * t * t
|
|
630
|
+
: 1 - Math.pow(-2 * t + 2, 3) / 2;
|
|
631
|
+
},
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* Back ease-out: slightly overshoots then returns.
|
|
635
|
+
* @param {number} t
|
|
636
|
+
* @returns {number}
|
|
637
|
+
*/
|
|
638
|
+
backOut(t) {
|
|
639
|
+
const c1 = 1.70158;
|
|
640
|
+
const c3 = c1 + 1;
|
|
641
|
+
return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
|
|
642
|
+
},
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Back ease-in: pulls back before accelerating.
|
|
646
|
+
* @param {number} t
|
|
647
|
+
* @returns {number}
|
|
648
|
+
*/
|
|
649
|
+
backIn(t) {
|
|
650
|
+
const c1 = 1.70158;
|
|
651
|
+
const c3 = c1 + 1;
|
|
652
|
+
return c3 * t * t * t - c1 * t * t;
|
|
653
|
+
},
|
|
654
|
+
|
|
655
|
+
/**
|
|
656
|
+
* Exponential ease-out.
|
|
657
|
+
* @param {number} t
|
|
658
|
+
* @returns {number}
|
|
659
|
+
*/
|
|
660
|
+
expoOut(t) {
|
|
661
|
+
return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
|
|
662
|
+
},
|
|
663
|
+
|
|
664
|
+
/**
|
|
665
|
+
* Exponential ease-in.
|
|
666
|
+
* @param {number} t
|
|
667
|
+
* @returns {number}
|
|
668
|
+
*/
|
|
669
|
+
expoIn(t) {
|
|
670
|
+
return t === 0 ? 0 : Math.pow(2, 10 * t - 10);
|
|
671
|
+
},
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* Sinusoidal ease-in-out.
|
|
675
|
+
* @param {number} t
|
|
676
|
+
* @returns {number}
|
|
677
|
+
*/
|
|
678
|
+
sineInOut(t) {
|
|
679
|
+
return -(Math.cos(Math.PI * t) - 1) / 2;
|
|
680
|
+
}
|
|
681
|
+
};
|
|
682
|
+
}
|
|
683
|
+
}
|