@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
|
@@ -16,11 +16,10 @@
|
|
|
16
16
|
import type { Snippet } from 'svelte'
|
|
17
17
|
|
|
18
18
|
import { T, type Props as ThrelteProps } from '@threlte/core'
|
|
19
|
-
import {
|
|
19
|
+
import { type ThrelteGltf, useGltfAnimations } from '@threlte/extras'
|
|
20
20
|
import { Group, type Object3D } from 'three'
|
|
21
21
|
|
|
22
|
-
import { traits,
|
|
23
|
-
import { poseToObject3d } from '../../transform'
|
|
22
|
+
import { traits, useTrait } from '../../ecs'
|
|
24
23
|
|
|
25
24
|
import AxesHelper from '../AxesHelper.svelte'
|
|
26
25
|
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
@@ -34,11 +33,8 @@
|
|
|
34
33
|
|
|
35
34
|
const { gltf, actions } = useGltfAnimations()
|
|
36
35
|
|
|
37
|
-
const
|
|
38
|
-
const parent = useParentName(() => entity)
|
|
39
|
-
const pose = useTrait(() => entity, traits.Pose)
|
|
36
|
+
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
|
|
40
37
|
const gltfTrait = useTrait(() => entity, traits.GLTF)
|
|
41
|
-
const scale = useTrait(() => entity, traits.Scale)
|
|
42
38
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
43
39
|
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
44
40
|
const events = useEntityEvents(() => entity)
|
|
@@ -46,10 +42,12 @@
|
|
|
46
42
|
const animationName = $derived(gltfTrait.current?.animationName)
|
|
47
43
|
|
|
48
44
|
const group = new Group()
|
|
45
|
+
group.matrixAutoUpdate = false
|
|
49
46
|
|
|
50
47
|
$effect.pre(() => {
|
|
51
|
-
if (
|
|
52
|
-
|
|
48
|
+
if (worldMatrix.current) {
|
|
49
|
+
group.matrix.copy(worldMatrix.current)
|
|
50
|
+
group.updateMatrixWorld()
|
|
53
51
|
}
|
|
54
52
|
})
|
|
55
53
|
|
|
@@ -84,30 +82,23 @@
|
|
|
84
82
|
})
|
|
85
83
|
</script>
|
|
86
84
|
|
|
87
|
-
<
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
{#if name.current}
|
|
108
|
-
<PortalTarget id={name.current} />
|
|
109
|
-
{/if}
|
|
110
|
-
</T>
|
|
111
|
-
{/if}
|
|
112
|
-
</T>
|
|
113
|
-
</Portal>
|
|
85
|
+
<T is={group}>
|
|
86
|
+
{#if showAxesHelper.current}
|
|
87
|
+
<AxesHelper
|
|
88
|
+
name={entity}
|
|
89
|
+
width={3}
|
|
90
|
+
length={0.1}
|
|
91
|
+
/>
|
|
92
|
+
{/if}
|
|
93
|
+
{#if $gltf}
|
|
94
|
+
<T
|
|
95
|
+
is={$gltf.scene as Object3D}
|
|
96
|
+
name={entity}
|
|
97
|
+
visible={invisible.current !== true}
|
|
98
|
+
{...events}
|
|
99
|
+
{...rest}
|
|
100
|
+
>
|
|
101
|
+
{@render children?.()}
|
|
102
|
+
</T>
|
|
103
|
+
{/if}
|
|
104
|
+
</T>
|
|
@@ -8,9 +8,9 @@ Renders a Viam Geometry object
|
|
|
8
8
|
import type { Snippet } from 'svelte'
|
|
9
9
|
|
|
10
10
|
import { T, useThrelte } from '@threlte/core'
|
|
11
|
-
import {
|
|
11
|
+
import { Group } from 'three'
|
|
12
12
|
|
|
13
|
-
import { traits,
|
|
13
|
+
import { traits, useTrait } from '../../ecs'
|
|
14
14
|
import { use3DModels } from '../../hooks/use3DModels.svelte'
|
|
15
15
|
import { useSettings } from '../../hooks/useSettings.svelte'
|
|
16
16
|
import { poseToObject3d } from '../../transform'
|
|
@@ -31,7 +31,7 @@ Renders a Viam Geometry object
|
|
|
31
31
|
const models = use3DModels()
|
|
32
32
|
|
|
33
33
|
const name = useTrait(() => entity, traits.Name)
|
|
34
|
-
const
|
|
34
|
+
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
|
|
35
35
|
const center = useTrait(() => entity, traits.Center)
|
|
36
36
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
37
37
|
|
|
@@ -52,6 +52,16 @@ Renders a Viam Geometry object
|
|
|
52
52
|
return models.current[componentName]?.[id]?.clone() ?? undefined
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
+
const group = new Group()
|
|
56
|
+
group.matrixAutoUpdate = false
|
|
57
|
+
|
|
58
|
+
$effect.pre(() => {
|
|
59
|
+
if (!worldMatrix.current) return
|
|
60
|
+
group.matrix.copy(worldMatrix.current)
|
|
61
|
+
group.updateMatrixWorld()
|
|
62
|
+
invalidate()
|
|
63
|
+
})
|
|
64
|
+
|
|
55
65
|
$effect.pre(() => {
|
|
56
66
|
if (model && center.current) {
|
|
57
67
|
poseToObject3d(center.current, model)
|
|
@@ -62,24 +72,25 @@ Renders a Viam Geometry object
|
|
|
62
72
|
const events = useEntityEvents(() => entity)
|
|
63
73
|
</script>
|
|
64
74
|
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
<T
|
|
76
|
+
is={group}
|
|
77
|
+
visible={invisible.current !== true}
|
|
78
|
+
>
|
|
79
|
+
{#if model}
|
|
80
|
+
<T
|
|
81
|
+
is={model}
|
|
82
|
+
name={entity}
|
|
83
|
+
{...events}
|
|
84
|
+
/>
|
|
85
|
+
{/if}
|
|
86
|
+
|
|
87
|
+
{#if settings.current.renderArmModels.includes('colliders') || !model}
|
|
88
|
+
<Mesh
|
|
89
|
+
{entity}
|
|
90
|
+
center={center.current}
|
|
91
|
+
{...events}
|
|
92
|
+
>
|
|
93
|
+
{@render children?.()}
|
|
94
|
+
</Mesh>
|
|
95
|
+
{/if}
|
|
96
|
+
</T>
|
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
import type { Snippet } from 'svelte'
|
|
4
4
|
|
|
5
5
|
import { T, useThrelte } from '@threlte/core'
|
|
6
|
-
import { meshBounds
|
|
6
|
+
import { meshBounds } from '@threlte/extras'
|
|
7
7
|
import { Line2, LineMaterial } from 'three/examples/jsm/Addons.js'
|
|
8
8
|
|
|
9
9
|
import { isVertexColors, STRIDE } from '../../buffer'
|
|
10
|
-
import { traits,
|
|
11
|
-
import { poseToObject3d } from '../../transform'
|
|
10
|
+
import { traits, useTrait } from '../../ecs'
|
|
12
11
|
|
|
13
12
|
import AxesHelper from '../AxesHelper.svelte'
|
|
14
13
|
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
@@ -24,8 +23,7 @@
|
|
|
24
23
|
|
|
25
24
|
const { invalidate } = useThrelte()
|
|
26
25
|
const name = useTrait(() => entity, traits.Name)
|
|
27
|
-
const
|
|
28
|
-
const pose = useTrait(() => entity, traits.Pose)
|
|
26
|
+
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
|
|
29
27
|
const color = useTrait(() => entity, traits.Color)
|
|
30
28
|
const colors = useTrait(() => entity, traits.Colors)
|
|
31
29
|
const dotColors = useTrait(() => entity, traits.DotColors)
|
|
@@ -63,48 +61,48 @@
|
|
|
63
61
|
const currentOpacity = $derived(opacity.current ?? 0.7)
|
|
64
62
|
|
|
65
63
|
const mesh = new Line2()
|
|
64
|
+
mesh.matrixAutoUpdate = false
|
|
66
65
|
|
|
67
66
|
$effect.pre(() => {
|
|
68
|
-
if (
|
|
69
|
-
|
|
67
|
+
if (worldMatrix.current) {
|
|
68
|
+
mesh.matrix.copy(worldMatrix.current)
|
|
69
|
+
mesh.updateMatrixWorld()
|
|
70
70
|
invalidate()
|
|
71
71
|
}
|
|
72
72
|
})
|
|
73
73
|
</script>
|
|
74
74
|
|
|
75
|
-
<
|
|
75
|
+
<T
|
|
76
|
+
is={mesh}
|
|
77
|
+
name={entity}
|
|
78
|
+
userData.name={name}
|
|
79
|
+
raycast={meshBounds}
|
|
80
|
+
renderOrder={renderOrder.current}
|
|
81
|
+
visible={invisible.current !== true}
|
|
82
|
+
{...events}
|
|
83
|
+
>
|
|
84
|
+
<LineGeometry
|
|
85
|
+
positions={linePositions.current}
|
|
86
|
+
colors={lineColors}
|
|
87
|
+
/>
|
|
76
88
|
<T
|
|
77
|
-
is={
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
vertexColors={hasVertexColors}
|
|
93
|
-
transparent={currentOpacity < 1}
|
|
94
|
-
depthWrite={currentOpacity === 1}
|
|
95
|
-
opacity={currentOpacity}
|
|
96
|
-
worldUnits={!screenSpace.current}
|
|
97
|
-
linewidth={(lineWidth.current ?? 5) * (screenSpace.current ? 1 : 0.001)}
|
|
98
|
-
depthTest={materialProps.current?.depthTest ?? true}
|
|
89
|
+
is={LineMaterial}
|
|
90
|
+
color={hasVertexColors ? [1, 1, 1] : lineColor}
|
|
91
|
+
vertexColors={hasVertexColors}
|
|
92
|
+
transparent={currentOpacity < 1}
|
|
93
|
+
depthWrite={currentOpacity === 1}
|
|
94
|
+
opacity={currentOpacity}
|
|
95
|
+
worldUnits={!screenSpace.current}
|
|
96
|
+
linewidth={(lineWidth.current ?? 5) * (screenSpace.current ? 1 : 0.001)}
|
|
97
|
+
depthTest={materialProps.current?.depthTest ?? true}
|
|
98
|
+
/>
|
|
99
|
+
{#if showAxesHelper.current}
|
|
100
|
+
<AxesHelper
|
|
101
|
+
name={entity}
|
|
102
|
+
width={3}
|
|
103
|
+
length={0.1}
|
|
99
104
|
/>
|
|
100
|
-
|
|
101
|
-
<AxesHelper
|
|
102
|
-
name={entity}
|
|
103
|
-
width={3}
|
|
104
|
-
length={0.1}
|
|
105
|
-
/>
|
|
106
|
-
{/if}
|
|
107
|
-
</T>
|
|
105
|
+
{/if}
|
|
108
106
|
|
|
109
107
|
{#if linePositions.current && dotSize.current}
|
|
110
108
|
<LineDots
|
|
@@ -115,9 +113,5 @@
|
|
|
115
113
|
/>
|
|
116
114
|
{/if}
|
|
117
115
|
|
|
118
|
-
{#if name.current}
|
|
119
|
-
<PortalTarget id={name.current} />
|
|
120
|
-
{/if}
|
|
121
|
-
|
|
122
116
|
{@render children?.()}
|
|
123
|
-
</
|
|
117
|
+
</T>
|
|
@@ -137,9 +137,18 @@
|
|
|
137
137
|
renderOrder={renderOrder.current}
|
|
138
138
|
{...rest}
|
|
139
139
|
>
|
|
140
|
-
{#if box.current}
|
|
140
|
+
{#if box.current || sphere.current}
|
|
141
|
+
{@const meshGeometry = box.current ? unitBox : unitSphere}
|
|
142
|
+
{@const edgesGeometry = box.current ? unitBoxEdges : unitSphereEdges}
|
|
143
|
+
<!--
|
|
144
|
+
Switch via a derived `is` on the same <T> so `useAttach`'s effect
|
|
145
|
+
cleanup runs before the new attach. Splitting these across two
|
|
146
|
+
branches of an {#if}/{:else if} races mount-new against unmount-old:
|
|
147
|
+
the new attach saves `mesh.geometry`, then the old cleanup restores
|
|
148
|
+
it to the pre-attach value (null), leaving the mesh geometryless.
|
|
149
|
+
-->
|
|
141
150
|
<T
|
|
142
|
-
is={
|
|
151
|
+
is={meshGeometry}
|
|
143
152
|
dispose={false}
|
|
144
153
|
/>
|
|
145
154
|
<T.LineSegments
|
|
@@ -147,22 +156,7 @@
|
|
|
147
156
|
bvh={{ enabled: false }}
|
|
148
157
|
>
|
|
149
158
|
<T
|
|
150
|
-
is={
|
|
151
|
-
dispose={false}
|
|
152
|
-
/>
|
|
153
|
-
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
154
|
-
</T.LineSegments>
|
|
155
|
-
{:else if sphere.current}
|
|
156
|
-
<T
|
|
157
|
-
is={unitSphere}
|
|
158
|
-
dispose={false}
|
|
159
|
-
/>
|
|
160
|
-
<T.LineSegments
|
|
161
|
-
raycast={() => null}
|
|
162
|
-
bvh={{ enabled: false }}
|
|
163
|
-
>
|
|
164
|
-
<T
|
|
165
|
-
is={unitSphereEdges}
|
|
159
|
+
is={edgesGeometry}
|
|
166
160
|
dispose={false}
|
|
167
161
|
/>
|
|
168
162
|
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
@@ -3,13 +3,11 @@
|
|
|
3
3
|
import type { Snippet } from 'svelte'
|
|
4
4
|
|
|
5
5
|
import { T, useTask, useThrelte } from '@threlte/core'
|
|
6
|
-
import { Portal } from '@threlte/extras'
|
|
7
6
|
import { OrthographicCamera, Points, PointsMaterial } from 'three'
|
|
8
7
|
|
|
9
8
|
import { asColor, isSingleColor } from '../../buffer'
|
|
10
|
-
import { traits,
|
|
9
|
+
import { traits, useTrait } from '../../ecs'
|
|
11
10
|
import { useSettings } from '../../hooks/useSettings.svelte'
|
|
12
|
-
import { poseToObject3d } from '../../transform'
|
|
13
11
|
|
|
14
12
|
import AxesHelper from '../AxesHelper.svelte'
|
|
15
13
|
import { useEntityEvents } from './hooks/useEntityEvents.svelte'
|
|
@@ -24,8 +22,7 @@
|
|
|
24
22
|
const { camera } = useThrelte()
|
|
25
23
|
const settings = useSettings()
|
|
26
24
|
|
|
27
|
-
const
|
|
28
|
-
const pose = useTrait(() => entity, traits.Pose)
|
|
25
|
+
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
|
|
29
26
|
const geometry = useTrait(() => entity, traits.BufferGeometry)
|
|
30
27
|
const entityColor = useTrait(() => entity, traits.Color)
|
|
31
28
|
const colors = useTrait(() => entity, traits.Colors)
|
|
@@ -42,6 +39,7 @@
|
|
|
42
39
|
const orthographic = $derived(settings.current.cameraMode === 'orthographic')
|
|
43
40
|
|
|
44
41
|
const points = new Points()
|
|
42
|
+
points.matrixAutoUpdate = false
|
|
45
43
|
const material = points.material as PointsMaterial
|
|
46
44
|
material.toneMapped = false
|
|
47
45
|
|
|
@@ -98,8 +96,9 @@
|
|
|
98
96
|
})
|
|
99
97
|
|
|
100
98
|
$effect.pre(() => {
|
|
101
|
-
if (
|
|
102
|
-
|
|
99
|
+
if (worldMatrix.current) {
|
|
100
|
+
points.matrix.copy(worldMatrix.current)
|
|
101
|
+
points.updateMatrixWorld()
|
|
103
102
|
}
|
|
104
103
|
})
|
|
105
104
|
|
|
@@ -125,25 +124,23 @@
|
|
|
125
124
|
</script>
|
|
126
125
|
|
|
127
126
|
{#if geometry.current}
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
</T>
|
|
148
|
-
</Portal>
|
|
127
|
+
<T
|
|
128
|
+
is={points}
|
|
129
|
+
name={entity}
|
|
130
|
+
bvh={{ maxDepth: 40, maxLeafSize: 20 }}
|
|
131
|
+
visible={invisible.current !== true}
|
|
132
|
+
renderOrder={renderOrder.current}
|
|
133
|
+
{...events}
|
|
134
|
+
>
|
|
135
|
+
<T is={geometry.current} />
|
|
136
|
+
<T is={material} />
|
|
137
|
+
{#if showAxesHelper.current}
|
|
138
|
+
<AxesHelper
|
|
139
|
+
name={entity}
|
|
140
|
+
width={3}
|
|
141
|
+
length={0.1}
|
|
142
|
+
/>
|
|
143
|
+
{/if}
|
|
144
|
+
{@render children?.()}
|
|
145
|
+
</T>
|
|
149
146
|
{/if}
|
|
@@ -1,52 +1,45 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import type { Pose } from '@viamrobotics/sdk'
|
|
3
2
|
import type { Entity } from 'koota'
|
|
4
3
|
import type { Snippet } from 'svelte'
|
|
5
4
|
|
|
5
|
+
import { Matrix4 } from 'three'
|
|
6
|
+
|
|
6
7
|
import { traits, useParentName, useTrait } from '../../ecs'
|
|
7
|
-
import { usePartConfig } from '../../hooks/usePartConfig.svelte'
|
|
8
8
|
import { usePose } from '../../hooks/usePose.svelte'
|
|
9
|
-
import {
|
|
9
|
+
import { poseToMatrix } from '../../transform'
|
|
10
10
|
|
|
11
11
|
interface Props {
|
|
12
12
|
entity: Entity
|
|
13
|
-
children: Snippet
|
|
13
|
+
children: Snippet
|
|
14
14
|
}
|
|
15
15
|
let { entity, children }: Props = $props()
|
|
16
16
|
|
|
17
|
-
const partConfig = usePartConfig()
|
|
18
17
|
const name = useTrait(() => entity, traits.Name)
|
|
19
18
|
const parent = useParentName(() => entity)
|
|
20
|
-
const editedPose = useTrait(() => entity, traits.EditedPose)
|
|
21
|
-
const entityPose = useTrait(() => entity, traits.Pose)
|
|
22
19
|
|
|
23
20
|
const pose = usePose(
|
|
24
21
|
() => name.current,
|
|
25
22
|
() => parent.current
|
|
26
23
|
)
|
|
27
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Mirror the robot's live kinematics-resolved pose into LiveMatrix so
|
|
27
|
+
* Frame.svelte can compose the rendered transform via
|
|
28
|
+
* `composeLocalMatrix(live, baseline, edited)`. Mutate the stored
|
|
29
|
+
* `Matrix4` in place when present and notify via `entity.changed` —
|
|
30
|
+
* allocate only on first add.
|
|
31
|
+
*/
|
|
28
32
|
$effect.pre(() => {
|
|
29
33
|
if (pose.current === undefined) return
|
|
30
34
|
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
const live = entity.get(traits.LiveMatrix)
|
|
36
|
+
if (live) {
|
|
37
|
+
poseToMatrix(pose.current, live)
|
|
38
|
+
entity.changed(traits.LiveMatrix)
|
|
33
39
|
} else {
|
|
34
|
-
entity.add(traits.
|
|
40
|
+
entity.add(traits.LiveMatrix(poseToMatrix(pose.current, new Matrix4())))
|
|
35
41
|
}
|
|
36
42
|
})
|
|
37
|
-
|
|
38
|
-
// Always render through the live blend: live × network⁻¹ × edited. With
|
|
39
|
-
// `edited === network` (no edits) this collapses to `live`, so the rendered
|
|
40
|
-
// pose tracks the robot's kinematics-resolved position. With edits, the
|
|
41
|
-
// formula composes the staged delta on top of live. Input handlers that
|
|
42
|
-
// drive edits (gizmo onChange, Details panel) compute `edited` such that
|
|
43
|
-
// the blend renders to the user's intent.
|
|
44
|
-
const resolvedPose = $derived.by(() => {
|
|
45
|
-
if (pose.current === undefined || partConfig.hasPendingSave) return editedPose.current
|
|
46
|
-
if (!entityPose.current || !editedPose.current) return undefined
|
|
47
|
-
|
|
48
|
-
return composeRenderedPose(pose.current, entityPose.current, editedPose.current)
|
|
49
|
-
})
|
|
50
43
|
</script>
|
|
51
44
|
|
|
52
|
-
{@render children(
|
|
45
|
+
{@render children()}
|
|
@@ -1,11 +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
|
interface Props {
|
|
5
4
|
entity: Entity;
|
|
6
|
-
children: Snippet
|
|
7
|
-
pose: Pose | undefined;
|
|
8
|
-
}]>;
|
|
5
|
+
children: Snippet;
|
|
9
6
|
}
|
|
10
7
|
declare const Pose: import("svelte").Component<Props, {}, "">;
|
|
11
8
|
type Pose = ReturnType<typeof Pose>;
|
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { useCursor } from '@threlte/extras';
|
|
2
|
-
import { Vector2 } from 'three';
|
|
2
|
+
import { MathUtils, Matrix4, Quaternion, Vector2 } from 'three';
|
|
3
3
|
import { traits, useTrait } from '../../../ecs';
|
|
4
4
|
import { useFocusedEntity, useSelectedEntity } from '../../../hooks/useSelection.svelte';
|
|
5
5
|
import { updateHoverInfo } from '../../../HoverUpdater.svelte';
|
|
6
|
-
import {
|
|
6
|
+
import { OrientationVector } from '../../../three/OrientationVector';
|
|
7
|
+
const tempHoverMatrix = new Matrix4();
|
|
8
|
+
const hoverQuat = new Quaternion();
|
|
9
|
+
const hoverOv = new OrientationVector();
|
|
10
|
+
const infoToLocalMatrix = (info, out) => {
|
|
11
|
+
hoverOv.set(info.oX, info.oY, info.oZ, MathUtils.degToRad(info.theta));
|
|
12
|
+
hoverOv.toQuaternion(hoverQuat);
|
|
13
|
+
out.makeRotationFromQuaternion(hoverQuat);
|
|
14
|
+
out.setPosition(info.x, info.y, info.z);
|
|
15
|
+
};
|
|
7
16
|
export const useEntityEvents = (entity) => {
|
|
8
17
|
const down = new Vector2();
|
|
9
18
|
const selectedEntity = useSelectedEntity();
|
|
@@ -19,15 +28,18 @@ export const useEntityEvents = (entity) => {
|
|
|
19
28
|
if (currentEntity && !currentEntity.has(traits.Hovered)) {
|
|
20
29
|
const hoverInfo = updateHoverInfo(currentEntity, event);
|
|
21
30
|
if (hoverInfo) {
|
|
22
|
-
|
|
31
|
+
infoToLocalMatrix(hoverInfo, tempHoverMatrix);
|
|
32
|
+
const worldMatrix = currentEntity.get(traits.WorldMatrix);
|
|
33
|
+
const composed = new Matrix4();
|
|
34
|
+
if (worldMatrix) {
|
|
35
|
+
composed.copy(worldMatrix).multiply(tempHoverMatrix);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
composed.copy(tempHoverMatrix);
|
|
39
|
+
}
|
|
40
|
+
currentEntity.add(traits.InstancedMatrix({
|
|
41
|
+
matrix: composed,
|
|
23
42
|
index: hoverInfo.index,
|
|
24
|
-
x: hoverInfo.x,
|
|
25
|
-
y: hoverInfo.y,
|
|
26
|
-
z: hoverInfo.z,
|
|
27
|
-
oX: hoverInfo.oX,
|
|
28
|
-
oY: hoverInfo.oY,
|
|
29
|
-
oZ: hoverInfo.oZ,
|
|
30
|
-
theta: hoverInfo.theta,
|
|
31
43
|
}));
|
|
32
44
|
}
|
|
33
45
|
currentEntity.add(traits.Hovered);
|
|
@@ -40,34 +52,21 @@ export const useEntityEvents = (entity) => {
|
|
|
40
52
|
const currentEntity = entity();
|
|
41
53
|
if (currentEntity?.has(traits.Hovered)) {
|
|
42
54
|
const hoverInfo = updateHoverInfo(currentEntity, event);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const hoverPoseMatrix = poseToMatrix(hoverPose);
|
|
56
|
-
const worldPoseMatrix = poseToMatrix(worldPose);
|
|
57
|
-
const resultMatrix = worldPoseMatrix.multiply(hoverPoseMatrix);
|
|
58
|
-
const resultPose = matrixToPose(resultMatrix);
|
|
59
|
-
if (hoverInfo) {
|
|
60
|
-
currentEntity.set(traits.InstancedPose, {
|
|
61
|
-
index: hoverInfo.index,
|
|
62
|
-
x: resultPose.x,
|
|
63
|
-
y: resultPose.y,
|
|
64
|
-
z: resultPose.z,
|
|
65
|
-
oX: resultPose.oX,
|
|
66
|
-
oY: resultPose.oY,
|
|
67
|
-
oZ: resultPose.oZ,
|
|
68
|
-
theta: resultPose.theta,
|
|
69
|
-
});
|
|
55
|
+
if (!hoverInfo)
|
|
56
|
+
return;
|
|
57
|
+
infoToLocalMatrix(hoverInfo, tempHoverMatrix);
|
|
58
|
+
const instanced = currentEntity.get(traits.InstancedMatrix);
|
|
59
|
+
if (!instanced)
|
|
60
|
+
return;
|
|
61
|
+
const worldMatrix = currentEntity.get(traits.WorldMatrix);
|
|
62
|
+
if (worldMatrix) {
|
|
63
|
+
instanced.matrix.copy(worldMatrix).multiply(tempHoverMatrix);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
instanced.matrix.copy(tempHoverMatrix);
|
|
70
67
|
}
|
|
68
|
+
instanced.index = hoverInfo.index;
|
|
69
|
+
currentEntity.changed(traits.InstancedMatrix);
|
|
71
70
|
}
|
|
72
71
|
};
|
|
73
72
|
const onpointerleave = (event) => {
|
|
@@ -77,8 +76,8 @@ export const useEntityEvents = (entity) => {
|
|
|
77
76
|
if (currentEntity?.has(traits.Hovered)) {
|
|
78
77
|
currentEntity.remove(traits.Hovered);
|
|
79
78
|
}
|
|
80
|
-
if (currentEntity?.has(traits.
|
|
81
|
-
currentEntity.remove(traits.
|
|
79
|
+
if (currentEntity?.has(traits.InstancedMatrix)) {
|
|
80
|
+
currentEntity.remove(traits.InstancedMatrix);
|
|
82
81
|
}
|
|
83
82
|
};
|
|
84
83
|
const ondblclick = (event) => {
|
|
@@ -109,8 +108,8 @@ export const useEntityEvents = (entity) => {
|
|
|
109
108
|
if (currentEntity?.has(traits.Hovered)) {
|
|
110
109
|
currentEntity.remove(traits.Hovered);
|
|
111
110
|
}
|
|
112
|
-
if (currentEntity?.has(traits.
|
|
113
|
-
currentEntity.remove(traits.
|
|
111
|
+
if (currentEntity?.has(traits.InstancedMatrix)) {
|
|
112
|
+
currentEntity.remove(traits.InstancedMatrix);
|
|
114
113
|
}
|
|
115
114
|
}
|
|
116
115
|
});
|
|
@@ -51,7 +51,13 @@
|
|
|
51
51
|
enabled.set(settings.current.interactionMode === 'navigate')
|
|
52
52
|
})
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
const bvhEnabled = $derived(
|
|
55
|
+
settings.current.renderSubEntityHoverDetail ||
|
|
56
|
+
settings.current.interactionMode === 'measure' ||
|
|
57
|
+
settings.current.interactionMode === 'select'
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
bvh(raycaster, () => ({ helper: false, enabled: bvhEnabled }))
|
|
55
61
|
|
|
56
62
|
const focusedObject = $derived(focusedObject3d.current)
|
|
57
63
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte'
|
|
3
3
|
|
|
4
|
-
import { provideHierarchy } from '../ecs'
|
|
4
|
+
import { provideHierarchy, provideWorldMatrix } from '../ecs'
|
|
5
5
|
import { provide3DModels } from '../hooks/use3DModels.svelte'
|
|
6
6
|
import { provideArmClient } from '../hooks/useArmClient.svelte'
|
|
7
7
|
import { provideArmKinematics } from '../hooks/useArmKinematics.svelte'
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
provideLogs()
|
|
44
44
|
|
|
45
45
|
provideHierarchy()
|
|
46
|
+
provideWorldMatrix()
|
|
46
47
|
provideOrigin()
|
|
47
48
|
provideDrawAPI()
|
|
48
49
|
provideRelationships()
|