@viji-dev/sdk 1.0.0 → 1.0.2
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/README.md +70 -63
- package/bin/viji.js +9 -29
- package/dist/assets/artist-dts-BHUsvSI6.js +613 -0
- package/dist/assets/artist-dts-p5-Cyw8vmy_.js +736 -0
- package/dist/assets/core-CiQx3w0t.js +12 -0
- package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/assets/docs-api-PBLtY4Ni.js +12381 -0
- package/dist/assets/engine-javascript-CXyY7cc8.js +141 -0
- package/dist/assets/essentia-wasm.web-0S-sW98u-CYV1l1zv.js +38 -0
- package/dist/assets/essentia.js-core.es-DnrJE0uR-DOSrF5_G.js +32 -0
- package/dist/assets/glsl-DMyvO4G4.js +1 -0
- package/dist/assets/index-BhFxsauQ.js +215 -0
- package/dist/assets/index-BqhVeA7U.css +1 -0
- package/dist/assets/index-T4TOjvD0.js +1 -0
- package/dist/assets/index-Wz9WqGqz.js +52 -0
- package/dist/assets/index-t24aGwla.js +1 -0
- package/dist/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/assets/shader-uniforms-GdaUkQPK.js +1 -0
- package/dist/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/assets/viji.worker-CQSJ0SiO-ljtBlcNZ.js +27018 -0
- package/{index.html → dist/index.html} +2 -1
- package/package.json +31 -35
- package/src/cli/commands/build.js +50 -99
- package/src/cli/commands/create.js +49 -46
- package/src/cli/commands/dev.js +30 -97
- package/src/cli/server/dev-server.js +233 -0
- package/src/cli/server/scene-scanner.js +93 -0
- package/src/cli/server/vite-scene-plugin.d.ts +2 -0
- package/src/cli/server/vite-scene-plugin.js +134 -0
- package/src/cli/utils/cli-utils.js +29 -139
- package/src/cli/utils/scene-compiler.js +10 -17
- package/src/templates/scene-templates.js +85 -0
- package/.gitignore +0 -29
- package/eslint.config.js +0 -37
- package/postcss.config.js +0 -6
- package/scenes/audio-visualizer/main.js +0 -287
- package/scenes/core-demo/main.js +0 -532
- package/scenes/demo-scene/main.js +0 -619
- package/scenes/global.d.ts +0 -15
- package/scenes/particle-system/main.js +0 -349
- package/scenes/tsconfig.json +0 -12
- package/scenes/video-mirror/main.ts +0 -436
- package/src/App.css +0 -42
- package/src/App.tsx +0 -279
- package/src/cli/commands/init.js +0 -262
- package/src/components/SDKPage.tsx +0 -337
- package/src/components/core/CoreContainer.tsx +0 -126
- package/src/components/ui/DeviceSelectionList.tsx +0 -137
- package/src/components/ui/FPSCounter.tsx +0 -78
- package/src/components/ui/FileDropzonePanel.tsx +0 -120
- package/src/components/ui/FileListPanel.tsx +0 -285
- package/src/components/ui/InputExpansionPanel.tsx +0 -31
- package/src/components/ui/MediaPlayerControls.tsx +0 -191
- package/src/components/ui/MenuContainer.tsx +0 -71
- package/src/components/ui/ParametersMenu.tsx +0 -797
- package/src/components/ui/ProjectSwitcherMenu.tsx +0 -192
- package/src/components/ui/QuickInputControls.tsx +0 -542
- package/src/components/ui/SDKMenuSystem.tsx +0 -96
- package/src/components/ui/SettingsMenu.tsx +0 -346
- package/src/components/ui/SimpleInputControls.tsx +0 -137
- package/src/index.css +0 -68
- package/src/main.tsx +0 -10
- package/src/scenes-hmr.ts +0 -158
- package/src/services/project-filesystem.ts +0 -436
- package/src/stores/scene-player/index.ts +0 -3
- package/src/stores/scene-player/input-manager.store.ts +0 -1045
- package/src/stores/scene-player/scene-session.store.ts +0 -659
- package/src/styles/globals.css +0 -111
- package/src/templates/minimal-template.js +0 -11
- package/src/utils/debounce.js +0 -34
- package/src/vite-env.d.ts +0 -1
- package/tailwind.config.js +0 -18
- package/tsconfig.app.json +0 -27
- package/tsconfig.json +0 -27
- package/tsconfig.node.json +0 -27
- package/vite.config.ts +0 -54
- /package/{public → dist}/favicon.png +0 -0
|
@@ -1,659 +0,0 @@
|
|
|
1
|
-
import { create } from 'zustand';
|
|
2
|
-
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
3
|
-
import { VijiCore } from '@viji-dev/core';
|
|
4
|
-
import { useInputManagerStore } from './input-manager.store';
|
|
5
|
-
|
|
6
|
-
// Core Instance Configuration
|
|
7
|
-
export interface CoreInstanceConfig {
|
|
8
|
-
resolution: number;
|
|
9
|
-
frameRateMode: 'full' | 'half';
|
|
10
|
-
allowUserInteraction: boolean;
|
|
11
|
-
audioStream?: MediaStream | null;
|
|
12
|
-
videoStream?: MediaStream | null;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Scene Player Session
|
|
16
|
-
export interface ScenePlayerSession {
|
|
17
|
-
// Core Identification
|
|
18
|
-
sceneId: string;
|
|
19
|
-
sceneTitle: string;
|
|
20
|
-
sceneThumbnail?: string;
|
|
21
|
-
sceneCode: string;
|
|
22
|
-
|
|
23
|
-
// Author Information (for SDK, this might be local project info)
|
|
24
|
-
authorId: string;
|
|
25
|
-
authorUsername: string;
|
|
26
|
-
|
|
27
|
-
// Core Configuration
|
|
28
|
-
coreConfig: CoreInstanceConfig;
|
|
29
|
-
coreInstance?: VijiCore;
|
|
30
|
-
|
|
31
|
-
// Preview Instances (for parameter previews)
|
|
32
|
-
previewInstances: Map<string, VijiCore>;
|
|
33
|
-
|
|
34
|
-
// Parameters
|
|
35
|
-
parameters: Record<string, any>;
|
|
36
|
-
parameterGroups: any[];
|
|
37
|
-
|
|
38
|
-
// Presets (simplified for SDK - local only)
|
|
39
|
-
availablePresets: any[];
|
|
40
|
-
activePresetId?: string;
|
|
41
|
-
|
|
42
|
-
// Session State
|
|
43
|
-
hasUnsavedChanges: boolean;
|
|
44
|
-
isActive: boolean;
|
|
45
|
-
createdAt: Date;
|
|
46
|
-
lastActiveAt: Date;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Application Context Types
|
|
50
|
-
export type AppContext = 'sdk';
|
|
51
|
-
|
|
52
|
-
// Scene Session Store State
|
|
53
|
-
interface SceneSessionState {
|
|
54
|
-
// SDK Session (single context for SDK)
|
|
55
|
-
session: ScenePlayerSession | null;
|
|
56
|
-
activeContext: AppContext | null;
|
|
57
|
-
|
|
58
|
-
// UI Preferences
|
|
59
|
-
uiPreferences: {
|
|
60
|
-
showFPSCounter: boolean;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// Persistent Parameters (survives session clearing)
|
|
64
|
-
persistentParameters: Record<string, Record<string, any>>; // sceneId -> parameters
|
|
65
|
-
|
|
66
|
-
// Session Management
|
|
67
|
-
isSessionActive: boolean;
|
|
68
|
-
|
|
69
|
-
// Core initialization control
|
|
70
|
-
initializationAbortController: AbortController | null;
|
|
71
|
-
|
|
72
|
-
// Scene Management (for SDK, these are local projects)
|
|
73
|
-
availableScenes: any[]; // Local projects
|
|
74
|
-
isLoadingScenes: boolean;
|
|
75
|
-
isLoadingScene: boolean;
|
|
76
|
-
|
|
77
|
-
// Core Management
|
|
78
|
-
isInitializingCore: boolean;
|
|
79
|
-
coreReady: boolean;
|
|
80
|
-
|
|
81
|
-
// Preset Management (local only)
|
|
82
|
-
isLoadingPresets: boolean;
|
|
83
|
-
isSavingPreset: boolean;
|
|
84
|
-
|
|
85
|
-
// Error Handling
|
|
86
|
-
lastError: string | null;
|
|
87
|
-
sceneError: string | null;
|
|
88
|
-
presetError: string | null;
|
|
89
|
-
|
|
90
|
-
// Persistence state tracking
|
|
91
|
-
_hasHydrated: boolean;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Scene Session Store Actions
|
|
95
|
-
interface SceneSessionActions {
|
|
96
|
-
// Session Management
|
|
97
|
-
createSession: (sceneId: string, sceneCode?: string, sceneTitle?: string) => Promise<void>;
|
|
98
|
-
updateSession: (updates: Partial<ScenePlayerSession>) => void;
|
|
99
|
-
clearSession: () => Promise<void>;
|
|
100
|
-
switchToContext: () => void;
|
|
101
|
-
getSession: () => ScenePlayerSession | null;
|
|
102
|
-
|
|
103
|
-
// Core Management
|
|
104
|
-
initializeCore: (container: HTMLElement) => Promise<void>;
|
|
105
|
-
destroyCore: () => Promise<void>;
|
|
106
|
-
cancelInitialization: () => void;
|
|
107
|
-
updateCoreConfig: (config: Partial<CoreInstanceConfig>) => Promise<void>;
|
|
108
|
-
|
|
109
|
-
// Parameter Management
|
|
110
|
-
updateParameters: (parameters: Record<string, any>, persist?: boolean) => void;
|
|
111
|
-
resetParameters: () => void;
|
|
112
|
-
setParameterGroups: (groups: any[]) => void;
|
|
113
|
-
|
|
114
|
-
// Preset Management (simplified for SDK)
|
|
115
|
-
loadPresets: (sceneId: string) => Promise<void>;
|
|
116
|
-
applyPreset: (presetId: string) => Promise<void>;
|
|
117
|
-
saveCurrentAsPreset: (name: string) => Promise<void>;
|
|
118
|
-
deletePreset: (presetId: string) => Promise<void>;
|
|
119
|
-
renamePreset: (presetId: string, newName: string) => Promise<void>;
|
|
120
|
-
|
|
121
|
-
// Scene Management (local projects)
|
|
122
|
-
loadAvailableScenes: () => Promise<void>;
|
|
123
|
-
|
|
124
|
-
// UI Preferences
|
|
125
|
-
setShowFPSCounter: (show: boolean) => void;
|
|
126
|
-
|
|
127
|
-
// Error Handling
|
|
128
|
-
setLastError: (error: string | null) => void;
|
|
129
|
-
setSceneError: (error: string | null) => void;
|
|
130
|
-
setPresetError: (error: string | null) => void;
|
|
131
|
-
clearErrors: () => void;
|
|
132
|
-
|
|
133
|
-
// Core Ready State
|
|
134
|
-
setCoreReady: (ready: boolean) => void;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
// Combined Store Type
|
|
138
|
-
type SceneSessionStore = SceneSessionState & SceneSessionActions;
|
|
139
|
-
|
|
140
|
-
// Helper function to create default core config
|
|
141
|
-
const createDefaultCoreConfig = (): CoreInstanceConfig => ({
|
|
142
|
-
resolution: 1.0,
|
|
143
|
-
frameRateMode: 'full',
|
|
144
|
-
allowUserInteraction: true,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Initial State
|
|
148
|
-
const initialState: SceneSessionState = {
|
|
149
|
-
session: null,
|
|
150
|
-
activeContext: null,
|
|
151
|
-
uiPreferences: {
|
|
152
|
-
showFPSCounter: false,
|
|
153
|
-
},
|
|
154
|
-
persistentParameters: {},
|
|
155
|
-
isSessionActive: false,
|
|
156
|
-
initializationAbortController: null,
|
|
157
|
-
availableScenes: [],
|
|
158
|
-
isLoadingScenes: false,
|
|
159
|
-
isLoadingScene: false,
|
|
160
|
-
isInitializingCore: false,
|
|
161
|
-
coreReady: false,
|
|
162
|
-
isLoadingPresets: false,
|
|
163
|
-
isSavingPreset: false,
|
|
164
|
-
lastError: null,
|
|
165
|
-
sceneError: null,
|
|
166
|
-
presetError: null,
|
|
167
|
-
_hasHydrated: false,
|
|
168
|
-
};
|
|
169
|
-
|
|
170
|
-
// Create Zustand Store with Persistence
|
|
171
|
-
export const useSceneSessionStore = create<SceneSessionStore>()(
|
|
172
|
-
persist(
|
|
173
|
-
(set, get) => ({
|
|
174
|
-
// Initial State
|
|
175
|
-
...initialState,
|
|
176
|
-
|
|
177
|
-
// Session Management Actions
|
|
178
|
-
createSession: async (sceneId: string, sceneCode?: string, sceneTitle?: string) => {
|
|
179
|
-
try {
|
|
180
|
-
console.log(`🎬 [SDK STORE] Creating session for scene: ${sceneId}`);
|
|
181
|
-
set({ isLoadingScene: true, lastError: null, activeContext: 'sdk' });
|
|
182
|
-
|
|
183
|
-
// For SDK, we create a session with provided or default values
|
|
184
|
-
const session: ScenePlayerSession = {
|
|
185
|
-
sceneId,
|
|
186
|
-
sceneTitle: sceneTitle || 'Untitled Scene',
|
|
187
|
-
sceneCode: sceneCode || '// SDK Scene Code\nconsole.log("Hello from Viji SDK");',
|
|
188
|
-
authorId: 'local',
|
|
189
|
-
authorUsername: 'SDK User',
|
|
190
|
-
coreConfig: createDefaultCoreConfig(),
|
|
191
|
-
previewInstances: new Map(),
|
|
192
|
-
parameters: get().persistentParameters[sceneId] || {},
|
|
193
|
-
parameterGroups: [],
|
|
194
|
-
availablePresets: [],
|
|
195
|
-
hasUnsavedChanges: false,
|
|
196
|
-
isActive: true,
|
|
197
|
-
createdAt: new Date(),
|
|
198
|
-
lastActiveAt: new Date(),
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
set({
|
|
202
|
-
session,
|
|
203
|
-
isSessionActive: true,
|
|
204
|
-
isLoadingScene: false,
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
console.log(`🎬 [SDK STORE] Session created successfully`);
|
|
208
|
-
} catch (error) {
|
|
209
|
-
console.error(`🎬 [SDK STORE] Failed to create session:`, error);
|
|
210
|
-
set({
|
|
211
|
-
lastError: error instanceof Error ? error.message : 'Failed to create session',
|
|
212
|
-
isLoadingScene: false
|
|
213
|
-
});
|
|
214
|
-
throw error;
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
|
|
218
|
-
updateSession: (updates: Partial<ScenePlayerSession>) => {
|
|
219
|
-
const currentSession = get().session;
|
|
220
|
-
if (!currentSession) return;
|
|
221
|
-
|
|
222
|
-
const updatedSession = { ...currentSession, ...updates };
|
|
223
|
-
set({ session: updatedSession });
|
|
224
|
-
},
|
|
225
|
-
|
|
226
|
-
clearSession: async () => {
|
|
227
|
-
const currentSession = get().session;
|
|
228
|
-
if (currentSession?.coreInstance) {
|
|
229
|
-
try {
|
|
230
|
-
console.log('🧹 Destroying VijiCore worker...');
|
|
231
|
-
await currentSession.coreInstance.destroy();
|
|
232
|
-
console.log('✅ VijiCore worker destroyed successfully');
|
|
233
|
-
} catch (error) {
|
|
234
|
-
console.error('❌ Error destroying VijiCore worker:', error);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
set({
|
|
239
|
-
session: null,
|
|
240
|
-
isSessionActive: false,
|
|
241
|
-
coreReady: false,
|
|
242
|
-
});
|
|
243
|
-
},
|
|
244
|
-
|
|
245
|
-
switchToContext: () => {
|
|
246
|
-
set({ activeContext: 'sdk' });
|
|
247
|
-
},
|
|
248
|
-
|
|
249
|
-
getSession: () => get().session,
|
|
250
|
-
|
|
251
|
-
// Core Management Actions
|
|
252
|
-
initializeCore: async (container: HTMLElement) => {
|
|
253
|
-
const session = get().session;
|
|
254
|
-
if (!session) throw new Error('No active session');
|
|
255
|
-
|
|
256
|
-
// Prevent multiple simultaneous initializations
|
|
257
|
-
if (get().isInitializingCore) {
|
|
258
|
-
console.log('⚠️ [SDK STORE] Core initialization already in progress, skipping...');
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
try {
|
|
263
|
-
set({ isInitializingCore: true, sceneError: null });
|
|
264
|
-
|
|
265
|
-
// Cancel any existing initialization
|
|
266
|
-
if (get().initializationAbortController) {
|
|
267
|
-
get().initializationAbortController!.abort();
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
const abortController = new AbortController();
|
|
271
|
-
set({ initializationAbortController: abortController });
|
|
272
|
-
|
|
273
|
-
console.log('🚀 [SDK STORE] Initializing Viji Core...');
|
|
274
|
-
|
|
275
|
-
// Create Core instance
|
|
276
|
-
const coreInstance = new VijiCore({
|
|
277
|
-
hostContainer: container,
|
|
278
|
-
sceneCode: session.sceneCode, // Scene code is at session level
|
|
279
|
-
frameRateMode: session.coreConfig.frameRateMode,
|
|
280
|
-
allowUserInteraction: session.coreConfig.allowUserInteraction,
|
|
281
|
-
audioStream: undefined, // Will be set by input manager
|
|
282
|
-
videoStream: undefined, // Will be set by input manager
|
|
283
|
-
});
|
|
284
|
-
|
|
285
|
-
// Set up parameter detection
|
|
286
|
-
coreInstance.onParametersDefined((groups: any[]) => {
|
|
287
|
-
console.log('📊 [SDK STORE] Parameters detected:', groups);
|
|
288
|
-
get().setParameterGroups(groups);
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
// Set up capabilities change listener
|
|
292
|
-
if (coreInstance.onCapabilitiesChange) {
|
|
293
|
-
coreInstance.onCapabilitiesChange((capabilities: any) => {
|
|
294
|
-
console.log('🔧 [SDK STORE] Capabilities changed:', capabilities);
|
|
295
|
-
if (coreInstance && coreInstance.parametersReady) {
|
|
296
|
-
get().setParameterGroups(coreInstance.getParameterGroups?.() || []);
|
|
297
|
-
}
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
// Check for cancellation before initialization
|
|
302
|
-
if (abortController.signal.aborted) {
|
|
303
|
-
await coreInstance.destroy();
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
// Initialize core
|
|
308
|
-
await coreInstance.initialize();
|
|
309
|
-
|
|
310
|
-
// Update session with core instance
|
|
311
|
-
get().updateSession({ coreInstance });
|
|
312
|
-
|
|
313
|
-
// Re-apply current input streams and interaction state from InputManager to preserve across scenes
|
|
314
|
-
try {
|
|
315
|
-
const ims = useInputManagerStore.getState();
|
|
316
|
-
const streams = await ims.updateStreamsForCore();
|
|
317
|
-
await get().updateCoreConfig({
|
|
318
|
-
audioStream: streams.audioStream,
|
|
319
|
-
videoStream: streams.videoStream,
|
|
320
|
-
allowUserInteraction: ims.inputConfiguration.interactionEnabled,
|
|
321
|
-
});
|
|
322
|
-
} catch (e) {
|
|
323
|
-
console.warn('⚠️ [SDK STORE] Failed to re-apply input streams to new core:', e);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
set({
|
|
327
|
-
coreReady: true,
|
|
328
|
-
isInitializingCore: false,
|
|
329
|
-
initializationAbortController: null
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
console.log('✅ [SDK STORE] Viji Core initialized successfully');
|
|
333
|
-
|
|
334
|
-
} catch (error) {
|
|
335
|
-
console.error('❌ [SDK STORE] Failed to initialize core:', error);
|
|
336
|
-
const errorMessage = error instanceof Error ? error.message : 'Failed to initialize core';
|
|
337
|
-
set({
|
|
338
|
-
sceneError: errorMessage,
|
|
339
|
-
isInitializingCore: false,
|
|
340
|
-
initializationAbortController: null
|
|
341
|
-
});
|
|
342
|
-
throw error;
|
|
343
|
-
}
|
|
344
|
-
},
|
|
345
|
-
|
|
346
|
-
destroyCore: async () => {
|
|
347
|
-
const session = get().session;
|
|
348
|
-
if (session?.coreInstance) {
|
|
349
|
-
try {
|
|
350
|
-
await session.coreInstance.destroy();
|
|
351
|
-
get().updateSession({ coreInstance: undefined });
|
|
352
|
-
set({ coreReady: false });
|
|
353
|
-
console.log('🧹 [SDK STORE] Core destroyed');
|
|
354
|
-
} catch (error) {
|
|
355
|
-
console.error('Error destroying core:', error);
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
},
|
|
359
|
-
|
|
360
|
-
cancelInitialization: () => {
|
|
361
|
-
const abortController = get().initializationAbortController;
|
|
362
|
-
if (abortController) {
|
|
363
|
-
abortController.abort();
|
|
364
|
-
set({ initializationAbortController: null, isInitializingCore: false });
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
|
|
368
|
-
updateCoreConfig: async (config: Partial<CoreInstanceConfig>) => {
|
|
369
|
-
console.log(`🎯 [SDK STORE] updateCoreConfig called:`, {
|
|
370
|
-
configKeys: Object.keys(config),
|
|
371
|
-
hasAudioStream: 'audioStream' in config,
|
|
372
|
-
hasVideoStream: 'videoStream' in config,
|
|
373
|
-
timestamp: new Date().toISOString()
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
const session = get().session;
|
|
377
|
-
if (!session) {
|
|
378
|
-
console.log(`❌ [SDK STORE] No session available, skipping updateCoreConfig`);
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
const updatedConfig = { ...session.coreConfig, ...config };
|
|
383
|
-
get().updateSession({ coreConfig: updatedConfig });
|
|
384
|
-
|
|
385
|
-
// Apply config to core instance if available
|
|
386
|
-
if (session.coreInstance) {
|
|
387
|
-
console.log(`🎯 [SDK STORE] Applying config to core instance...`);
|
|
388
|
-
|
|
389
|
-
if (config.frameRateMode) {
|
|
390
|
-
if (config.frameRateMode === 'full') {
|
|
391
|
-
await session.coreInstance.setFullFrameRate();
|
|
392
|
-
} else {
|
|
393
|
-
await session.coreInstance.setHalfFrameRate();
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
if (config.resolution !== undefined) {
|
|
398
|
-
await session.coreInstance.setResolution(config.resolution);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (config.allowUserInteraction !== undefined) {
|
|
402
|
-
await session.coreInstance.setInteractionEnabled(config.allowUserInteraction);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
if ('audioStream' in config) {
|
|
406
|
-
console.log(`🎵 [SDK STORE] Setting audio stream on core:`, {
|
|
407
|
-
streamExists: !!config.audioStream,
|
|
408
|
-
streamId: config.audioStream?.id
|
|
409
|
-
});
|
|
410
|
-
await session.coreInstance.setAudioStream(config.audioStream ?? null);
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
if ('videoStream' in config) {
|
|
414
|
-
console.log(`📹 [SDK STORE] Setting video stream on core:`, {
|
|
415
|
-
streamExists: !!config.videoStream,
|
|
416
|
-
streamId: config.videoStream?.id
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
try {
|
|
420
|
-
await session.coreInstance.setVideoStream(config.videoStream ?? null);
|
|
421
|
-
} catch (error) {
|
|
422
|
-
console.error(`❌ [SDK STORE] Failed to set video stream:`, error);
|
|
423
|
-
// Don't throw to prevent breaking the entire config update
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
console.log(`✅ [SDK STORE] All core config updates completed`);
|
|
428
|
-
} else {
|
|
429
|
-
console.log(`⚠️ [SDK STORE] No core instance available, config stored but not applied`);
|
|
430
|
-
}
|
|
431
|
-
},
|
|
432
|
-
|
|
433
|
-
// Parameter Management Actions
|
|
434
|
-
updateParameters: (parameters: Record<string, any>, persist = false) => {
|
|
435
|
-
const session = get().session;
|
|
436
|
-
if (!session) return;
|
|
437
|
-
|
|
438
|
-
const updatedParameters = { ...session.parameters, ...parameters };
|
|
439
|
-
get().updateSession({ parameters: updatedParameters });
|
|
440
|
-
|
|
441
|
-
// Apply parameters to core instance
|
|
442
|
-
if (session.coreInstance) {
|
|
443
|
-
Object.entries(parameters).forEach(([name, value]) => {
|
|
444
|
-
try {
|
|
445
|
-
session.coreInstance!.setParameter(name, value);
|
|
446
|
-
} catch (error) {
|
|
447
|
-
console.warn(`Failed to set parameter ${name}:`, error);
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
// Persist parameters if requested
|
|
453
|
-
if (persist && session.sceneId) {
|
|
454
|
-
const { persistentParameters } = get();
|
|
455
|
-
set({
|
|
456
|
-
persistentParameters: {
|
|
457
|
-
...persistentParameters,
|
|
458
|
-
[session.sceneId]: updatedParameters,
|
|
459
|
-
},
|
|
460
|
-
});
|
|
461
|
-
}
|
|
462
|
-
},
|
|
463
|
-
|
|
464
|
-
resetParameters: () => {
|
|
465
|
-
const session = get().session;
|
|
466
|
-
if (!session) return;
|
|
467
|
-
|
|
468
|
-
get().updateSession({ parameters: {} });
|
|
469
|
-
|
|
470
|
-
// Clear persistent parameters for this scene
|
|
471
|
-
if (session.sceneId) {
|
|
472
|
-
const { persistentParameters } = get();
|
|
473
|
-
const { [session.sceneId]: _, ...remaining } = persistentParameters;
|
|
474
|
-
set({ persistentParameters: remaining });
|
|
475
|
-
}
|
|
476
|
-
},
|
|
477
|
-
|
|
478
|
-
setParameterGroups: (parameterGroups: any[]) => {
|
|
479
|
-
get().updateSession({ parameterGroups });
|
|
480
|
-
},
|
|
481
|
-
|
|
482
|
-
// Preset Management (simplified for SDK - local storage only)
|
|
483
|
-
loadPresets: async (sceneId: string) => {
|
|
484
|
-
set({ isLoadingPresets: true, presetError: null });
|
|
485
|
-
|
|
486
|
-
try {
|
|
487
|
-
// For SDK, presets are stored locally
|
|
488
|
-
const localPresets = localStorage.getItem(`viji-sdk-presets-${sceneId}`);
|
|
489
|
-
const presets = localPresets ? JSON.parse(localPresets) : [];
|
|
490
|
-
|
|
491
|
-
get().updateSession({ availablePresets: presets });
|
|
492
|
-
|
|
493
|
-
} catch (error) {
|
|
494
|
-
const errorMessage = error instanceof Error ? error.message : 'Failed to load presets';
|
|
495
|
-
set({ presetError: errorMessage });
|
|
496
|
-
} finally {
|
|
497
|
-
set({ isLoadingPresets: false });
|
|
498
|
-
}
|
|
499
|
-
},
|
|
500
|
-
|
|
501
|
-
applyPreset: async (presetId: string) => {
|
|
502
|
-
const session = get().session;
|
|
503
|
-
if (!session) return;
|
|
504
|
-
|
|
505
|
-
const preset = session.availablePresets.find(p => p.id === presetId);
|
|
506
|
-
if (!preset) {
|
|
507
|
-
set({ presetError: 'Preset not found' });
|
|
508
|
-
return;
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
// Apply preset parameters
|
|
512
|
-
get().updateParameters(preset.parameters, true);
|
|
513
|
-
get().updateSession({ activePresetId: presetId });
|
|
514
|
-
},
|
|
515
|
-
|
|
516
|
-
saveCurrentAsPreset: async (name: string) => {
|
|
517
|
-
const session = get().session;
|
|
518
|
-
if (!session) return;
|
|
519
|
-
|
|
520
|
-
set({ isSavingPreset: true, presetError: null });
|
|
521
|
-
|
|
522
|
-
try {
|
|
523
|
-
const preset = {
|
|
524
|
-
id: crypto.randomUUID(),
|
|
525
|
-
name,
|
|
526
|
-
parameters: session.parameters,
|
|
527
|
-
createdAt: new Date().toISOString(),
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
const updatedPresets = [...session.availablePresets, preset];
|
|
531
|
-
|
|
532
|
-
// Save to local storage
|
|
533
|
-
localStorage.setItem(`viji-sdk-presets-${session.sceneId}`, JSON.stringify(updatedPresets));
|
|
534
|
-
|
|
535
|
-
get().updateSession({ availablePresets: updatedPresets });
|
|
536
|
-
|
|
537
|
-
} catch (error) {
|
|
538
|
-
const errorMessage = error instanceof Error ? error.message : 'Failed to save preset';
|
|
539
|
-
set({ presetError: errorMessage });
|
|
540
|
-
} finally {
|
|
541
|
-
set({ isSavingPreset: false });
|
|
542
|
-
}
|
|
543
|
-
},
|
|
544
|
-
|
|
545
|
-
deletePreset: async (presetId: string) => {
|
|
546
|
-
const session = get().session;
|
|
547
|
-
if (!session) return;
|
|
548
|
-
|
|
549
|
-
try {
|
|
550
|
-
const updatedPresets = session.availablePresets.filter(p => p.id !== presetId);
|
|
551
|
-
|
|
552
|
-
// Save to local storage
|
|
553
|
-
localStorage.setItem(`viji-sdk-presets-${session.sceneId}`, JSON.stringify(updatedPresets));
|
|
554
|
-
|
|
555
|
-
get().updateSession({ availablePresets: updatedPresets });
|
|
556
|
-
|
|
557
|
-
// Clear active preset if it was deleted
|
|
558
|
-
if (session.activePresetId === presetId) {
|
|
559
|
-
get().updateSession({ activePresetId: undefined });
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
} catch (error) {
|
|
563
|
-
const errorMessage = error instanceof Error ? error.message : 'Failed to delete preset';
|
|
564
|
-
set({ presetError: errorMessage });
|
|
565
|
-
}
|
|
566
|
-
},
|
|
567
|
-
|
|
568
|
-
renamePreset: async (presetId: string, newName: string) => {
|
|
569
|
-
const session = get().session;
|
|
570
|
-
if (!session) return;
|
|
571
|
-
|
|
572
|
-
try {
|
|
573
|
-
const updatedPresets = session.availablePresets.map(p =>
|
|
574
|
-
p.id === presetId ? { ...p, name: newName } : p
|
|
575
|
-
);
|
|
576
|
-
|
|
577
|
-
// Save to local storage
|
|
578
|
-
localStorage.setItem(`viji-sdk-presets-${session.sceneId}`, JSON.stringify(updatedPresets));
|
|
579
|
-
|
|
580
|
-
get().updateSession({ availablePresets: updatedPresets });
|
|
581
|
-
|
|
582
|
-
} catch (error) {
|
|
583
|
-
const errorMessage = error instanceof Error ? error.message : 'Failed to rename preset';
|
|
584
|
-
set({ presetError: errorMessage });
|
|
585
|
-
}
|
|
586
|
-
},
|
|
587
|
-
|
|
588
|
-
// Scene Management (local projects for SDK)
|
|
589
|
-
loadAvailableScenes: async () => {
|
|
590
|
-
set({ isLoadingScenes: true });
|
|
591
|
-
|
|
592
|
-
try {
|
|
593
|
-
// For SDK, scenes are local projects
|
|
594
|
-
// This would be implemented by the CLI/project management system
|
|
595
|
-
const localProjects = []; // TODO: Implement project discovery
|
|
596
|
-
|
|
597
|
-
set({ availableScenes: localProjects });
|
|
598
|
-
|
|
599
|
-
} catch (error) {
|
|
600
|
-
console.error('Failed to load available scenes:', error);
|
|
601
|
-
} finally {
|
|
602
|
-
set({ isLoadingScenes: false });
|
|
603
|
-
}
|
|
604
|
-
},
|
|
605
|
-
|
|
606
|
-
// UI Preferences
|
|
607
|
-
setShowFPSCounter: (showFPSCounter: boolean) => {
|
|
608
|
-
const { uiPreferences } = get();
|
|
609
|
-
set({
|
|
610
|
-
uiPreferences: {
|
|
611
|
-
...uiPreferences,
|
|
612
|
-
showFPSCounter,
|
|
613
|
-
},
|
|
614
|
-
});
|
|
615
|
-
},
|
|
616
|
-
|
|
617
|
-
// Error Handling
|
|
618
|
-
setLastError: (lastError: string | null) => {
|
|
619
|
-
set({ lastError });
|
|
620
|
-
},
|
|
621
|
-
|
|
622
|
-
setSceneError: (sceneError: string | null) => {
|
|
623
|
-
set({ sceneError });
|
|
624
|
-
},
|
|
625
|
-
|
|
626
|
-
setPresetError: (presetError: string | null) => {
|
|
627
|
-
set({ presetError });
|
|
628
|
-
},
|
|
629
|
-
|
|
630
|
-
clearErrors: () => {
|
|
631
|
-
set({
|
|
632
|
-
lastError: null,
|
|
633
|
-
sceneError: null,
|
|
634
|
-
presetError: null,
|
|
635
|
-
});
|
|
636
|
-
},
|
|
637
|
-
|
|
638
|
-
// Core Ready State
|
|
639
|
-
setCoreReady: (coreReady: boolean) => {
|
|
640
|
-
set({ coreReady });
|
|
641
|
-
},
|
|
642
|
-
}),
|
|
643
|
-
{
|
|
644
|
-
name: 'viji-sdk-scene-session',
|
|
645
|
-
storage: createJSONStorage(() => localStorage),
|
|
646
|
-
// Don't persist core instances, abort controllers, or temporary state
|
|
647
|
-
partialize: (state) => ({
|
|
648
|
-
uiPreferences: state.uiPreferences,
|
|
649
|
-
persistentParameters: state.persistentParameters,
|
|
650
|
-
_hasHydrated: true, // Mark as hydrated
|
|
651
|
-
}),
|
|
652
|
-
onRehydrateStorage: () => (state) => {
|
|
653
|
-
if (state) {
|
|
654
|
-
state._hasHydrated = true;
|
|
655
|
-
}
|
|
656
|
-
},
|
|
657
|
-
}
|
|
658
|
-
)
|
|
659
|
-
);
|