feat(npcs): inspect cards, Show overlay, and optional external link

Clicking an NPC tile opens description cards (multi-select accordion); Show puts avatars on screen. Optional URL opens a webview tab. Avatar pan in the editor commits on pointer up.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-08-19 10:42:57 +08:00
parent 1a9f0f2557
commit 0f4bb76b41
35 changed files with 1189 additions and 259 deletions
@@ -248,6 +248,7 @@ void test('selectNpcsByIds / buildPartialExportProject: explicit NPCs, relations
disposition: 'neutral',
imageOffset: { x: 0, y: 0 },
imageScale: 1,
externalUrl: '',
},
{
id: n2,
@@ -261,6 +262,7 @@ void test('selectNpcsByIds / buildPartialExportProject: explicit NPCs, relations
disposition: 'neutral',
imageOffset: { x: 0, y: 0 },
imageScale: 1,
externalUrl: '',
},
{
id: n3,
@@ -274,6 +276,7 @@ void test('selectNpcsByIds / buildPartialExportProject: explicit NPCs, relations
disposition: 'neutral',
imageOffset: { x: 0, y: 0 },
imageScale: 1,
externalUrl: '',
},
];
const relations: ProjectNpcRelation[] = [
@@ -364,6 +367,7 @@ void test('buildPartialExportProject: keeps npcTokens only for exported NPCs', (
disposition: 'neutral',
imageOffset: { x: 0, y: 0 },
imageScale: 1,
externalUrl: '',
},
{
id: n2,
@@ -377,6 +381,7 @@ void test('buildPartialExportProject: keeps npcTokens only for exported NPCs', (
disposition: 'neutral',
imageOffset: { x: 0, y: 0 },
imageScale: 1,
externalUrl: '',
},
],
});
@@ -430,6 +435,7 @@ void test('mergeStorylinesIntoProject: remaps npcTokens to created NPC ids', ()
disposition: 'neutral',
imageOffset: { x: 0.1, y: -0.1 },
imageScale: 1,
externalUrl: '',
},
],
});
@@ -489,6 +495,7 @@ void test('mergeStorylinesIntoProject: imports all NPCs from export bundle', ()
disposition: 'neutral',
imageOffset: { x: 0, y: 0 },
imageScale: 1,
externalUrl: '',
},
],
});
@@ -22,6 +22,7 @@ import {
asSceneNpcTokenId,
asTokenId,
} from '../types/ids';
import { normalizeNpcExternalUrl } from '../types/npcExternalUrl';
import {
getConnectedComponent,
@@ -700,6 +701,7 @@ export function mergeStorylinesIntoProject(
disposition: n.disposition === 'hostile' || n.disposition === 'friendly' ? n.disposition : 'neutral',
imageOffset: n.imageOffset ?? { x: 0, y: 0 },
imageScale: typeof n.imageScale === 'number' && Number.isFinite(n.imageScale) ? n.imageScale : 1,
externalUrl: normalizeNpcExternalUrl(n.externalUrl),
});
npcNameKeys.add(name.toLowerCase());
npcsCreated += 1;