@vib3code/sdk 2.0.3-canary.45332e3 → 2.0.3-canary.4874bcf

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 (80) hide show
  1. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +2 -0
  2. package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
  3. package/DOCS/ARCHITECTURE.md +1 -0
  4. package/DOCS/CI_TESTING.md +2 -0
  5. package/DOCS/CLI_ONBOARDING.md +2 -0
  6. package/DOCS/CONTROL_REFERENCE.md +2 -0
  7. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +2 -0
  8. package/DOCS/ENV_SETUP.md +2 -0
  9. package/DOCS/EPIC_SCROLL_EVENTS.md +2 -0
  10. package/DOCS/EXPANSION_DESIGN.md +979 -0
  11. package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
  12. package/DOCS/EXPORT_FORMATS.md +2 -0
  13. package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
  14. package/DOCS/HANDOFF_LANDING_PAGE.md +2 -0
  15. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +2 -0
  16. package/DOCS/LICENSING_TIERS.md +2 -0
  17. package/DOCS/MASTER_PLAN_2026-01-31.md +2 -0
  18. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +3 -1
  19. package/DOCS/OBS_SETUP_GUIDE.md +2 -0
  20. package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
  21. package/DOCS/PRODUCT_STRATEGY.md +2 -0
  22. package/DOCS/PROJECT_SETUP.md +2 -0
  23. package/DOCS/README.md +5 -3
  24. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +2 -0
  25. package/DOCS/RENDERER_LIFECYCLE.md +2 -0
  26. package/DOCS/REPO_MANIFEST.md +2 -0
  27. package/DOCS/ROADMAP.md +2 -0
  28. package/DOCS/SCROLL_TIMELINE_v3.md +2 -0
  29. package/DOCS/SITE_REFACTOR_PLAN.md +2 -0
  30. package/DOCS/STATUS.md +2 -0
  31. package/DOCS/SYSTEM_INVENTORY.md +2 -0
  32. package/DOCS/TELEMETRY_EXPORTS.md +2 -0
  33. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +2 -0
  34. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +2 -0
  35. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +2 -0
  36. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +2 -0
  37. package/DOCS/WEBGPU_STATUS.md +2 -0
  38. package/DOCS/XR_BENCHMARKS.md +2 -0
  39. package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -34
  40. package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -80
  41. package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -42
  42. package/DOCS/archive/SESSION_014_PLAN.md +1 -195
  43. package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -56
  44. package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -72
  45. package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -741
  46. package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -38
  47. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-01-31.md +2 -0
  48. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +2 -0
  49. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +2 -0
  50. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +2 -0
  51. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +2 -0
  52. package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
  53. package/DOCS/dev-tracks/README.md +2 -0
  54. package/package.json +2 -4
  55. package/src/cli/index.js +59 -5
  56. package/src/experimental/GameLoop.js +72 -0
  57. package/src/experimental/LatticePhysics.js +100 -0
  58. package/src/experimental/LiveDirector.js +143 -0
  59. package/src/experimental/PlayerController4D.js +154 -0
  60. package/src/experimental/VIB3Actor.js +138 -0
  61. package/src/experimental/VIB3Compositor.js +117 -0
  62. package/src/experimental/VIB3Link.js +122 -0
  63. package/src/experimental/VIB3Orchestrator.js +146 -0
  64. package/src/experimental/VIB3Universe.js +109 -0
  65. package/src/experimental/demos/CrystalLabyrinth.js +202 -0
  66. package/src/export/SVGExporter.js +9 -5
  67. package/src/features/CollectionManager.js +27 -9
  68. package/src/gallery/CollectionManager.js +27 -9
  69. package/src/geometry/generators/Crystal.js +2 -2
  70. package/src/geometry/warp/HypersphereCore.js +53 -24
  71. package/src/math/Mat4x4.js +418 -142
  72. package/src/math/Projection.js +57 -7
  73. package/src/math/Rotor4D.js +102 -73
  74. package/src/math/Vec4.js +265 -111
  75. package/src/quantum/QuantumVisualizer.js +28 -0
  76. package/src/scene/Node4D.js +74 -24
  77. package/src/testing/ProjectionClass.test.js +38 -0
  78. package/src/variations/VariationManager.js +6 -1
  79. package/src/wasm/WasmLoader.js +11 -6
  80. package/tools/update_projection.py +109 -0
@@ -0,0 +1,100 @@
1
+ /**
2
+ * LatticePhysics - Function-Based Collision Detection
3
+ *
4
+ * Provides a physics engine for "Lattice Worlds" where geometry is defined
5
+ * by mathematical density functions (SDFs, fractals).
6
+ *
7
+ * @experimental
8
+ */
9
+ export class LatticePhysics {
10
+ constructor() {
11
+ this.gravity = 9.8; // m/s²
12
+ this.friction = 0.95; // Velocity decay per step
13
+ this.densityThreshold = 0.8; // Collision threshold (0-1)
14
+ }
15
+
16
+ /**
17
+ * Update physics for all entities in the universe.
18
+ * @param {Map<string, object>} entities
19
+ * @param {number} dt
20
+ */
21
+ update(entities, dt) {
22
+ entities.forEach(entity => {
23
+ if (entity.physics && entity.active) {
24
+ this.updateEntity(entity, dt);
25
+ }
26
+ });
27
+ }
28
+
29
+ /**
30
+ * Update a single entity's physics state.
31
+ * @param {object} entity
32
+ * @param {number} dt
33
+ */
34
+ updateEntity(entity, dt) {
35
+ const { pos, vel, acc } = entity.physics;
36
+
37
+ // Apply forces (Gravity)
38
+ // In this abstract world, gravity pulls "down" in Y
39
+ acc.y -= this.gravity * dt;
40
+
41
+ // Integrate Velocity (Euler)
42
+ vel.x += acc.x * dt;
43
+ vel.y += acc.y * dt;
44
+ vel.z += acc.z * dt;
45
+
46
+ // Reset acceleration (forces are transient)
47
+ acc.x = 0; acc.y = 0; acc.z = 0;
48
+
49
+ // Collision Check (Projected Position)
50
+ const nextX = pos.x + vel.x * dt;
51
+ const nextY = pos.y + vel.y * dt;
52
+ const nextZ = pos.z + vel.z * dt;
53
+
54
+ // Sample density at next position
55
+ const density = this.getDensityAt(nextX, nextY, nextZ);
56
+
57
+ if (density > this.densityThreshold) {
58
+ // Collision!
59
+ // Simple response: Stop velocity component and push out
60
+ // A real engine would calculate surface normal from gradient
61
+
62
+ // Simplified: Just stop movement and bounce slightly
63
+ vel.x *= -0.5;
64
+ vel.y *= -0.5;
65
+ vel.z *= -0.5;
66
+
67
+ // Don't update position into solid
68
+ } else {
69
+ // Move freely
70
+ pos.x = nextX;
71
+ pos.y = nextY;
72
+ pos.z = nextZ;
73
+ }
74
+
75
+ // Apply Friction (Air/Ether drag)
76
+ vel.x *= this.friction;
77
+ vel.y *= this.friction;
78
+ vel.z *= this.friction;
79
+ }
80
+
81
+ /**
82
+ * Sample the "world density" at a given point.
83
+ * This mimics the shader's generation logic (e.g., fractal noise).
84
+ * @param {number} x
85
+ * @param {number} y
86
+ * @param {number} z
87
+ * @returns {number} Density 0.0 to 1.0
88
+ */
89
+ getDensityAt(x, y, z) {
90
+ // Mock function: simple floor plane at y = -2
91
+ if (y < -2) return 1.0;
92
+
93
+ // Mock function: occasional "floating islands" based on sine waves
94
+ // simulating the VIB3 lattice structure
95
+ const noise = (Math.sin(x * 0.5) + Math.cos(z * 0.5)) * 0.5 + 0.5;
96
+ if (y > 0 && y < 1 && noise > 0.8) return 1.0;
97
+
98
+ return 0.0;
99
+ }
100
+ }
@@ -0,0 +1,143 @@
1
+ /**
2
+ * LiveDirector - Autonomous Creative Agent
3
+ *
4
+ * An AI agent that analyzes user input ("Audience Reaction") and adjusts the
5
+ * VIB3Universe in real-time to maintain engagement, flow, and narrative tension.
6
+ *
7
+ * @experimental
8
+ */
9
+ export class LiveDirector {
10
+ constructor(universe) {
11
+ this.universe = universe;
12
+ this.active = false;
13
+
14
+ // Audience State
15
+ this.audience = {
16
+ energy: 0.5, // 0.0 (Bored) -> 1.0 (Excited)
17
+ attention: 0.8, // 0.0 (Distracted) -> 1.0 (Focused)
18
+ sentiment: 0.0, // -1.0 (Negative) -> 1.0 (Positive)
19
+ };
20
+
21
+ // Directing State
22
+ this.pacing = 'build'; // 'intro', 'build', 'climax', 'resolve'
23
+ this.lastActionTime = 0;
24
+ this.decisionInterval = 2000; // ms
25
+
26
+ // Bind methods
27
+ this.update = this.update.bind(this);
28
+ }
29
+
30
+ /**
31
+ * Start the director loop.
32
+ */
33
+ start() {
34
+ if (this.active) return;
35
+ this.active = true;
36
+ this.lastActionTime = performance.now();
37
+ requestAnimationFrame(this.update);
38
+ console.log('LiveDirector: Started directing.');
39
+ }
40
+
41
+ /**
42
+ * Stop the director loop.
43
+ */
44
+ stop() {
45
+ this.active = false;
46
+ console.log('LiveDirector: Stopped directing.');
47
+ }
48
+
49
+ /**
50
+ * Feed audience input signal.
51
+ * @param {string} type - 'audio', 'video', 'input'
52
+ * @param {object} data - Analysis data
53
+ */
54
+ feedInput(type, data) {
55
+ if (type === 'audio') {
56
+ // Loud audio = high energy
57
+ this.audience.energy = Math.min(1.0, this.audience.energy + data.volume * 0.1);
58
+ } else if (type === 'input') {
59
+ // Interaction = high attention
60
+ this.audience.attention = Math.min(1.0, this.audience.attention + 0.05);
61
+ }
62
+
63
+ // Decay logic runs in update loop
64
+ }
65
+
66
+ /**
67
+ * Main decision loop.
68
+ * @param {number} timestamp
69
+ */
70
+ update(timestamp) {
71
+ if (!this.active) return;
72
+
73
+ const dt = (timestamp - this.lastActionTime);
74
+
75
+ // Decay audience metrics over time
76
+ this.audience.energy = Math.max(0, this.audience.energy - 0.001);
77
+ this.audience.attention = Math.max(0, this.audience.attention - 0.0005);
78
+
79
+ // Make a directing decision periodically
80
+ if (dt > this.decisionInterval) {
81
+ this.makeDecision();
82
+ this.lastActionTime = timestamp;
83
+ }
84
+
85
+ requestAnimationFrame(this.update);
86
+ }
87
+
88
+ /**
89
+ * The "Brain" of the Director.
90
+ * Decides what to change based on current state.
91
+ */
92
+ makeDecision() {
93
+ const { energy, attention } = this.audience;
94
+
95
+ console.log(`LiveDirector: Audience state - Energy: ${energy.toFixed(2)}, Attention: ${attention.toFixed(2)}`);
96
+
97
+ // Strategy: Maintain a "Sine Wave" of tension
98
+ // If energy is too low, spike it. If too high, calm it down.
99
+
100
+ if (attention < 0.3) {
101
+ // Lost attention -> TRIGGER EVENT
102
+ this.triggerEvent('focus_snap');
103
+ } else if (energy < 0.2) {
104
+ // Boring -> INCREASE INTENSITY
105
+ this.adjustGlobalParams({ speed: 1.5, chaos: 0.4 });
106
+ } else if (energy > 0.8) {
107
+ // Too frantic -> CALM DOWN
108
+ this.adjustGlobalParams({ speed: 0.5, chaos: 0.1 });
109
+ } else {
110
+ // Just right -> DO NOTHING or subtle shift
111
+ // Maybe drift hue slightly?
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Execute a parameter adjustment across all actors.
117
+ * @param {object} params
118
+ */
119
+ adjustGlobalParams(params) {
120
+ console.log('LiveDirector: Adjusting global parameters', params);
121
+ this.universe.actors.forEach(actor => {
122
+ if (actor.animator) {
123
+ actor.animator.transition(params, 2000, 'easeInOut');
124
+ }
125
+ });
126
+ }
127
+
128
+ /**
129
+ * Trigger a specific scripted event.
130
+ * @param {string} eventName
131
+ */
132
+ triggerEvent(eventName) {
133
+ console.log(`LiveDirector: Triggering event '${eventName}'`);
134
+ // Example: Flash screen, spawn particle burst, etc.
135
+ if (eventName === 'focus_snap') {
136
+ // Quick snap zoom / flash
137
+ this.adjustGlobalParams({ intensity: 1.0, speed: 0.0 });
138
+ setTimeout(() => {
139
+ this.adjustGlobalParams({ intensity: 0.5, speed: 1.0 });
140
+ }, 200);
141
+ }
142
+ }
143
+ }
@@ -0,0 +1,154 @@
1
+ /**
2
+ * PlayerController4D - Navigation in Hyperspace
3
+ *
4
+ * Maps 2D/3D inputs (WASD, Mouse) into 4D motion vectors (X, Y, Z, W).
5
+ * Handles movement, strafing, and "portal rotation" (XW/YW planes).
6
+ *
7
+ * @experimental
8
+ */
9
+ export class PlayerController4D {
10
+ /**
11
+ * @param {HTMLElement} domElement - Element to listen for events on
12
+ * @param {object} engine - VIB3Engine instance to drive
13
+ */
14
+ constructor(domElement, engine) {
15
+ this.domElement = domElement;
16
+ this.engine = engine;
17
+
18
+ // Input State
19
+ this.keys = {
20
+ w: false, a: false, s: false, d: false,
21
+ q: false, e: false, space: false, shift: false
22
+ };
23
+
24
+ this.mouse = {
25
+ dx: 0, dy: 0,
26
+ down: false
27
+ };
28
+
29
+ // Player Physics State
30
+ this.velocity = { x: 0, y: 0, z: 0, w: 0 };
31
+ this.rotation = { x: 0, y: 0 }; // Looking direction (Pitch/Yaw)
32
+ this.portalRot = 0; // XW plane rotation
33
+
34
+ // Config
35
+ this.speed = 5.0;
36
+ this.sensitivity = 0.002;
37
+ this.damping = 0.9;
38
+
39
+ // Bind events
40
+ this.onKeyDown = this.onKeyDown.bind(this);
41
+ this.onKeyUp = this.onKeyUp.bind(this);
42
+ this.onMouseMove = this.onMouseMove.bind(this);
43
+ this.onMouseDown = this.onMouseDown.bind(this);
44
+ this.onMouseUp = this.onMouseUp.bind(this);
45
+
46
+ this.setupListeners();
47
+ }
48
+
49
+ setupListeners() {
50
+ window.addEventListener('keydown', this.onKeyDown);
51
+ window.addEventListener('keyup', this.onKeyUp);
52
+ this.domElement.addEventListener('mousemove', this.onMouseMove);
53
+ this.domElement.addEventListener('mousedown', this.onMouseDown);
54
+ this.domElement.addEventListener('mouseup', this.onMouseUp);
55
+ }
56
+
57
+ onKeyDown(e) {
58
+ const k = e.key.toLowerCase();
59
+ if (this.keys.hasOwnProperty(k)) this.keys[k] = true;
60
+ }
61
+
62
+ onKeyUp(e) {
63
+ const k = e.key.toLowerCase();
64
+ if (this.keys.hasOwnProperty(k)) this.keys[k] = false;
65
+ }
66
+
67
+ onMouseDown() { this.mouse.down = true; }
68
+ onMouseUp() { this.mouse.down = false; }
69
+
70
+ onMouseMove(e) {
71
+ if (this.mouse.down) {
72
+ this.mouse.dx += e.movementX;
73
+ this.mouse.dy += e.movementY;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Update loop called by GameLoop.
79
+ * @param {number} dt
80
+ */
81
+ update(dt) {
82
+ // 1. Process Rotation (Mouse)
83
+ this.rotation.y -= this.mouse.dx * this.sensitivity; // Yaw
84
+ this.rotation.x -= this.mouse.dy * this.sensitivity; // Pitch
85
+
86
+ // Clamp pitch to avoid flipping
87
+ this.rotation.x = Math.max(-Math.PI/2, Math.min(Math.PI/2, this.rotation.x));
88
+
89
+ // Reset mouse delta (consumed)
90
+ this.mouse.dx = 0;
91
+ this.mouse.dy = 0;
92
+
93
+ // 2. Process Movement (WASD)
94
+ // Forward vector derived from Yaw
95
+ const fwdX = Math.sin(this.rotation.y);
96
+ const fwdZ = Math.cos(this.rotation.y);
97
+ const rightX = Math.cos(this.rotation.y); // Perpendicular
98
+ const rightZ = -Math.sin(this.rotation.y);
99
+
100
+ const moveSpeed = this.speed * dt;
101
+
102
+ if (this.keys.w) {
103
+ this.velocity.x += fwdX * moveSpeed;
104
+ this.velocity.z -= fwdZ * moveSpeed; // WebGL Z is negative forward
105
+ }
106
+ if (this.keys.s) {
107
+ this.velocity.x -= fwdX * moveSpeed;
108
+ this.velocity.z += fwdZ * moveSpeed;
109
+ }
110
+ if (this.keys.a) {
111
+ this.velocity.x -= rightX * moveSpeed;
112
+ this.velocity.z += rightZ * moveSpeed;
113
+ }
114
+ if (this.keys.d) {
115
+ this.velocity.x += rightX * moveSpeed;
116
+ this.velocity.z -= rightZ * moveSpeed;
117
+ }
118
+
119
+ // Vertical Movement (Space/Shift)
120
+ if (this.keys.space) this.velocity.y += moveSpeed;
121
+ if (this.keys.shift) this.velocity.y -= moveSpeed;
122
+
123
+ // 4D Portal Rotation (Q/E)
124
+ if (this.keys.q) this.portalRot -= moveSpeed;
125
+ if (this.keys.e) this.portalRot += moveSpeed;
126
+
127
+ // Apply Damping (Friction)
128
+ this.velocity.x *= this.damping;
129
+ this.velocity.y *= this.damping;
130
+ this.velocity.z *= this.damping;
131
+
132
+ // 3. Apply to VIB3Engine Parameters
133
+ // Map 4D position to shader uniforms (e.g., u_noiseOffset or camera pos)
134
+ // Here we map to rotation parameters as a proxy for camera movement
135
+
136
+ // Visual feedback: Velocity tilts the view
137
+ this.engine.setParameter('rot4dXY', this.rotation.y + this.velocity.x * 0.1);
138
+ this.engine.setParameter('rot4dYZ', this.rotation.x + this.velocity.y * 0.1);
139
+
140
+ // Portal rotation affects XW plane
141
+ this.engine.setParameter('rot4dXW', this.portalRot);
142
+
143
+ // "Moving forward" increases grid density/scale to simulate zooming through
144
+ // In a real implementation, we'd update a u_cameraPosition uniform
145
+ }
146
+
147
+ destroy() {
148
+ window.removeEventListener('keydown', this.onKeyDown);
149
+ window.removeEventListener('keyup', this.onKeyUp);
150
+ this.domElement.removeEventListener('mousemove', this.onMouseMove);
151
+ this.domElement.removeEventListener('mousedown', this.onMouseDown);
152
+ this.domElement.removeEventListener('mouseup', this.onMouseUp);
153
+ }
154
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * VIB3Actor - A VIB3+ Entity with Personality
3
+ *
4
+ * Wraps a VIB3Engine instance with emotional state and expression logic.
5
+ * Actors can "emote" (transition parameters based on mood) and "speak"
6
+ * (modulate geometry).
7
+ *
8
+ * @experimental
9
+ */
10
+ import { TransitionAnimator } from '../creative/TransitionAnimator.js';
11
+
12
+ export class VIB3Actor {
13
+ /**
14
+ * @param {VIB3Engine} engine - The VIB3 engine instance
15
+ * @param {string|object} profile - Personality profile name or object
16
+ */
17
+ constructor(engine, profile = 'neutral') {
18
+ this.engine = engine;
19
+ this.id = `actor_${Math.random().toString(36).substr(2, 9)}`;
20
+ this.active = true;
21
+
22
+ // Emotional State (-1.0 to 1.0)
23
+ this.emotion = {
24
+ valence: 0, // Positive/Negative
25
+ arousal: 0 // High/Low Energy
26
+ };
27
+
28
+ // Animation system
29
+ this.animator = new TransitionAnimator(
30
+ (k, v) => this.engine.setParameter(k, v),
31
+ (k) => this.engine.getParameter(k)
32
+ );
33
+
34
+ // Load profile
35
+ this.profile = typeof profile === 'string' ? this._getProfile(profile) : profile;
36
+
37
+ // Apply base state
38
+ this.reset();
39
+ }
40
+
41
+ /**
42
+ * Update loop called by Orchestrator.
43
+ * @param {number} time - Total elapsed simulation time
44
+ * @param {number} dt - Delta time in seconds
45
+ */
46
+ update(time, dt) {
47
+ if (!this.active) return;
48
+
49
+ // Idle behavior (breathing)
50
+ // Sync morphFactor to universe time
51
+ const breath = Math.sin(time * 2.0) * 0.1; // 2.0 rad/s
52
+
53
+ // Apply breath modulation on top of base profile
54
+ // Note: This is a simple additive modulation.
55
+ // A real system would blend this with active transitions.
56
+ const currentMorph = this.engine.getParameter('morphFactor') || 1.0;
57
+ // Only modulate if not transitioning heavily
58
+ if (!this.animator.isAnimating()) {
59
+ // Gentle idle sway
60
+ this.engine.setParameter('morphFactor', 1.0 + breath);
61
+ }
62
+ }
63
+
64
+ /**
65
+ * Express an emotion.
66
+ * @param {string} emotionName - e.g., 'joy', 'anger', 'fear', 'sadness'
67
+ * @param {number} intensity - 0.0 to 1.0
68
+ * @param {number} duration - Transition duration in ms
69
+ */
70
+ emote(emotionName, intensity = 1.0, duration = 1000) {
71
+ const mapping = this.profile.emotions[emotionName];
72
+ if (!mapping) {
73
+ console.warn(`VIB3Actor: Unknown emotion '${emotionName}' for profile '${this.profile.name}'`);
74
+ return;
75
+ }
76
+
77
+ const targetParams = {};
78
+ for (const [param, baseVal] of Object.entries(mapping)) {
79
+ // Lerp between current/neutral and target based on intensity
80
+ // Simplified: just setting target value scaled by intensity logic could go here
81
+ // For now, we just use the mapped value directly as the "100% intensity" target
82
+ targetParams[param] = baseVal;
83
+ }
84
+
85
+ // Apply global intensity modifiers
86
+ if (targetParams.intensity) targetParams.intensity *= intensity;
87
+ if (targetParams.speed) targetParams.speed *= intensity;
88
+
89
+ this.animator.transition(targetParams, duration, 'easeOut');
90
+
91
+ // Update internal state (simplified)
92
+ this.emotion.lastEmote = emotionName;
93
+ }
94
+
95
+ /**
96
+ * Reset to neutral state.
97
+ */
98
+ reset(duration = 1000) {
99
+ this.animator.transition(this.profile.base, duration, 'easeInOut');
100
+ }
101
+
102
+ /**
103
+ * Get a predefined personality profile.
104
+ * @param {string} name
105
+ */
106
+ _getProfile(name) {
107
+ const profiles = {
108
+ neutral: {
109
+ name: 'neutral',
110
+ base: { hue: 200, saturation: 0.5, intensity: 0.5, chaos: 0, speed: 1.0, gridDensity: 20 },
111
+ emotions: {
112
+ joy: { hue: 50, saturation: 1.0, intensity: 0.8, speed: 2.0, chaos: 0.2 },
113
+ anger: { hue: 0, saturation: 1.0, intensity: 0.9, speed: 3.0, chaos: 0.8 },
114
+ sadness: { hue: 240, saturation: 0.2, intensity: 0.3, speed: 0.2, chaos: 0 },
115
+ fear: { hue: 280, saturation: 0.8, intensity: 0.6, speed: 2.5, chaos: 0.9, gridDensity: 50 }
116
+ }
117
+ },
118
+ heroic: {
119
+ name: 'heroic',
120
+ base: { hue: 210, saturation: 0.8, intensity: 0.7, chaos: 0.1, speed: 1.0, gridDensity: 15 },
121
+ emotions: {
122
+ joy: { hue: 50, saturation: 1.0, intensity: 1.0, speed: 1.5, morphFactor: 1.2 },
123
+ anger: { hue: 20, saturation: 1.0, intensity: 1.0, speed: 2.5, chaos: 0.5 },
124
+ determination: { hue: 220, saturation: 0.9, intensity: 0.9, speed: 1.2, gridDensity: 10 }
125
+ }
126
+ },
127
+ glitch: {
128
+ name: 'glitch',
129
+ base: { hue: 120, saturation: 0.0, intensity: 0.4, chaos: 0.5, speed: 2.0, gridDensity: 40 },
130
+ emotions: {
131
+ panic: { hue: 0, saturation: 0, intensity: 0.9, speed: 5.0, chaos: 1.0, rot4dXW: 1.5 },
132
+ calm: { hue: 120, saturation: 0.5, intensity: 0.4, speed: 0.5, chaos: 0.2 }
133
+ }
134
+ }
135
+ };
136
+ return profiles[name] || profiles.neutral;
137
+ }
138
+ }
@@ -0,0 +1,117 @@
1
+ /**
2
+ * VIB3Compositor - Visual Layering and Scene Management
3
+ *
4
+ * Handles the complexity of rendering multiple VIB3+ instances into a cohesive visual.
5
+ * Manages DOM structure, Z-indexing, masking, and blend modes for "Universe" rendering.
6
+ *
7
+ * @experimental
8
+ */
9
+ export class VIB3Compositor {
10
+ constructor(containerId = 'vib3-universe') {
11
+ this.containerId = containerId;
12
+ this.layers = []; // Ordered list of layer configs
13
+ this.activeInstances = new Map(); // instanceId -> DOM element
14
+
15
+ // Ensure container exists
16
+ if (typeof document !== 'undefined') {
17
+ this.container = document.getElementById(containerId);
18
+ if (!this.container) {
19
+ this.container = document.createElement('div');
20
+ this.container.id = containerId;
21
+ this.container.style.position = 'relative';
22
+ this.container.style.width = '100vw';
23
+ this.container.style.height = '100vh';
24
+ this.container.style.overflow = 'hidden';
25
+ document.body.appendChild(this.container);
26
+ }
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Register a VIB3 instance to be composited.
32
+ * @param {string} instanceId - Unique ID for the VIB3 instance
33
+ * @param {HTMLElement} canvasElement - The canvas element of the VIB3 instance
34
+ * @param {object} options - Layer configuration (zIndex, blendMode, opacity)
35
+ */
36
+ addInstance(instanceId, canvasElement, options = {}) {
37
+ if (this.activeInstances.has(instanceId)) {
38
+ console.warn(`VIB3Compositor: Instance ${instanceId} already registered.`);
39
+ return;
40
+ }
41
+
42
+ // Apply default styles for compositing
43
+ canvasElement.style.position = 'absolute';
44
+ canvasElement.style.top = '0';
45
+ canvasElement.style.left = '0';
46
+ canvasElement.style.width = '100%';
47
+ canvasElement.style.height = '100%';
48
+
49
+ // Apply options
50
+ this.updateLayer(instanceId, options);
51
+
52
+ this.container.appendChild(canvasElement);
53
+ this.activeInstances.set(instanceId, canvasElement);
54
+ this.layers.push(instanceId);
55
+
56
+ console.log(`VIB3Compositor: Added instance ${instanceId}`);
57
+ }
58
+
59
+ /**
60
+ * Remove a VIB3 instance from the compositor.
61
+ * @param {string} instanceId
62
+ */
63
+ removeInstance(instanceId) {
64
+ if (this.activeInstances.has(instanceId)) {
65
+ const canvasElement = this.activeInstances.get(instanceId);
66
+ if (canvasElement.parentNode) {
67
+ canvasElement.parentNode.removeChild(canvasElement);
68
+ }
69
+ this.activeInstances.delete(instanceId);
70
+ this.layers = this.layers.filter(id => id !== instanceId);
71
+ console.log(`VIB3Compositor: Removed instance ${instanceId}`);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Update visual properties of a layer.
77
+ * @param {string} instanceId
78
+ * @param {object} options - { zIndex, blendMode, opacity, visible }
79
+ */
80
+ updateLayer(instanceId, options) {
81
+ const canvasElement = this.activeInstances.get(instanceId);
82
+ if (!canvasElement) return;
83
+
84
+ if (options.zIndex !== undefined) canvasElement.style.zIndex = options.zIndex;
85
+ if (options.blendMode !== undefined) canvasElement.style.mixBlendMode = options.blendMode;
86
+ if (options.opacity !== undefined) canvasElement.style.opacity = options.opacity;
87
+ if (options.visible !== undefined) canvasElement.style.display = options.visible ? 'block' : 'none';
88
+
89
+ // Handle masking if provided (experimental CSS mask)
90
+ if (options.maskImage) {
91
+ canvasElement.style.webkitMaskImage = `url(${options.maskImage})`;
92
+ canvasElement.style.maskImage = `url(${options.maskImage})`;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Reorder layers based on a list of IDs.
98
+ * @param {string[]} order - Array of instance IDs, from bottom to top
99
+ */
100
+ setLayerOrder(order) {
101
+ order.forEach((id, index) => {
102
+ this.updateLayer(id, { zIndex: index });
103
+ });
104
+ this.layers = order;
105
+ }
106
+
107
+ /**
108
+ * Clear all instances.
109
+ */
110
+ clear() {
111
+ this.activeInstances.forEach((el, id) => {
112
+ if (el.parentNode) el.parentNode.removeChild(el);
113
+ });
114
+ this.activeInstances.clear();
115
+ this.layers = [];
116
+ }
117
+ }