@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.
Files changed (77) hide show
  1. package/README.md +70 -63
  2. package/bin/viji.js +9 -29
  3. package/dist/assets/artist-dts-BHUsvSI6.js +613 -0
  4. package/dist/assets/artist-dts-p5-Cyw8vmy_.js +736 -0
  5. package/dist/assets/core-CiQx3w0t.js +12 -0
  6. package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
  7. package/dist/assets/docs-api-PBLtY4Ni.js +12381 -0
  8. package/dist/assets/engine-javascript-CXyY7cc8.js +141 -0
  9. package/dist/assets/essentia-wasm.web-0S-sW98u-CYV1l1zv.js +38 -0
  10. package/dist/assets/essentia.js-core.es-DnrJE0uR-DOSrF5_G.js +32 -0
  11. package/dist/assets/glsl-DMyvO4G4.js +1 -0
  12. package/dist/assets/index-BhFxsauQ.js +215 -0
  13. package/dist/assets/index-BqhVeA7U.css +1 -0
  14. package/dist/assets/index-T4TOjvD0.js +1 -0
  15. package/dist/assets/index-Wz9WqGqz.js +52 -0
  16. package/dist/assets/index-t24aGwla.js +1 -0
  17. package/dist/assets/javascript-wDzz0qaB.js +1 -0
  18. package/dist/assets/shader-uniforms-GdaUkQPK.js +1 -0
  19. package/dist/assets/typescript-BPQ3VLAy.js +1 -0
  20. package/dist/assets/viji.worker-CQSJ0SiO-ljtBlcNZ.js +27018 -0
  21. package/{index.html → dist/index.html} +2 -1
  22. package/package.json +31 -35
  23. package/src/cli/commands/build.js +50 -99
  24. package/src/cli/commands/create.js +49 -46
  25. package/src/cli/commands/dev.js +30 -97
  26. package/src/cli/server/dev-server.js +233 -0
  27. package/src/cli/server/scene-scanner.js +93 -0
  28. package/src/cli/server/vite-scene-plugin.d.ts +2 -0
  29. package/src/cli/server/vite-scene-plugin.js +134 -0
  30. package/src/cli/utils/cli-utils.js +29 -139
  31. package/src/cli/utils/scene-compiler.js +10 -17
  32. package/src/templates/scene-templates.js +85 -0
  33. package/.gitignore +0 -29
  34. package/eslint.config.js +0 -37
  35. package/postcss.config.js +0 -6
  36. package/scenes/audio-visualizer/main.js +0 -287
  37. package/scenes/core-demo/main.js +0 -532
  38. package/scenes/demo-scene/main.js +0 -619
  39. package/scenes/global.d.ts +0 -15
  40. package/scenes/particle-system/main.js +0 -349
  41. package/scenes/tsconfig.json +0 -12
  42. package/scenes/video-mirror/main.ts +0 -436
  43. package/src/App.css +0 -42
  44. package/src/App.tsx +0 -279
  45. package/src/cli/commands/init.js +0 -262
  46. package/src/components/SDKPage.tsx +0 -337
  47. package/src/components/core/CoreContainer.tsx +0 -126
  48. package/src/components/ui/DeviceSelectionList.tsx +0 -137
  49. package/src/components/ui/FPSCounter.tsx +0 -78
  50. package/src/components/ui/FileDropzonePanel.tsx +0 -120
  51. package/src/components/ui/FileListPanel.tsx +0 -285
  52. package/src/components/ui/InputExpansionPanel.tsx +0 -31
  53. package/src/components/ui/MediaPlayerControls.tsx +0 -191
  54. package/src/components/ui/MenuContainer.tsx +0 -71
  55. package/src/components/ui/ParametersMenu.tsx +0 -797
  56. package/src/components/ui/ProjectSwitcherMenu.tsx +0 -192
  57. package/src/components/ui/QuickInputControls.tsx +0 -542
  58. package/src/components/ui/SDKMenuSystem.tsx +0 -96
  59. package/src/components/ui/SettingsMenu.tsx +0 -346
  60. package/src/components/ui/SimpleInputControls.tsx +0 -137
  61. package/src/index.css +0 -68
  62. package/src/main.tsx +0 -10
  63. package/src/scenes-hmr.ts +0 -158
  64. package/src/services/project-filesystem.ts +0 -436
  65. package/src/stores/scene-player/index.ts +0 -3
  66. package/src/stores/scene-player/input-manager.store.ts +0 -1045
  67. package/src/stores/scene-player/scene-session.store.ts +0 -659
  68. package/src/styles/globals.css +0 -111
  69. package/src/templates/minimal-template.js +0 -11
  70. package/src/utils/debounce.js +0 -34
  71. package/src/vite-env.d.ts +0 -1
  72. package/tailwind.config.js +0 -18
  73. package/tsconfig.app.json +0 -27
  74. package/tsconfig.json +0 -27
  75. package/tsconfig.node.json +0 -27
  76. package/vite.config.ts +0 -54
  77. /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
- );