242 lines
8.7 KiB
TypeScript
242 lines
8.7 KiB
TypeScript
import { create } from 'zustand';
|
|
import { immer } from 'zustand/middleware/immer';
|
|
|
|
interface AssetsStore {
|
|
assets: Assets;
|
|
|
|
// Asset CRUD operations
|
|
addAsset: (asset: Asset) => void;
|
|
removeAsset: (modelUuid: string) => void;
|
|
updateAsset: (modelUuid: string, updates: Partial<Asset>) => void;
|
|
clearAssets: () => void;
|
|
setAssets: (assets: Assets) => void;
|
|
|
|
// Asset properties
|
|
setName: (modelUuid: string, newName: string) => void;
|
|
setPosition: (modelUuid: string, position: [number, number, number]) => void;
|
|
setRotation: (modelUuid: string, rotation: [number, number, number]) => void;
|
|
setLock: (modelUuid: string, isLocked: boolean) => void;
|
|
setCollision: (modelUuid: string, isCollidable: boolean) => void;
|
|
setVisibility: (modelUuid: string, isVisible: boolean) => void;
|
|
setOpacity: (modelUuid: string, opacity: number) => void;
|
|
|
|
// Animation controls
|
|
setAnimation: (modelUuid: string, animation: string) => void;
|
|
setCurrentAnimation: (modelUuid: string, current: string, isPlaying: boolean) => void;
|
|
addAnimation: (modelUuid: string, animation: string) => void;
|
|
removeAnimation: (modelUuid: string, animation: string) => void;
|
|
|
|
// Event data operations
|
|
addEventData: (modelUuid: string, eventData: Asset['eventData']) => void;
|
|
updateEventData: (modelUuid: string, updates: Partial<Asset['eventData']>) => void;
|
|
removeEventData: (modelUuid: string) => void;
|
|
|
|
// Helper functions
|
|
getAssetById: (modelUuid: string) => Asset | undefined;
|
|
getAssetByPointUuid: (pointUuid: string) => Asset | undefined;
|
|
hasAsset: (modelUuid: string) => boolean;
|
|
}
|
|
|
|
export const createAssetStore = () => {
|
|
return create<AssetsStore>()(
|
|
immer((set, get) => ({
|
|
assets: [],
|
|
|
|
// Asset CRUD operations
|
|
addAsset: (asset) => {
|
|
set((state) => {
|
|
if (!state.assets.some(a => a.modelUuid === asset.modelUuid)) {
|
|
state.assets.push(asset);
|
|
}
|
|
});
|
|
},
|
|
|
|
removeAsset: (modelUuid) => {
|
|
set((state) => {
|
|
state.assets = state.assets.filter(a => a.modelUuid !== modelUuid);
|
|
});
|
|
},
|
|
|
|
updateAsset: (modelUuid, updates) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
Object.assign(asset, updates);
|
|
}
|
|
});
|
|
},
|
|
|
|
clearAssets: () => {
|
|
set((state) => {
|
|
state.assets = [];
|
|
});
|
|
},
|
|
|
|
setAssets: (assets) => {
|
|
set((state) => {
|
|
state.assets = assets;
|
|
});
|
|
},
|
|
|
|
// Asset properties
|
|
setName: (modelUuid, newName) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.modelName = newName;
|
|
}
|
|
});
|
|
},
|
|
|
|
setPosition: (modelUuid, position) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.position = position;
|
|
}
|
|
});
|
|
},
|
|
|
|
setRotation: (modelUuid, rotation) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.rotation = rotation;
|
|
}
|
|
});
|
|
},
|
|
|
|
setLock: (modelUuid, isLocked) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.isLocked = isLocked;
|
|
}
|
|
});
|
|
},
|
|
|
|
setCollision: (modelUuid, isCollidable) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.isCollidable = isCollidable;
|
|
}
|
|
});
|
|
},
|
|
|
|
setVisibility: (modelUuid, isVisible) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.isVisible = isVisible;
|
|
}
|
|
});
|
|
},
|
|
|
|
setOpacity: (modelUuid, opacity) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.opacity = opacity;
|
|
}
|
|
});
|
|
},
|
|
|
|
// Animation controls
|
|
setAnimation: (modelUuid, animation) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
if (!asset.animationState) {
|
|
asset.animationState = { current: animation, playing: false };
|
|
} else {
|
|
asset.animationState.current = animation;
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
setCurrentAnimation: (modelUuid, current, isPlaying) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset?.animationState) {
|
|
asset.animationState.current = current;
|
|
asset.animationState.playing = isPlaying;
|
|
}
|
|
});
|
|
},
|
|
|
|
addAnimation: (modelUuid, animation) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
if (!asset.animations) {
|
|
asset.animations = [animation];
|
|
} else if (!asset.animations.includes(animation)) {
|
|
asset.animations.push(animation);
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
removeAnimation: (modelUuid, animation) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset?.animations) {
|
|
asset.animations = asset.animations.filter(a => a !== animation);
|
|
if (asset.animationState?.current === animation) {
|
|
asset.animationState.playing = false;
|
|
asset.animationState.current = '';
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
// Event data operations
|
|
addEventData: (modelUuid, eventData) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
asset.eventData = eventData;
|
|
}
|
|
});
|
|
},
|
|
|
|
updateEventData: (modelUuid, updates) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset?.eventData) {
|
|
asset.eventData = { ...asset.eventData, ...updates };
|
|
}
|
|
});
|
|
},
|
|
|
|
removeEventData: (modelUuid) => {
|
|
set((state) => {
|
|
const asset = state.assets.find(a => a.modelUuid === modelUuid);
|
|
if (asset) {
|
|
delete asset.eventData;
|
|
}
|
|
});
|
|
},
|
|
|
|
// Helper functions
|
|
getAssetById: (modelUuid) => {
|
|
return get().assets.find(a => a.modelUuid === modelUuid);
|
|
},
|
|
|
|
getAssetByPointUuid: (pointUuid) => {
|
|
return get().assets.find(asset =>
|
|
asset.eventData?.point?.uuid === pointUuid ||
|
|
asset.eventData?.points?.some(p => p.uuid === pointUuid)
|
|
);
|
|
},
|
|
|
|
hasAsset: (modelUuid) => {
|
|
return get().assets.some(a => a.modelUuid === modelUuid);
|
|
}
|
|
}))
|
|
)
|
|
}
|
|
|
|
export type AssetStoreType = ReturnType<typeof createAssetStore>; |