@viamrobotics/motion-tools 1.26.1 → 1.27.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/FrameConfigUpdater.svelte.js +42 -29
- package/dist/assert.d.ts +13 -0
- package/dist/assert.js +20 -0
- package/dist/buf/common/v1/common_pb.d.ts +19 -0
- package/dist/buf/common/v1/common_pb.js +32 -0
- package/dist/components/BatchedArrows.svelte +43 -45
- package/dist/components/Entities/Arrows/Arrows.svelte +35 -29
- package/dist/components/Entities/Entities.svelte +3 -8
- package/dist/components/Entities/Frame.svelte +31 -32
- package/dist/components/Entities/Frame.svelte.d.ts +0 -2
- package/dist/components/Entities/GLTF.svelte +27 -36
- package/dist/components/Entities/Geometry.svelte +35 -24
- package/dist/components/Entities/Line.svelte +37 -43
- package/dist/components/Entities/Mesh.svelte +12 -18
- package/dist/components/Entities/Points.svelte +25 -28
- package/dist/components/Entities/Pose.svelte +17 -24
- package/dist/components/Entities/Pose.svelte.d.ts +1 -4
- package/dist/components/Entities/hooks/useEntityEvents.svelte.js +40 -41
- package/dist/components/Scene.svelte +7 -1
- package/dist/components/SceneProviders.svelte +2 -1
- package/dist/components/SelectedTransformControls.svelte +57 -34
- package/dist/components/StaticGeometries.svelte +1 -1
- package/dist/components/hover/HoveredEntity.svelte +33 -3
- package/dist/components/hover/LinkedHoveredEntity.svelte +2 -3
- package/dist/components/overlay/Details.svelte +72 -94
- package/dist/components/overlay/__tests__/__fixtures__/entity.js +14 -17
- package/dist/components/overlay/left-pane/Tree.svelte +9 -9
- package/dist/components/overlay/left-pane/Tree.svelte.d.ts +1 -2
- package/dist/components/overlay/left-pane/TreeContainer.svelte +4 -15
- package/dist/components/overlay/left-pane/TreeNode.svelte +1 -1
- package/dist/components/overlay/left-pane/TreeNode.svelte.d.ts +1 -1
- package/dist/components/overlay/left-pane/useTree.svelte.d.ts +14 -0
- package/dist/components/overlay/left-pane/useTree.svelte.js +63 -0
- package/dist/draw.js +24 -9
- package/dist/ecs/index.d.ts +1 -0
- package/dist/ecs/index.js +1 -0
- package/dist/ecs/provideWorldMatrix.svelte.d.ts +8 -0
- package/dist/ecs/provideWorldMatrix.svelte.js +13 -0
- package/dist/ecs/traits.d.ts +41 -50
- package/dist/ecs/traits.js +57 -29
- package/dist/ecs/useTrait.svelte.d.ts +1 -6
- package/dist/ecs/useTrait.svelte.js +21 -13
- package/dist/ecs/worldMatrix.d.ts +10 -0
- package/dist/ecs/worldMatrix.js +138 -0
- package/dist/editing/FrameEditSession.js +31 -18
- package/dist/hooks/use3DModels.svelte.js +1 -1
- package/dist/hooks/useConfigFrames.svelte.js +12 -0
- package/dist/hooks/useDrawAPI.svelte.js +14 -6
- package/dist/hooks/useDrawService.svelte.js +4 -7
- package/dist/hooks/useFrames.svelte.js +23 -11
- package/dist/hooks/useGeometries.svelte.js +11 -3
- package/dist/hooks/usePartConfig.svelte.js +43 -6
- package/dist/hooks/useWorldState.svelte.js +10 -2
- package/dist/plugins/bvh.svelte.js +37 -26
- package/dist/transform.js +55 -21
- package/package.json +3 -3
- package/dist/components/overlay/left-pane/buildTree.d.ts +0 -13
- package/dist/components/overlay/left-pane/buildTree.js +0 -48
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { hierarchy, traits } from './ecs';
|
|
2
|
+
import { createPose, matrixToPose, poseToMatrix } from './transform';
|
|
3
|
+
const tempPose = createPose();
|
|
2
4
|
export class FrameConfigUpdater {
|
|
3
5
|
updateFrame;
|
|
4
6
|
removeFrame;
|
|
@@ -10,19 +12,22 @@ export class FrameConfigUpdater {
|
|
|
10
12
|
const { x, y, z } = position;
|
|
11
13
|
if (x === undefined && y === undefined && z === undefined)
|
|
12
14
|
return;
|
|
13
|
-
const
|
|
15
|
+
const current = entity.get(traits.EditedMatrix);
|
|
16
|
+
if (!current)
|
|
17
|
+
return;
|
|
18
|
+
matrixToPose(current, tempPose);
|
|
14
19
|
if (x !== undefined)
|
|
15
|
-
|
|
20
|
+
tempPose.x = x;
|
|
16
21
|
if (y !== undefined)
|
|
17
|
-
|
|
22
|
+
tempPose.y = y;
|
|
18
23
|
if (z !== undefined)
|
|
19
|
-
|
|
20
|
-
|
|
24
|
+
tempPose.z = z;
|
|
25
|
+
poseToMatrix(tempPose, current);
|
|
26
|
+
entity.changed(traits.EditedMatrix);
|
|
21
27
|
const name = entity.get(traits.Name);
|
|
22
28
|
const parent = hierarchy.getParentName(entity) ?? 'world';
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
this.updateFrame(name, parent, updatedPose);
|
|
29
|
+
if (name) {
|
|
30
|
+
this.updateFrame(name, parent, { ...tempPose });
|
|
26
31
|
}
|
|
27
32
|
};
|
|
28
33
|
updateLocalOrientation = (entity, orientation) => {
|
|
@@ -30,27 +35,32 @@ export class FrameConfigUpdater {
|
|
|
30
35
|
if (oX === undefined && oY === undefined && oZ === undefined && theta === undefined) {
|
|
31
36
|
return;
|
|
32
37
|
}
|
|
33
|
-
const
|
|
38
|
+
const current = entity.get(traits.EditedMatrix);
|
|
39
|
+
if (!current)
|
|
40
|
+
return;
|
|
41
|
+
matrixToPose(current, tempPose);
|
|
34
42
|
if (oX !== undefined)
|
|
35
|
-
|
|
43
|
+
tempPose.oX = oX;
|
|
36
44
|
if (oY !== undefined)
|
|
37
|
-
|
|
45
|
+
tempPose.oY = oY;
|
|
38
46
|
if (oZ !== undefined)
|
|
39
|
-
|
|
47
|
+
tempPose.oZ = oZ;
|
|
40
48
|
if (theta !== undefined)
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
tempPose.theta = theta;
|
|
50
|
+
poseToMatrix(tempPose, current);
|
|
51
|
+
entity.changed(traits.EditedMatrix);
|
|
43
52
|
const name = entity.get(traits.Name);
|
|
44
53
|
const parent = hierarchy.getParentName(entity) ?? 'world';
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
this.updateFrame(name, parent, updatedPose);
|
|
54
|
+
if (name) {
|
|
55
|
+
this.updateFrame(name, parent, { ...tempPose });
|
|
48
56
|
}
|
|
49
57
|
};
|
|
50
58
|
updateGeometry = (entity, geometry) => {
|
|
51
59
|
const name = entity.get(traits.Name);
|
|
52
60
|
const parent = hierarchy.getParentName(entity) ?? 'world';
|
|
53
|
-
const
|
|
61
|
+
const matrix = entity.get(traits.EditedMatrix);
|
|
62
|
+
if (matrix)
|
|
63
|
+
matrixToPose(matrix, tempPose);
|
|
54
64
|
if (geometry?.type === 'box') {
|
|
55
65
|
const { x, y, z } = geometry;
|
|
56
66
|
if (x === undefined && y === undefined && z === undefined)
|
|
@@ -64,8 +74,8 @@ export class FrameConfigUpdater {
|
|
|
64
74
|
change.z = z;
|
|
65
75
|
entity.set(traits.Box, change);
|
|
66
76
|
const box = entity.get(traits.Box);
|
|
67
|
-
if (name && box &&
|
|
68
|
-
this.updateFrame(name, parent,
|
|
77
|
+
if (name && box && matrix) {
|
|
78
|
+
this.updateFrame(name, parent, { ...tempPose }, { type: 'box', ...box });
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
else if (geometry?.type === 'sphere') {
|
|
@@ -74,8 +84,8 @@ export class FrameConfigUpdater {
|
|
|
74
84
|
return;
|
|
75
85
|
entity.set(traits.Sphere, { r });
|
|
76
86
|
const sphere = entity.get(traits.Sphere);
|
|
77
|
-
if (name && sphere &&
|
|
78
|
-
this.updateFrame(name, parent,
|
|
87
|
+
if (name && sphere && matrix) {
|
|
88
|
+
this.updateFrame(name, parent, { ...tempPose }, { type: 'sphere', ...sphere });
|
|
79
89
|
}
|
|
80
90
|
}
|
|
81
91
|
else if (geometry?.type === 'capsule') {
|
|
@@ -89,16 +99,17 @@ export class FrameConfigUpdater {
|
|
|
89
99
|
change.l = l;
|
|
90
100
|
entity.set(traits.Capsule, change);
|
|
91
101
|
const capsule = entity.get(traits.Capsule);
|
|
92
|
-
if (name && capsule &&
|
|
93
|
-
this.updateFrame(name, parent,
|
|
102
|
+
if (name && capsule && matrix) {
|
|
103
|
+
this.updateFrame(name, parent, { ...tempPose }, { type: 'capsule', ...capsule });
|
|
94
104
|
}
|
|
95
105
|
}
|
|
96
106
|
};
|
|
97
107
|
setFrameParent = (entity, parentName) => {
|
|
98
108
|
const name = entity.get(traits.Name);
|
|
99
|
-
const
|
|
100
|
-
if (name &&
|
|
101
|
-
|
|
109
|
+
const matrix = entity.get(traits.EditedMatrix);
|
|
110
|
+
if (name && matrix) {
|
|
111
|
+
matrixToPose(matrix, tempPose);
|
|
112
|
+
this.updateFrame(name, parentName, { ...tempPose });
|
|
102
113
|
}
|
|
103
114
|
};
|
|
104
115
|
deleteFrame = (entity) => {
|
|
@@ -110,9 +121,11 @@ export class FrameConfigUpdater {
|
|
|
110
121
|
setGeometryType = (entity, type) => {
|
|
111
122
|
const name = entity.get(traits.Name);
|
|
112
123
|
const parent = hierarchy.getParentName(entity) ?? 'world';
|
|
113
|
-
const
|
|
114
|
-
if (!name || !
|
|
124
|
+
const matrix = entity.get(traits.EditedMatrix);
|
|
125
|
+
if (!name || !matrix)
|
|
115
126
|
return;
|
|
127
|
+
matrixToPose(matrix, tempPose);
|
|
128
|
+
const pose = { ...tempPose };
|
|
116
129
|
if (type === 'none') {
|
|
117
130
|
this.updateFrame(name, parent, pose, { type: 'none' });
|
|
118
131
|
}
|
package/dist/assert.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class AssertionError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Assert that a value is defined.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* const stringify = (value: number | undefined): number => {
|
|
9
|
+
* assertExists(value)
|
|
10
|
+
* return `${value}` // TS now knows that value is of type `number`
|
|
11
|
+
* }
|
|
12
|
+
*/
|
|
13
|
+
export declare const assertExists: <T>(value: T, message: string) => asserts value is NonNullable<T>;
|
package/dist/assert.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export class AssertionError extends Error {
|
|
2
|
+
constructor(message) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.name = 'AssertionError';
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Assert that a value is defined.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* const stringify = (value: number | undefined): number => {
|
|
12
|
+
* assertExists(value)
|
|
13
|
+
* return `${value}` // TS now knows that value is of type `number`
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
export const assertExists = (value, message) => {
|
|
17
|
+
if (value === null || value === undefined) {
|
|
18
|
+
throw new AssertionError(message);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
@@ -855,6 +855,25 @@ export declare class Get3DModelsResponse extends Message<Get3DModelsResponse> {
|
|
|
855
855
|
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Get3DModelsResponse;
|
|
856
856
|
static equals(a: Get3DModelsResponse | PlainMessage<Get3DModelsResponse> | undefined, b: Get3DModelsResponse | PlainMessage<Get3DModelsResponse> | undefined): boolean;
|
|
857
857
|
}
|
|
858
|
+
/**
|
|
859
|
+
* @generated from message viam.common.v1.GetWorldPoseResponse
|
|
860
|
+
*/
|
|
861
|
+
export declare class GetWorldPoseResponse extends Message<GetWorldPoseResponse> {
|
|
862
|
+
/**
|
|
863
|
+
* Pose of the component in the world reference frame
|
|
864
|
+
*
|
|
865
|
+
* @generated from field: viam.common.v1.Pose pose = 1;
|
|
866
|
+
*/
|
|
867
|
+
pose?: Pose;
|
|
868
|
+
constructor(data?: PartialMessage<GetWorldPoseResponse>);
|
|
869
|
+
static readonly runtime: typeof proto3;
|
|
870
|
+
static readonly typeName = "viam.common.v1.GetWorldPoseResponse";
|
|
871
|
+
static readonly fields: FieldList;
|
|
872
|
+
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetWorldPoseResponse;
|
|
873
|
+
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetWorldPoseResponse;
|
|
874
|
+
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetWorldPoseResponse;
|
|
875
|
+
static equals(a: GetWorldPoseResponse | PlainMessage<GetWorldPoseResponse> | undefined, b: GetWorldPoseResponse | PlainMessage<GetWorldPoseResponse> | undefined): boolean;
|
|
876
|
+
}
|
|
858
877
|
/**
|
|
859
878
|
* @generated from message viam.common.v1.GetReadingsRequest
|
|
860
879
|
*/
|
|
@@ -1260,6 +1260,38 @@ export class Get3DModelsResponse extends Message {
|
|
|
1260
1260
|
return proto3.util.equals(Get3DModelsResponse, a, b);
|
|
1261
1261
|
}
|
|
1262
1262
|
}
|
|
1263
|
+
/**
|
|
1264
|
+
* @generated from message viam.common.v1.GetWorldPoseResponse
|
|
1265
|
+
*/
|
|
1266
|
+
export class GetWorldPoseResponse extends Message {
|
|
1267
|
+
/**
|
|
1268
|
+
* Pose of the component in the world reference frame
|
|
1269
|
+
*
|
|
1270
|
+
* @generated from field: viam.common.v1.Pose pose = 1;
|
|
1271
|
+
*/
|
|
1272
|
+
pose;
|
|
1273
|
+
constructor(data) {
|
|
1274
|
+
super();
|
|
1275
|
+
proto3.util.initPartial(data, this);
|
|
1276
|
+
}
|
|
1277
|
+
static runtime = proto3;
|
|
1278
|
+
static typeName = "viam.common.v1.GetWorldPoseResponse";
|
|
1279
|
+
static fields = proto3.util.newFieldList(() => [
|
|
1280
|
+
{ no: 1, name: "pose", kind: "message", T: Pose },
|
|
1281
|
+
]);
|
|
1282
|
+
static fromBinary(bytes, options) {
|
|
1283
|
+
return new GetWorldPoseResponse().fromBinary(bytes, options);
|
|
1284
|
+
}
|
|
1285
|
+
static fromJson(jsonValue, options) {
|
|
1286
|
+
return new GetWorldPoseResponse().fromJson(jsonValue, options);
|
|
1287
|
+
}
|
|
1288
|
+
static fromJsonString(jsonString, options) {
|
|
1289
|
+
return new GetWorldPoseResponse().fromJsonString(jsonString, options);
|
|
1290
|
+
}
|
|
1291
|
+
static equals(a, b) {
|
|
1292
|
+
return proto3.util.equals(GetWorldPoseResponse, a, b);
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1263
1295
|
/**
|
|
1264
1296
|
* @generated from message viam.common.v1.GetReadingsRequest
|
|
1265
1297
|
*/
|
|
@@ -2,103 +2,101 @@
|
|
|
2
2
|
import type { Entity } from 'koota'
|
|
3
3
|
|
|
4
4
|
import { T } from '@threlte/core'
|
|
5
|
-
import {
|
|
6
|
-
import { Color, Vector3 } from 'three'
|
|
5
|
+
import { Color, Quaternion, Vector3 } from 'three'
|
|
7
6
|
|
|
8
|
-
import {
|
|
7
|
+
import { traits, useWorld } from '../ecs'
|
|
9
8
|
import { BatchedArrow } from '../three/BatchedArrow'
|
|
9
|
+
import { OrientationVector } from '../three/OrientationVector'
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
world: new BatchedArrow(),
|
|
13
|
-
})
|
|
14
|
-
const batchEntries = $derived(Object.entries(arrowBatchMap))
|
|
11
|
+
const batched = new BatchedArrow()
|
|
15
12
|
|
|
16
13
|
const world = useWorld()
|
|
17
14
|
|
|
18
15
|
const direction = new Vector3()
|
|
19
16
|
const origin = new Vector3()
|
|
20
17
|
const color = new Color()
|
|
18
|
+
const tempQuat = new Quaternion()
|
|
19
|
+
const tempScale = new Vector3()
|
|
20
|
+
const tempOv = new OrientationVector()
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Decompose the entity's `WorldMatrix` directly into the arrow's world
|
|
24
|
+
* origin (translation) and direction (OV components from the rotation).
|
|
25
|
+
*/
|
|
26
|
+
const decompose = (entity: Entity): boolean => {
|
|
27
|
+
const worldMatrix = entity.get(traits.WorldMatrix)
|
|
28
|
+
if (!worldMatrix) return false
|
|
29
|
+
worldMatrix.decompose(origin, tempQuat, tempScale)
|
|
30
|
+
tempOv.setFromQuaternion(tempQuat)
|
|
31
|
+
direction.set(tempOv.x, tempOv.y, tempOv.z)
|
|
32
|
+
return true
|
|
33
|
+
}
|
|
21
34
|
|
|
22
35
|
const onAdd = (entity: Entity) => {
|
|
23
|
-
const parent = hierarchy.getParentName(entity) ?? 'world'
|
|
24
|
-
|
|
25
|
-
arrowBatchMap[parent] ??= new BatchedArrow()
|
|
26
|
-
const batched = arrowBatchMap[parent]
|
|
27
|
-
|
|
28
|
-
const pose = entity.get(traits.Pose)
|
|
29
36
|
const colorRGB = entity.get(traits.Color)
|
|
30
37
|
|
|
38
|
+
if (!decompose(entity)) {
|
|
39
|
+
direction.set(0, 0, 0)
|
|
40
|
+
origin.set(0, 0, 0)
|
|
41
|
+
}
|
|
42
|
+
|
|
31
43
|
const instanceID = batched.addArrow(
|
|
32
|
-
direction
|
|
33
|
-
origin
|
|
44
|
+
direction,
|
|
45
|
+
origin,
|
|
34
46
|
colorRGB ? color.set(colorRGB.r, colorRGB.g, colorRGB.b) : color.set('yellow')
|
|
35
47
|
)
|
|
36
48
|
|
|
37
49
|
entity.add(traits.Instance({ instanceID, meshID: batched.mesh.id }))
|
|
38
50
|
}
|
|
39
51
|
|
|
40
|
-
const
|
|
52
|
+
const onWorldMatrixChange = (entity: Entity) => {
|
|
41
53
|
if (!entity.has(traits.Arrow)) return
|
|
42
54
|
|
|
43
|
-
const parent = hierarchy.getParentName(entity) ?? 'world'
|
|
44
|
-
const batch = arrowBatchMap[parent]
|
|
45
55
|
const instanceID = entity.get(traits.Instance)?.instanceID
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
batch?.updateArrow(
|
|
50
|
-
instanceID,
|
|
51
|
-
direction.set(pose.oX, pose.oY, pose.oZ),
|
|
52
|
-
origin.set(pose.x, pose.y, pose.z).multiplyScalar(0.001)
|
|
53
|
-
)
|
|
56
|
+
|
|
57
|
+
if (instanceID && instanceID !== -1 && decompose(entity)) {
|
|
58
|
+
batched.updateArrow(instanceID, direction, origin)
|
|
54
59
|
}
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
const onColorChange = (entity: Entity) => {
|
|
58
63
|
if (!entity.has(traits.Arrow)) return
|
|
59
64
|
|
|
60
|
-
const parent = hierarchy.getParentName(entity) ?? 'world'
|
|
61
|
-
const batch = arrowBatchMap[parent]
|
|
62
65
|
const instanceID = entity.get(traits.Instance)?.instanceID
|
|
63
66
|
const colorRGB = entity.get(traits.Color)
|
|
64
67
|
|
|
65
68
|
if (instanceID && instanceID !== -1 && colorRGB) {
|
|
66
69
|
color.set(colorRGB.r, colorRGB.g, colorRGB.b)
|
|
67
|
-
|
|
70
|
+
batched.mesh.setColorAt(instanceID, color)
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
const onInstanceRemove = (entity: Entity) => {
|
|
72
75
|
const instance = entity.get(traits.Instance)
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (batch.mesh.id === instance?.meshID) {
|
|
76
|
-
batch.removeArrow(instance.instanceID)
|
|
77
|
-
}
|
|
76
|
+
if (instance && instance.meshID === batched.mesh.id) {
|
|
77
|
+
batched.removeArrow(instance.instanceID)
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
$effect(() => {
|
|
82
82
|
const unsubAdd = world.onAdd(traits.Arrow, onAdd)
|
|
83
83
|
const unsubRemove = world.onRemove(traits.Instance, onInstanceRemove)
|
|
84
|
-
const
|
|
84
|
+
const unsubMatrixAdd = world.onAdd(traits.WorldMatrix, onWorldMatrixChange)
|
|
85
|
+
const unsubMatrixChange = world.onChange(traits.WorldMatrix, onWorldMatrixChange)
|
|
85
86
|
const unsubColorChange = world.onChange(traits.Color, onColorChange)
|
|
86
87
|
|
|
87
88
|
return () => {
|
|
88
89
|
unsubAdd()
|
|
89
90
|
unsubRemove()
|
|
90
|
-
|
|
91
|
+
unsubMatrixAdd()
|
|
92
|
+
unsubMatrixChange()
|
|
91
93
|
unsubColorChange()
|
|
92
94
|
}
|
|
93
95
|
})
|
|
94
96
|
</script>
|
|
95
97
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
bvh={{ enabled: false }}
|
|
102
|
-
/>
|
|
103
|
-
</Portal>
|
|
104
|
-
{/each}
|
|
98
|
+
<T
|
|
99
|
+
is={batched.mesh}
|
|
100
|
+
dispose={false}
|
|
101
|
+
bvh={{ enabled: false }}
|
|
102
|
+
/>
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Entity } from 'koota'
|
|
3
3
|
|
|
4
|
-
import { T } from '@threlte/core'
|
|
5
|
-
import { Portal } from '@threlte/extras'
|
|
4
|
+
import { T, useThrelte } from '@threlte/core'
|
|
6
5
|
|
|
7
6
|
import type { InstancedArrows } from '../../../three/InstancedArrows/InstancedArrows'
|
|
8
7
|
|
|
9
8
|
import AxesHelper from '../../AxesHelper.svelte'
|
|
10
9
|
import { useEntityEvents } from '../hooks/useEntityEvents.svelte'
|
|
11
|
-
import { traits,
|
|
10
|
+
import { traits, useTrait } from '../../../ecs'
|
|
12
11
|
import { useFocusedEntity, useSelectedEntity } from '../../../hooks/useSelection.svelte'
|
|
13
12
|
import { meshBoundsRaycast, raycast } from '../../../three/InstancedArrows/raycast'
|
|
14
13
|
|
|
@@ -19,7 +18,8 @@
|
|
|
19
18
|
|
|
20
19
|
let { entity, arrows }: Props = $props()
|
|
21
20
|
|
|
22
|
-
const
|
|
21
|
+
const { invalidate } = useThrelte()
|
|
22
|
+
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
|
|
23
23
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
24
24
|
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
25
25
|
|
|
@@ -35,32 +35,38 @@
|
|
|
35
35
|
}
|
|
36
36
|
return meshBoundsRaycast
|
|
37
37
|
})
|
|
38
|
+
|
|
39
|
+
$effect.pre(() => {
|
|
40
|
+
arrows.matrixAutoUpdate = false
|
|
41
|
+
if (!worldMatrix.current) return
|
|
42
|
+
arrows.matrix.copy(worldMatrix.current)
|
|
43
|
+
arrows.updateMatrixWorld()
|
|
44
|
+
invalidate()
|
|
45
|
+
})
|
|
38
46
|
</script>
|
|
39
47
|
|
|
40
|
-
<
|
|
48
|
+
<T
|
|
49
|
+
is={arrows}
|
|
50
|
+
name={entity}
|
|
51
|
+
{...events}
|
|
52
|
+
raycast={raycastFunction}
|
|
53
|
+
visible={invisible.current !== true}
|
|
54
|
+
>
|
|
41
55
|
<T
|
|
42
|
-
is={arrows}
|
|
43
|
-
|
|
44
|
-
{
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
raycast={() => null}
|
|
56
|
+
is={arrows.headMesh}
|
|
57
|
+
bvh={{ enabled: false }}
|
|
58
|
+
raycast={() => null}
|
|
59
|
+
/>
|
|
60
|
+
<T
|
|
61
|
+
is={arrows.shaftMesh}
|
|
62
|
+
bvh={{ enabled: false }}
|
|
63
|
+
raycast={() => null}
|
|
64
|
+
/>
|
|
65
|
+
{#if showAxesHelper.current}
|
|
66
|
+
<AxesHelper
|
|
67
|
+
name={entity}
|
|
68
|
+
width={3}
|
|
69
|
+
length={0.1}
|
|
57
70
|
/>
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
name={entity}
|
|
61
|
-
width={3}
|
|
62
|
-
length={0.1}
|
|
63
|
-
/>
|
|
64
|
-
{/if}
|
|
65
|
-
</T>
|
|
66
|
-
</Portal>
|
|
71
|
+
{/if}
|
|
72
|
+
</T>
|
|
@@ -64,14 +64,9 @@
|
|
|
64
64
|
|
|
65
65
|
{#each machineFramesEntities.current as entity (entity)}
|
|
66
66
|
<Pose {entity}>
|
|
67
|
-
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
{entity}
|
|
71
|
-
>
|
|
72
|
-
<Label text={entity.get(traits.Name)} />
|
|
73
|
-
</Frame>
|
|
74
|
-
{/snippet}
|
|
67
|
+
<Frame {entity}>
|
|
68
|
+
<Label text={entity.get(traits.Name)} />
|
|
69
|
+
</Frame>
|
|
75
70
|
</Pose>
|
|
76
71
|
{/each}
|
|
77
72
|
|
|
@@ -10,39 +10,34 @@ Renders a Viam Frame object
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
<script lang="ts">
|
|
13
|
-
import type { Pose } from '@viamrobotics/sdk'
|
|
14
13
|
import type { Entity } from 'koota'
|
|
15
14
|
import type { Snippet } from 'svelte'
|
|
16
15
|
|
|
17
16
|
import { T, useThrelte } from '@threlte/core'
|
|
18
|
-
import { Portal, PortalTarget } from '@threlte/extras'
|
|
19
17
|
import { Group, type Object3D } from 'three'
|
|
20
18
|
|
|
21
19
|
import { asColor } from '../../buffer'
|
|
22
20
|
import { colors, resourceColors } from '../../color'
|
|
23
|
-
import { traits,
|
|
21
|
+
import { traits, useTrait } from '../../ecs'
|
|
24
22
|
import { useResourceByName } from '../../hooks/useResourceByName.svelte'
|
|
25
|
-
import { poseToObject3d } from '../../transform'
|
|
26
23
|
|
|
27
24
|
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
28
25
|
import Mesh from './Mesh.svelte'
|
|
29
26
|
|
|
30
27
|
interface Props {
|
|
31
28
|
entity: Entity
|
|
32
|
-
pose?: Pose
|
|
33
29
|
children?: Snippet<[{ ref: Object3D }]>
|
|
34
30
|
}
|
|
35
31
|
|
|
36
|
-
let { entity,
|
|
32
|
+
let { entity, children }: Props = $props()
|
|
37
33
|
|
|
38
34
|
const { invalidate } = useThrelte()
|
|
39
35
|
const resourceByName = useResourceByName()
|
|
40
36
|
|
|
41
37
|
const name = useTrait(() => entity, traits.Name)
|
|
42
|
-
const parent = useParentName(() => entity)
|
|
43
38
|
const entityColors = useTrait(() => entity, traits.Colors)
|
|
44
39
|
const entityColor = useTrait(() => entity, traits.Color)
|
|
45
|
-
const
|
|
40
|
+
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
|
|
46
41
|
const center = useTrait(() => entity, traits.Center)
|
|
47
42
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
48
43
|
|
|
@@ -68,32 +63,36 @@ Renders a Viam Frame object
|
|
|
68
63
|
})
|
|
69
64
|
|
|
70
65
|
const group = new Group()
|
|
66
|
+
group.matrixAutoUpdate = false
|
|
71
67
|
|
|
72
|
-
const resolvedPose = $derived(pose ?? entityPose.current)
|
|
73
68
|
$effect.pre(() => {
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
if (!worldMatrix.current) return
|
|
70
|
+
|
|
71
|
+
group.matrix.copy(worldMatrix.current)
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Keep position/quaternion/scale in sync with matrix so TransformControls
|
|
75
|
+
* (which reads/writes those fields) sees the entity's actual transform on
|
|
76
|
+
* drag start. Without this, the gizmo applies its drag delta against an
|
|
77
|
+
* identity baseline and the frame snaps to identity on first onChange.
|
|
78
|
+
*/
|
|
79
|
+
group.matrix.decompose(group.position, group.quaternion, group.scale)
|
|
80
|
+
|
|
81
|
+
group.updateMatrixWorld()
|
|
82
|
+
invalidate()
|
|
78
83
|
})
|
|
79
84
|
</script>
|
|
80
85
|
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
<PortalTarget id={name.current} />
|
|
95
|
-
{/if}
|
|
96
|
-
|
|
97
|
-
{@render children?.({ ref: group })}
|
|
98
|
-
</T>
|
|
99
|
-
</Portal>
|
|
86
|
+
<T
|
|
87
|
+
is={group}
|
|
88
|
+
visible={invisible.current !== true}
|
|
89
|
+
>
|
|
90
|
+
<Mesh
|
|
91
|
+
{entity}
|
|
92
|
+
{color}
|
|
93
|
+
{...events}
|
|
94
|
+
center={center.current}
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
{@render children?.({ ref: group })}
|
|
98
|
+
</T>
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
import type { Pose } from '@viamrobotics/sdk';
|
|
2
1
|
import type { Entity } from 'koota';
|
|
3
2
|
import type { Snippet } from 'svelte';
|
|
4
3
|
import { type Object3D } from 'three';
|
|
5
4
|
interface Props {
|
|
6
5
|
entity: Entity;
|
|
7
|
-
pose?: Pose;
|
|
8
6
|
children?: Snippet<[{
|
|
9
7
|
ref: Object3D;
|
|
10
8
|
}]>;
|