@dreamerbird/camera-studio 0.2.0 → 0.3.0
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.
- package/dist/CameraScene.d.ts +1 -1
- package/dist/CameraScene.d.ts.map +1 -1
- package/dist/CameraScene.js +36 -6
- package/dist/PlacementManager.d.ts +15 -1
- package/dist/PlacementManager.d.ts.map +1 -1
- package/dist/PlacementManager.js +123 -14
- package/dist/agent/api.d.ts +5 -0
- package/dist/agent/api.d.ts.map +1 -1
- package/dist/agent/api.js +25 -0
- package/dist/agent/api.test.js +75 -1
- package/dist/agent/commands/assets.d.ts +5 -0
- package/dist/agent/commands/assets.d.ts.map +1 -1
- package/dist/agent/commands/assets.js +93 -21
- package/dist/agent/commands/assets.test.js +53 -0
- package/dist/agent/commands/materials.d.ts +18 -0
- package/dist/agent/commands/materials.d.ts.map +1 -0
- package/dist/agent/commands/materials.js +192 -0
- package/dist/agent/commands/materials.test.d.ts +2 -0
- package/dist/agent/commands/materials.test.d.ts.map +1 -0
- package/dist/agent/commands/materials.test.js +294 -0
- package/dist/agent/commands/modelRecovery.test.d.ts +2 -0
- package/dist/agent/commands/modelRecovery.test.d.ts.map +1 -0
- package/dist/agent/commands/modelRecovery.test.js +122 -0
- package/dist/agent/commands/models.d.ts +13 -0
- package/dist/agent/commands/models.d.ts.map +1 -1
- package/dist/agent/commands/models.js +98 -1
- package/dist/agent/commands/primitives.d.ts +27 -0
- package/dist/agent/commands/primitives.d.ts.map +1 -0
- package/dist/agent/commands/primitives.js +117 -0
- package/dist/agent/commands/primitives.test.d.ts +2 -0
- package/dist/agent/commands/primitives.test.d.ts.map +1 -0
- package/dist/agent/commands/primitives.test.js +135 -0
- package/dist/agent/expectedCommands.d.ts +1 -1
- package/dist/agent/expectedCommands.d.ts.map +1 -1
- package/dist/agent/expectedCommands.js +6 -0
- package/dist/agent/propAccess.d.ts +2 -0
- package/dist/agent/propAccess.d.ts.map +1 -1
- package/dist/agent/propAccess.js +21 -0
- package/dist/agent/registerCommands.d.ts.map +1 -1
- package/dist/agent/registerCommands.js +5 -1
- package/dist/agent/runtime/objectRuntime.d.ts +2 -0
- package/dist/agent/runtime/objectRuntime.d.ts.map +1 -1
- package/dist/agent/runtime/objectRuntime.js +15 -1
- package/dist/agent/runtime.d.ts +1 -0
- package/dist/agent/runtime.d.ts.map +1 -1
- package/dist/agent/runtime.js +2 -0
- package/dist/assetLibrary/dispose.d.ts +4 -2
- package/dist/assetLibrary/dispose.d.ts.map +1 -1
- package/dist/assetLibrary/dispose.js +7 -5
- package/dist/assetLibrary/gltfLoader.d.ts +2 -1
- package/dist/assetLibrary/gltfLoader.d.ts.map +1 -1
- package/dist/assetLibrary/gltfLoader.js +2 -2
- package/dist/assetLibrary/gltfResourceSet.d.ts +6 -0
- package/dist/assetLibrary/gltfResourceSet.d.ts.map +1 -0
- package/dist/assetLibrary/gltfResourceSet.js +27 -0
- package/dist/assetLibrary/gltfResourceSet.test.d.ts +2 -0
- package/dist/assetLibrary/gltfResourceSet.test.d.ts.map +1 -0
- package/dist/assetLibrary/gltfResourceSet.test.js +40 -0
- package/dist/assetLibrary/importModelFile.d.ts +5 -0
- package/dist/assetLibrary/importModelFile.d.ts.map +1 -1
- package/dist/assetLibrary/importModelFile.js +3 -16
- package/dist/assetLibrary/importModelFiles.d.ts +15 -0
- package/dist/assetLibrary/importModelFiles.d.ts.map +1 -0
- package/dist/assetLibrary/importModelFiles.js +58 -0
- package/dist/assetLibrary/importModelFiles.test.d.ts +2 -0
- package/dist/assetLibrary/importModelFiles.test.d.ts.map +1 -0
- package/dist/assetLibrary/importModelFiles.test.js +217 -0
- package/dist/assetLibrary/importPipeline.d.ts +15 -1
- package/dist/assetLibrary/importPipeline.d.ts.map +1 -1
- package/dist/assetLibrary/importPipeline.js +74 -38
- package/dist/assetLibrary/importPipeline.test.js +25 -0
- package/dist/assetLibrary/library.d.ts +1 -0
- package/dist/assetLibrary/library.d.ts.map +1 -1
- package/dist/assetLibrary/library.js +22 -1
- package/dist/assetLibrary/library.test.js +76 -0
- package/dist/bootstrap.d.ts +2 -1
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +69 -7
- package/dist/bootstrap.test.js +111 -0
- package/dist/config.d.ts +10 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/hostFlows.d.ts +1 -0
- package/dist/hostFlows.d.ts.map +1 -1
- package/dist/hostFlows.js +9 -0
- package/dist/index.d.ts +10 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/materials/modelMaterials.d.ts +19 -0
- package/dist/materials/modelMaterials.d.ts.map +1 -0
- package/dist/materials/modelMaterials.js +253 -0
- package/dist/materials/modelMaterials.test.d.ts +2 -0
- package/dist/materials/modelMaterials.test.d.ts.map +1 -0
- package/dist/materials/modelMaterials.test.js +188 -0
- package/dist/materials/types.d.ts +20 -0
- package/dist/materials/types.d.ts.map +1 -0
- package/dist/materials/types.js +1 -0
- package/dist/materials/useModelMaterials.d.ts +10 -0
- package/dist/materials/useModelMaterials.d.ts.map +1 -0
- package/dist/materials/useModelMaterials.js +26 -0
- package/dist/materials/useModelMaterials.test.d.ts +2 -0
- package/dist/materials/useModelMaterials.test.d.ts.map +1 -0
- package/dist/materials/useModelMaterials.test.js +75 -0
- package/dist/poses.d.ts +38 -0
- package/dist/poses.d.ts.map +1 -0
- package/dist/poses.js +41 -0
- package/dist/poses.test.d.ts +2 -0
- package/dist/poses.test.d.ts.map +1 -0
- package/dist/poses.test.js +38 -0
- package/dist/primitives.d.ts +5 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +15 -0
- package/dist/primitives.test.d.ts +2 -0
- package/dist/primitives.test.d.ts.map +1 -0
- package/dist/primitives.test.js +27 -0
- package/dist/reset.realStudio.test.d.ts +2 -0
- package/dist/reset.realStudio.test.d.ts.map +1 -0
- package/dist/reset.realStudio.test.js +60 -0
- package/dist/studioRoot.d.ts +4 -0
- package/dist/studioRoot.d.ts.map +1 -0
- package/dist/studioRoot.js +36 -0
- package/dist/studioRoot.test.d.ts +2 -0
- package/dist/studioRoot.test.d.ts.map +1 -0
- package/dist/studioRoot.test.js +62 -0
- package/dist/useCameraStudio.d.ts.map +1 -1
- package/dist/useCameraStudio.js +3 -2
- package/package.json +9 -1
|
@@ -238,7 +238,16 @@ export class Library {
|
|
|
238
238
|
await this.enqueue(async () => {
|
|
239
239
|
const writable = this.requireWritable();
|
|
240
240
|
const blobId = await writable.putBlob(data);
|
|
241
|
-
|
|
241
|
+
try {
|
|
242
|
+
await writable.putEntry(makeEntry(blobId));
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
const referenced = await this.referencedBlobIdsForRollback().catch(() => undefined);
|
|
246
|
+
if (referenced && !referenced.has(blobId)) {
|
|
247
|
+
await writable.deleteBlob(blobId).catch(() => { });
|
|
248
|
+
}
|
|
249
|
+
throw error;
|
|
250
|
+
}
|
|
242
251
|
this.emit();
|
|
243
252
|
});
|
|
244
253
|
}
|
|
@@ -265,6 +274,18 @@ export class Library {
|
|
|
265
274
|
}
|
|
266
275
|
return ids;
|
|
267
276
|
}
|
|
277
|
+
async referencedBlobIdsForRollback() {
|
|
278
|
+
const catalogs = await Promise.all(this.sources.map((source) => source.listEntries()));
|
|
279
|
+
const ids = new Set();
|
|
280
|
+
for (const entry of catalogs.flat()) {
|
|
281
|
+
if ('blobId' in entry)
|
|
282
|
+
ids.add(entry.blobId);
|
|
283
|
+
if ('thumbnailId' in entry && entry.thumbnailId) {
|
|
284
|
+
ids.add(entry.thumbnailId);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return ids;
|
|
288
|
+
}
|
|
268
289
|
/** 删条目并清理它的 blob;blob 被其他条目共享时保留 */
|
|
269
290
|
async deleteEntryDeep(id) {
|
|
270
291
|
await this.enqueue(async () => {
|
|
@@ -400,6 +400,82 @@ describe('骨架族别名并集读(终审 M-4)', () => {
|
|
|
400
400
|
});
|
|
401
401
|
});
|
|
402
402
|
describe('blob 生命周期', () => {
|
|
403
|
+
test('putBlobWithEntry rolls back the upload when entry creation fails', async () => {
|
|
404
|
+
const backend = memoryBackend();
|
|
405
|
+
const failure = new Error('entry write failed');
|
|
406
|
+
backend.putEntry = async () => {
|
|
407
|
+
throw failure;
|
|
408
|
+
};
|
|
409
|
+
backend.deleteBlob = jest.fn(async () => { });
|
|
410
|
+
const lib = new Library({ sources: [backend] });
|
|
411
|
+
await expect(lib.putBlobWithEntry(new Blob(['model']), model)).rejects.toBe(failure);
|
|
412
|
+
expect(backend.deleteBlob).toHaveBeenCalledWith('blob-x');
|
|
413
|
+
});
|
|
414
|
+
test('putBlobWithEntry preserves a blob referenced by an existing entry after a later failure', async () => {
|
|
415
|
+
const backend = new IndexedDBBackend();
|
|
416
|
+
const lib = new Library({ sources: [backend] });
|
|
417
|
+
const bytes = new Blob(['shared-model-bytes']);
|
|
418
|
+
let sharedBlobId = '';
|
|
419
|
+
await lib.putBlobWithEntry(bytes, (blobId) => {
|
|
420
|
+
sharedBlobId = blobId;
|
|
421
|
+
return { ...model('shared-original'), blobId, contentHash: blobId };
|
|
422
|
+
});
|
|
423
|
+
const failure = new Error('second entry write failed');
|
|
424
|
+
backend.putEntry = async () => {
|
|
425
|
+
throw failure;
|
|
426
|
+
};
|
|
427
|
+
await expect(lib.putBlobWithEntry(bytes, (blobId) => ({
|
|
428
|
+
...model('shared-second'),
|
|
429
|
+
blobId,
|
|
430
|
+
contentHash: blobId,
|
|
431
|
+
}))).rejects.toBe(failure);
|
|
432
|
+
expect(await lib.listBlobIds()).toContain(sharedBlobId);
|
|
433
|
+
expect(await lib.getEntry('shared-original')).toMatchObject({
|
|
434
|
+
blobId: sharedBlobId,
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
test('putBlobWithEntry preserves shared bytes and the original error when any source cannot be enumerated', async () => {
|
|
438
|
+
const backend = new IndexedDBBackend();
|
|
439
|
+
const sourceFailure = new Error('catalog source unavailable');
|
|
440
|
+
let sourceEntries = [];
|
|
441
|
+
let sourceUnavailable = false;
|
|
442
|
+
const unavailableSource = {
|
|
443
|
+
id: 'unavailable-source',
|
|
444
|
+
listEntries: async () => {
|
|
445
|
+
if (sourceUnavailable)
|
|
446
|
+
throw sourceFailure;
|
|
447
|
+
return sourceEntries;
|
|
448
|
+
},
|
|
449
|
+
getEntry: async (id) => sourceEntries.find((entry) => entry.id === id),
|
|
450
|
+
getBlobUrl: async () => {
|
|
451
|
+
throw sourceFailure;
|
|
452
|
+
},
|
|
453
|
+
};
|
|
454
|
+
const lib = new Library({ sources: [backend, unavailableSource] });
|
|
455
|
+
const bytes = new Blob(['shared-partial-catalog-bytes']);
|
|
456
|
+
let sharedBlobId = '';
|
|
457
|
+
await lib.putBlobWithEntry(bytes, (blobId) => {
|
|
458
|
+
sharedBlobId = blobId;
|
|
459
|
+
return { ...model('shared-partial-original'), blobId, contentHash: blobId };
|
|
460
|
+
});
|
|
461
|
+
sourceEntries = [(await backend.getEntry('shared-partial-original'))];
|
|
462
|
+
await backend.deleteEntry('shared-partial-original');
|
|
463
|
+
sourceUnavailable = true;
|
|
464
|
+
const failure = new Error('partial catalog entry write failed');
|
|
465
|
+
backend.putEntry = async () => {
|
|
466
|
+
throw failure;
|
|
467
|
+
};
|
|
468
|
+
await expect(lib.putBlobWithEntry(bytes, (blobId) => ({
|
|
469
|
+
...model('shared-partial-second'),
|
|
470
|
+
blobId,
|
|
471
|
+
contentHash: blobId,
|
|
472
|
+
}))).rejects.toBe(failure);
|
|
473
|
+
await expect(backend.getBlobUrl(sharedBlobId)).resolves.toBe('blob:mock-url');
|
|
474
|
+
expect(await unavailableSource.getEntry('shared-partial-original')).toMatchObject({
|
|
475
|
+
blobId: sharedBlobId,
|
|
476
|
+
});
|
|
477
|
+
await backend.deleteBlob(sharedBlobId);
|
|
478
|
+
});
|
|
403
479
|
test('deleteEntryDeep: 缩略图被两个模型共享时,删一个不删 blob', async () => {
|
|
404
480
|
const lib = new Library({ sources: [new IndexedDBBackend()] });
|
|
405
481
|
const thumbId = await lib.putBlob(new Blob(['thumb']));
|
package/dist/bootstrap.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface BootCtx {
|
|
|
7
7
|
library: Library;
|
|
8
8
|
unregisterEditors: () => void;
|
|
9
9
|
/** 节流通道手动 flush:dispose 时调用,尾部变更不丢 */
|
|
10
|
-
flushState: () => void
|
|
10
|
+
flushState: () => Promise<void>;
|
|
11
11
|
/**
|
|
12
12
|
* 状态通道入口:生产由 project 历史指针订阅喂入,测试可直接调。
|
|
13
13
|
* 尾部节流(缺省 1000ms)后转给 config.state.onStateChange。
|
|
@@ -34,4 +34,5 @@ export declare function isBootedWithDifferentConfig(config: CameraStudioConfig):
|
|
|
34
34
|
export declare function getBootConfig(): CameraStudioConfig | undefined;
|
|
35
35
|
export declare function initCameraStudio(config: CameraStudioConfig): Promise<BootCtx>;
|
|
36
36
|
export declare function disposeCameraStudio(ctx?: BootCtx): Promise<void>;
|
|
37
|
+
export declare function resetCameraStudio(): Promise<void>;
|
|
37
38
|
//# sourceMappingURL=bootstrap.d.ts.map
|
package/dist/bootstrap.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAwBA,OAAO,qBAAqB,CAAA;AAS5B,OAAO,KAAK,EAAC,gBAAgB,EAAE,kBAAkB,EAAC,MAAM,UAAU,CAAA;AAKlE,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,wBAAwB,CAAA;AAqBnD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAOhD,MAAM,WAAW,OAAO;IACtB,MAAM,EAAE,kBAAkB,CAAA;IAC1B,OAAO,EAAE,OAAO,CAAA;IAChB,iBAAiB,EAAE,MAAM,IAAI,CAAA;IAC7B,sCAAsC;IACtC,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC/B;;;OAGG;IACH,iBAAiB,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IAC7C,UAAU,EAAE,gBAAgB,CAAA;IAC5B,uDAAuD;IACvD,GAAG,EAAE,eAAe,CAAA;CACrB;AAaD;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AACD,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAuBD,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,kBAAkB,GACzB,gBAAgB,CASlB;AA0CD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAIT;AAED,0DAA0D;AAC1D,wBAAgB,aAAa,IAAI,kBAAkB,GAAG,SAAS,CAE9D;AAoRD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CA6B7E;AAED,wBAAsB,mBAAmB,CAAC,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAMtE;AAED,wBAAgB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CA4CjD"}
|
package/dist/bootstrap.js
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*
|
|
6
6
|
* 生命周期分层(R14):
|
|
7
7
|
* - boot 级(一次性,initPromise 保留):Library 单例、IDB 连接、词典、
|
|
8
|
-
* theatre.init、project 解析、节流机械。重挂幂等复用,dispose
|
|
8
|
+
* theatre.init、project 解析、节流机械。重挂幂等复用,dispose 不拆;
|
|
9
|
+
* 显式场景切换可在全部消费者卸载后经 resetCameraStudio 清空重 boot。
|
|
9
10
|
* - 会话级(每次挂载 acquire,dispose 拆解):3 个自定义属性编辑器注册、
|
|
10
11
|
* state 通道订阅、studio.ui 显隐。picker 注册表与宿主句柄由各自模块
|
|
11
12
|
* 自管(CameraScene 组件挂载时接线),这里不碰。
|
|
@@ -18,6 +19,8 @@ import theatre, { getProject, getStudio, getStudioSync, onChange, } from '@dream
|
|
|
18
19
|
import '@dreamerbird/studio';
|
|
19
20
|
import { initState } from '@dreamerbird/core/initState';
|
|
20
21
|
import { privateAPI } from '@dreamerbird/core/privateAPIs';
|
|
22
|
+
import projectsSingleton from '@dreamerbird/core/projects/projectsSingleton';
|
|
23
|
+
import getStudioInternal from '@dreamerbird/studio/getStudio';
|
|
21
24
|
import { registerCustomPropEditor, unregisterCustomPropEditor, } from '@dreamerbird/studio/propEditors/customPropEditors';
|
|
22
25
|
import { cameraErrorFromLibrary, cameraErrorFromUnknown } from './errors';
|
|
23
26
|
import { registerCameraMessages } from './i18n';
|
|
@@ -28,9 +31,11 @@ import { StaticCatalogSource } from './assetLibrary/staticCatalogSource';
|
|
|
28
31
|
import { isWritableSource } from './assetLibrary/source';
|
|
29
32
|
import { cleanupLegacySeeds } from './assetLibrary/legacySeedCleanup';
|
|
30
33
|
import { setUiConfig } from './uiConfig';
|
|
34
|
+
import { mountStudioRootWhenReady } from './studioRoot';
|
|
31
35
|
import PosePropEditor from './poseMode/PosePropEditor';
|
|
32
36
|
import { GesturePropEditorLeft, GesturePropEditorRight, } from './gesturePropsEditor';
|
|
33
37
|
import { createAgentRuntime } from './agent/runtime';
|
|
38
|
+
import { clearSceneSheetObjects } from './agent/runtime/objectRuntime';
|
|
34
39
|
import { activateCameraStudioApi, disposeCameraStudioApi, getActiveAgentRegistry, getCameraStudioApi, } from './agent/api';
|
|
35
40
|
import { createAgentBridgeClient } from './agent/bridgeClient';
|
|
36
41
|
/** 内置 IDB 缺省库名(与现状一字不差,硬约束:老用户浏览器里的库零迁移) */
|
|
@@ -40,6 +45,7 @@ let initPromise;
|
|
|
40
45
|
let bootConfig;
|
|
41
46
|
/** 漂移告警只发一次(同页多次重挂不同 config 不刷屏) */
|
|
42
47
|
let warnedConfigDrift = false;
|
|
48
|
+
let resetPromise;
|
|
43
49
|
/** 会话拆解函数;undefined = 当前无活跃会话(acquire 幂等守卫) */
|
|
44
50
|
let sessionTeardown;
|
|
45
51
|
/** 消费者计数由 hook 管(acquire/release 成对);dispose 据此做末位守卫 */
|
|
@@ -65,7 +71,12 @@ function resolveProject(config) {
|
|
|
65
71
|
}
|
|
66
72
|
const name = config.project ?? 'Space';
|
|
67
73
|
const initialState = config.state?.initialState;
|
|
68
|
-
return getProject(name,
|
|
74
|
+
return getProject(name, {
|
|
75
|
+
...(initialState === undefined ? {} : { state: initialState }),
|
|
76
|
+
...(config.ui?.projectName === undefined
|
|
77
|
+
? {}
|
|
78
|
+
: { name: config.ui.projectName }),
|
|
79
|
+
});
|
|
69
80
|
}
|
|
70
81
|
/** sceneProps 同步解析(hook 首帧就要返回;getProject 渲染期调用安全,App 既有先例) */
|
|
71
82
|
export function resolveSceneProps(config) {
|
|
@@ -73,6 +84,9 @@ export function resolveSceneProps(config) {
|
|
|
73
84
|
project: resolveProject(config),
|
|
74
85
|
onFlows: config.flows?.onFlows,
|
|
75
86
|
onError: config.onError,
|
|
87
|
+
...(config.scene?.includeDemoModel === undefined
|
|
88
|
+
? {}
|
|
89
|
+
: { includeDemoModel: config.scene.includeDemoModel }),
|
|
76
90
|
};
|
|
77
91
|
}
|
|
78
92
|
/** 参与漂移比对的顶层配置键(flows 回调引用每次渲染都新,不比) */
|
|
@@ -185,6 +199,13 @@ async function boot(config) {
|
|
|
185
199
|
if (config.ui?.hideLeftStrip) {
|
|
186
200
|
withStudioUi((ui) => ui.setLeftStripHidden(true));
|
|
187
201
|
}
|
|
202
|
+
if (config.ui?.panels) {
|
|
203
|
+
const panels = config.ui.panels;
|
|
204
|
+
withStudioUi((ui) => ui.setPanelVisibility(panels));
|
|
205
|
+
}
|
|
206
|
+
withStudioUi(() => {
|
|
207
|
+
void mountStudioRootWhenReady(config.ui?.portalContainer);
|
|
208
|
+
});
|
|
188
209
|
// 1. 数据源:可写源(若有) + 内置目录,聚合进 Library 单例
|
|
189
210
|
const { sources, idbName } = resolveSources(config);
|
|
190
211
|
const catalog = new StaticCatalogSource({
|
|
@@ -238,7 +259,7 @@ async function boot(config) {
|
|
|
238
259
|
let pendingContent;
|
|
239
260
|
let hasPending = false;
|
|
240
261
|
let timer;
|
|
241
|
-
const flushState = () => {
|
|
262
|
+
const flushState = async () => {
|
|
242
263
|
if (timer !== undefined) {
|
|
243
264
|
clearTimeout(timer);
|
|
244
265
|
timer = undefined;
|
|
@@ -248,7 +269,7 @@ async function boot(config) {
|
|
|
248
269
|
hasPending = false;
|
|
249
270
|
const content = pendingContent;
|
|
250
271
|
pendingContent = undefined;
|
|
251
|
-
config.state?.onStateChange?.(content);
|
|
272
|
+
await config.state?.onStateChange?.(content);
|
|
252
273
|
};
|
|
253
274
|
const notifyStateChange = (content) => {
|
|
254
275
|
if (!config.state?.onStateChange)
|
|
@@ -277,7 +298,7 @@ async function boot(config) {
|
|
|
277
298
|
}
|
|
278
299
|
/** studio.ui 显隐操作:studio 未挂载(宿主以 studio:false init 等)时静默降级 */
|
|
279
300
|
function withStudioUi(fn) {
|
|
280
|
-
Promise.resolve()
|
|
301
|
+
return Promise.resolve()
|
|
281
302
|
.then(() => getStudio())
|
|
282
303
|
.then(async (studio) => {
|
|
283
304
|
// 必须等 studio 初始化收尾(持久化/同步状态恢复落库)再读写显隐:
|
|
@@ -352,11 +373,13 @@ function acquireSession(ctx) {
|
|
|
352
373
|
ctx.unregisterEditors();
|
|
353
374
|
unsubState?.();
|
|
354
375
|
// 先断订阅再 flush:尾部变更带给宿主,不丢
|
|
355
|
-
ctx.flushState();
|
|
356
|
-
withStudioUi((ui) => ui.hide());
|
|
376
|
+
await ctx.flushState();
|
|
377
|
+
await withStudioUi((ui) => ui.hide());
|
|
357
378
|
};
|
|
358
379
|
}
|
|
359
380
|
export function initCameraStudio(config) {
|
|
381
|
+
if (resetPromise)
|
|
382
|
+
return resetPromise.then(() => initCameraStudio(config));
|
|
360
383
|
if (!initPromise) {
|
|
361
384
|
bootConfig = config;
|
|
362
385
|
const p = boot(config);
|
|
@@ -392,3 +415,42 @@ export async function disposeCameraStudio(ctx) {
|
|
|
392
415
|
return;
|
|
393
416
|
await sessionTeardown?.();
|
|
394
417
|
}
|
|
418
|
+
export function resetCameraStudio() {
|
|
419
|
+
if (resetPromise)
|
|
420
|
+
return resetPromise;
|
|
421
|
+
const previousInit = initPromise;
|
|
422
|
+
resetPromise = (async () => {
|
|
423
|
+
if (activeConsumers > 0) {
|
|
424
|
+
throw new Error('resetCameraStudio requires all camera-studio consumers to be unmounted');
|
|
425
|
+
}
|
|
426
|
+
const previousCtx = previousInit
|
|
427
|
+
? await previousInit.catch(() => undefined)
|
|
428
|
+
: undefined;
|
|
429
|
+
if (activeConsumers > 0) {
|
|
430
|
+
throw new Error('resetCameraStudio requires all camera-studio consumers to be unmounted');
|
|
431
|
+
}
|
|
432
|
+
await sessionTeardown?.();
|
|
433
|
+
clearSceneSheetObjects();
|
|
434
|
+
if (previousCtx) {
|
|
435
|
+
const projectId = previousCtx.sceneProps.project.address.projectId;
|
|
436
|
+
projectsSingleton.remove(projectId);
|
|
437
|
+
const studio = getStudioInternal();
|
|
438
|
+
if (studio) {
|
|
439
|
+
studio.transaction(({ stateEditors }) => {
|
|
440
|
+
stateEditors.deleteProject({ projectId });
|
|
441
|
+
}, false);
|
|
442
|
+
studio.ephemeralAtom.reduceByPointer((p) => p.coreByProject, (projects) => {
|
|
443
|
+
const next = { ...projects };
|
|
444
|
+
delete next[projectId];
|
|
445
|
+
return next;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
initPromise = undefined;
|
|
450
|
+
bootConfig = undefined;
|
|
451
|
+
warnedConfigDrift = false;
|
|
452
|
+
})().finally(() => {
|
|
453
|
+
resetPromise = undefined;
|
|
454
|
+
});
|
|
455
|
+
return resetPromise;
|
|
456
|
+
}
|
package/dist/bootstrap.test.js
CHANGED
|
@@ -31,11 +31,13 @@ const initSpy = jest.fn(async (_opts) => { });
|
|
|
31
31
|
const fakeSheet = { fakeSheet: true };
|
|
32
32
|
const getProjectSpy = jest.fn((_name, _opts) => ({
|
|
33
33
|
fake: true,
|
|
34
|
+
address: { projectId: _name },
|
|
34
35
|
sheet: jest.fn(() => fakeSheet),
|
|
35
36
|
}));
|
|
36
37
|
// studio.ui 替身:hide/restore 翻转 isHidden(与真 UI 行为一致;
|
|
37
38
|
// bootstrap 仅在 isHidden 时才 restore)
|
|
38
39
|
const setLeftStripHiddenSpy = jest.fn();
|
|
40
|
+
const setPanelVisibilitySpy = jest.fn();
|
|
39
41
|
const uiBox = {
|
|
40
42
|
isHidden: false,
|
|
41
43
|
hide: jest.fn(() => {
|
|
@@ -45,6 +47,7 @@ const uiBox = {
|
|
|
45
47
|
uiBox.isHidden = false;
|
|
46
48
|
}),
|
|
47
49
|
setLeftStripHidden: setLeftStripHiddenSpy,
|
|
50
|
+
setPanelVisibility: setPanelVisibilitySpy,
|
|
48
51
|
};
|
|
49
52
|
const hideSpy = uiBox.hide;
|
|
50
53
|
const restoreSpy = uiBox.restore;
|
|
@@ -103,6 +106,11 @@ initSpy.mockImplementation(async (opts) => {
|
|
|
103
106
|
jest.doMock('@dreamerbird/studio', () => ({
|
|
104
107
|
__esModule: true,
|
|
105
108
|
}));
|
|
109
|
+
jest.doMock('@dreamerbird/studio/UI/UINonSSRBits', () => ({
|
|
110
|
+
__esModule: true,
|
|
111
|
+
default: class {
|
|
112
|
+
},
|
|
113
|
+
}));
|
|
106
114
|
jest.doMock('@dreamerbird/core', () => ({
|
|
107
115
|
__esModule: true,
|
|
108
116
|
default: { init: initSpy },
|
|
@@ -158,6 +166,7 @@ beforeEach(async () => {
|
|
|
158
166
|
uiBox.isHidden = false;
|
|
159
167
|
initializedBox.promise = Promise.resolve();
|
|
160
168
|
setLeftStripHiddenSpy.mockClear();
|
|
169
|
+
setPanelVisibilitySpy.mockClear();
|
|
161
170
|
getStudioSyncSpy.mockClear();
|
|
162
171
|
activateApiSpy.mockClear();
|
|
163
172
|
disposeApiSpy.mockClear();
|
|
@@ -645,3 +654,105 @@ test('14. ui.hideLeftStrip → boot 经 studio.ui.setLeftStripHidden(true) 应
|
|
|
645
654
|
expect(setLeftStripHiddenSpy).toHaveBeenCalledWith(true);
|
|
646
655
|
await h.unmount();
|
|
647
656
|
});
|
|
657
|
+
test('flushState emits the pending throttled state exactly once', async () => {
|
|
658
|
+
let resolveState;
|
|
659
|
+
const onStateChange = jest.fn(() => new Promise((resolve) => {
|
|
660
|
+
resolveState = resolve;
|
|
661
|
+
}));
|
|
662
|
+
const h = hookHost({ state: { onStateChange, throttleMs: 60000 } });
|
|
663
|
+
await h.mount();
|
|
664
|
+
const historicCallback = onChangeSpy.mock.calls[1][1];
|
|
665
|
+
historicCallback({ rev: 1 });
|
|
666
|
+
let flushed = false;
|
|
667
|
+
const firstFlush = h.result.current.flushState().then(() => {
|
|
668
|
+
flushed = true;
|
|
669
|
+
});
|
|
670
|
+
await Promise.resolve();
|
|
671
|
+
expect(onStateChange).toHaveBeenCalledTimes(1);
|
|
672
|
+
expect(onStateChange).toHaveBeenCalledWith({ rev: 1 });
|
|
673
|
+
expect(flushed).toBe(false);
|
|
674
|
+
resolveState();
|
|
675
|
+
await firstFlush;
|
|
676
|
+
await h.result.current.flushState();
|
|
677
|
+
expect(onStateChange).toHaveBeenCalledTimes(1);
|
|
678
|
+
await h.unmount();
|
|
679
|
+
});
|
|
680
|
+
test('ui.panels hides only the requested panel without changing timeline visibility', async () => {
|
|
681
|
+
const h = hookHost({ ui: { panels: { outline: false, details: true } } });
|
|
682
|
+
await h.mount();
|
|
683
|
+
await flush();
|
|
684
|
+
expect(setPanelVisibilitySpy).toHaveBeenCalledWith({
|
|
685
|
+
outline: false,
|
|
686
|
+
details: true,
|
|
687
|
+
});
|
|
688
|
+
expect(hideSpy).not.toHaveBeenCalled();
|
|
689
|
+
expect(restoreSpy).not.toHaveBeenCalled();
|
|
690
|
+
const [{ default: UI }, { Atom, val }] = await Promise.all([
|
|
691
|
+
import('@dreamerbird/studio/UI/UI'),
|
|
692
|
+
import('@dreamerbird/dataverse'),
|
|
693
|
+
]);
|
|
694
|
+
const studio = {
|
|
695
|
+
ephemeralAtom: new Atom({}),
|
|
696
|
+
atomP: { ahistoric: { visibilityState: 'everythingIsVisible' } },
|
|
697
|
+
};
|
|
698
|
+
UI.prototype.setPanelVisibility.call({ studio }, {
|
|
699
|
+
outline: false,
|
|
700
|
+
details: true,
|
|
701
|
+
});
|
|
702
|
+
expect(val(studio.ephemeralAtom.pointer.hiddenPanels)).toEqual({
|
|
703
|
+
outline: true,
|
|
704
|
+
details: false,
|
|
705
|
+
});
|
|
706
|
+
expect(studio.atomP.ahistoric.visibilityState).toBe('everythingIsVisible');
|
|
707
|
+
await h.unmount();
|
|
708
|
+
});
|
|
709
|
+
test('resetCameraStudio clears retained project/state config across A→B→A remounts', async () => {
|
|
710
|
+
const stateA = { objects: { a: { position: [1, 0, 0] } } };
|
|
711
|
+
const stateB = { objects: { b: { position: [2, 0, 0] } } };
|
|
712
|
+
const stateA2 = { objects: { a2: { position: [3, 0, 0] } } };
|
|
713
|
+
const onA = jest.fn();
|
|
714
|
+
const onB = jest.fn();
|
|
715
|
+
const onA2 = jest.fn();
|
|
716
|
+
const a = hookHost({
|
|
717
|
+
project: 'SceneA',
|
|
718
|
+
storage: false,
|
|
719
|
+
state: { initialState: stateA, onStateChange: onA },
|
|
720
|
+
});
|
|
721
|
+
await a.mount();
|
|
722
|
+
const projectA = a.result.current?.sceneProps.project;
|
|
723
|
+
expect(projectA).toBeDefined();
|
|
724
|
+
await a.unmount();
|
|
725
|
+
await bootstrap.resetCameraStudio();
|
|
726
|
+
const b = hookHost({
|
|
727
|
+
project: 'SceneB',
|
|
728
|
+
storage: false,
|
|
729
|
+
state: { initialState: stateB, onStateChange: onB },
|
|
730
|
+
});
|
|
731
|
+
await b.mount();
|
|
732
|
+
expect(b.result.current?.sceneProps.project).not.toBe(projectA);
|
|
733
|
+
const projectB = b.result.current?.sceneProps.project;
|
|
734
|
+
const stateCallbackB = onChangeSpy.mock.calls.at(-1)?.[1];
|
|
735
|
+
stateCallbackB({ scene: 'B' });
|
|
736
|
+
await b.result.current.flushState();
|
|
737
|
+
expect(onB).toHaveBeenCalledWith({ scene: 'B' });
|
|
738
|
+
expect(onA).not.toHaveBeenCalled();
|
|
739
|
+
await b.unmount();
|
|
740
|
+
await bootstrap.resetCameraStudio();
|
|
741
|
+
const a2 = hookHost({
|
|
742
|
+
project: 'SceneA',
|
|
743
|
+
storage: false,
|
|
744
|
+
state: { initialState: stateA2, onStateChange: onA2 },
|
|
745
|
+
});
|
|
746
|
+
await a2.mount();
|
|
747
|
+
expect(a2.result.current?.sceneProps.project).not.toBe(projectA);
|
|
748
|
+
expect(a2.result.current?.sceneProps.project).not.toBe(projectB);
|
|
749
|
+
const stateCallbackA2 = onChangeSpy.mock.calls.at(-1)?.[1];
|
|
750
|
+
stateCallbackA2({ scene: 'A2' });
|
|
751
|
+
await a2.result.current.flushState();
|
|
752
|
+
expect(onA2).toHaveBeenCalledWith({ scene: 'A2' });
|
|
753
|
+
expect(onB).toHaveBeenCalledTimes(1);
|
|
754
|
+
await a2.unmount();
|
|
755
|
+
expect(getProjectSpy).toHaveBeenCalledWith('SceneA', { state: stateA });
|
|
756
|
+
expect(getProjectSpy).toHaveBeenCalledWith('SceneB', { state: stateB });
|
|
757
|
+
expect(getProjectSpy).toHaveBeenCalledWith('SceneA', { state: stateA2 });
|
|
758
|
+
});
|
package/dist/config.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* CameraFlows 类型取自 ./hostFlows(定义所在);简报草样写 './App',
|
|
5
5
|
* 但 App.tsx 只默认导出组件、不转出口该类型,从定义处引入才编译得过。
|
|
6
6
|
*/
|
|
7
|
-
import type { IProject } from '@dreamerbird/core';
|
|
7
|
+
import type { IProject, StudioPanelVisibility } from '@dreamerbird/core';
|
|
8
8
|
import type { WritableLibrarySource } from './assetLibrary/source';
|
|
9
9
|
import type { CameraStudioErrorHandler } from './errors';
|
|
10
10
|
import type { CameraFlows } from './hostFlows';
|
|
@@ -60,12 +60,19 @@ export interface CameraStudioConfig {
|
|
|
60
60
|
sync?: {
|
|
61
61
|
serverUrl?: string;
|
|
62
62
|
} | false;
|
|
63
|
+
scene?: {
|
|
64
|
+
/** 是否渲染内置 Thingy 演示模型;缺省 true */
|
|
65
|
+
includeDemoModel?: boolean;
|
|
66
|
+
};
|
|
63
67
|
ui?: {
|
|
64
68
|
portalContainer?: HTMLElement;
|
|
65
69
|
zIndexBase?: number;
|
|
66
70
|
locale?: string;
|
|
67
71
|
/** 隐藏 studio 左上角带 logo 的整条 LeftStrip(应用 logo + 工作区按钮) */
|
|
68
72
|
hideLeftStrip?: boolean;
|
|
73
|
+
panels?: StudioPanelVisibility;
|
|
74
|
+
/** Scene Tree 顶部项目节点的显示名;不改变持久化 projectId */
|
|
75
|
+
projectName?: string;
|
|
69
76
|
};
|
|
70
77
|
flows?: {
|
|
71
78
|
onFlows?: (flows: CameraFlows) => void;
|
|
@@ -78,6 +85,7 @@ export type CameraSceneProps = {
|
|
|
78
85
|
project: IProject;
|
|
79
86
|
onFlows?: (flows: CameraFlows) => void;
|
|
80
87
|
onError?: CameraStudioErrorHandler;
|
|
88
|
+
includeDemoModel?: boolean;
|
|
81
89
|
};
|
|
82
90
|
export interface CameraStudioHandle {
|
|
83
91
|
ready: boolean;
|
|
@@ -88,5 +96,6 @@ export interface CameraStudioHandle {
|
|
|
88
96
|
* 同一对象);`api.ready` 在 project+studio+Scene Runtime 就位后兑现
|
|
89
97
|
*/
|
|
90
98
|
api: CameraStudioApi;
|
|
99
|
+
flushState(): Promise<void>;
|
|
91
100
|
}
|
|
92
101
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAC,QAAQ,EAAE,qBAAqB,EAAC,MAAM,mBAAmB,CAAA;AACtE,OAAO,KAAK,EAAC,qBAAqB,EAAC,MAAM,uBAAuB,CAAA;AAChE,OAAO,KAAK,EAAC,wBAAwB,EAAC,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAA;AAC5C,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,aAAa,CAAA;AAEhD;;;;GAIG;AACH,MAAM,MAAM,6BAA6B,GAAG;IAC1C,6CAA6C;IAC7C,GAAG,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,kDAAkD;AAClD,MAAM,MAAM,uBAAuB,GAAG;IACpC;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,8BAA8B;IAC9B,MAAM,CAAC,EAAE,6BAA6B,CAAA;CACvC,CAAA;AAED,MAAM,WAAW,kBAAkB;IACjC,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAA;IAC3B,kCAAkC;IAClC,KAAK,CAAC,EAAE;QACN,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;QAC1C,iDAAiD;QACjD,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,8CAA8C;IAC9C,OAAO,CAAC,EAAE,wBAAwB,CAAA;IAClC;4DACwD;IACxD,OAAO,CAAC,EAAE,qBAAqB,GAAG;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAA;IAC9D,0BAA0B;IAC1B,MAAM,CAAC,EAAE;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAC,CAAA;IAC3B,uBAAuB;IACvB,IAAI,CAAC,EAAE;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAC,GAAG,KAAK,CAAA;IACnC,KAAK,CAAC,EAAE;QACN,iCAAiC;QACjC,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAC3B,CAAA;IACD,EAAE,CAAC,EAAE;QACH,eAAe,CAAC,EAAE,WAAW,CAAA;QAC7B,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,yDAAyD;QACzD,aAAa,CAAC,EAAE,OAAO,CAAA;QACvB,MAAM,CAAC,EAAE,qBAAqB,CAAA;QAC9B,6CAA6C;QAC7C,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;IACD,KAAK,CAAC,EAAE;QAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;KAAC,CAAA;IAChD,uCAAuC;IACvC,KAAK,CAAC,EAAE,uBAAuB,CAAA;CAChC;AAED,iDAAiD;AACjD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,QAAQ,CAAA;IACjB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAA;IACtC,OAAO,CAAC,EAAE,wBAAwB,CAAA;IAClC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,OAAO,CAAA;IACd,KAAK,EAAE,KAAK,GAAG,SAAS,CAAA;IACxB,UAAU,EAAE,gBAAgB,CAAA;IAC5B;;;OAGG;IACH,GAAG,EAAE,eAAe,CAAA;IACpB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5B"}
|
package/dist/hostFlows.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export type DropPointContext = {
|
|
|
32
32
|
camera: Camera;
|
|
33
33
|
};
|
|
34
34
|
export declare function setDropPointContext(ctx: DropPointContext | null): void;
|
|
35
|
+
export declare function isDropPointInsideCanvas(clientX: number, clientY: number): boolean;
|
|
35
36
|
export declare function dropPointFromClient(clientX: number, clientY: number): Vec3 | null;
|
|
36
37
|
/**
|
|
37
38
|
* App 用既有函数注入组装 CameraFlows;纯转发,可单测。
|
package/dist/hostFlows.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hostFlows.d.ts","sourceRoot":"","sources":["../src/hostFlows.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"hostFlows.d.ts","sourceRoot":"","sources":["../src/hostFlows.ts"],"names":[],"mappings":"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"}
|
package/dist/hostFlows.js
CHANGED
|
@@ -46,6 +46,15 @@ let dropCtx = null;
|
|
|
46
46
|
export function setDropPointContext(ctx) {
|
|
47
47
|
dropCtx = ctx;
|
|
48
48
|
}
|
|
49
|
+
export function isDropPointInsideCanvas(clientX, clientY) {
|
|
50
|
+
if (!dropCtx)
|
|
51
|
+
return false;
|
|
52
|
+
const rect = dropCtx.gl.domElement.getBoundingClientRect();
|
|
53
|
+
return (clientX >= rect.left &&
|
|
54
|
+
clientX <= rect.right &&
|
|
55
|
+
clientY >= rect.top &&
|
|
56
|
+
clientY <= rect.bottom);
|
|
57
|
+
}
|
|
49
58
|
export function dropPointFromClient(clientX, clientY) {
|
|
50
59
|
if (!dropCtx)
|
|
51
60
|
return null;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export type { CameraStudioConfig, CameraStudioHandle, CameraSceneProps, CameraSt
|
|
|
6
6
|
export type { CameraFlows, Vec3 } from './hostFlows';
|
|
7
7
|
export type { PathPreset } from './pathPresets';
|
|
8
8
|
export type { CameraStudioError, CameraStudioErrorHandler, CameraStudioErrorSource, } from './errors';
|
|
9
|
-
export { initCameraStudio, disposeCameraStudio } from './bootstrap';
|
|
9
|
+
export { initCameraStudio, disposeCameraStudio, resetCameraStudio, } from './bootstrap';
|
|
10
10
|
export type { BootCtx } from './bootstrap';
|
|
11
11
|
export type { CameraStudioApi } from './agent/api';
|
|
12
12
|
export { AgentApiError, AGENT_API_ERROR_CODES } from './agent/errors';
|
|
@@ -16,6 +16,10 @@ export type { SceneObjectId, SceneObjectKind, JobSnapshot, JobState, AgentErrorD
|
|
|
16
16
|
export type { SceneApi, ObjectsApi, SceneSnapshot, SceneObjectSummary, } from './agent/commands/scene';
|
|
17
17
|
export type { SelectionApi } from './agent/commands/selection';
|
|
18
18
|
export type { ModelsApi } from './agent/commands/models';
|
|
19
|
+
export type { PrimitivesApi } from './agent/commands/primitives';
|
|
20
|
+
export type { PrimitiveKind } from './primitives';
|
|
21
|
+
export type { MaterialsApi } from './agent/commands/materials';
|
|
22
|
+
export type { MaterialSlot, MaterialValues } from './materials/types';
|
|
19
23
|
export type { AssetsApi } from './agent/commands/assets';
|
|
20
24
|
export type { PosesApi, PosesSessionApi } from './agent/commands/poses';
|
|
21
25
|
export type { AnimationsApi, AnimationStatusDto, } from './agent/commands/animations';
|
|
@@ -35,8 +39,13 @@ export type { GizmoMode } from './PlacementManager';
|
|
|
35
39
|
export type { PoseBones } from './poseMode/poseOverride';
|
|
36
40
|
export type { GestureSide } from './gestureProps';
|
|
37
41
|
export type { PoseFrameMode } from './poseMode/poseFrame';
|
|
42
|
+
export { BUILTIN_POSE_RIG, BUILTIN_POSE_SOURCES, listBuiltinPoses, getBuiltinPose, applyPose, capturePose, captureBindPose, } from './poses';
|
|
43
|
+
export type { BuiltinPoseSourceId } from './poses';
|
|
38
44
|
export type { LibrarySource, LibrarySourceCapabilities, WritableLibrarySource, LibraryErrorCode, } from './assetLibrary/source';
|
|
39
45
|
export { LibraryError, isWritableSource } from './assetLibrary/source';
|
|
40
46
|
export type { RigId, RigAlias, EntryKind, ModelEntry, PoseEntry, AnimationEntry, LibraryEntry, } from './assetLibrary/types';
|
|
41
47
|
export { IndexedDBBackend } from './assetLibrary/indexedDBBackend';
|
|
48
|
+
export { importModelFiles } from './assetLibrary/importModelFiles';
|
|
49
|
+
export { registerModelPicker, unregisterModelPicker } from './pickerRegistry';
|
|
50
|
+
export type { ModelPickerProps } from './pickerRegistry';
|
|
42
51
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,CAAA;AACf,OAAO,EAAC,WAAW,EAAC,MAAM,eAAe,CAAA;AACzC,OAAO,EAAC,qBAAqB,EAAC,MAAM,WAAW,CAAA;AAC/C,OAAO,EAAC,eAAe,EAAC,MAAM,mBAAmB,CAAA;AACjD,YAAY,EACV,kBAAkB,EAClB,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EAEvB,6BAA6B,GAC9B,MAAM,UAAU,CAAA;AAEjB,YAAY,EAAC,WAAW,EAAE,IAAI,EAAC,MAAM,aAAa,CAAA;AAClD,YAAY,EAAC,UAAU,EAAC,MAAM,eAAe,CAAA;AAC7C,YAAY,EACV,iBAAiB,EACjB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,UAAU,CAAA;AAEjB,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,12 @@ export { CameraScene } from './CameraScene';
|
|
|
5
5
|
export { CAMERA_STUDIO_VERSION } from './version';
|
|
6
6
|
export { useCameraStudio } from './useCameraStudio';
|
|
7
7
|
// 测试与高级宿主可用:绕过 hook 直接管 init/dispose 生命周期
|
|
8
|
-
export { initCameraStudio, disposeCameraStudio } from './bootstrap';
|
|
8
|
+
export { initCameraStudio, disposeCameraStudio, resetCameraStudio, } from './bootstrap';
|
|
9
9
|
export { AgentApiError, AGENT_API_ERROR_CODES } from './agent/errors';
|
|
10
|
+
// 内置静态姿势库:引用本包的项目可直接取姿势数据并应用到自己的骨架,
|
|
11
|
+
// 不必先启动编辑器。轻量消费可走 `@dreamerbird/camera-studio/poses` 子路径
|
|
12
|
+
export { BUILTIN_POSE_RIG, BUILTIN_POSE_SOURCES, listBuiltinPoses, getBuiltinPose, applyPose, capturePose, captureBindPose, } from './poses';
|
|
10
13
|
export { LibraryError, isWritableSource } from './assetLibrary/source';
|
|
11
14
|
export { IndexedDBBackend } from './assetLibrary/indexedDBBackend';
|
|
15
|
+
export { importModelFiles } from './assetLibrary/importModelFiles';
|
|
16
|
+
export { registerModelPicker, unregisterModelPicker } from './pickerRegistry';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Texture, type Object3D } from 'three';
|
|
2
|
+
import type { MaterialSlot, MaterialValues } from './types';
|
|
3
|
+
type MaterialOverrides = Record<string, Partial<MaterialValues>>;
|
|
4
|
+
export declare function cloneModelMaterials(root: Object3D): void;
|
|
5
|
+
export declare function collectMaterialSlots(root: Object3D): MaterialSlot[];
|
|
6
|
+
export declare function applyMaterialScalars(root: Object3D, slots: MaterialSlot[], overrides: MaterialOverrides): void;
|
|
7
|
+
export declare function createMaterialOverridesConfig(slots: MaterialSlot[]): any;
|
|
8
|
+
type TextureControllerOptions = {
|
|
9
|
+
getBlobUrl(blobId: string): Promise<string>;
|
|
10
|
+
loadTexture(url: string): Promise<Texture>;
|
|
11
|
+
onError?(error: unknown, slotId: string, property: string): void;
|
|
12
|
+
invalidate(): void;
|
|
13
|
+
};
|
|
14
|
+
export declare function createMaterialTextureController(options: TextureControllerOptions): {
|
|
15
|
+
update(root: Object3D, slots: MaterialSlot[], overrides: MaterialOverrides): Promise<void>;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
};
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=modelMaterials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"modelMaterials.d.ts","sourceRoot":"","sources":["../../src/materials/modelMaterials.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,OAAO,EAEZ,KAAK,QAAQ,EACd,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAC,YAAY,EAAE,cAAc,EAAC,MAAM,SAAS,CAAA;AAWzD,KAAK,iBAAiB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC,CAAA;AAyDhE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAYxD;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,QAAQ,GAAG,YAAY,EAAE,CAuBnE;AAqBD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,YAAY,EAAE,EACrB,SAAS,EAAE,iBAAiB,GAC3B,IAAI,CA+BN;AAiBD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,YAAY,EAAE,OAkBlE;AAED,KAAK,wBAAwB,GAAG;IAC9B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAC3C,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;IAC1C,OAAO,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IAChE,UAAU,IAAI,IAAI,CAAA;CACnB,CAAA;AAED,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,wBAAwB;iBAyDvB,QAAQ,SACP,YAAY,EAAE,aACV,iBAAiB,GAC3B,OAAO,CAAC,IAAI,CAAC;eA4BL,IAAI;EAWlB"}
|