@vib3code/sdk 2.0.1 → 2.0.3-canary.0a63e71
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 +36 -0
- package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +245 -0
- package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
- package/DOCS/ARCHITECTURE.md +1 -0
- package/DOCS/CI_TESTING.md +2 -0
- package/DOCS/CLI_ONBOARDING.md +3 -1
- package/DOCS/CONTROL_REFERENCE.md +2 -0
- package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +119 -0
- package/DOCS/ENV_SETUP.md +2 -0
- package/DOCS/EPIC_SCROLL_EVENTS.md +775 -0
- package/DOCS/EXPANSION_DESIGN.md +979 -0
- package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
- package/DOCS/EXPORT_FORMATS.md +2 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
- package/DOCS/HANDOFF_LANDING_PAGE.md +156 -0
- package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +495 -0
- package/DOCS/LICENSING_TIERS.md +2 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +4 -2
- package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +939 -0
- package/DOCS/OBS_SETUP_GUIDE.md +2 -0
- package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
- package/DOCS/PRODUCT_STRATEGY.md +65 -0
- package/DOCS/PROJECT_SETUP.md +2 -0
- package/DOCS/README.md +105 -0
- package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +99 -0
- package/DOCS/RENDERER_LIFECYCLE.md +2 -0
- package/DOCS/REPO_MANIFEST.md +2 -0
- package/DOCS/ROADMAP.md +113 -0
- package/DOCS/SCROLL_TIMELINE_v3.md +271 -0
- package/DOCS/SITE_REFACTOR_PLAN.md +102 -0
- package/DOCS/STATUS.md +26 -0
- package/DOCS/SYSTEM_INVENTORY.md +37 -32
- package/DOCS/TELEMETRY_EXPORTS.md +2 -0
- package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +87 -0
- package/DOCS/VISUAL_ANALYSIS_FACETAD.md +135 -0
- package/DOCS/VISUAL_ANALYSIS_SIMONE.md +97 -0
- package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +88 -0
- package/DOCS/WEBGPU_STATUS.md +121 -38
- package/DOCS/XR_BENCHMARKS.md +2 -0
- package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -0
- package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -0
- package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -0
- package/DOCS/archive/SESSION_014_PLAN.md +1 -0
- package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -0
- package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -0
- package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -0
- package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -0
- package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +3 -1
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +233 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +129 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +144 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +110 -0
- package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
- package/DOCS/dev-tracks/README.md +12 -0
- package/README.md +26 -13
- package/cpp/CMakeLists.txt +236 -0
- package/cpp/bindings/embind.cpp +269 -0
- package/cpp/build.sh +129 -0
- package/cpp/geometry/Crystal.cpp +103 -0
- package/cpp/geometry/Fractal.cpp +136 -0
- package/cpp/geometry/GeometryGenerator.cpp +262 -0
- package/cpp/geometry/KleinBottle.cpp +71 -0
- package/cpp/geometry/Sphere.cpp +134 -0
- package/cpp/geometry/Tesseract.cpp +94 -0
- package/cpp/geometry/Tetrahedron.cpp +83 -0
- package/cpp/geometry/Torus.cpp +65 -0
- package/cpp/geometry/WarpFunctions.cpp +238 -0
- package/cpp/geometry/Wave.cpp +85 -0
- package/cpp/include/vib3_ffi.h +238 -0
- package/cpp/math/Mat4x4.cpp +409 -0
- package/cpp/math/Mat4x4.hpp +209 -0
- package/cpp/math/Projection.cpp +142 -0
- package/cpp/math/Projection.hpp +148 -0
- package/cpp/math/Rotor4D.cpp +322 -0
- package/cpp/math/Rotor4D.hpp +204 -0
- package/cpp/math/Vec4.cpp +303 -0
- package/cpp/math/Vec4.hpp +225 -0
- package/cpp/src/vib3_ffi.cpp +607 -0
- package/cpp/tests/Geometry_test.cpp +213 -0
- package/cpp/tests/Mat4x4_test.cpp +494 -0
- package/cpp/tests/Projection_test.cpp +298 -0
- package/cpp/tests/Rotor4D_test.cpp +423 -0
- package/cpp/tests/Vec4_test.cpp +489 -0
- package/docs/webgpu-live.html +1 -1
- package/package.json +41 -30
- package/src/agent/index.js +1 -3
- package/src/agent/mcp/MCPServer.js +1220 -144
- package/src/agent/mcp/index.js +1 -1
- package/src/agent/mcp/stdio-server.js +264 -0
- package/src/agent/mcp/tools.js +498 -31
- package/src/cli/index.js +431 -47
- package/src/core/CanvasManager.js +97 -204
- package/src/core/ErrorReporter.js +1 -1
- package/src/core/Parameters.js +1 -1
- package/src/core/VIB3Engine.js +93 -4
- package/src/core/VitalitySystem.js +53 -0
- package/src/core/index.js +18 -0
- package/src/core/renderers/FacetedRendererAdapter.js +10 -9
- package/src/core/renderers/HolographicRendererAdapter.js +13 -9
- package/src/core/renderers/QuantumRendererAdapter.js +11 -7
- package/src/creative/AestheticMapper.js +628 -0
- package/src/creative/ChoreographyPlayer.js +481 -0
- package/src/creative/index.js +11 -0
- package/src/experimental/GameLoop.js +72 -0
- package/src/experimental/LatticePhysics.js +100 -0
- package/src/experimental/LiveDirector.js +143 -0
- package/src/experimental/PlayerController4D.js +154 -0
- package/src/experimental/VIB3Actor.js +138 -0
- package/src/experimental/VIB3Compositor.js +117 -0
- package/src/experimental/VIB3Link.js +122 -0
- package/src/experimental/VIB3Orchestrator.js +146 -0
- package/src/experimental/VIB3Universe.js +109 -0
- package/src/experimental/demos/CrystalLabyrinth.js +202 -0
- package/src/export/TradingCardManager.js +3 -4
- package/src/export/index.js +11 -1
- package/src/faceted/FacetedSystem.js +260 -394
- package/src/games/glyph-war/GlyphWarVisualizer.js +641 -0
- package/src/geometry/generators/Crystal.js +2 -2
- package/src/geometry/warp/HypersphereCore.js +53 -24
- package/src/holograms/HolographicVisualizer.js +84 -98
- package/src/holograms/RealHolographicSystem.js +194 -43
- package/src/math/Mat4x4.js +308 -105
- package/src/math/Rotor4D.js +124 -40
- package/src/math/Vec4.js +200 -103
- package/src/math/index.js +7 -7
- package/src/polychora/PolychoraSystem.js +77 -0
- package/src/quantum/QuantumEngine.js +103 -66
- package/src/quantum/QuantumVisualizer.js +31 -22
- package/src/reactivity/index.js +3 -5
- package/src/render/LayerPresetManager.js +372 -0
- package/src/render/LayerReactivityBridge.js +344 -0
- package/src/render/LayerRelationshipGraph.js +610 -0
- package/src/render/MultiCanvasBridge.js +148 -25
- package/src/render/ShaderLoader.js +38 -0
- package/src/render/ShaderProgram.js +4 -4
- package/src/render/UnifiedRenderBridge.js +4 -1
- package/src/render/backends/WebGPUBackend.js +8 -4
- package/src/render/index.js +27 -2
- package/src/scene/Node4D.js +74 -24
- package/src/scene/index.js +4 -4
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +4 -4
- package/src/shaders/common/rotation4d.wgsl +2 -2
- package/src/shaders/common/uniforms.wgsl +15 -8
- package/src/shaders/faceted/faceted.frag.glsl +220 -80
- package/src/shaders/faceted/faceted.frag.wgsl +144 -90
- package/src/shaders/holographic/holographic.frag.glsl +28 -9
- package/src/shaders/holographic/holographic.frag.wgsl +112 -41
- package/src/shaders/quantum/quantum.frag.glsl +1 -0
- package/src/shaders/quantum/quantum.frag.wgsl +6 -4
- package/src/testing/ParallelTestFramework.js +2 -2
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
- package/src/viewer/GalleryUI.js +17 -0
- package/src/viewer/ViewerPortal.js +2 -2
- package/src/viewer/index.js +1 -1
- package/tools/headless-renderer.js +258 -0
- package/tools/shader-sync-verify.js +14 -8
- package/tools/site-analysis/all-reports.json +32 -0
- package/tools/site-analysis/combined-analysis.md +50 -0
- package/tools/site-analyzer.mjs +779 -0
- package/tools/visual-catalog/capture.js +276 -0
- package/tools/visual-catalog/composite.js +138 -0
- package/types/adaptive-sdk.d.ts +204 -5
- package/types/agent/cli.d.ts +78 -0
- package/types/agent/index.d.ts +18 -0
- package/types/agent/mcp.d.ts +87 -0
- package/types/agent/telemetry.d.ts +190 -0
- package/types/core/VIB3Engine.d.ts +26 -0
- package/types/core/index.d.ts +261 -0
- package/types/creative/AestheticMapper.d.ts +72 -0
- package/types/creative/ChoreographyPlayer.d.ts +96 -0
- package/types/creative/index.d.ts +17 -0
- package/types/export/index.d.ts +243 -0
- package/types/geometry/index.d.ts +164 -0
- package/types/math/index.d.ts +214 -0
- package/types/render/LayerPresetManager.d.ts +78 -0
- package/types/render/LayerReactivityBridge.d.ts +85 -0
- package/types/render/LayerRelationshipGraph.d.ts +174 -0
- package/types/render/index.d.ts +3 -0
- package/types/scene/index.d.ts +204 -0
- package/types/systems/index.d.ts +244 -0
- package/types/variations/index.d.ts +62 -0
- package/types/viewer/index.d.ts +225 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +0 -34
- package/DOCS/DEV_TRACK_ANALYSIS.md +0 -77
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +0 -42
- package/DOCS/SESSION_014_PLAN.md +0 -195
- package/DOCS/SESSION_LOG_2026-01-07.md +0 -56
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +0 -72
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +0 -738
- /package/src/viewer/{ReactivityManager.js → ViewerInputHandler.js} +0 -0
|
@@ -0,0 +1,372 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LayerPresetManager — Save, load, tune, and share layer relationship presets
|
|
3
|
+
*
|
|
4
|
+
* Works with LayerRelationshipGraph to persist custom layer configurations.
|
|
5
|
+
* Users and agents can:
|
|
6
|
+
* - Save the current graph state as a named preset
|
|
7
|
+
* - Load presets by name
|
|
8
|
+
* - Tune individual relationship parameters at runtime
|
|
9
|
+
* - Import/export preset libraries as JSON
|
|
10
|
+
* - List available presets (built-in + user)
|
|
11
|
+
*
|
|
12
|
+
* Storage: localStorage by default, configurable via constructor.
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* const presets = new LayerPresetManager(graph);
|
|
16
|
+
* presets.save('my-look'); // save current graph
|
|
17
|
+
* presets.load('my-look'); // restore to graph
|
|
18
|
+
* presets.tune('shadow', { opacity: 0.6, gain: 3 }); // tweak a layer
|
|
19
|
+
* const lib = presets.exportLibrary(); // full JSON export
|
|
20
|
+
* presets.importLibrary(lib); // bulk import
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { LayerRelationshipGraph, PROFILES, PRESET_REGISTRY } from './LayerRelationshipGraph.js';
|
|
24
|
+
|
|
25
|
+
const STORAGE_KEY = 'vib3_layer_presets';
|
|
26
|
+
|
|
27
|
+
export class LayerPresetManager {
|
|
28
|
+
/**
|
|
29
|
+
* @param {LayerRelationshipGraph} graph - The live graph to save from / load into
|
|
30
|
+
* @param {object} [options]
|
|
31
|
+
* @param {Storage} [options.storage] - Storage backend (default: localStorage)
|
|
32
|
+
* @param {string} [options.storageKey] - Key prefix for storage
|
|
33
|
+
*/
|
|
34
|
+
constructor(graph, options = {}) {
|
|
35
|
+
if (!(graph instanceof LayerRelationshipGraph)) {
|
|
36
|
+
throw new Error('LayerPresetManager requires a LayerRelationshipGraph instance');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** @type {LayerRelationshipGraph} */
|
|
40
|
+
this._graph = graph;
|
|
41
|
+
|
|
42
|
+
/** @type {Storage|null} */
|
|
43
|
+
this._storage = options.storage !== undefined ? options.storage : this._getStorage();
|
|
44
|
+
|
|
45
|
+
/** @type {string} */
|
|
46
|
+
this._storageKey = options.storageKey || STORAGE_KEY;
|
|
47
|
+
|
|
48
|
+
/** @type {Map<string, object>} In-memory preset cache */
|
|
49
|
+
this._presets = new Map();
|
|
50
|
+
|
|
51
|
+
// Load persisted presets into memory
|
|
52
|
+
this._loadFromStorage();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get localStorage safely (returns null in non-browser / restricted environments).
|
|
57
|
+
* @private
|
|
58
|
+
* @returns {Storage|null}
|
|
59
|
+
*/
|
|
60
|
+
_getStorage() {
|
|
61
|
+
try {
|
|
62
|
+
if (typeof localStorage !== 'undefined') {
|
|
63
|
+
// Verify it works
|
|
64
|
+
localStorage.setItem('__vib3_test', '1');
|
|
65
|
+
localStorage.removeItem('__vib3_test');
|
|
66
|
+
return localStorage;
|
|
67
|
+
}
|
|
68
|
+
} catch (_e) { /* restricted */ }
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Load all presets from storage into the in-memory cache.
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
_loadFromStorage() {
|
|
77
|
+
if (!this._storage) return;
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const raw = this._storage.getItem(this._storageKey);
|
|
81
|
+
if (raw) {
|
|
82
|
+
const data = JSON.parse(raw);
|
|
83
|
+
if (data && typeof data === 'object') {
|
|
84
|
+
for (const [name, preset] of Object.entries(data)) {
|
|
85
|
+
this._presets.set(name, preset);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} catch (e) {
|
|
90
|
+
console.warn('LayerPresetManager: failed to load presets from storage:', e.message);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Persist the in-memory preset cache to storage.
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
_saveToStorage() {
|
|
99
|
+
if (!this._storage) return;
|
|
100
|
+
|
|
101
|
+
try {
|
|
102
|
+
const data = {};
|
|
103
|
+
for (const [name, preset] of this._presets) {
|
|
104
|
+
data[name] = preset;
|
|
105
|
+
}
|
|
106
|
+
this._storage.setItem(this._storageKey, JSON.stringify(data));
|
|
107
|
+
} catch (e) {
|
|
108
|
+
console.warn('LayerPresetManager: failed to save presets to storage:', e.message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ========================================================================
|
|
113
|
+
// Save / Load
|
|
114
|
+
// ========================================================================
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Save the current graph state as a named preset.
|
|
118
|
+
*
|
|
119
|
+
* @param {string} name - Preset name (must not collide with built-in profile names)
|
|
120
|
+
* @param {object} [metadata] - Optional metadata (description, author, tags)
|
|
121
|
+
* @returns {object} The saved preset data
|
|
122
|
+
*/
|
|
123
|
+
save(name, metadata = {}) {
|
|
124
|
+
if (!name || typeof name !== 'string') {
|
|
125
|
+
throw new Error('Preset name must be a non-empty string');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (PROFILES[name]) {
|
|
129
|
+
throw new Error(`Cannot overwrite built-in profile "${name}". Choose a different name.`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const config = this._graph.exportConfig();
|
|
133
|
+
const preset = {
|
|
134
|
+
name,
|
|
135
|
+
config,
|
|
136
|
+
metadata: {
|
|
137
|
+
...metadata,
|
|
138
|
+
createdAt: new Date().toISOString(),
|
|
139
|
+
updatedAt: new Date().toISOString()
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
this._presets.set(name, preset);
|
|
144
|
+
this._saveToStorage();
|
|
145
|
+
|
|
146
|
+
return preset;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Load a preset by name into the live graph.
|
|
151
|
+
* Checks user presets first, then built-in profiles.
|
|
152
|
+
*
|
|
153
|
+
* @param {string} name - Preset or profile name
|
|
154
|
+
* @returns {boolean} True if loaded successfully
|
|
155
|
+
*/
|
|
156
|
+
load(name) {
|
|
157
|
+
// User preset
|
|
158
|
+
const preset = this._presets.get(name);
|
|
159
|
+
if (preset && preset.config) {
|
|
160
|
+
this._graph.importConfig(preset.config);
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Built-in profile
|
|
165
|
+
if (PROFILES[name]) {
|
|
166
|
+
this._graph.loadProfile(name);
|
|
167
|
+
return true;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Delete a user preset.
|
|
175
|
+
*
|
|
176
|
+
* @param {string} name
|
|
177
|
+
* @returns {boolean} True if deleted
|
|
178
|
+
*/
|
|
179
|
+
delete(name) {
|
|
180
|
+
if (PROFILES[name]) {
|
|
181
|
+
throw new Error(`Cannot delete built-in profile "${name}".`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const existed = this._presets.delete(name);
|
|
185
|
+
if (existed) {
|
|
186
|
+
this._saveToStorage();
|
|
187
|
+
}
|
|
188
|
+
return existed;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Check if a preset exists (user or built-in).
|
|
193
|
+
*
|
|
194
|
+
* @param {string} name
|
|
195
|
+
* @returns {boolean}
|
|
196
|
+
*/
|
|
197
|
+
has(name) {
|
|
198
|
+
return this._presets.has(name) || !!PROFILES[name];
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get a preset's data without loading it.
|
|
203
|
+
*
|
|
204
|
+
* @param {string} name
|
|
205
|
+
* @returns {object|null}
|
|
206
|
+
*/
|
|
207
|
+
get(name) {
|
|
208
|
+
return this._presets.get(name) || null;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ========================================================================
|
|
212
|
+
// List / Browse
|
|
213
|
+
// ========================================================================
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* List all available presets (user + built-in).
|
|
217
|
+
*
|
|
218
|
+
* @returns {{ user: string[], builtIn: string[] }}
|
|
219
|
+
*/
|
|
220
|
+
list() {
|
|
221
|
+
return {
|
|
222
|
+
user: Array.from(this._presets.keys()),
|
|
223
|
+
builtIn: Object.keys(PROFILES)
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* List all preset names (user + built-in) as a flat array.
|
|
229
|
+
*
|
|
230
|
+
* @returns {string[]}
|
|
231
|
+
*/
|
|
232
|
+
listAll() {
|
|
233
|
+
return [
|
|
234
|
+
...Object.keys(PROFILES),
|
|
235
|
+
...Array.from(this._presets.keys())
|
|
236
|
+
];
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Get the count of user presets.
|
|
241
|
+
*
|
|
242
|
+
* @returns {number}
|
|
243
|
+
*/
|
|
244
|
+
get count() {
|
|
245
|
+
return this._presets.size;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// ========================================================================
|
|
249
|
+
// Tune
|
|
250
|
+
// ========================================================================
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Tune (hot-patch) a layer's relationship config without replacing the full graph.
|
|
254
|
+
* Re-instantiates the relationship function with updated config.
|
|
255
|
+
*
|
|
256
|
+
* @param {string} layerName - Layer to tune
|
|
257
|
+
* @param {object} configOverrides - Config values to merge (e.g., { opacity: 0.6, gain: 3 })
|
|
258
|
+
* @returns {boolean} True if tuned successfully
|
|
259
|
+
*/
|
|
260
|
+
tune(layerName, configOverrides) {
|
|
261
|
+
if (!configOverrides || typeof configOverrides !== 'object') return false;
|
|
262
|
+
|
|
263
|
+
// Read current config for this layer from the graph
|
|
264
|
+
const graphConfig = this._graph.exportConfig();
|
|
265
|
+
const currentRel = graphConfig.relationships[layerName];
|
|
266
|
+
|
|
267
|
+
if (!currentRel || !currentRel.preset) {
|
|
268
|
+
// Can't tune a custom function or missing relationship
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const factory = PRESET_REGISTRY[currentRel.preset];
|
|
273
|
+
if (!factory) return false;
|
|
274
|
+
|
|
275
|
+
// Merge overrides into existing config
|
|
276
|
+
const newConfig = { ...(currentRel.config || {}), ...configOverrides };
|
|
277
|
+
|
|
278
|
+
// Re-set the relationship with updated config
|
|
279
|
+
this._graph.setRelationship(layerName, {
|
|
280
|
+
preset: currentRel.preset,
|
|
281
|
+
config: newConfig
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
return true;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Get the current tunable config for a layer.
|
|
289
|
+
*
|
|
290
|
+
* @param {string} layerName
|
|
291
|
+
* @returns {object|null} The current { preset, config } or null
|
|
292
|
+
*/
|
|
293
|
+
getLayerConfig(layerName) {
|
|
294
|
+
const graphConfig = this._graph.exportConfig();
|
|
295
|
+
return graphConfig.relationships[layerName] || null;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ========================================================================
|
|
299
|
+
// Import / Export
|
|
300
|
+
// ========================================================================
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Export all user presets as a JSON-serializable library.
|
|
304
|
+
*
|
|
305
|
+
* @returns {object} Library object with version and presets
|
|
306
|
+
*/
|
|
307
|
+
exportLibrary() {
|
|
308
|
+
const presets = {};
|
|
309
|
+
for (const [name, preset] of this._presets) {
|
|
310
|
+
presets[name] = preset;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
version: '1.0',
|
|
315
|
+
type: 'vib3_layer_presets',
|
|
316
|
+
exportedAt: new Date().toISOString(),
|
|
317
|
+
count: this._presets.size,
|
|
318
|
+
presets
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Import presets from a library object.
|
|
324
|
+
* Does not overwrite existing presets unless `overwrite` is true.
|
|
325
|
+
*
|
|
326
|
+
* @param {object} library - Library object from exportLibrary()
|
|
327
|
+
* @param {object} [options]
|
|
328
|
+
* @param {boolean} [options.overwrite=false] - Overwrite existing presets
|
|
329
|
+
* @returns {{ imported: number, skipped: number }}
|
|
330
|
+
*/
|
|
331
|
+
importLibrary(library, options = {}) {
|
|
332
|
+
const { overwrite = false } = options;
|
|
333
|
+
|
|
334
|
+
if (!library || !library.presets || typeof library.presets !== 'object') {
|
|
335
|
+
throw new Error('Invalid library format: missing presets object');
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
let imported = 0;
|
|
339
|
+
let skipped = 0;
|
|
340
|
+
|
|
341
|
+
for (const [name, preset] of Object.entries(library.presets)) {
|
|
342
|
+
if (PROFILES[name]) {
|
|
343
|
+
skipped++;
|
|
344
|
+
continue; // Never overwrite built-in profiles
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (!overwrite && this._presets.has(name)) {
|
|
348
|
+
skipped++;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
this._presets.set(name, preset);
|
|
353
|
+
imported++;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (imported > 0) {
|
|
357
|
+
this._saveToStorage();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return { imported, skipped };
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Clear all user presets.
|
|
365
|
+
*/
|
|
366
|
+
clear() {
|
|
367
|
+
this._presets.clear();
|
|
368
|
+
this._saveToStorage();
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export default LayerPresetManager;
|