soonspacejs 2.16.7 → 3.0.0-alpha.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/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "soonspacejs",
3
- "version": "2.16.7",
3
+ "version": "3.0.0-alpha.0",
4
4
  "homepage": "https://www.xwbuilders.com/soonspacejs/",
5
- "description": "soonspacejs 2.x",
5
+ "description": "SoonSpace.js 3.0 alpha",
6
6
  "module": "./dist/index.esm.js",
7
7
  "main": "./dist/index.esm.js",
8
8
  "types": "./types/index.d.ts",
@@ -25,11 +25,15 @@
25
25
  ],
26
26
  "author": "xunwei",
27
27
  "license": "UNLICENSED",
28
+ "dependencies": {
29
+ "@robotlegsjs/signals": "^2.1.0",
30
+ "localforage": "1.10.0"
31
+ },
28
32
  "peerDependencies": {
29
- "@types/three": ">=0.185.4",
33
+ "@types/three": ">=0.186.0",
30
34
  "camera-controls": ">=3.1.2",
31
- "postprocessing": ">=6.39.4",
32
- "three": ">=0.185.1",
35
+ "postprocessing": ">=6.39.5",
36
+ "three": ">=0.186.1",
33
37
  "three-mesh-bvh": ">=0.9.9"
34
38
  },
35
39
  "gitHead": "4a87dd85050651088e11c3da777c49fab3db7e5d"
@@ -10,5 +10,6 @@ declare class Controls extends CameraControls {
10
10
  draggingSmoothTime: number;
11
11
  constructor(viewport: Viewport);
12
12
  setOptions(options: ControlsOptions): void;
13
+ protected _createOnRestPromise(resolveImmediately: boolean): Promise<void>;
13
14
  }
14
15
  export default Controls;
@@ -0,0 +1,38 @@
1
+ import { BatchedMesh, Matrix4, BufferGeometry } from 'three';
2
+ /** Entity-owned batches reuse only the commands left by the immediately preceding pass. */
3
+ export declare class CachedBatchedMesh extends BatchedMesh {
4
+ private commandRevision;
5
+ private cachedRevision;
6
+ private cachedCamera?;
7
+ private cachedGeometry?;
8
+ private cachedPosition?;
9
+ private cachedPositionVersion;
10
+ private cachedIndex?;
11
+ private cachedIndexVersion;
12
+ private cachedIndexArray?;
13
+ private cachedCoordinateSystem?;
14
+ private cachedReversedDepth?;
15
+ private cachedSort?;
16
+ private cachedCull?;
17
+ private cachedTransparent?;
18
+ private cachedWireframe?;
19
+ private readonly cachedWorld;
20
+ private readonly cachedCameraWorld;
21
+ private readonly cachedView;
22
+ private readonly cachedProjection;
23
+ invalidateDrawCommands(): void;
24
+ onBeforeRender(...args: Parameters<BatchedMesh['onBeforeRender']>): void;
25
+ private rebuildDrawCommands;
26
+ setMatrixAt(instanceId: number, matrix: Matrix4): this;
27
+ setVisibleAt(instanceId: number, visible: boolean): this;
28
+ setGeometryIdAt(instanceId: number, geometryId: number): this;
29
+ addInstance(geometryId: number): number;
30
+ deleteInstance(instanceId: number): this;
31
+ addGeometry(geometry: BufferGeometry, reservedVertices?: number, reservedIndices?: number): number;
32
+ setGeometryAt(geometryId: number, geometry: BufferGeometry): number;
33
+ deleteGeometry(geometryId: number): this;
34
+ optimize(): this;
35
+ setGeometrySize(maxVertices: number, maxIndices: number): void;
36
+ setInstanceCount(maxInstances: number): void;
37
+ copy(source: this): this;
38
+ }
@@ -0,0 +1,41 @@
1
+ import { Matrix4, Object3D, Quaternion, Vector3 } from 'three';
2
+ import { ModelLease, ModelLoadOptions } from './ModelResources';
3
+ import { EntityCollection } from './EntityCollection';
4
+ export type EntityChange = 'transform' | 'visibility';
5
+ export interface EntityOptions {
6
+ id: string;
7
+ model?: ModelLease;
8
+ parent?: Entity | null;
9
+ owner?: string;
10
+ name?: string;
11
+ position?: readonly [number, number, number];
12
+ quaternion?: readonly [number, number, number, number];
13
+ scale?: readonly [number, number, number];
14
+ visible?: boolean;
15
+ /** Own model and native attachments only; descendants keep their hierarchical visibility. */
16
+ contentVisible?: boolean;
17
+ }
18
+ /** Logical identity. Editable fields are drafts; notifications capture snapshots. */
19
+ export declare class Entity {
20
+ private collection;
21
+ readonly position: Vector3;
22
+ readonly quaternion: Quaternion;
23
+ readonly scale: Vector3;
24
+ visible: boolean;
25
+ /** Draft value committed together with visible by notifyChange( 'visibility' ). */
26
+ contentVisible: boolean;
27
+ name: string;
28
+ readonly id: string;
29
+ readonly owner: string;
30
+ constructor(collection: EntityCollection, options: EntityOptions);
31
+ get parent(): Entity | null;
32
+ get children(): readonly Entity[];
33
+ get isShowing(): boolean;
34
+ get loadState(): "error" | "idle" | "loading" | "ready";
35
+ get loadError(): unknown;
36
+ replaceModel(source: ModelLease | string | null, options?: ModelLoadOptions): Promise<void>;
37
+ notifyChange(type: EntityChange): void;
38
+ getWorldMatrix(): Matrix4;
39
+ attachObject3D(object: Object3D): void;
40
+ detachObject3D(object: Object3D): void;
41
+ }
@@ -0,0 +1,61 @@
1
+ import { Box3, Matrix4, Object3D, Raycaster, Scene } from 'three';
2
+ import { Entity, EntityChange, EntityOptions } from './Entity';
3
+ import { EntityHit } from './EntityRenderer';
4
+ import { ModelResources, ModelLease, ModelLoadOptions } from './ModelResources';
5
+ export declare class EntityCollection {
6
+ private scene;
7
+ private requestRender;
8
+ private models;
9
+ private nodes;
10
+ private ids;
11
+ private pending;
12
+ private structureDirty;
13
+ private attachmentOwners;
14
+ private renderer;
15
+ private disposed;
16
+ private batchDepth;
17
+ private updatedEntities;
18
+ private pendingModels;
19
+ private selected;
20
+ private selectionDirty;
21
+ constructor(scene: Scene, requestRender: () => void, models: ModelResources);
22
+ get roots(): readonly Entity[];
23
+ getById(id: string): Entity | undefined;
24
+ parentOf(entity: Entity): Entity | null;
25
+ childrenOf(entity: Entity): readonly Entity[];
26
+ showing(entity: Entity): boolean;
27
+ worldOf(entity: Entity): Matrix4;
28
+ private node;
29
+ add(options: EntityOptions): Entity;
30
+ notify(entity: Entity, type: EntityChange): void;
31
+ private schedule;
32
+ getLoadState(entity: Entity): "error" | "idle" | "loading" | "ready";
33
+ getLoadError(entity: Entity): unknown;
34
+ /** Resolve a candidate without releasing or modifying the currently drawn model. */
35
+ replaceModel(entity: Entity, source: ModelLease | string | null, options?: ModelLoadOptions): Promise<void>;
36
+ setParent(entity: Entity, parent: Entity | null): void;
37
+ remove(entity: Entity): void;
38
+ private deferredReleases;
39
+ batch(callback: () => void): void;
40
+ flushUpdates(): void;
41
+ attach(entity: Entity, object: Object3D): void;
42
+ detach(entity: Entity, object: Object3D): void;
43
+ pick(raycaster: Raycaster): EntityHit[];
44
+ /** Fresh world bounds from committed transforms, including hidden content. */
45
+ getBounds(entity: Entity, options?: {
46
+ includeDescendants?: boolean;
47
+ }): Box3;
48
+ getStats(): {
49
+ updatedEntities: number;
50
+ entities: number;
51
+ instancedBatches: number;
52
+ batchedBatches: number;
53
+ independentObjects: number;
54
+ rebuilds: number;
55
+ };
56
+ setSelection(entities: readonly Entity[]): void;
57
+ getSelection(): readonly Entity[];
58
+ setInstancingEnabled(enabled: boolean): void;
59
+ setBatchedEnabled(enabled: boolean): void;
60
+ dispose(): void;
61
+ }
@@ -0,0 +1,56 @@
1
+ import { Box3, Group, Matrix4, Raycaster, Intersection } from 'three';
2
+ import { Entity } from './Entity';
3
+ import { RegisteredPart } from './ModelResources';
4
+ export interface EntityRenderInput {
5
+ entity: Entity;
6
+ parts: readonly RegisteredPart[];
7
+ world: Matrix4;
8
+ visible: boolean;
9
+ contentVisible: boolean;
10
+ }
11
+ export interface EntityHit extends Intersection {
12
+ entity: Entity;
13
+ partIndex?: number;
14
+ attachment?: boolean;
15
+ }
16
+ export declare class EntityRenderer {
17
+ readonly root: Group<import('three').Object3DEventMap>;
18
+ private entries;
19
+ private batches;
20
+ private mappings;
21
+ private groups;
22
+ private groupBatches;
23
+ private dirtyGroups;
24
+ private policyDirty;
25
+ private bounds;
26
+ private enabled;
27
+ private batchedEnabled;
28
+ private rebuilds;
29
+ private selection;
30
+ private selectionDirty;
31
+ private highlights;
32
+ private highlightMaterial;
33
+ constructor();
34
+ add(input: EntityRenderInput): void;
35
+ remove(entity: Entity): void;
36
+ setEnabled(enabled: boolean): void;
37
+ setBatchedEnabled(enabled: boolean): void;
38
+ setSelection(selection: ReadonlySet<Entity>): void;
39
+ private removeHighlight;
40
+ private updateHighlight;
41
+ update(changed: readonly Entity[]): void;
42
+ private assignGroup;
43
+ private rebuildGroup;
44
+ private createBatch;
45
+ private updateBatch;
46
+ pick(raycaster: Raycaster): EntityHit[];
47
+ getBounds(entity: Entity): Box3;
48
+ getStats(): {
49
+ instancedBatches: number;
50
+ batchedBatches: number;
51
+ independentObjects: number;
52
+ rebuilds: number;
53
+ };
54
+ private clearBatches;
55
+ dispose(): void;
56
+ }
@@ -0,0 +1,83 @@
1
+ import { BufferGeometry, Material, Matrix4, Texture } from 'three';
2
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
3
+ export interface ModelPart {
4
+ geometry: BufferGeometry;
5
+ material: Material | MaterialLease;
6
+ matrix: Matrix4;
7
+ visible?: boolean;
8
+ name?: string;
9
+ castShadow?: boolean;
10
+ receiveShadow?: boolean;
11
+ renderOrder?: number;
12
+ layersMask?: number;
13
+ frustumCulled?: boolean;
14
+ /** Explicitly accept batch-local transparent sorting; cross-batch order is not preserved. */
15
+ transparentBatch?: 'sorted';
16
+ /** Linear RGB multiplier, applied without modifying the shared material. */
17
+ color?: readonly [number, number, number];
18
+ }
19
+ export interface RegisteredPart extends Omit<ModelPart, 'material'> {
20
+ material: Material;
21
+ }
22
+ interface ResourceRecord<T> {
23
+ value: T;
24
+ refs: number;
25
+ dead: boolean;
26
+ gpu: Set<BufferGeometry | Material | Texture>;
27
+ dependencies: Set<ResourceRecord<Material>>;
28
+ }
29
+ export declare class ResourceLease<T> {
30
+ readonly registry: ModelResources;
31
+ private record;
32
+ private released;
33
+ constructor(registry: ModelResources, record: ResourceRecord<T>);
34
+ /** Internal ownership boundary; callers cannot retain a released lease. */
35
+ retain(): ResourceLease<T>;
36
+ get value(): T;
37
+ release(): void;
38
+ assertActive(): void;
39
+ }
40
+ export type ModelLease = ResourceLease<readonly RegisteredPart[]>;
41
+ export type MaterialLease = ResourceLease<Material>;
42
+ export interface ModelLoadOptions {
43
+ signal?: AbortSignal;
44
+ }
45
+ export type UnsupportedModelReason = 'animation-clips' | 'material-array' | 'skinning' | 'morph-targets' | 'instanced-mesh' | 'batched-mesh' | 'line-or-points';
46
+ /** A decoded resource that cannot be faithfully represented by static model parts. */
47
+ export declare class ModelResourceUnsupportedError extends Error {
48
+ readonly url: string;
49
+ readonly code = "MODEL_RESOURCE_UNSUPPORTED";
50
+ readonly reasons: readonly UnsupportedModelReason[];
51
+ constructor(url: string, reasons: readonly UnsupportedModelReason[]);
52
+ }
53
+ export declare function entityAbortError(): DOMException;
54
+ /** Owns transferred GPU graphs. Does not add loaded source trees to the Scene. */
55
+ export declare class ModelResources {
56
+ isDisposed: boolean;
57
+ private records;
58
+ private gpuRefs;
59
+ private transferred;
60
+ private pending;
61
+ private urls;
62
+ private gltfLoader;
63
+ /** Borrow a host-configured loader; its decoder workers remain host-owned. */
64
+ setGLTFLoader(loader: GLTFLoader): void;
65
+ readonly materials: {
66
+ register: (material: Material, options: {
67
+ ownership: "transfer";
68
+ }) => MaterialLease;
69
+ };
70
+ register(input: {
71
+ parts: readonly ModelPart[];
72
+ }, options: {
73
+ ownership: 'transfer';
74
+ }): ModelLease;
75
+ load(url: string, options?: ModelLoadOptions): Promise<ModelLease>;
76
+ private resolveLoad;
77
+ private create;
78
+ lease<T>(record: ResourceRecord<T>): ResourceLease<T>;
79
+ release(record: ResourceRecord<unknown>): void;
80
+ private assertLive;
81
+ dispose(): void;
82
+ }
83
+ export {};
@@ -0,0 +1,6 @@
1
+ export { Entity, } from './Entity';
2
+ export type { EntityOptions, EntityChange, } from './Entity';
3
+ export { EntityCollection, } from './EntityCollection';
4
+ export { ModelResources, ResourceLease, ModelResourceUnsupportedError, } from './ModelResources';
5
+ export type { ModelLease, MaterialLease, ModelPart, ModelLoadOptions, UnsupportedModelReason, } from './ModelResources';
6
+ export type { EntityHit, } from './EntityRenderer';
@@ -0,0 +1,3 @@
1
+ import { Intersection, Plane } from 'three';
2
+ /** Test world-space hit points using the submitted material's clipping policy. */
3
+ export declare function isEntityHitUnclipped(hit: Intersection, worldPlanes?: readonly Plane[]): boolean;
@@ -0,0 +1,12 @@
1
+ import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
2
+ interface RequestScope {
3
+ rootURL: string;
4
+ headers: HeadersInit;
5
+ signal?: AbortSignal;
6
+ }
7
+ /** Each standard GLTFLoader parse constructs its parser synchronously, before any await. */
8
+ export declare function parseScopedGLTF(loader: GLTFLoader, data: ArrayBuffer, path: string, scope: RequestScope): Promise<{
9
+ gltf: GLTF;
10
+ dependencyError?: unknown;
11
+ }>;
12
+ export {};
@@ -7,7 +7,7 @@ declare function IVector3ToEuler(val: IVector3 | Euler): Euler;
7
7
  * @param object
8
8
  * @returns
9
9
  */
10
- declare function getBoundingBox(object: Object3D, precise?: boolean, cachedBounds?: Box3 | null): Box3;
10
+ declare function getBoundingBox(object: Object3D, precise?: boolean): Box3;
11
11
  declare function rotationAxisFix(axis: AxisType, source: Euler, target: Euler): Euler;
12
12
  declare function rotationAFix(source: Euler, target: Euler): Euler;
13
13
  declare function deg2Euler(deg: number): number;
@@ -25,7 +25,9 @@ declare class Scener {
25
25
  constructor(signals: SignalsState, viewportState: ViewportState);
26
26
  addObject(object: Object3D, parent?: Object3D | null): void;
27
27
  attachObject(object: Object3D, parent?: Object3D | null): void;
28
- removeObject(object: Object3D): void;
28
+ removeObject(object: Object3D, options?: {
29
+ dispose?: boolean;
30
+ }): void;
29
31
  openSceneFog(options?: FogOptions): void;
30
32
  closeSceneFog(): void;
31
33
  edgeShow(object: Object3D | Object3D[], options?: EdgeSelectOptions): Promise<void>;
@@ -16,7 +16,7 @@ import { default as EventHandler } from './EventHandler';
16
16
  import { default as Info } from './Info';
17
17
  import { ViewHelper } from './ViewHelper';
18
18
  import { ObjectsCache } from '../Cache';
19
- import { default as AutoInstancingManager, AutoInstancingOptions, AutoInstancingStats } from './AutoInstancingManager';
19
+ import { EntityCollection, ModelResources } from '../Entity';
20
20
  export declare const innerRenderState: {
21
21
  needsUpdate: boolean;
22
22
  };
@@ -36,7 +36,8 @@ declare class Viewport {
36
36
  renderer: WebGLRenderer;
37
37
  rendererCSS2D: CSS2DRenderer;
38
38
  rendererCSS3D: CSS3DRenderer;
39
- autoInstancingManager: AutoInstancingManager;
39
+ readonly models: ModelResources;
40
+ readonly entities: EntityCollection;
40
41
  pmremGenerator: PMREMGenerator;
41
42
  info: Info;
42
43
  stats: Stats;
@@ -59,14 +60,11 @@ declare class Viewport {
59
60
  */
60
61
  postRender: Map<string | number, () => void>;
61
62
  private _loop;
62
- private outlineSelection;
63
63
  private pendingRenderResolvers;
64
64
  resizeObserver: ResizeObserver;
65
65
  constructor(options: ViewportOptions, signals: SignalsState, cache: ObjectsCache);
66
66
  _initInfo(): void;
67
67
  _initStats(): void;
68
- setAutoInstancing(enabled: boolean, root?: Object3D, options?: AutoInstancingOptions): void;
69
- getAutoInstancingStats(root?: Object3D): AutoInstancingStats | AutoInstancingStats[] | null;
70
68
  /**
71
69
  ***************************** post-processing ***************************
72
70
  */
@@ -116,7 +114,6 @@ declare class Viewport {
116
114
  * effect passes
117
115
  */
118
116
  _passesObserver(): void;
119
- private _syncAutoInstancingOutlineSelection;
120
117
  /**
121
118
  * 每帧都会被执行
122
119
  * @param time