varunm2004 commited on
Commit
f6cb498
ยท
verified ยท
1 Parent(s): a0d54b4

Update src/store/useStudioStore.ts

Browse files
Files changed (1) hide show
  1. src/store/useStudioStore.ts +80 -19
src/store/useStudioStore.ts CHANGED
@@ -1,8 +1,9 @@
1
  import { create } from 'zustand';
2
- import * as THREE from 'three';
3
 
4
  export type Mode = 'model' | 'render' | 'animate';
5
  export type SkyboxType = 'none' | 'gradient' | 'uploaded';
 
6
 
7
  export interface AnimationClip {
8
  name: string;
@@ -39,11 +40,11 @@ export interface ErrorLog {
39
  }
40
 
41
  interface StudioStore {
42
- // Mode
43
  mode: Mode;
44
  setMode: (mode: Mode) => void;
45
 
46
- // Objects
47
  objects: SceneObject[];
48
  selectedId: string | null;
49
  addObject: (obj: SceneObject) => void;
@@ -51,12 +52,28 @@ interface StudioStore {
51
  updateObject: (id: string, patch: Partial<SceneObject>) => void;
52
  setSelectedId: (id: string | null) => void;
53
 
54
- // Skybox
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  skyboxType: SkyboxType;
56
  skyboxUrl: string | null;
57
  setSkybox: (type: SkyboxType, url?: string) => void;
58
 
59
- // Rendering
60
  ambientIntensity: number;
61
  directionalIntensity: number;
62
  bgColor: string;
@@ -72,7 +89,7 @@ interface StudioStore {
72
  setPostProcessing: (v: boolean) => void;
73
  setBloomIntensity: (v: number) => void;
74
 
75
- // AI Error Resolver
76
  openrouterKey: string;
77
  setOpenrouterKey: (k: string) => void;
78
  errorLogs: ErrorLog[];
@@ -81,31 +98,73 @@ interface StudioStore {
81
  setErrorResolving: (id: string, v: boolean) => void;
82
  clearErrors: () => void;
83
 
84
- // Recording
85
  isRecording: boolean;
86
  setIsRecording: (v: boolean) => void;
87
  }
88
 
89
  export const useStudioStore = create<StudioStore>((set, get) => ({
 
90
  mode: 'model',
91
  setMode: (mode) => set({ mode }),
92
 
 
93
  objects: [],
94
  selectedId: null,
95
- addObject: (obj) => set((s) => ({ objects: [...s.objects, obj], selectedId: obj.id })),
96
- removeObject: (id) => set((s) => ({
97
- objects: s.objects.filter(o => o.id !== id),
98
  selectedId: s.selectedId === id ? null : s.selectedId,
 
99
  })),
100
  updateObject: (id, patch) => set((s) => ({
101
  objects: s.objects.map(o => o.id === id ? { ...o, ...patch } : o),
102
  })),
103
  setSelectedId: (id) => set({ selectedId: id }),
104
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
  skyboxType: 'gradient',
106
  skyboxUrl: null,
107
  setSkybox: (type, url) => set({ skyboxType: type, skyboxUrl: url || null }),
108
 
 
109
  ambientIntensity: 0.5,
110
  directionalIntensity: 1.0,
111
  bgColor: '#1a1a2e',
@@ -113,14 +172,15 @@ export const useStudioStore = create<StudioStore>((set, get) => ({
113
  showAxes: true,
114
  postProcessing: false,
115
  bloomIntensity: 0.5,
116
- setAmbientIntensity: (v) => set({ ambientIntensity: v }),
117
- setDirectionalIntensity: (v) => set({ directionalIntensity: v }),
118
- setBgColor: (c) => set({ bgColor: c }),
119
- setShowGrid: (v) => set({ showGrid: v }),
120
- setShowAxes: (v) => set({ showAxes: v }),
121
- setPostProcessing: (v) => set({ postProcessing: v }),
122
- setBloomIntensity: (v) => set({ bloomIntensity: v }),
123
-
 
124
  openrouterKey: '',
125
  setOpenrouterKey: (k) => set({ openrouterKey: k }),
126
  errorLogs: [],
@@ -139,6 +199,7 @@ export const useStudioStore = create<StudioStore>((set, get) => ({
139
  })),
140
  clearErrors: () => set({ errorLogs: [] }),
141
 
 
142
  isRecording: false,
143
  setIsRecording: (v) => set({ isRecording: v }),
144
- }));
 
1
  import { create } from 'zustand';
2
+ import { Track, Keyframe } from '../utils/timeline';
3
 
4
  export type Mode = 'model' | 'render' | 'animate';
5
  export type SkyboxType = 'none' | 'gradient' | 'uploaded';
6
+ export type GizmoMode = 'translate' | 'rotate' | 'scale';
7
 
8
  export interface AnimationClip {
9
  name: string;
 
40
  }
41
 
42
  interface StudioStore {
43
+ // โ”€โ”€ Mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
44
  mode: Mode;
45
  setMode: (mode: Mode) => void;
46
 
47
+ // โ”€โ”€ Scene objects โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
48
  objects: SceneObject[];
49
  selectedId: string | null;
50
  addObject: (obj: SceneObject) => void;
 
52
  updateObject: (id: string, patch: Partial<SceneObject>) => void;
53
  setSelectedId: (id: string | null) => void;
54
 
55
+ // โ”€โ”€ Gizmo โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
56
+ gizmoMode: GizmoMode;
57
+ setGizmoMode: (m: GizmoMode) => void;
58
+
59
+ // โ”€โ”€ Timeline / keyframes โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
60
+ tracks: Track[];
61
+ timelineDuration: number;
62
+ playhead: number;
63
+ timelinePlaying: boolean;
64
+ setPlayhead: (t: number) => void;
65
+ setTimelinePlaying: (v: boolean) => void;
66
+ setTimelineDuration: (d: number) => void;
67
+ addKeyframe: (objectId: string, kf: Keyframe) => void;
68
+ removeKeyframe: (objectId: string, kfId: string) => void;
69
+ getTrack: (objectId: string) => Track | undefined;
70
+
71
+ // โ”€โ”€ Skybox โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
72
  skyboxType: SkyboxType;
73
  skyboxUrl: string | null;
74
  setSkybox: (type: SkyboxType, url?: string) => void;
75
 
76
+ // โ”€โ”€ Lighting / scene โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
77
  ambientIntensity: number;
78
  directionalIntensity: number;
79
  bgColor: string;
 
89
  setPostProcessing: (v: boolean) => void;
90
  setBloomIntensity: (v: number) => void;
91
 
92
+ // โ”€โ”€ AI Error Resolver โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
93
  openrouterKey: string;
94
  setOpenrouterKey: (k: string) => void;
95
  errorLogs: ErrorLog[];
 
98
  setErrorResolving: (id: string, v: boolean) => void;
99
  clearErrors: () => void;
100
 
101
+ // โ”€โ”€ Recording โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
102
  isRecording: boolean;
103
  setIsRecording: (v: boolean) => void;
104
  }
105
 
106
  export const useStudioStore = create<StudioStore>((set, get) => ({
107
+ // โ”€โ”€ Mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
108
  mode: 'model',
109
  setMode: (mode) => set({ mode }),
110
 
111
+ // โ”€โ”€ Scene objects โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
112
  objects: [],
113
  selectedId: null,
114
+ addObject: (obj) => set((s) => ({ objects: [...s.objects, obj], selectedId: obj.id })),
115
+ removeObject: (id) => set((s) => ({
116
+ objects: s.objects.filter(o => o.id !== id),
117
  selectedId: s.selectedId === id ? null : s.selectedId,
118
+ tracks: s.tracks.filter(t => t.objectId !== id),
119
  })),
120
  updateObject: (id, patch) => set((s) => ({
121
  objects: s.objects.map(o => o.id === id ? { ...o, ...patch } : o),
122
  })),
123
  setSelectedId: (id) => set({ selectedId: id }),
124
 
125
+ // โ”€โ”€ Gizmo โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
126
+ gizmoMode: 'translate',
127
+ setGizmoMode: (m) => set({ gizmoMode: m }),
128
+
129
+ // โ”€โ”€ Timeline โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
130
+ tracks: [],
131
+ timelineDuration: 5,
132
+ playhead: 0,
133
+ timelinePlaying: false,
134
+ setPlayhead: (t) => set({ playhead: t }),
135
+ setTimelinePlaying: (v) => set({ timelinePlaying: v }),
136
+ setTimelineDuration:(d) => set({ timelineDuration: d }),
137
+
138
+ addKeyframe: (objectId, kf) => set((s) => {
139
+ const exists = s.tracks.find(t => t.objectId === objectId);
140
+ if (exists) {
141
+ return {
142
+ tracks: s.tracks.map(t =>
143
+ t.objectId === objectId
144
+ ? { ...t, keyframes: [...t.keyframes.filter(k => Math.abs(k.time - kf.time) > 0.05), kf] }
145
+ : t
146
+ ),
147
+ };
148
+ }
149
+ return { tracks: [...s.tracks, { objectId, keyframes: [kf] }] };
150
+ }),
151
+
152
+ removeKeyframe: (objectId, kfId) => set((s) => ({
153
+ tracks: s.tracks.map(t =>
154
+ t.objectId === objectId
155
+ ? { ...t, keyframes: t.keyframes.filter(k => k.id !== kfId) }
156
+ : t
157
+ ),
158
+ })),
159
+
160
+ getTrack: (objectId) => get().tracks.find(t => t.objectId === objectId),
161
+
162
+ // โ”€โ”€ Skybox โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
163
  skyboxType: 'gradient',
164
  skyboxUrl: null,
165
  setSkybox: (type, url) => set({ skyboxType: type, skyboxUrl: url || null }),
166
 
167
+ // โ”€โ”€ Lighting โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
168
  ambientIntensity: 0.5,
169
  directionalIntensity: 1.0,
170
  bgColor: '#1a1a2e',
 
172
  showAxes: true,
173
  postProcessing: false,
174
  bloomIntensity: 0.5,
175
+ setAmbientIntensity: (v) => set({ ambientIntensity: v }),
176
+ setDirectionalIntensity:(v) => set({ directionalIntensity: v }),
177
+ setBgColor: (c) => set({ bgColor: c }),
178
+ setShowGrid: (v) => set({ showGrid: v }),
179
+ setShowAxes: (v) => set({ showAxes: v }),
180
+ setPostProcessing:(v) => set({ postProcessing: v }),
181
+ setBloomIntensity:(v) => set({ bloomIntensity: v }),
182
+
183
+ // โ”€โ”€ AI Error Resolver โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
184
  openrouterKey: '',
185
  setOpenrouterKey: (k) => set({ openrouterKey: k }),
186
  errorLogs: [],
 
199
  })),
200
  clearErrors: () => set({ errorLogs: [] }),
201
 
202
+ // โ”€โ”€ Recording โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
203
  isRecording: false,
204
  setIsRecording: (v) => set({ isRecording: v }),
205
+ }));