u-space 0.0.23 → 0.0.26
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/index.cjs +3 -3
- package/dist/index.js +504 -489
- package/dist/plugins/u-manager/index.cjs +56 -56
- package/dist/plugins/u-manager/index.js +9664 -9091
- package/dist/plugins/u-manager/semantics/SemanticLoader.d.ts +2 -2
- package/dist/plugins/u-manager/semantics/SemanticParser.d.ts +3 -3
- package/dist/plugins/u-manager/semantics/index.d.ts +2 -0
- package/dist/plugins/u-manager/semantics/objects/BuildingGroup.d.ts +21 -4
- package/dist/plugins/u-manager/semantics/objects/FacilityInstancedLayer.d.ts +31 -0
- package/dist/plugins/u-manager/semantics/objects/FloorMesh.d.ts +18 -7
- package/dist/plugins/u-manager/semantics/objects/SemanticSceneGroup.d.ts +31 -0
- package/dist/plugins/u-manager/semantics/types.d.ts +2 -0
- package/docs/api-plugin-u-manager.md +105 -19
- package/docs/changelog.md +39 -0
- package/docs/examples-guide.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/mcp.md +1 -1
- package/package.json +2 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Loader } from 'three/webgpu';
|
|
2
2
|
import type { Viewer } from 'u-space';
|
|
3
|
-
import {
|
|
3
|
+
import { SemanticSceneGroup } from './objects/SemanticSceneGroup';
|
|
4
4
|
export declare class SemanticLoader extends Loader {
|
|
5
5
|
#private;
|
|
6
6
|
viewer: Viewer;
|
|
@@ -8,7 +8,7 @@ export declare class SemanticLoader extends Loader {
|
|
|
8
8
|
cachedIds: Set<string>;
|
|
9
9
|
constructor(viewer: Viewer);
|
|
10
10
|
setKey(key: string): this;
|
|
11
|
-
loadAsync(): Promise<
|
|
11
|
+
loadAsync(): Promise<SemanticSceneGroup>;
|
|
12
12
|
clearCache(): void;
|
|
13
13
|
dispose(): void;
|
|
14
14
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type LoadingManager, type Object3D } from 'three/webgpu';
|
|
2
|
-
import {
|
|
2
|
+
import { SemanticSceneGroup } from './objects/SemanticSceneGroup';
|
|
3
3
|
import type { SemanticObject } from './semantic.types';
|
|
4
4
|
import type { ITreeData } from '../types';
|
|
5
5
|
export interface SemanticParserOptions {
|
|
@@ -10,6 +10,6 @@ export interface SemanticParserOptions {
|
|
|
10
10
|
}
|
|
11
11
|
export declare class SemanticParser {
|
|
12
12
|
#private;
|
|
13
|
-
parse(semanticData: SemanticObject):
|
|
14
|
-
parseAsync(semanticData: SemanticObject, options?: SemanticParserOptions): Promise<
|
|
13
|
+
parse(semanticData: SemanticObject): SemanticSceneGroup;
|
|
14
|
+
parseAsync(semanticData: SemanticObject, options?: SemanticParserOptions): Promise<SemanticSceneGroup>;
|
|
15
15
|
}
|
|
@@ -5,5 +5,7 @@ export * from './objects/VerticalShaftMesh';
|
|
|
5
5
|
export * from './objects/ElevatorMesh';
|
|
6
6
|
export * from './objects/VentMesh';
|
|
7
7
|
export * from './objects/BuildingGroup';
|
|
8
|
+
export * from './objects/SemanticSceneGroup';
|
|
9
|
+
export * from './objects/FacilityInstancedLayer';
|
|
8
10
|
export * from './SemanticParser';
|
|
9
11
|
export * from './SemanticLoader';
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import type { ColorRepresentation, Object3D } from 'three/webgpu';
|
|
1
2
|
import { BaseGroup } from 'u-space';
|
|
2
3
|
import type { ElevatorMesh } from './ElevatorMesh';
|
|
3
|
-
import type { FloorMesh } from './FloorMesh';
|
|
4
|
-
import type { SemanticKind } from '../types';
|
|
4
|
+
import type { FloorMesh, FloorSemanticKind } from './FloorMesh';
|
|
5
5
|
import type { VentMesh } from './VentMesh';
|
|
6
6
|
export type BuildingFloorReference = FloorMesh | number;
|
|
7
|
+
export type BuildingFacilityReference = Object3D | string;
|
|
7
8
|
export declare class BuildingGroup extends BaseGroup {
|
|
9
|
+
#private;
|
|
8
10
|
isBuildingGroup: boolean;
|
|
9
11
|
type: string;
|
|
10
12
|
floorMeshes: FloorMesh[];
|
|
@@ -12,19 +14,34 @@ export declare class BuildingGroup extends BaseGroup {
|
|
|
12
14
|
ventMeshes: VentMesh[];
|
|
13
15
|
constructor();
|
|
14
16
|
addFloor(mesh: FloorMesh): this;
|
|
17
|
+
hasFloor(mesh: FloorMesh): boolean;
|
|
15
18
|
getFloorAt(index: number): FloorMesh;
|
|
19
|
+
getFloorById(id: string): FloorMesh | undefined;
|
|
16
20
|
removeFloor(mesh: FloorMesh): this;
|
|
17
21
|
addElevator(mesh: ElevatorMesh): this;
|
|
18
22
|
getElevatorAt(index: number): ElevatorMesh;
|
|
23
|
+
getElevatorById(id: string): ElevatorMesh | undefined;
|
|
19
24
|
removeElevator(mesh: ElevatorMesh): this;
|
|
20
25
|
addVent(mesh: VentMesh): this;
|
|
21
26
|
getVentAt(index: number): VentMesh;
|
|
27
|
+
getVentById(id: string): VentMesh | undefined;
|
|
22
28
|
removeVent(mesh: VentMesh): this;
|
|
23
29
|
isolateFloor(floor: BuildingFloorReference | BuildingFloorReference[]): this;
|
|
24
30
|
isolateFloors(floors: BuildingFloorReference[]): this;
|
|
25
31
|
showAllFloors(): this;
|
|
26
32
|
showAllFacilities(): this;
|
|
27
33
|
hideAllFacilities(): this;
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
getFacilityById(id: string): Object3D<import("three").Object3DEventMap> | undefined;
|
|
35
|
+
setFacilityVisible(facility: BuildingFacilityReference, visible: boolean): this;
|
|
36
|
+
showFacility(facility: BuildingFacilityReference): this;
|
|
37
|
+
hideFacility(facility: BuildingFacilityReference): this;
|
|
38
|
+
setFacilityColor(facility: BuildingFacilityReference, color: ColorRepresentation): this;
|
|
39
|
+
resetFacilityColor(facility: BuildingFacilityReference): this;
|
|
40
|
+
setFacilityOpacity(facility: BuildingFacilityReference, opacity: number): this;
|
|
41
|
+
syncFacilityIndexes(): this;
|
|
42
|
+
get facilityIndexVersion(): number;
|
|
43
|
+
getFacilityIndexIds(): MapIterator<string>;
|
|
44
|
+
getFacilityIndexObjects(): MapIterator<Object3D<import("three").Object3DEventMap>>;
|
|
45
|
+
planishFloors(kind?: FloorSemanticKind): this;
|
|
46
|
+
unplanishFloors(kind?: FloorSemanticKind): this;
|
|
30
47
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Box3, Color, Group, Object3D, type ColorRepresentation } from 'three/webgpu';
|
|
2
|
+
import { BaseGroup } from 'u-space';
|
|
3
|
+
export declare class FacilityInstanceObject extends Group {
|
|
4
|
+
#private;
|
|
5
|
+
isFacilityInstanceObject: boolean;
|
|
6
|
+
type: string;
|
|
7
|
+
setLocalBounds(bounds: Box3): this;
|
|
8
|
+
getFacilityBoundingBox(target?: Box3, world?: boolean): Box3;
|
|
9
|
+
setFacilityVisible(visible: boolean): this;
|
|
10
|
+
setFacilityColor(color: ColorRepresentation): this;
|
|
11
|
+
resetFacilityColor(): this;
|
|
12
|
+
setFacilityOpacity(opacity: number): this;
|
|
13
|
+
getFacilityColor(target?: Color): Color;
|
|
14
|
+
hasFacilityColor(): boolean;
|
|
15
|
+
getFacilityOpacity(): number;
|
|
16
|
+
}
|
|
17
|
+
export declare class FacilityInstancedLayer extends BaseGroup {
|
|
18
|
+
#private;
|
|
19
|
+
isFacilityInstancedLayer: boolean;
|
|
20
|
+
type: string;
|
|
21
|
+
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
22
|
+
cameraDistanceCulling: boolean;
|
|
23
|
+
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
24
|
+
cameraCullDistance: number;
|
|
25
|
+
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
26
|
+
cameraCullOverviewFactor: number;
|
|
27
|
+
/** @deprecated No effect; facility culling uses per-instance bounding-box frustum tests only. */
|
|
28
|
+
cameraCullPlanViewThreshold: number;
|
|
29
|
+
constructor();
|
|
30
|
+
addFacilityBatch(url: string, template: Object3D, facilities: FacilityInstanceObject[]): boolean;
|
|
31
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { Box3, BufferGeometry, Matrix4, MeshStandardNodeMaterial, Sphere, Vector3, Vector4, type Intersection, type Object3D, type Raycaster } from 'three/webgpu';
|
|
1
|
+
import { Box3, BufferGeometry, Matrix4, MeshStandardNodeMaterial, Sphere, Vector3, Vector4, type ColorRepresentation, type Intersection, type Object3D, type Raycaster } from 'three/webgpu';
|
|
2
2
|
import { BaseMesh, type InteractionEvent, type InteractionEventMap } from 'u-space';
|
|
3
3
|
import type { SemanticColor, SemanticGeometryEntry, SemanticKind } from '../types';
|
|
4
4
|
type FacilityReference = Object3D | string;
|
|
5
5
|
type FacilitySemanticKind = 'Facilities';
|
|
6
|
+
type FloorMeshMaterial = MeshStandardNodeMaterial | MeshStandardNodeMaterial[];
|
|
6
7
|
export type FloorSemanticKind = SemanticKind | FacilitySemanticKind;
|
|
7
8
|
export interface FloorGeometrySemanticEntity {
|
|
8
9
|
type: 'geometry';
|
|
@@ -26,25 +27,28 @@ type FloorMeshEventPayload<T> = T extends {
|
|
|
26
27
|
} ? {
|
|
27
28
|
event: FloorMeshInteractionEvent;
|
|
28
29
|
} : T;
|
|
29
|
-
export interface FloorMeshIntersection extends Intersection<
|
|
30
|
+
export interface FloorMeshIntersection extends Intersection<Object3D> {
|
|
30
31
|
semanticId: string;
|
|
31
|
-
semanticKind:
|
|
32
|
+
semanticKind: FloorSemanticKind;
|
|
32
33
|
semanticName?: string;
|
|
33
34
|
semanticIndex: number;
|
|
34
35
|
instanceId: number;
|
|
36
|
+
facility?: Object3D;
|
|
37
|
+
facilityId?: string;
|
|
35
38
|
}
|
|
36
39
|
export type FloorMeshInteractionEvent = Omit<InteractionEvent, 'target' | 'currentTarget' | 'intersect'> & {
|
|
37
|
-
readonly target:
|
|
40
|
+
readonly target: Object3D<InteractionEventMap>;
|
|
38
41
|
currentTarget: FloorMesh;
|
|
39
42
|
readonly intersect: FloorMeshIntersection | null;
|
|
40
43
|
};
|
|
41
44
|
export type FloorMeshEventMap = {
|
|
42
45
|
[K in keyof InteractionEventMap]: FloorMeshEventPayload<InteractionEventMap[K]>;
|
|
43
46
|
};
|
|
44
|
-
export declare class FloorMesh extends BaseMesh<BufferGeometry,
|
|
47
|
+
export declare class FloorMesh extends BaseMesh<BufferGeometry, FloorMeshMaterial, FloorMeshEventMap> {
|
|
45
48
|
#private;
|
|
46
49
|
isFloorMergedSemanticMesh: boolean;
|
|
47
50
|
type: string;
|
|
51
|
+
pivot: Vector3;
|
|
48
52
|
boundingBox: Box3 | null;
|
|
49
53
|
boundingSphere: Sphere | null;
|
|
50
54
|
wallsInstances: Map<string, number>;
|
|
@@ -57,9 +61,10 @@ export declare class FloorMesh extends BaseMesh<BufferGeometry, MeshStandardNode
|
|
|
57
61
|
semanticEntities: Map<string, FloorSemanticEntity>;
|
|
58
62
|
facilityObjectsById: Map<string, Object3D>;
|
|
59
63
|
facilityObjects: Object3D[];
|
|
64
|
+
facilityIndexVersion: number;
|
|
60
65
|
constructor(entries: SemanticGeometryEntry[]);
|
|
61
|
-
planish(kind?:
|
|
62
|
-
unplanish(kind?:
|
|
66
|
+
planish(kind?: FloorSemanticKind): this;
|
|
67
|
+
unplanish(kind?: FloorSemanticKind): this;
|
|
63
68
|
get semanticCount(): number;
|
|
64
69
|
get instanceCount(): number;
|
|
65
70
|
getSemanticIndexById(id: string): number | undefined;
|
|
@@ -75,6 +80,12 @@ export declare class FloorMesh extends BaseMesh<BufferGeometry, MeshStandardNode
|
|
|
75
80
|
getFacilityById(id: string): Object3D<import("three").Object3DEventMap> | undefined;
|
|
76
81
|
getFacilityAt(index: number): Object3D<import("three").Object3DEventMap>;
|
|
77
82
|
getFacilities(): Object3D<import("three").Object3DEventMap>[];
|
|
83
|
+
setFacilityVisible(facility: FacilityReference, visible: boolean): this;
|
|
84
|
+
showFacility(facility: FacilityReference): this;
|
|
85
|
+
hideFacility(facility: FacilityReference): this;
|
|
86
|
+
setFacilityColor(facility: FacilityReference, color: ColorRepresentation): this;
|
|
87
|
+
resetFacilityColor(facility: FacilityReference): this;
|
|
88
|
+
setFacilityOpacity(facility: FacilityReference, opacity: number): this;
|
|
78
89
|
removeFacility(facility: FacilityReference): this;
|
|
79
90
|
setColorAt(index: number, color: SemanticColor): this;
|
|
80
91
|
getColorAt(index: number, target?: Vector4): Vector4;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ColorRepresentation, type Object3D } from 'three/webgpu';
|
|
2
|
+
import { BaseGroup } from 'u-space';
|
|
3
|
+
import type { BuildingFacilityReference, BuildingGroup } from './BuildingGroup';
|
|
4
|
+
import type { FloorMesh, FloorSemanticKind } from './FloorMesh';
|
|
5
|
+
export declare class SemanticSceneGroup extends BaseGroup {
|
|
6
|
+
#private;
|
|
7
|
+
isSemanticSceneGroup: boolean;
|
|
8
|
+
type: string;
|
|
9
|
+
buildings: BuildingGroup[];
|
|
10
|
+
facilityLayer: Object3D | null;
|
|
11
|
+
constructor();
|
|
12
|
+
addBuilding(group: BuildingGroup): this;
|
|
13
|
+
getBuildingAt(index: number): BuildingGroup;
|
|
14
|
+
getBuildingById(id: string): BuildingGroup | undefined;
|
|
15
|
+
getBuildings(): BuildingGroup[];
|
|
16
|
+
removeBuilding(group: BuildingGroup): this;
|
|
17
|
+
get floorMeshes(): FloorMesh[];
|
|
18
|
+
setFacilityLayer(layer: Object3D | null): this;
|
|
19
|
+
showAllFacilities(): this;
|
|
20
|
+
hideAllFacilities(): this;
|
|
21
|
+
getFacilityById(id: string): Object3D<import("three").Object3DEventMap> | undefined;
|
|
22
|
+
setFacilityVisible(facility: BuildingFacilityReference, visible: boolean): this;
|
|
23
|
+
showFacility(facility: BuildingFacilityReference): this;
|
|
24
|
+
hideFacility(facility: BuildingFacilityReference): this;
|
|
25
|
+
setFacilityColor(facility: BuildingFacilityReference, color: ColorRepresentation): this;
|
|
26
|
+
resetFacilityColor(facility: BuildingFacilityReference): this;
|
|
27
|
+
setFacilityOpacity(facility: BuildingFacilityReference, opacity: number): this;
|
|
28
|
+
showAllFloors(): this;
|
|
29
|
+
planishFloors(kind?: FloorSemanticKind): this;
|
|
30
|
+
unplanishFloors(kind?: FloorSemanticKind): this;
|
|
31
|
+
}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## `SemanticLoader`
|
|
8
8
|
|
|
9
|
-
加载 `db/semantic_model.json`
|
|
9
|
+
加载 `db/semantic_model.json` 楼层语义数据。`loadAsync()` 返回顶层 `SemanticSceneGroup`,用于组织整次语义解析产生的建筑、楼层以及 scene-level facility layer。每个建筑包含多个 `FloorMesh`,每个楼层把墙、柱、空间、楼梯等语义对象合并为一个 TSL 材质驱动的网格;建筑级电梯井和通风井会使用 `ExtrudeMesh` 独立渲染。语义模型包含 `Facilities` 时,`SemanticLoader` 会额外读取 `SceneMetadata.json` 指向的 `tree_models`,按场景授权配置解密,再把对应设备模型挂载到所属楼层。
|
|
10
10
|
|
|
11
11
|
```typescript
|
|
12
12
|
import { Vector3, Vector4 } from 'three';
|
|
@@ -16,10 +16,10 @@ const loader = new SemanticLoader(viewer);
|
|
|
16
16
|
loader.setPath('./scenes/my-scene');
|
|
17
17
|
loader.setKey('YOUR_LICENSE_KEY'); // 官方授权场景解析 tree_models 时必需
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
viewer.scene.add(
|
|
19
|
+
const semanticScene = await loader.loadAsync(); // SemanticSceneGroup
|
|
20
|
+
viewer.scene.add(semanticScene);
|
|
21
21
|
|
|
22
|
-
const building =
|
|
22
|
+
const building = semanticScene.getBuildingAt(0);
|
|
23
23
|
const floor = building.getFloorAt(0);
|
|
24
24
|
|
|
25
25
|
building.isolateFloor(floor);
|
|
@@ -35,9 +35,35 @@ floor.addEventListener('click', ({ event }) => {
|
|
|
35
35
|
});
|
|
36
36
|
```
|
|
37
37
|
|
|
38
|
+
### `SemanticSceneGroup`
|
|
39
|
+
|
|
40
|
+
`SemanticSceneGroup` 继承自 `BaseGroup`,是单次 `SemanticParser` 解析结果的顶层容器。它管理所有 `BuildingGroup`,并把跨楼层共享的 Facilities `InstancedMesh` 渲染层作为建筑的同级对象挂在 `facilityLayer`,而不是挂到某个 `BuildingGroup` 内。
|
|
41
|
+
|
|
42
|
+
建筑 ID 和设备 ID 查询使用内部 `Map` 索引维护;`getBuildingById()`、`getFacilityById()` 以及单设备控制方法不会通过数组扫描查找语义对象。
|
|
43
|
+
|
|
44
|
+
| 属性 / 方法 | 说明 |
|
|
45
|
+
| :---------- | :--- |
|
|
46
|
+
| `buildings` | 当前语义场景内的 `BuildingGroup[]`。 |
|
|
47
|
+
| `facilityLayer` | scene-level 设备渲染层;同模型 URL 的静态设备会合并为 `InstancedMesh` batch。 |
|
|
48
|
+
| `addBuilding(group)` / `removeBuilding(group)` | 添加或移除建筑,并同步更新 group 子节点。 |
|
|
49
|
+
| `getBuildingAt(index)` / `getBuildingById(id)` / `getBuildings()` | 按下标、`Building.ID` 或整体列表获取建筑。 |
|
|
50
|
+
| `floorMeshes` | 聚合返回所有建筑内的 `FloorMesh[]`。 |
|
|
51
|
+
| `setFacilityLayer(layer)` | 设置跨楼层设备渲染层;传入 `null` 会移除已有 layer。 |
|
|
52
|
+
| `getFacilityById(id)` | 在整次语义解析结果中按 `Facility.ID` 或显式别名查找设备。 |
|
|
53
|
+
| `showFacility(id \| object)` / `hideFacility(id \| object)` | 显示或隐藏单个设备。 |
|
|
54
|
+
| `setFacilityVisible(id \| object, visible)` | 设置单个设备显隐状态。 |
|
|
55
|
+
| `setFacilityColor(id \| object, color)` | 设置单个设备材质颜色。 |
|
|
56
|
+
| `resetFacilityColor(id \| object)` | 清除单个设备颜色 override,恢复模型原始颜色;透明度 override 不受影响。 |
|
|
57
|
+
| `setFacilityOpacity(id \| object, opacity)` | 设置单个设备材质透明度,`opacity` 会被限制在 `0..1`。 |
|
|
58
|
+
| `showAllFacilities()` / `hideAllFacilities()` | 显示或隐藏整次语义解析结果中的全部设备。 |
|
|
59
|
+
| `showAllFloors()` | 显示所有建筑的所有楼层。 |
|
|
60
|
+
| `planishFloors(kind?)` / `unplanishFloors(kind?)` | 压扁或恢复所有楼层;默认覆盖所有合并语义实例和 Facilities,并按包围盒贴到楼层平面附近,同时添加稳定的轻微 Y 偏移以减少共面闪烁;传入 `kind` 时只作用于该语义类型,`kind` 可包含 `Facilities`。 |
|
|
61
|
+
|
|
38
62
|
### `BuildingGroup`
|
|
39
63
|
|
|
40
|
-
`BuildingGroup` 继承自 `BaseGroup`,用于组织一个建筑下的所有楼层、电梯井和通风井。设备语义对象不会直接挂到 `BuildingGroup
|
|
64
|
+
`BuildingGroup` 继承自 `BaseGroup`,用于组织一个建筑下的所有楼层、电梯井和通风井。设备语义对象不会直接挂到 `BuildingGroup`;能 instancing 的设备会渲染到 `SemanticSceneGroup.facilityLayer`,同时在对应 `FloorMesh` 下保留可检索、可控制的轻量引用。
|
|
65
|
+
|
|
66
|
+
建筑内设备 ID 到楼层的关系由内部 `Map` 索引维护,并通过楼层设备索引版本自动同步。
|
|
41
67
|
|
|
42
68
|
| 属性 / 方法 | 说明 |
|
|
43
69
|
| :---------- | :--- |
|
|
@@ -47,17 +73,26 @@ floor.addEventListener('click', ({ event }) => {
|
|
|
47
73
|
| `addFloor(floor)` | 添加楼层,并同步加入 group。 |
|
|
48
74
|
| `removeFloor(floor)` | 移除楼层,并同步从 group 移除。 |
|
|
49
75
|
| `getFloorAt(index)` | 按楼层下标获取 `FloorMesh`。 |
|
|
76
|
+
| `getFloorById(id)` | 按楼层语义 ID 获取 `FloorMesh`,内部使用 `Map` 索引。 |
|
|
50
77
|
| `addElevator(elevator)` / `removeElevator(elevator)` | 添加或移除电梯井,并同步更新 group。 |
|
|
51
78
|
| `getElevatorAt(index)` | 按下标获取电梯井 `ExtrudeMesh`。 |
|
|
79
|
+
| `getElevatorById(id)` | 按电梯井语义 ID 获取电梯井,内部使用 `Map` 索引。 |
|
|
52
80
|
| `addVent(vent)` / `removeVent(vent)` | 添加或移除通风井,并同步更新 group。 |
|
|
53
81
|
| `getVentAt(index)` | 按下标获取通风井 `ExtrudeMesh`。 |
|
|
82
|
+
| `getVentById(id)` | 按通风井语义 ID 获取通风井,内部使用 `Map` 索引。 |
|
|
54
83
|
| `isolateFloor(floor \| index)` | 只显示指定楼层,隐藏其他楼层;也兼容传入楼层数组。 |
|
|
55
84
|
| `isolateFloors(floors \| indexes)` | 只显示指定多个楼层,隐藏其他楼层。 |
|
|
56
85
|
| `showAllFloors()` | 显示全部楼层。 |
|
|
86
|
+
| `getFacilityById(id)` | 在当前建筑的楼层中按 `Facility.ID` 或显式别名查找设备。 |
|
|
87
|
+
| `showFacility(id \| object)` / `hideFacility(id \| object)` | 显示或隐藏当前建筑内的单个设备。 |
|
|
88
|
+
| `setFacilityVisible(id \| object, visible)` | 设置当前建筑内单个设备显隐状态。 |
|
|
89
|
+
| `setFacilityColor(id \| object, color)` | 设置当前建筑内单个设备材质颜色。 |
|
|
90
|
+
| `resetFacilityColor(id \| object)` | 清除当前建筑内单个设备颜色 override。 |
|
|
91
|
+
| `setFacilityOpacity(id \| object, opacity)` | 设置当前建筑内单个设备材质透明度。 |
|
|
57
92
|
| `showAllFacilities()` | 显示整栋建筑内全部楼层设备。 |
|
|
58
93
|
| `hideAllFacilities()` | 隐藏整栋建筑内全部楼层设备。 |
|
|
59
|
-
| `planishFloors(kind?)` |
|
|
60
|
-
| `unplanishFloors(kind?)` |
|
|
94
|
+
| `planishFloors(kind?)` | 压扁所有楼层;默认覆盖所有合并语义实例和 Facilities,并按包围盒贴到楼层平面附近,同时添加稳定的轻微 Y 偏移以减少共面闪烁;传入 `kind` 时只压扁该语义类型,`kind` 可包含 `Facilities`。 |
|
|
95
|
+
| `unplanishFloors(kind?)` | 恢复所有楼层;默认恢复所有合并语义实例和 Facilities;传入 `kind` 时只恢复该语义类型,`kind` 可包含 `Facilities`。 |
|
|
61
96
|
|
|
62
97
|
### 电梯井和通风井
|
|
63
98
|
|
|
@@ -65,7 +100,9 @@ floor.addEventListener('click', ({ event }) => {
|
|
|
65
100
|
|
|
66
101
|
```typescript
|
|
67
102
|
const elevator = building.getElevatorAt(0);
|
|
103
|
+
const elevatorById = building.getElevatorById('ELEVATOR_001');
|
|
68
104
|
const vent = building.getVentAt(0);
|
|
105
|
+
const ventById = building.getVentById('VENT_001');
|
|
69
106
|
|
|
70
107
|
if (elevator) {
|
|
71
108
|
await viewer.controls.flyToObject(elevator);
|
|
@@ -84,24 +121,50 @@ if (vent) {
|
|
|
84
121
|
|
|
85
122
|
`tree_models.matrix` 是相对父节点的本地矩阵;`SemanticLoader` 会沿树父级累乘得到设备世界矩阵,再转换为对应 `FloorMesh` 的局部矩阵。因此楼层移动、隔离或显示隐藏时设备会跟随楼层一起工作。即使某个 story 只有 `Facilities`、没有墙柱空间等合并几何,也会创建一个空的 `FloorMesh` 作为设备容器。
|
|
86
123
|
|
|
87
|
-
|
|
124
|
+
Facilities 会在单次 `SemanticParser` 解析范围内按模型 URL 自动分组。静态模型会被转换为 scene-level `InstancedMesh` batch,挂到 `SemanticSceneGroup.facilityLayer`;每个设备仍会在所属 `FloorMesh` 下保留一个轻量引用,用于 `getFacilityById()`、显隐、颜色、透明度和 `viewer.objectManager` 检索。带动画、骨骼、morph target 或多材质 Mesh 的模型会自动回退为普通 `Model`,继续作为实际 `Object3D` 挂到所属 `FloorMesh`。
|
|
125
|
+
|
|
126
|
+
`facilityLayer` 使用 `FacilityInstancedLayer`,并继承自 `BaseGroup`。当 `facilityLayer.visible = false` 时,layer 会阻止内部 `InstancedMesh` 继续参与射线检测,避免隐藏的批处理设备仍被点击命中;单个设备的显隐仍应通过楼层下的设备引用或 `showFacility()` / `hideFacility()` 控制。
|
|
127
|
+
|
|
128
|
+
Instanced 设备通过 per-instance opacity attribute 控制单个设备透明度。batch 材质默认沿用源材质的透明状态;只有源材质本身透明,或当前参与渲染的设备存在 `opacity < 1` 时,材质才会切到 `transparent: true`,`setFacilityOpacity(id, 1)` 可在没有其他半透明实例时回到不透明渲染队列。`resetFacilityColor()` 只清除颜色 override,不影响透明度 override。`FacilityInstancedLayer` 会在渲染前同步实例矩阵、颜色和透明度,但只有检测到数据变化时才上传对应 buffer,静态设备不会每帧重复提交全部 instance 数据。layer 会把每个 Facility 的完整模板包围盒转成世界包围盒,并用当前相机视锥压缩本帧 active instance count;裁剪不再使用相机距离阈值,因此侧视、立面和俯视视角都只由包围盒是否进入视锥决定。`cameraDistanceCulling`、`cameraCullDistance`、`cameraCullOverviewFactor` 和 `cameraCullPlanViewThreshold` 旧字段仅保留兼容,不再影响裁剪结果。普通 fallback `Model` 的颜色和透明度控制依赖 `MaterialEffects`,单材质和多材质 Mesh 都会应用 override。
|
|
129
|
+
|
|
130
|
+
加载成功后,设备引用会写入 `userData.facilityId`、`semanticId`、`semanticKind: 'Facilities'`、`semanticName`、`spaces`、`twinsIdentifier`、`storyId` 和 `floorIndex`,并按 `Facility.ID` 注册到 `viewer.objectManager`。自动 instancing 的引用还会带有 `userData.instanced: true` 和 `userData.modelUrl`。
|
|
88
131
|
|
|
89
132
|
```typescript
|
|
133
|
+
import { Box3 } from 'three';
|
|
134
|
+
|
|
90
135
|
const floor = building.getFloorAt(0);
|
|
136
|
+
const box = new Box3();
|
|
91
137
|
|
|
92
138
|
const facility = floor.getFacilityById('FACILITY_001') ?? viewer.objectManager.getById('FACILITY_001');
|
|
93
139
|
const facilityEntity = floor.getSemanticById('FACILITY_001');
|
|
94
140
|
|
|
95
141
|
if (facility && facilityEntity?.type === 'object') {
|
|
96
|
-
|
|
142
|
+
const facilityBox =
|
|
143
|
+
typeof facility.getFacilityBoundingBox === 'function'
|
|
144
|
+
? facility.getFacilityBoundingBox(box, true)
|
|
145
|
+
: box.setFromObject(facility);
|
|
146
|
+
|
|
147
|
+
await viewer.controls.flyToBox(facilityBox, {
|
|
148
|
+
viewpoint: 'rightFrontTop',
|
|
149
|
+
padding: 0.2,
|
|
150
|
+
});
|
|
97
151
|
}
|
|
98
152
|
|
|
99
153
|
const facilities = floor.getSemanticsByKind('Facilities');
|
|
154
|
+
|
|
155
|
+
semanticScene.hideFacility('FACILITY_001');
|
|
156
|
+
semanticScene
|
|
157
|
+
.setFacilityColor('FACILITY_001', '#ff5533')
|
|
158
|
+
.setFacilityOpacity('FACILITY_001', 0.45)
|
|
159
|
+
.resetFacilityColor('FACILITY_001')
|
|
160
|
+
.showFacility('FACILITY_001');
|
|
100
161
|
```
|
|
101
162
|
|
|
163
|
+
对 Facilities 推荐使用 `controls.flyToBox()` 飞向设备包围盒。instanced 设备引用是楼层下的轻量 `FacilityInstanceObject`,可通过 `getFacilityBoundingBox(box, true)` 取得完整世界包围盒;普通 fallback `Model` 也可以直接使用 `viewer.controls.flyToObject(facility)`。
|
|
164
|
+
|
|
102
165
|
### `FloorMesh`
|
|
103
166
|
|
|
104
|
-
`FloorMesh` 继承自 `BaseMesh`,表示一个楼层。它不是 `BatchedMesh`,而是把同一楼层内的语义对象合并为一份几何,并通过 TSL + `DataTexture` 在 GPU 侧按 `semanticIndex`
|
|
167
|
+
`FloorMesh` 继承自 `BaseMesh`,表示一个楼层。它不是 `BatchedMesh`,而是把同一楼层内的语义对象合并为一份几何,并通过 TSL + `DataTexture` 在 GPU 侧按 `semanticIndex` 控制颜色、透明度、显示隐藏和实例矩阵。楼层语义网格会按实例透明度拆分为不透明和透明两个材质通道;墙、柱、门等默认不透明实例会进入 opaque pipeline,`Spaces`、`Windows` 或通过 `setOpacityAt()` 改成半透明的实例会进入 transparent pipeline。Facilities 通过楼层下的引用对象进行检索和控制;实际渲染可能来自 `SemanticSceneGroup.facilityLayer` 的 `InstancedMesh` batch,也可能是 fallback 的普通 `Model`。
|
|
105
168
|
|
|
106
169
|
这种结构的目标是让每个楼层通常只占一个主渲染 draw call,同时仍保留实例级控制能力。`xxxAt` 方法全部作用于单个语义实例;没有 `At` 后缀的方法作用于整个楼层 mesh。
|
|
107
170
|
|
|
@@ -111,8 +174,8 @@ const facilities = floor.getSemanticsByKind('Facilities');
|
|
|
111
174
|
| `semanticInstances` | `Map<string, number>`,从语义对象 ID 映射到实例下标。 |
|
|
112
175
|
| `wallsInstances` / `columnsInstances` / `spacesInstances` / `doorsInstances` / `windowsInstances` / `staircasesInstances` | 按语义类型维护的 ID 到实例下标映射。 |
|
|
113
176
|
| `semanticEntities` | `Map<string, FloorSemanticEntity>`,统一索引楼层内合并几何语义和 `Facilities` 对象语义。 |
|
|
114
|
-
| `facilityObjectsById` | `Map<string, Object3D>`,按 `Facility.ID
|
|
115
|
-
| `facilityObjects` |
|
|
177
|
+
| `facilityObjectsById` | `Map<string, Object3D>`,按 `Facility.ID` 或显式别名查找设备引用。 |
|
|
178
|
+
| `facilityObjects` | 当前楼层挂载的设备引用数组。 |
|
|
116
179
|
| `getSemanticIndexById(id)` | 根据语义 ID 获取实例下标。 |
|
|
117
180
|
| `getSemanticById(id)` | 根据语义 ID 或设备别名获取统一语义实体。 |
|
|
118
181
|
| `getSemantics()` | 获取楼层内全部语义实体,包含合并几何和设备对象。 |
|
|
@@ -122,10 +185,15 @@ const facilities = floor.getSemanticsByKind('Facilities');
|
|
|
122
185
|
| `getSemanticNameAt(index)` | 获取实例名称;当前 `Spaces` 会从语义数据的 `Name` 写入,其他类型可能为 `undefined`。 |
|
|
123
186
|
| `showAllFacilities()` | 显示当前楼层的全部设备对象。 |
|
|
124
187
|
| `hideAllFacilities()` | 隐藏当前楼层的全部设备对象。 |
|
|
125
|
-
| `addFacility(object, ids?)` | 把设备对象挂到楼层,并按显式 ID、`facilityId`、`semanticId`、`id
|
|
126
|
-
| `getFacilityById(id)` | 根据 `Facility.ID
|
|
188
|
+
| `addFacility(object, ids?)` | 把设备对象挂到楼层,并按显式 ID、`facilityId`、`semanticId`、`id` 建立检索别名。 |
|
|
189
|
+
| `getFacilityById(id)` | 根据 `Facility.ID` 或别名获取设备对象。 |
|
|
127
190
|
| `getFacilityAt(index)` | 按楼层设备数组下标获取设备对象。 |
|
|
128
191
|
| `getFacilities()` | 获取当前楼层全部设备对象。 |
|
|
192
|
+
| `showFacility(id \| object)` / `hideFacility(id \| object)` | 显示或隐藏当前楼层内的单个设备。 |
|
|
193
|
+
| `setFacilityVisible(id \| object, visible)` | 设置当前楼层内单个设备显隐状态。 |
|
|
194
|
+
| `setFacilityColor(id \| object, color)` | 设置当前楼层内单个设备材质颜色。 |
|
|
195
|
+
| `resetFacilityColor(id \| object)` | 清除当前楼层内单个设备颜色 override。 |
|
|
196
|
+
| `setFacilityOpacity(id \| object, opacity)` | 设置当前楼层内单个设备材质透明度。 |
|
|
129
197
|
| `removeFacility(facility)` | 按设备对象或 ID 从楼层移除设备,并同步清理检索索引。 |
|
|
130
198
|
| `setColorAt(index, color)` / `getColorAt(index, target?)` | 修改或读取实例颜色,支持 `Color`、`Vector3`、`Vector4`。 |
|
|
131
199
|
| `setOpacityAt(index, opacity)` / `getOpacityAt(index)` | 修改或读取实例透明度。 |
|
|
@@ -137,11 +205,11 @@ const facilities = floor.getSemanticsByKind('Facilities');
|
|
|
137
205
|
| `getBoundingBoxAt(index, target?, world?)` | 获取实例包围盒;`world = true` 时包含 `FloorMesh.matrixWorld`。 |
|
|
138
206
|
| `getBoundingSphereAt(index, target?, world?)` | 获取实例包围球;`world = true` 时包含 `FloorMesh.matrixWorld`。 |
|
|
139
207
|
| `computeBoundingBox()` / `computeBoundingSphere()` | 计算整个楼层的包围体。 |
|
|
140
|
-
| `planish(kind?)` / `unplanish(kind?)` |
|
|
208
|
+
| `planish(kind?)` / `unplanish(kind?)` | 压扁或恢复楼层内所有合并语义实例和 Facilities;压平时按各自包围盒贴到楼层平面附近,并加入稳定的轻微 Y 偏移;传入 `kind` 时只作用于该语义类型,`kind` 可包含 `Facilities`。 |
|
|
141
209
|
|
|
142
210
|
### 飞向语义实例
|
|
143
211
|
|
|
144
|
-
点击、射线检测命中 `FloorMesh`
|
|
212
|
+
点击、射线检测命中 `FloorMesh` 里的语义几何或设备时,`intersect` 上会附加语义字段:`semanticIndex`、`semanticId`、`semanticKind`。普通楼层语义几何的事件目标是 `FloorMesh`;instanced Facilities 的事件目标是楼层下的 `FacilityInstanceObject` 引用,事件会继续冒泡到所属 `FloorMesh`、`BuildingGroup` 和 `SemanticSceneGroup`。因此楼层监听器中应使用 `event.currentTarget` 操作楼层,用 `intersect.facility` 或 `event.target` 取得设备对象。
|
|
145
213
|
|
|
146
214
|
```typescript
|
|
147
215
|
import { Box3 } from 'three';
|
|
@@ -149,8 +217,24 @@ import { Box3 } from 'three';
|
|
|
149
217
|
const box = new Box3();
|
|
150
218
|
|
|
151
219
|
floor.addEventListener('click', async ({ event }) => {
|
|
152
|
-
const {
|
|
153
|
-
|
|
220
|
+
const { currentTarget, intersect } = event;
|
|
221
|
+
if (!intersect) return;
|
|
222
|
+
|
|
223
|
+
if (intersect.semanticKind === 'Facilities') {
|
|
224
|
+
const facility = intersect.facility ?? event.target;
|
|
225
|
+
const facilityBox =
|
|
226
|
+
typeof facility.getFacilityBoundingBox === 'function'
|
|
227
|
+
? facility.getFacilityBoundingBox(box, true)
|
|
228
|
+
: box.setFromObject(facility);
|
|
229
|
+
|
|
230
|
+
await viewer.controls.flyToBox(facilityBox, {
|
|
231
|
+
viewpoint: 'rightFrontTop',
|
|
232
|
+
padding: 0.2,
|
|
233
|
+
});
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const semanticBox = currentTarget.getBoundingBoxAt(intersect.semanticIndex, box, true);
|
|
154
238
|
|
|
155
239
|
if (semanticBox) {
|
|
156
240
|
await viewer.controls.flyToBox(semanticBox, {
|
|
@@ -174,7 +258,9 @@ if (index !== undefined) {
|
|
|
174
258
|
|
|
175
259
|
### 楼层压扁
|
|
176
260
|
|
|
177
|
-
`planish()` / `unplanish()`
|
|
261
|
+
`planish()` / `unplanish()` 默认作用于当前楼层的全部合并语义实例,包含墙、柱、空间、门窗、楼梯等语义几何,也包含楼层下的 Facilities 引用;传入 `kind` 时只处理该类型,例如 `floor.planish('Walls')` 或 `floor.planish('Facilities')`。所有被压平的实例都会按自身包围盒把压平后的薄片贴到楼层平面 `FloorMesh.pivot.y` 附近,而不是围绕实例自身基点压缩;压平时还会按语义类型和实例 ID 加入稳定的轻微 Y 偏移,减少门、墙或其他重叠实例之间的共面闪烁。`unplanish()` 会恢复合并几何实例的原始矩阵,`unplanish('Facilities')` 会恢复设备原始 `position.y` 和 `scale.y`。instanced Facilities 会通过楼层下的 `FacilityInstanceObject` transform 同步到 `SemanticSceneGroup.facilityLayer`。
|
|
262
|
+
|
|
263
|
+
如果只想调整单个合并几何实例,可以使用 `setScaleAt()` 或 `setScaleYAt()`,它们会保留该语义对象自己的基点矩阵,因此压扁墙、柱、房间时不会被压到世界原点。
|
|
178
264
|
|
|
179
265
|
## `SceneLoader`
|
|
180
266
|
|
package/docs/changelog.md
CHANGED
|
@@ -2,6 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
## 未发布
|
|
4
4
|
|
|
5
|
+
### 修复
|
|
6
|
+
|
|
7
|
+
- **u-manager semantics** — `FloorMesh.planish()` 会在压平后的语义实例和 Facilities 上加入稳定的轻微 Y 偏移,减少门、墙等重叠薄片之间的共面闪烁。
|
|
8
|
+
- **u-manager semantics** — `FloorMesh` 会按实例透明度把合并语义网格拆分到不透明和透明材质通道,避免墙、柱、门等完全不透明实例也走透明渲染队列,降低近距离压平场景的 overdraw 成本。
|
|
9
|
+
- **u-manager semantics** — `BuildingGroup` 新增 `getFloorById()`、`getElevatorById()` 和 `getVentById()`,内部通过 `Map` 维护楼层、电梯井和通风井语义 ID 索引。
|
|
10
|
+
- **u-manager semantics** — `FacilityInstancedLayer` 只在实例矩阵、颜色或透明度变化时上传对应 instance buffer,静态 Facilities 不再每帧重复提交全部实例数据;渲染前会按每个 Facility 实例的世界包围盒和当前相机视锥压缩本帧 active instance count,不再通过相机距离阈值裁剪设备。
|
|
11
|
+
- **u-manager semantics** — 修复 Facilities 视锥裁剪在视角切换后可能沿用上一帧 active subset 的 `visible` / `boundingSphere` 状态,导致某些视角下设备整批隐藏的问题;instanced batch 会保留完整包围球,同时用 `count` 控制本帧 active 实例。
|
|
12
|
+
- **u-manager semantics** — Instanced Facilities 的 batch 材质默认保持不透明,只有源材质本身透明或当前渲染实例存在半透明 opacity 时才切到透明队列,减少完全不透明设备在近距离视角下的 overdraw。
|
|
13
|
+
- **MaterialEffects** — 高亮、呼吸色、线框和淡入淡出效果支持材质数组,确保多材质 Mesh 和 `FloorMesh` 双材质通道都能正确应用并恢复材质状态。
|
|
14
|
+
- **docs/mcp** — 补充 Facilities auto instancing 的动态材质透明度、包围盒视锥裁剪、`controls.flyToBox()` 飞向设备,以及多材质 fallback 对颜色/透明度 override 的支持说明。
|
|
15
|
+
|
|
16
|
+
## 0.0.25
|
|
17
|
+
|
|
18
|
+
### 新增
|
|
19
|
+
|
|
20
|
+
- **u-manager semantics** — 新增 `SemanticSceneGroup`,作为单次 `SemanticParser` 解析结果的顶层容器;`SemanticLoader.loadAsync()` / `SemanticParser.parseAsync()` 直接返回完整语义场景。
|
|
21
|
+
- **u-manager semantics** — `SemanticSceneGroup` 新增 `getBuildingById(id)`,支持按语义数据里的 `Building.ID` 获取建筑。
|
|
22
|
+
- **u-manager semantics** — `SemanticSceneGroup` 和 `BuildingGroup` 的建筑/设备 ID 查询改为内部 `Map` 索引,并通过楼层设备索引版本自动同步,避免每次查询扫描数组。
|
|
23
|
+
- **u-manager semantics** — `FloorMesh.planish()` / `unplanish()`、`BuildingGroup.planishFloors()` / `unplanishFloors()` 和 `SemanticSceneGroup.planishFloors()` / `unplanishFloors()` 会把所有合并语义实例和 Facilities 都按包围盒贴到楼层平面,而不是围绕实例自身基点压缩。
|
|
24
|
+
- **u-manager semantics** — 新增 scene-level Facilities auto instancing:同模型 URL 的静态设备会合并到 `SemanticSceneGroup.facilityLayer` 的 `InstancedMesh` batch,同时保留楼层下的设备引用用于检索、显隐、颜色和透明度控制;带动画、骨骼、morph target 或多材质 Mesh 的设备自动回退为普通 `Model`。
|
|
25
|
+
- **u-manager semantics** — `SemanticSceneGroup`、`BuildingGroup` 和 `FloorMesh` 新增单个设备控制 API:`getFacilityById()`、`showFacility()`、`hideFacility()`、`setFacilityVisible()`、`setFacilityColor()`、`resetFacilityColor()` 和 `setFacilityOpacity()`,同时支持普通设备模型和 scene-level instanced 设备引用。
|
|
26
|
+
- **docs/mcp** — 补充 Facilities auto instancing 的材质透明度行为、`resetFacilityColor()` 语义,以及多材质 fallback 对颜色/透明度 override 的限制说明。
|
|
27
|
+
|
|
28
|
+
### 修复
|
|
29
|
+
|
|
30
|
+
- **u-manager semantics** — 修复 scene-level instanced Facilities 的点击和指针事件派发:射线命中会映射回楼层下的 `FacilityInstanceObject`,并继续冒泡到所属 `FloorMesh`、`BuildingGroup` 和 `SemanticSceneGroup`。
|
|
31
|
+
- **u-manager semantics** — `FacilityInstancedLayer` 继承 `BaseGroup`,避免 `facilityLayer.visible = false` 后内部 `InstancedMesh` 仍参与射线检测并触发隐藏设备点击事件。
|
|
32
|
+
- **u-manager semantics** — 移除语义设备解析里的 `sid` 检索和注册逻辑;Facilities 只按 `Facility.ID` 以及显式传入的别名进入楼层索引和 `viewer.objectManager`。
|
|
33
|
+
|
|
34
|
+
### 示例与文档
|
|
35
|
+
|
|
36
|
+
- **在线示例** — `examples/importmap.js` 的 CDN fallback 版本更新为 `0.0.25`,Vercel 部署会继续按 `package.json` 注入当前版本。
|
|
37
|
+
|
|
38
|
+
## 0.0.23
|
|
39
|
+
|
|
5
40
|
### 新增
|
|
6
41
|
|
|
7
42
|
- **u-manager semantics** — `BuildingGroup` 新增 `isolateFloors(floors)`,支持按多个 `FloorMesh` 或楼层下标同时隔离显示多个楼层;`isolateFloor()` 继续兼容单楼层调用,并可接收数组作为便捷写法。
|
|
@@ -9,6 +44,10 @@
|
|
|
9
44
|
- **u-manager semantics** — `FloorMesh` 新增楼层设备检索与统一语义实体 API:`getFacilityById()`、`getFacilityAt()`、`getFacilities()`、`removeFacility()`、`showAllFacilities()`、`hideAllFacilities()`、`getSemanticById()`、`getSemantics()` 和 `getSemanticsByKind('Facilities')`;`BuildingGroup.showAllFacilities()/hideAllFacilities()` 支持批量显示或隐藏整栋建筑内的楼层设备。
|
|
10
45
|
- **u-space MCP** — 文档索引同步楼层 `Facilities` 解析和检索 API,MCP 客户端可检索设备按楼层挂载、`tree_models` 解密匹配、本地矩阵父级累乘和世界坐标转换规则。
|
|
11
46
|
|
|
47
|
+
### 示例与文档
|
|
48
|
+
|
|
49
|
+
- **在线示例** — `examples/importmap.js` 的 CDN fallback 版本更新为 `0.0.23`,部署流程仍会优先按 `package.json` 注入当前版本。
|
|
50
|
+
|
|
12
51
|
## 0.0.21
|
|
13
52
|
|
|
14
53
|
### 新增
|
package/docs/examples-guide.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## 运行方式与版本
|
|
6
6
|
|
|
7
|
-
示例统一通过 `examples/importmap.js` 注入 Import Map。本地通过 `localhost`、`127.0.0.1`、`0.0.0.0` 或 `192.168.x.x` 访问时会加载仓库里的 `../dist/` 构建产物;在线部署或非本地域名访问时会从 jsDelivr 加载当前发布版本 `u-space@0.0.
|
|
7
|
+
示例统一通过 `examples/importmap.js` 注入 Import Map。本地通过 `localhost`、`127.0.0.1`、`0.0.0.0` 或 `192.168.x.x` 访问时会加载仓库里的 `../dist/` 构建产物;在线部署或非本地域名访问时会从 jsDelivr 加载当前发布版本 `u-space@0.0.25`。Vercel 文档部署会继续把 `__VERSION__` 占位符替换为 `package.json` 中的版本号,源码里的 `0.0.25` 作为直接托管 `examples/` 时的 fallback。
|
|
8
8
|
|
|
9
9
|
插件示例可以在页面加载 `importmap.js` 前通过 `window.__IMPORTS__` 声明额外依赖。将 `u-space/plugins/<name>` 的值设为 `true` 时,`importmap.js` 会自动在本地和 CDN 路径之间切换。
|
|
10
10
|
|
package/docs/getting-started.md
CHANGED
|
@@ -125,7 +125,7 @@ box.addEventListener('pointerleave', (e) => {
|
|
|
125
125
|
|
|
126
126
|
```typescript
|
|
127
127
|
import { version } from 'u-space';
|
|
128
|
-
console.log(version); // e.g. '0.0.
|
|
128
|
+
console.log(version); // e.g. '0.0.25'
|
|
129
129
|
|
|
130
130
|
// 也可以通过全局变量访问
|
|
131
131
|
console.log(window.__USPACE__.version);
|
package/docs/mcp.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# u-space MCP
|
|
2
2
|
|
|
3
|
-
`u-space-mcp` 是面向 `u-space` 文档的 Model Context Protocol(MCP)服务器。它把当前文档打包成只读 MCP 工具,方便 Mastra、Claude Desktop、Cursor 等 MCP 客户端在回答 `u-space` API、插件和示例问题时直接检索官方文档,包括 `u-manager` 的 `SemanticLoader`、`BuildingGroup`、`FloorMesh` 语义楼层 API、楼层 `Facilities`
|
|
3
|
+
`u-space-mcp` 是面向 `u-space` 文档的 Model Context Protocol(MCP)服务器。它把当前文档打包成只读 MCP 工具,方便 Mastra、Claude Desktop、Cursor 等 MCP 客户端在回答 `u-space` API、插件和示例问题时直接检索官方文档,包括 `u-manager` 的 `SemanticLoader`、`SemanticSceneGroup`、`BuildingGroup`、`FloorMesh` 语义楼层 API、楼层 `Facilities` 设备检索与 scene-level auto instancing、设备显隐/颜色/透明度控制、电梯井/通风井语义体块,以及 atmosphere 插件的 `skyBackground()`、`skyEnvironment()` 和 RenderPipeline output effect 配置。
|
|
4
4
|
|
|
5
5
|
## 安装与启动
|
|
6
6
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "u-space",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"types": "dist/src/index.d.ts",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"docs:build": "vitepress build docs",
|
|
30
30
|
"docs:preview": "vitepress preview docs",
|
|
31
31
|
"docs:deploy": "pnpm docs:build && vercel --prod",
|
|
32
|
-
"publish:mcp": "npm --prefix ./packages/u-space-mcp version patch
|
|
32
|
+
"publish:mcp": "npm --prefix ./packages/u-space-mcp version patch && pnpm --filter u-space-mcp build && npm publish ./packages/u-space-mcp --access public --ignore-scripts",
|
|
33
33
|
"release": "npm version patch && pnpm build && npm publish --access=public"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|