@viamrobotics/motion-tools 1.1.4 → 1.1.6
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/components/App.svelte +7 -1
- package/dist/components/App.svelte.d.ts +2 -0
- package/dist/components/BatchedGeometry.svelte +0 -0
- package/dist/components/BatchedGeometry.svelte.d.ts +26 -0
- package/dist/components/Frame.svelte +29 -12
- package/dist/components/Geometry2.svelte +81 -90
- package/dist/components/Geometry2.svelte.d.ts +2 -1
- package/dist/components/Tree/TreeContainer.svelte +33 -35
- package/dist/components/dashboard/Button.svelte +3 -2
- package/dist/components/dashboard/Button.svelte.d.ts +3 -2
- package/dist/defines.d.ts +8 -0
- package/dist/defines.js +8 -0
- package/dist/hooks/useDrawAPI.svelte.js +41 -16
- package/dist/hooks/useDrawConnectionConfig.svelte.d.ts +10 -0
- package/dist/hooks/useDrawConnectionConfig.svelte.js +13 -0
- package/dist/hooks/useFrames.svelte.js +1 -1
- package/package.json +5 -1
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
import { provideEnvironment } from '../hooks/useEnvironment.svelte'
|
|
23
23
|
import type { CameraPose } from '../hooks/useControls.svelte'
|
|
24
24
|
import { provideWorld } from '../ecs'
|
|
25
|
+
import {
|
|
26
|
+
provideDrawConnectionConfig,
|
|
27
|
+
type DrawConnectionConfig,
|
|
28
|
+
} from '../hooks/useDrawConnectionConfig.svelte'
|
|
25
29
|
|
|
26
30
|
interface LocalConfigProps {
|
|
27
31
|
getLocalPartConfig: () => Struct
|
|
@@ -36,6 +40,7 @@
|
|
|
36
40
|
children?: Snippet
|
|
37
41
|
dashboard?: Snippet
|
|
38
42
|
localConfigProps?: LocalConfigProps
|
|
43
|
+
drawConnectionConfig?: DrawConnectionConfig
|
|
39
44
|
|
|
40
45
|
/**
|
|
41
46
|
* Allows setting the initial camera pose
|
|
@@ -48,6 +53,7 @@
|
|
|
48
53
|
enableKeybindings = true,
|
|
49
54
|
localConfigProps,
|
|
50
55
|
cameraPose,
|
|
56
|
+
drawConnectionConfig,
|
|
51
57
|
children: appChildren,
|
|
52
58
|
dashboard,
|
|
53
59
|
}: Props = $props()
|
|
@@ -63,7 +69,7 @@
|
|
|
63
69
|
})
|
|
64
70
|
|
|
65
71
|
createPartIDContext(() => partID)
|
|
66
|
-
|
|
72
|
+
provideDrawConnectionConfig(() => drawConnectionConfig)
|
|
67
73
|
provideWeblabs()
|
|
68
74
|
provideToast()
|
|
69
75
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import type { Struct } from '@viamrobotics/sdk';
|
|
3
3
|
import type { CameraPose } from '../hooks/useControls.svelte';
|
|
4
|
+
import { type DrawConnectionConfig } from '../hooks/useDrawConnectionConfig.svelte';
|
|
4
5
|
interface LocalConfigProps {
|
|
5
6
|
getLocalPartConfig: () => Struct;
|
|
6
7
|
setLocalPartConfig: (config: Struct) => void;
|
|
@@ -13,6 +14,7 @@ interface Props {
|
|
|
13
14
|
children?: Snippet;
|
|
14
15
|
dashboard?: Snippet;
|
|
15
16
|
localConfigProps?: LocalConfigProps;
|
|
17
|
+
drawConnectionConfig?: DrawConnectionConfig;
|
|
16
18
|
/**
|
|
17
19
|
* Allows setting the initial camera pose
|
|
18
20
|
*/
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export default BatchedGeometry;
|
|
2
|
+
type BatchedGeometry = SvelteComponent<{
|
|
3
|
+
[x: string]: never;
|
|
4
|
+
}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {}> & {
|
|
7
|
+
$$bindings?: string | undefined;
|
|
8
|
+
};
|
|
9
|
+
declare const BatchedGeometry: $$__sveltets_2_IsomorphicComponent<{
|
|
10
|
+
[x: string]: never;
|
|
11
|
+
}, {
|
|
12
|
+
[evt: string]: CustomEvent<any>;
|
|
13
|
+
}, {}, {}, string>;
|
|
14
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
15
|
+
new (options: import("svelte").ComponentConstructorOptions<Props>): import("svelte").SvelteComponent<Props, Events, Slots> & {
|
|
16
|
+
$$bindings?: Bindings;
|
|
17
|
+
} & Exports;
|
|
18
|
+
(internal: unknown, props: {
|
|
19
|
+
$$events?: Events;
|
|
20
|
+
$$slots?: Slots;
|
|
21
|
+
}): Exports & {
|
|
22
|
+
$set?: any;
|
|
23
|
+
$on?: any;
|
|
24
|
+
};
|
|
25
|
+
z_$$bindings?: Bindings;
|
|
26
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte'
|
|
3
3
|
import { useObjectEvents } from '../hooks/useObjectEvents.svelte'
|
|
4
|
-
import { Color, type Object3D } from 'three'
|
|
4
|
+
import { Color, Group, type Object3D } from 'three'
|
|
5
5
|
import Geometry from './Geometry2.svelte'
|
|
6
6
|
import { useWeblabs } from '../hooks/useWeblabs.svelte'
|
|
7
7
|
import { useSelectedEntity } from '../hooks/useSelection.svelte'
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
import { traits, useTrait } from '../ecs'
|
|
14
14
|
import type { Pose } from '@viamrobotics/sdk'
|
|
15
15
|
import { useResourceByName } from '../hooks/useResourceByName.svelte'
|
|
16
|
+
import { Portal, PortalTarget } from '@threlte/extras'
|
|
16
17
|
|
|
17
18
|
interface Props {
|
|
18
19
|
entity: Entity
|
|
@@ -22,14 +23,20 @@
|
|
|
22
23
|
|
|
23
24
|
let { entity, pose, children }: Props = $props()
|
|
24
25
|
|
|
26
|
+
let ref = $state<Group>()
|
|
27
|
+
|
|
25
28
|
const colorUtil = new Color()
|
|
29
|
+
|
|
26
30
|
const settings = useSettings()
|
|
27
31
|
const componentModels = use3DModels()
|
|
28
32
|
const selectedEntity = useSelectedEntity()
|
|
29
33
|
const resourceByName = useResourceByName()
|
|
30
34
|
const weblabs = useWeblabs()
|
|
35
|
+
|
|
31
36
|
const name = useTrait(() => entity, traits.Name)
|
|
37
|
+
const parent = useTrait(() => entity, traits.Parent)
|
|
32
38
|
const entityColor = useTrait(() => entity, traits.Color)
|
|
39
|
+
|
|
33
40
|
const events = useObjectEvents(() => entity)
|
|
34
41
|
const resourceColor = $derived.by(() => {
|
|
35
42
|
if (!name.current) {
|
|
@@ -66,14 +73,24 @@
|
|
|
66
73
|
})
|
|
67
74
|
</script>
|
|
68
75
|
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
<Portal id={parent.current}>
|
|
77
|
+
<Geometry
|
|
78
|
+
bind:ref
|
|
79
|
+
{entity}
|
|
80
|
+
{model}
|
|
81
|
+
{pose}
|
|
82
|
+
renderMode={settings.current.renderArmModels}
|
|
83
|
+
color={selectedEntity.current === entity
|
|
84
|
+
? `#${darkenColor(color, 75).getHexString()}`
|
|
85
|
+
: `#${colorUtil.set(color).getHexString()}`}
|
|
86
|
+
{...events}
|
|
87
|
+
>
|
|
88
|
+
{#if name.current}
|
|
89
|
+
<PortalTarget id={name.current} />
|
|
90
|
+
{/if}
|
|
91
|
+
|
|
92
|
+
{#if ref}
|
|
93
|
+
{@render children?.({ ref })}
|
|
94
|
+
{/if}
|
|
95
|
+
</Geometry>
|
|
96
|
+
</Portal>
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { T, useThrelte, type Props as ThrelteProps } from '@threlte/core'
|
|
3
3
|
import { type Snippet } from 'svelte'
|
|
4
|
-
import {
|
|
5
|
-
meshBounds,
|
|
6
|
-
MeshLineMaterial,
|
|
7
|
-
MeshLineGeometry,
|
|
8
|
-
Portal,
|
|
9
|
-
PortalTarget,
|
|
10
|
-
} from '@threlte/extras'
|
|
4
|
+
import { meshBounds, MeshLineMaterial, MeshLineGeometry } from '@threlte/extras'
|
|
11
5
|
import { BufferGeometry, Color, DoubleSide, FrontSide, Group, Mesh } from 'three'
|
|
12
6
|
import { CapsuleGeometry } from '../three/CapsuleGeometry'
|
|
13
7
|
import { colors, darkenColor } from '../color'
|
|
@@ -23,6 +17,7 @@
|
|
|
23
17
|
model?: Group
|
|
24
18
|
pose?: Pose
|
|
25
19
|
renderMode?: 'model' | 'colliders' | 'colliders+model'
|
|
20
|
+
ref?: Group
|
|
26
21
|
children?: Snippet<[{ ref: Group }]>
|
|
27
22
|
}
|
|
28
23
|
|
|
@@ -32,6 +27,7 @@
|
|
|
32
27
|
model,
|
|
33
28
|
renderMode = 'colliders',
|
|
34
29
|
pose,
|
|
30
|
+
ref = $bindable(),
|
|
35
31
|
children,
|
|
36
32
|
...rest
|
|
37
33
|
}: Props = $props()
|
|
@@ -40,7 +36,6 @@
|
|
|
40
36
|
|
|
41
37
|
const { invalidate } = useThrelte()
|
|
42
38
|
const name = useTrait(() => entity, traits.Name)
|
|
43
|
-
const parent = useTrait(() => entity, traits.Parent)
|
|
44
39
|
const entityColor = useTrait(() => entity, traits.Color)
|
|
45
40
|
const opacity = useTrait(() => entity, traits.Opacity)
|
|
46
41
|
const box = useTrait(() => entity, traits.Box)
|
|
@@ -71,6 +66,8 @@
|
|
|
71
66
|
})
|
|
72
67
|
|
|
73
68
|
const group = new Group()
|
|
69
|
+
ref = group
|
|
70
|
+
|
|
74
71
|
const mesh = $derived.by(() => {
|
|
75
72
|
if (geometryType === undefined) {
|
|
76
73
|
return
|
|
@@ -103,8 +100,8 @@
|
|
|
103
100
|
|
|
104
101
|
let geo = $state.raw<BufferGeometry>()
|
|
105
102
|
|
|
106
|
-
const oncreate = (
|
|
107
|
-
geo =
|
|
103
|
+
const oncreate = (bufferGeometry: BufferGeometry) => {
|
|
104
|
+
geo = bufferGeometry
|
|
108
105
|
}
|
|
109
106
|
|
|
110
107
|
$effect.pre(() => {
|
|
@@ -120,87 +117,81 @@
|
|
|
120
117
|
})
|
|
121
118
|
</script>
|
|
122
119
|
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
{#if !model || renderMode.includes('colliders')}
|
|
144
|
-
{#if lineGeometry.current}
|
|
145
|
-
<MeshLineGeometry points={lineGeometry.current} />
|
|
146
|
-
{:else if box.current}
|
|
147
|
-
{@const { x, y, z } = box.current ?? { x: 0, y: 0, z: 0 }}
|
|
148
|
-
<T.BoxGeometry
|
|
149
|
-
args={[x * 0.001, y * 0.001, z * 0.001]}
|
|
150
|
-
{oncreate}
|
|
151
|
-
/>
|
|
152
|
-
{:else if sphere.current}
|
|
153
|
-
{@const { r } = sphere.current ?? { r: 0 }}
|
|
154
|
-
<T.SphereGeometry
|
|
155
|
-
args={[r * 0.001]}
|
|
156
|
-
{oncreate}
|
|
157
|
-
/>
|
|
158
|
-
{:else if capsule.current}
|
|
159
|
-
{@const { r, l } = capsule.current ?? { r: 0, l: 0 }}
|
|
160
|
-
<T
|
|
161
|
-
is={CapsuleGeometry}
|
|
162
|
-
args={[r * 0.001, l * 0.001]}
|
|
163
|
-
{oncreate}
|
|
164
|
-
/>
|
|
165
|
-
{/if}
|
|
166
|
-
{/if}
|
|
167
|
-
|
|
120
|
+
<T
|
|
121
|
+
is={group}
|
|
122
|
+
{...rest}
|
|
123
|
+
>
|
|
124
|
+
{#if geometryType}
|
|
125
|
+
<AxesHelper
|
|
126
|
+
width={3}
|
|
127
|
+
length={0.1}
|
|
128
|
+
/>
|
|
129
|
+
|
|
130
|
+
<T
|
|
131
|
+
is={mesh}
|
|
132
|
+
name={name.current}
|
|
133
|
+
bvh={{ enabled: geometryType === 'buffer' }}
|
|
134
|
+
>
|
|
135
|
+
{#if model && renderMode.includes('model')}
|
|
136
|
+
<T is={model} />
|
|
137
|
+
{/if}
|
|
138
|
+
|
|
139
|
+
{#if !model || renderMode.includes('colliders')}
|
|
168
140
|
{#if lineGeometry.current}
|
|
169
|
-
<
|
|
170
|
-
|
|
171
|
-
|
|
141
|
+
<MeshLineGeometry points={lineGeometry.current} />
|
|
142
|
+
{:else if box.current}
|
|
143
|
+
{@const { x, y, z } = box.current ?? { x: 0, y: 0, z: 0 }}
|
|
144
|
+
<T.BoxGeometry
|
|
145
|
+
args={[x * 0.001, y * 0.001, z * 0.001]}
|
|
146
|
+
{oncreate}
|
|
172
147
|
/>
|
|
173
|
-
{:else}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
opacity={opacity.current ?? 0.7}
|
|
148
|
+
{:else if sphere.current}
|
|
149
|
+
{@const { r } = sphere.current ?? { r: 0 }}
|
|
150
|
+
<T.SphereGeometry
|
|
151
|
+
args={[r * 0.001]}
|
|
152
|
+
{oncreate}
|
|
179
153
|
/>
|
|
180
|
-
|
|
181
|
-
{
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
154
|
+
{:else if capsule.current}
|
|
155
|
+
{@const { r, l } = capsule.current ?? { r: 0, l: 0 }}
|
|
156
|
+
<T
|
|
157
|
+
is={CapsuleGeometry}
|
|
158
|
+
args={[r * 0.001, l * 0.001]}
|
|
159
|
+
{oncreate}
|
|
160
|
+
/>
|
|
161
|
+
{/if}
|
|
162
|
+
{/if}
|
|
163
|
+
|
|
164
|
+
{#if lineGeometry.current}
|
|
165
|
+
<MeshLineMaterial
|
|
166
|
+
{color}
|
|
167
|
+
width={0.005}
|
|
168
|
+
/>
|
|
169
|
+
{:else}
|
|
170
|
+
<T.MeshToonMaterial
|
|
171
|
+
{color}
|
|
172
|
+
side={geometryType === 'buffer' ? DoubleSide : FrontSide}
|
|
173
|
+
transparent
|
|
174
|
+
opacity={opacity.current ?? 0.7}
|
|
175
|
+
/>
|
|
176
|
+
|
|
177
|
+
{#if geo}
|
|
178
|
+
<T.LineSegments
|
|
179
|
+
raycast={() => null}
|
|
180
|
+
bvh={{ enabled: false }}
|
|
181
|
+
>
|
|
182
|
+
<T.EdgesGeometry args={[geo, 0]} />
|
|
183
|
+
<T.LineBasicMaterial color={darkenColor(color, 10)} />
|
|
184
|
+
</T.LineSegments>
|
|
190
185
|
{/if}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
<PortalTarget id={name.current} />
|
|
204
|
-
{/if}
|
|
205
|
-
</T>
|
|
206
|
-
</Portal>
|
|
186
|
+
{/if}
|
|
187
|
+
</T>
|
|
188
|
+
{:else}
|
|
189
|
+
<AxesHelper
|
|
190
|
+
name={name.current}
|
|
191
|
+
width={3}
|
|
192
|
+
length={0.1}
|
|
193
|
+
/>
|
|
194
|
+
{/if}
|
|
195
|
+
|
|
196
|
+
{@render children?.({ ref: group })}
|
|
197
|
+
</T>
|
|
@@ -9,10 +9,11 @@ interface Props extends ThrelteProps<Group> {
|
|
|
9
9
|
model?: Group;
|
|
10
10
|
pose?: Pose;
|
|
11
11
|
renderMode?: 'model' | 'colliders' | 'colliders+model';
|
|
12
|
+
ref?: Group;
|
|
12
13
|
children?: Snippet<[{
|
|
13
14
|
ref: Group;
|
|
14
15
|
}]>;
|
|
15
16
|
}
|
|
16
|
-
declare const Geometry2: import("svelte").Component<Props, {}, "">;
|
|
17
|
+
declare const Geometry2: import("svelte").Component<Props, {}, "ref">;
|
|
17
18
|
type Geometry2 = ReturnType<typeof Geometry2>;
|
|
18
19
|
export default Geometry2;
|
|
@@ -69,41 +69,39 @@
|
|
|
69
69
|
})
|
|
70
70
|
</script>
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const value = event.selectedValue[0]
|
|
72
|
+
<div
|
|
73
|
+
bind:this={container}
|
|
74
|
+
class="bg-extralight border-medium absolute top-0 left-0 z-1000 m-2 resize overflow-y-auto border text-xs"
|
|
75
|
+
style:min-width="{MIN_DIMENSIONS.width}px"
|
|
76
|
+
style:min-height="{MIN_DIMENSIONS.height}px"
|
|
77
|
+
style:width={resizable.current ? `${resizable.current.width}px` : undefined}
|
|
78
|
+
style:height={resizable.current ? `${resizable.current.height}px` : undefined}
|
|
79
|
+
use:draggable={{
|
|
80
|
+
bounds: 'body',
|
|
81
|
+
handle: dragElement,
|
|
82
|
+
defaultPosition: dragPosition.current,
|
|
83
|
+
onDragEnd(data) {
|
|
84
|
+
dragPosition.current = { x: Math.max(data.offsetX, 0), y: Math.max(data.offsetY, 0) }
|
|
85
|
+
},
|
|
86
|
+
}}
|
|
87
|
+
{...rest}
|
|
88
|
+
>
|
|
89
|
+
<Tree
|
|
90
|
+
{rootNode}
|
|
91
|
+
{nodeMap}
|
|
92
|
+
bind:dragElement
|
|
93
|
+
onSelectionChange={(event) => {
|
|
94
|
+
const value = event.selectedValue[0]
|
|
96
95
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
selectedEntity.set(value ? (Number(value) as Entity) : undefined)
|
|
97
|
+
}}
|
|
98
|
+
/>
|
|
100
99
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
100
|
+
{#if environment.current.isStandalone && partID.current && partConfig.hasEditPermissions}
|
|
101
|
+
<AddFrames />
|
|
102
|
+
{/if}
|
|
104
103
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
{/if}
|
|
104
|
+
<Logs />
|
|
105
|
+
<Settings />
|
|
106
|
+
<Widgets />
|
|
107
|
+
</div>
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { Icon, type IconName, Tooltip } from '@viamrobotics/prime-core'
|
|
3
3
|
import { Ruler } from 'lucide-svelte'
|
|
4
|
+
import type { ClassValue, MouseEventHandler } from 'svelte/elements'
|
|
4
5
|
|
|
5
6
|
interface Props {
|
|
6
7
|
icon: IconName | 'ruler'
|
|
7
8
|
active?: boolean
|
|
8
9
|
description: string
|
|
9
10
|
hotkey?: string
|
|
10
|
-
class?:
|
|
11
|
-
onclick?:
|
|
11
|
+
class?: ClassValue | null | undefined
|
|
12
|
+
onclick?: MouseEventHandler<HTMLButtonElement> | null | undefined
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
let {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { type IconName } from '@viamrobotics/prime-core';
|
|
2
|
+
import type { ClassValue, MouseEventHandler } from 'svelte/elements';
|
|
2
3
|
interface Props {
|
|
3
4
|
icon: IconName | 'ruler';
|
|
4
5
|
active?: boolean;
|
|
5
6
|
description: string;
|
|
6
7
|
hotkey?: string;
|
|
7
|
-
class?:
|
|
8
|
-
onclick?:
|
|
8
|
+
class?: ClassValue | null | undefined;
|
|
9
|
+
onclick?: MouseEventHandler<HTMLButtonElement> | null | undefined;
|
|
9
10
|
}
|
|
10
11
|
declare const Button: import("svelte").Component<Props, {}, "">;
|
|
11
12
|
type Button = ReturnType<typeof Button>;
|
package/dist/defines.js
ADDED
|
@@ -12,6 +12,7 @@ import {} from 'koota';
|
|
|
12
12
|
import { parsePlyInput } from '../ply';
|
|
13
13
|
import { useLogs } from './useLogs.svelte';
|
|
14
14
|
import { createBox, createCapsule, createSphere } from '../geometry';
|
|
15
|
+
import { useDrawConnectionConfig } from './useDrawConnectionConfig.svelte';
|
|
15
16
|
const colorUtil = new Color();
|
|
16
17
|
const bufferTypes = {
|
|
17
18
|
DRAW_POINTS: 0,
|
|
@@ -70,6 +71,9 @@ export const provideDrawAPI = () => {
|
|
|
70
71
|
const logs = useLogs();
|
|
71
72
|
const cameraControls = useCameraControls();
|
|
72
73
|
const { invalidate } = useThrelte();
|
|
74
|
+
const drawConnectionConfig = useDrawConnectionConfig();
|
|
75
|
+
const backendIP = $derived(drawConnectionConfig.current?.backendIP);
|
|
76
|
+
const websocketPort = $derived(drawConnectionConfig.current?.websocketPort);
|
|
73
77
|
let pointsIndex = 0;
|
|
74
78
|
let geometryIndex = 0;
|
|
75
79
|
let poseIndex = 0;
|
|
@@ -82,7 +86,7 @@ export const provideDrawAPI = () => {
|
|
|
82
86
|
const loader = new GLTFLoader();
|
|
83
87
|
const entities = new Map();
|
|
84
88
|
const sendResponse = (response) => {
|
|
85
|
-
ws
|
|
89
|
+
ws?.send(JSON.stringify(response));
|
|
86
90
|
};
|
|
87
91
|
const drawFrames = async (data) => {
|
|
88
92
|
for (const rawFrame of data) {
|
|
@@ -286,6 +290,7 @@ export const provideDrawAPI = () => {
|
|
|
286
290
|
for (const entity of world.query(traits.DrawAPI)) {
|
|
287
291
|
if (entity.get(traits.Name) === name) {
|
|
288
292
|
entity.destroy();
|
|
293
|
+
entities.delete(name);
|
|
289
294
|
}
|
|
290
295
|
}
|
|
291
296
|
}
|
|
@@ -294,21 +299,27 @@ export const provideDrawAPI = () => {
|
|
|
294
299
|
for (const entity of world.query(traits.DrawAPI)) {
|
|
295
300
|
entity.destroy();
|
|
296
301
|
}
|
|
302
|
+
entities.clear();
|
|
297
303
|
pointsIndex = 0;
|
|
298
304
|
geometryIndex = 0;
|
|
299
305
|
poseIndex = 0;
|
|
300
306
|
};
|
|
301
307
|
const scheduleReconnect = () => {
|
|
302
308
|
setTimeout(() => {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
309
|
+
if (backendIP && websocketPort) {
|
|
310
|
+
reconnectDelay = Math.min(reconnectDelay * 2, maxReconnectDelay);
|
|
311
|
+
logs.add(`Reconnecting to drawing server in ${reconnectDelay / 1000} seconds...`, 'warn');
|
|
312
|
+
connect(backendIP, websocketPort);
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
logs.add('No provided backend IP or websocket port', 'error');
|
|
316
|
+
}
|
|
306
317
|
}, reconnectDelay);
|
|
307
318
|
};
|
|
308
319
|
const onOpen = () => {
|
|
309
320
|
connectionStatus = 'open';
|
|
310
321
|
reconnectDelay = 1000;
|
|
311
|
-
logs.add(`Connected to drawing server at ${
|
|
322
|
+
logs.add(`Connected to drawing server at ${backendIP}:${websocketPort}`);
|
|
312
323
|
};
|
|
313
324
|
const onClose = () => {
|
|
314
325
|
connectionStatus = 'closed';
|
|
@@ -317,7 +328,7 @@ export const provideDrawAPI = () => {
|
|
|
317
328
|
};
|
|
318
329
|
const onError = (event) => {
|
|
319
330
|
const stringified = JSON.stringify(event);
|
|
320
|
-
ws
|
|
331
|
+
ws?.close();
|
|
321
332
|
if (stringified === '{"isTrusted":true}') {
|
|
322
333
|
return;
|
|
323
334
|
}
|
|
@@ -409,17 +420,31 @@ export const provideDrawAPI = () => {
|
|
|
409
420
|
}
|
|
410
421
|
invalidate();
|
|
411
422
|
};
|
|
412
|
-
const connect = () => {
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
423
|
+
const connect = (backendIP, websocketPort) => {
|
|
424
|
+
const protocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
|
425
|
+
ws = new WebSocket(`${protocol}://${backendIP}:${websocketPort}/ws`);
|
|
426
|
+
ws.onclose = onClose;
|
|
427
|
+
ws.onerror = onError;
|
|
428
|
+
ws.onopen = onOpen;
|
|
429
|
+
ws.onmessage = onMessage;
|
|
430
|
+
};
|
|
431
|
+
const disconnect = () => {
|
|
432
|
+
ws?.removeEventListener('close', onClose);
|
|
433
|
+
ws?.removeEventListener('error', onError);
|
|
434
|
+
ws?.removeEventListener('open', onOpen);
|
|
435
|
+
ws?.removeEventListener('message', onMessage);
|
|
436
|
+
ws?.close();
|
|
437
|
+
ws = undefined;
|
|
421
438
|
};
|
|
422
|
-
|
|
439
|
+
$effect(() => {
|
|
440
|
+
if (!backendIP || !websocketPort) {
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
connect(backendIP, websocketPort);
|
|
444
|
+
return () => {
|
|
445
|
+
disconnect();
|
|
446
|
+
};
|
|
447
|
+
});
|
|
423
448
|
setContext(key, {
|
|
424
449
|
get connectionStatus() {
|
|
425
450
|
return connectionStatus;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export interface DrawConnectionConfig {
|
|
2
|
+
backendIP: string;
|
|
3
|
+
websocketPort: string;
|
|
4
|
+
}
|
|
5
|
+
interface Context {
|
|
6
|
+
current: DrawConnectionConfig | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare const provideDrawConnectionConfig: (args: () => DrawConnectionConfig | undefined) => void;
|
|
9
|
+
export declare const useDrawConnectionConfig: () => Context;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getContext, setContext } from 'svelte';
|
|
2
|
+
const key = Symbol('draw-connection-config-key');
|
|
3
|
+
export const provideDrawConnectionConfig = (args) => {
|
|
4
|
+
const current = $derived(args());
|
|
5
|
+
setContext(key, {
|
|
6
|
+
get current() {
|
|
7
|
+
return current;
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
export const useDrawConnectionConfig = () => {
|
|
12
|
+
return getContext(key);
|
|
13
|
+
};
|
|
@@ -18,7 +18,7 @@ export const provideFrames = (partID) => {
|
|
|
18
18
|
const machineStatus = useMachineStatus(partID);
|
|
19
19
|
const logs = useLogs();
|
|
20
20
|
const query = createRobotQuery(client, 'frameSystemConfig', () => ({
|
|
21
|
-
enabled: environment.current.viewerMode === 'monitor',
|
|
21
|
+
enabled: partID() !== '' && environment.current.viewerMode === 'monitor',
|
|
22
22
|
}));
|
|
23
23
|
const revision = $derived(machineStatus.current?.config?.revision);
|
|
24
24
|
const partConfig = usePartConfig();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viamrobotics/motion-tools",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"description": "Motion visualization with Viam",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -39,6 +39,8 @@
|
|
|
39
39
|
"@viamrobotics/svelte-sdk": "1.0.1",
|
|
40
40
|
"@vitejs/plugin-basic-ssl": "2.1.0",
|
|
41
41
|
"@vitest/coverage-v8": "^3.2.4",
|
|
42
|
+
"@zag-js/collapsible": "1.22.1",
|
|
43
|
+
"@zag-js/floating-panel": "1.22.1",
|
|
42
44
|
"@zag-js/svelte": "1.22.1",
|
|
43
45
|
"@zag-js/tree-view": "1.22.1",
|
|
44
46
|
"camera-controls": "3.1.0",
|
|
@@ -78,6 +80,8 @@
|
|
|
78
80
|
"@viamrobotics/prime-core": ">=0.1",
|
|
79
81
|
"@viamrobotics/sdk": ">=0.38",
|
|
80
82
|
"@viamrobotics/svelte-sdk": ">=0.1",
|
|
83
|
+
"@zag-js/collapsible": ">=1",
|
|
84
|
+
"@zag-js/floating-panel": ">=1",
|
|
81
85
|
"@zag-js/svelte": ">=1",
|
|
82
86
|
"@zag-js/tree-view": ">=1",
|
|
83
87
|
"camera-controls": ">=3",
|