feat(players): app Players library and circular NPC tokens on scenes
Add userData players/teams, scene npcTokens with hex-inscribed sizing, session scale synced to presentation, and Playwright e2e coverage. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -50,11 +50,7 @@ type Actions = {
|
||||
importCampaignAudio: () => Promise<void>;
|
||||
importCampaignAudioFromPaths: (filePaths: string[]) => Promise<void>;
|
||||
updateCampaignAudios: (next: Project['campaignAudios']) => Promise<void>;
|
||||
upsertMaterial: (input: {
|
||||
materialId?: MaterialId;
|
||||
name: string;
|
||||
filePath?: string;
|
||||
}) => Promise<void>;
|
||||
upsertMaterial: (input: { materialId?: MaterialId; name: string; filePath?: string }) => Promise<void>;
|
||||
deleteMaterial: (materialId: MaterialId) => Promise<void>;
|
||||
setMaterialsOrder: (materialIds: MaterialId[]) => Promise<void>;
|
||||
setMaterialRotation: (materialId: MaterialId, rotationDeg: 0 | 90 | 180 | 270) => Promise<void>;
|
||||
@@ -104,7 +100,10 @@ type Actions = {
|
||||
mode: 'folder' | 'archive',
|
||||
) => Promise<{ canceled: true } | { canceled: false; sourcePath: string }>;
|
||||
importFoundryProject: (sourcePath: string) => Promise<void>;
|
||||
peekImportZip: (labels: StorylineLabels, targetHasMainStart: boolean) => Promise<
|
||||
peekImportZip: (
|
||||
labels: StorylineLabels,
|
||||
targetHasMainStart: boolean,
|
||||
) => Promise<
|
||||
| { canceled: true }
|
||||
| {
|
||||
canceled: false;
|
||||
@@ -355,6 +354,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
darkenScene: false,
|
||||
traps: [],
|
||||
tokens: [],
|
||||
npcTokens: [],
|
||||
grid: { enabled: false, type: 'square', sizeN: 0.06, color: '#ffffff' },
|
||||
media: { videos: [], audios: [] },
|
||||
settings: { autoplayVideo: false, autoplayAudio: true, loopVideo: true, loopAudio: true },
|
||||
@@ -509,11 +509,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
await refreshProjects();
|
||||
};
|
||||
|
||||
const upsertMaterial = async (input: {
|
||||
materialId?: MaterialId;
|
||||
name: string;
|
||||
filePath?: string;
|
||||
}) => {
|
||||
const upsertMaterial = async (input: { materialId?: MaterialId; name: string; filePath?: string }) => {
|
||||
const res = await api.invoke(ipcChannels.project.upsertMaterial, input);
|
||||
setState((s) => ({ ...s, project: res.project }));
|
||||
await refreshProjects();
|
||||
@@ -531,10 +527,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
await refreshProjects();
|
||||
};
|
||||
|
||||
const setMaterialRotation = async (
|
||||
materialId: MaterialId,
|
||||
rotationDeg: 0 | 90 | 180 | 270,
|
||||
) => {
|
||||
const setMaterialRotation = async (materialId: MaterialId, rotationDeg: 0 | 90 | 180 | 270) => {
|
||||
const res = await api.invoke(ipcChannels.project.setMaterialRotation, {
|
||||
materialId,
|
||||
rotationDeg,
|
||||
@@ -570,6 +563,9 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
previewRotationDeg?: 0 | 90 | 180 | 270;
|
||||
darkenScene?: boolean;
|
||||
traps?: import('../../../shared/types').SceneTrap[];
|
||||
tokens?: import('../../../shared/types').SceneToken[];
|
||||
npcTokens?: import('../../../shared/types').SceneNpcToken[];
|
||||
grid?: import('../../../shared/types').SceneGrid;
|
||||
settings?: Partial<Scene['settings']>;
|
||||
media?: Partial<Scene['media']>;
|
||||
layout?: { x: number; y: number };
|
||||
@@ -598,6 +594,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
|
||||
...(patch.darkenScene !== undefined ? { darkenScene: patch.darkenScene } : null),
|
||||
...(patch.traps !== undefined ? { traps: patch.traps } : null),
|
||||
...(patch.tokens !== undefined ? { tokens: patch.tokens } : null),
|
||||
...(patch.npcTokens !== undefined ? { npcTokens: patch.npcTokens } : null),
|
||||
...(patch.grid !== undefined ? { grid: patch.grid } : null),
|
||||
...(patch.settings ? { settings: { ...scene.settings, ...patch.settings } } : null),
|
||||
...(patch.media ? { media: { ...scene.media, ...patch.media } } : null),
|
||||
|
||||
Reference in New Issue
Block a user