@viamrobotics/motion-tools 1.19.0 → 1.21.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/buf/draw/v1/metadata_pb.d.ts +39 -0
- package/dist/buf/draw/v1/metadata_pb.js +55 -0
- package/dist/buf/draw/v1/service_connect.d.ts +34 -1
- package/dist/buf/draw/v1/service_connect.js +34 -1
- package/dist/buf/draw/v1/service_pb.d.ts +136 -0
- package/dist/buf/draw/v1/service_pb.js +201 -0
- package/dist/components/Entities/Arrows/ArrowGroups.svelte +1 -0
- package/dist/components/Entities/Arrows/Arrows.svelte +1 -1
- package/dist/components/Entities/Entities.svelte +1 -0
- package/dist/components/Entities/Points.svelte +23 -23
- package/dist/components/Entities/hooks/useEntityEvents.svelte.js +18 -1
- package/dist/components/FileDrop/FileDrop.svelte +8 -1
- package/dist/components/PCD.svelte +9 -1
- package/dist/components/PCD.svelte.d.ts +2 -0
- package/dist/components/SceneProviders.svelte +2 -0
- package/dist/components/Snapshot.svelte +12 -7
- package/dist/components/overlay/AddRelationship.svelte +25 -3
- package/dist/components/overlay/Details.svelte +293 -227
- package/dist/draw.d.ts +22 -9
- package/dist/draw.js +75 -46
- package/dist/ecs/relations.js +1 -1
- package/dist/ecs/traits.d.ts +2 -0
- package/dist/ecs/traits.js +63 -0
- package/dist/hooks/useDrawService.svelte.d.ts +2 -0
- package/dist/hooks/useDrawService.svelte.js +139 -20
- package/dist/hooks/useRelationships.svelte.d.ts +12 -0
- package/dist/hooks/useRelationships.svelte.js +78 -0
- package/dist/hooks/useWorldState.svelte.js +10 -4
- package/dist/metadata.d.ts +7 -3
- package/dist/metadata.js +26 -2
- package/dist/snapshot.d.ts +6 -1
- package/dist/snapshot.js +10 -5
- package/package.json +5 -2
|
@@ -33,6 +33,8 @@
|
|
|
33
33
|
const opacity = useTrait(() => entity, traits.Opacity)
|
|
34
34
|
const invisible = useTrait(() => entity, traits.Invisible)
|
|
35
35
|
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
36
|
+
const renderOrder = useTrait(() => entity, traits.RenderOrder)
|
|
37
|
+
const materialProps = useTrait(() => entity, traits.Material)
|
|
36
38
|
|
|
37
39
|
const pointSize = $derived(
|
|
38
40
|
entityPointSize.current ? entityPointSize.current * 0.001 : settings.current.pointSize
|
|
@@ -61,41 +63,38 @@
|
|
|
61
63
|
})
|
|
62
64
|
|
|
63
65
|
/**
|
|
64
|
-
* Points
|
|
66
|
+
* Points transparency is very costly for the GPU, so we turn it on conservatively.
|
|
67
|
+
* Uniform opacity (entity trait) and per-vertex RGBA alpha are both considered here
|
|
68
|
+
* to avoid the two sources conflicting with each other.
|
|
65
69
|
*/
|
|
66
70
|
$effect.pre(() => {
|
|
67
|
-
|
|
68
|
-
material.transparent = true
|
|
69
|
-
material.opacity = opacity.current
|
|
70
|
-
|
|
71
|
-
return () => {
|
|
72
|
-
material.transparent = false
|
|
73
|
-
material.opacity = 1
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
$effect.pre(() => {
|
|
79
|
-
const colors = geometry.current?.getAttribute('color')
|
|
71
|
+
const vertexColors = geometry.current?.getAttribute('color')
|
|
80
72
|
const positions = geometry.current?.getAttribute('position')
|
|
81
73
|
|
|
82
|
-
material.vertexColors =
|
|
74
|
+
material.vertexColors = vertexColors !== undefined
|
|
83
75
|
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
const hasUniformOpacity = opacity.current !== undefined && opacity.current < 1
|
|
77
|
+
material.opacity = hasUniformOpacity ? opacity.current! : 1
|
|
86
78
|
|
|
87
|
-
|
|
79
|
+
let hasVertexAlpha = false
|
|
80
|
+
if (vertexColors && positions) {
|
|
81
|
+
const hasAlphaChannel = positions.array.length / vertexColors.array.length === 0.75
|
|
88
82
|
if (hasAlphaChannel) {
|
|
89
|
-
for (let i = 3, l =
|
|
90
|
-
if (
|
|
91
|
-
|
|
83
|
+
for (let i = 3, l = vertexColors.array.length; i < l; i += 4) {
|
|
84
|
+
if (vertexColors.array[i] < 1) {
|
|
85
|
+
hasVertexAlpha = true
|
|
92
86
|
break
|
|
93
87
|
}
|
|
94
88
|
}
|
|
95
89
|
}
|
|
96
|
-
|
|
97
|
-
material.transparent = transparent
|
|
98
90
|
}
|
|
91
|
+
|
|
92
|
+
material.transparent = hasUniformOpacity || hasVertexAlpha
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
$effect.pre(() => {
|
|
96
|
+
material.depthTest = materialProps.current?.depthTest ?? true
|
|
97
|
+
material.depthWrite = materialProps.current?.depthWrite ?? true
|
|
99
98
|
})
|
|
100
99
|
|
|
101
100
|
$effect.pre(() => {
|
|
@@ -132,6 +131,7 @@
|
|
|
132
131
|
name={entity}
|
|
133
132
|
bvh={{ maxDepth: 40, maxLeafSize: 20 }}
|
|
134
133
|
visible={invisible.current !== true}
|
|
134
|
+
renderOrder={renderOrder.current}
|
|
135
135
|
{...events}
|
|
136
136
|
>
|
|
137
137
|
<T is={geometry.current} />
|
|
@@ -9,7 +9,10 @@ export const useEntityEvents = (entity) => {
|
|
|
9
9
|
const selectedEntity = useSelectedEntity();
|
|
10
10
|
const focusedEntity = useFocusedEntity();
|
|
11
11
|
const cursor = useCursor();
|
|
12
|
+
const invisible = useTrait(entity, traits.Invisible);
|
|
12
13
|
const onpointerenter = (event) => {
|
|
14
|
+
if (invisible.current)
|
|
15
|
+
return;
|
|
13
16
|
event.stopPropagation();
|
|
14
17
|
cursor.onPointerEnter();
|
|
15
18
|
const currentEntity = entity();
|
|
@@ -31,6 +34,8 @@ export const useEntityEvents = (entity) => {
|
|
|
31
34
|
}
|
|
32
35
|
};
|
|
33
36
|
const onpointermove = (event) => {
|
|
37
|
+
if (invisible.current)
|
|
38
|
+
return;
|
|
34
39
|
event.stopPropagation();
|
|
35
40
|
const currentEntity = entity();
|
|
36
41
|
if (currentEntity?.has(traits.Hovered)) {
|
|
@@ -77,24 +82,36 @@ export const useEntityEvents = (entity) => {
|
|
|
77
82
|
}
|
|
78
83
|
};
|
|
79
84
|
const ondblclick = (event) => {
|
|
85
|
+
if (invisible.current)
|
|
86
|
+
return;
|
|
80
87
|
event.stopPropagation();
|
|
81
88
|
const currentEntity = entity();
|
|
82
89
|
focusedEntity.set(currentEntity, event.instanceId ?? event.batchId);
|
|
83
90
|
};
|
|
84
91
|
const onpointerdown = (event) => {
|
|
92
|
+
if (invisible.current)
|
|
93
|
+
return;
|
|
85
94
|
down.copy(event.pointer);
|
|
86
95
|
};
|
|
87
96
|
const onclick = (event) => {
|
|
97
|
+
if (invisible.current)
|
|
98
|
+
return;
|
|
88
99
|
event.stopPropagation();
|
|
89
100
|
if (down.distanceToSquared(event.pointer) < 0.1) {
|
|
90
101
|
const currentEntity = entity();
|
|
91
102
|
selectedEntity.set(currentEntity, event.instanceId ?? event.batchId);
|
|
92
103
|
}
|
|
93
104
|
};
|
|
94
|
-
const invisible = useTrait(entity, traits.Invisible);
|
|
95
105
|
$effect(() => {
|
|
96
106
|
if (invisible.current) {
|
|
97
107
|
cursor.onPointerLeave();
|
|
108
|
+
const currentEntity = entity();
|
|
109
|
+
if (currentEntity?.has(traits.Hovered)) {
|
|
110
|
+
currentEntity.remove(traits.Hovered);
|
|
111
|
+
}
|
|
112
|
+
if (currentEntity?.has(traits.InstancedPose)) {
|
|
113
|
+
currentEntity.remove(traits.InstancedPose);
|
|
114
|
+
}
|
|
98
115
|
}
|
|
99
116
|
});
|
|
100
117
|
return {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
import { traits } from '../../ecs'
|
|
9
9
|
import { useWorld } from '../../ecs/useWorld'
|
|
10
10
|
import { useCameraControls } from '../../hooks/useControls.svelte'
|
|
11
|
+
import { useRelationships } from '../../hooks/useRelationships.svelte'
|
|
11
12
|
import { spawnSnapshotEntities } from '../../snapshot'
|
|
12
13
|
|
|
13
14
|
import type { FileDropperSuccess } from './file-dropper'
|
|
@@ -19,12 +20,18 @@
|
|
|
19
20
|
const world = useWorld()
|
|
20
21
|
const toast = useToast()
|
|
21
22
|
const cameraControls = useCameraControls()
|
|
23
|
+
const relationships = useRelationships()
|
|
22
24
|
|
|
23
25
|
const fileDrop = useFileDrop(
|
|
24
26
|
(result: FileDropperSuccess) => {
|
|
25
27
|
switch (result.type) {
|
|
26
28
|
case 'snapshot': {
|
|
27
|
-
spawnSnapshotEntities(world, result.snapshot)
|
|
29
|
+
const spawned = spawnSnapshotEntities(world, result.snapshot)
|
|
30
|
+
for (const entity of spawned) {
|
|
31
|
+
relationships.apply(entity.entity, entity.relationships)
|
|
32
|
+
const uuid = entity.entity.get(traits.UUID)
|
|
33
|
+
if (uuid) relationships.flush(uuid)
|
|
34
|
+
}
|
|
28
35
|
|
|
29
36
|
const { sceneCamera } = result.snapshot.sceneMetadata ?? {}
|
|
30
37
|
|
|
@@ -12,11 +12,14 @@
|
|
|
12
12
|
data: Uint8Array
|
|
13
13
|
name?: string
|
|
14
14
|
renderOrder?: number
|
|
15
|
+
depthTest?: boolean
|
|
16
|
+
depthWrite?: boolean
|
|
15
17
|
interactionLayers?: InteractionLayerValue[]
|
|
16
18
|
oncreate?: (positions: Float32Array, colors: Uint8Array | undefined) => void
|
|
17
19
|
}
|
|
18
20
|
|
|
19
|
-
let { data, name, renderOrder, interactionLayers, oncreate }: Props =
|
|
21
|
+
let { data, name, renderOrder, depthTest, depthWrite, interactionLayers, oncreate }: Props =
|
|
22
|
+
$props()
|
|
20
23
|
|
|
21
24
|
const world = useWorld()
|
|
22
25
|
|
|
@@ -38,6 +41,11 @@
|
|
|
38
41
|
if (renderOrder) {
|
|
39
42
|
entityTraits.push(traits.RenderOrder(renderOrder))
|
|
40
43
|
}
|
|
44
|
+
if (depthTest !== undefined || depthWrite !== undefined) {
|
|
45
|
+
entityTraits.push(
|
|
46
|
+
traits.Material({ depthTest: depthTest ?? true, depthWrite: depthWrite ?? true })
|
|
47
|
+
)
|
|
48
|
+
}
|
|
41
49
|
if (interactionLayers?.includes('selectTool')) {
|
|
42
50
|
entityTraits.push(traits.SelectToolInteractionLayer)
|
|
43
51
|
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
import { usePartID } from '../hooks/usePartID.svelte'
|
|
21
21
|
import { providePointcloudObjects } from '../hooks/usePointcloudObjects.svelte'
|
|
22
22
|
import { providePointclouds } from '../hooks/usePointclouds.svelte'
|
|
23
|
+
import { provideRelationships } from '../hooks/useRelationships.svelte'
|
|
23
24
|
import { provideResourceByName } from '../hooks/useResourceByName.svelte'
|
|
24
25
|
import { provideSelection } from '../hooks/useSelection.svelte'
|
|
25
26
|
import { provideWorldStates } from '../hooks/useWorldState.svelte'
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
|
|
42
43
|
provideOrigin()
|
|
43
44
|
provideDrawAPI()
|
|
45
|
+
provideRelationships()
|
|
44
46
|
provideDrawService()
|
|
45
47
|
|
|
46
48
|
provideResourceByName(() => partID.current)
|
|
@@ -14,17 +14,16 @@ Renders a Snapshot protobuf by spawning its transforms and drawings as entities
|
|
|
14
14
|
```
|
|
15
15
|
-->
|
|
16
16
|
<script lang="ts">
|
|
17
|
-
import type { Entity } from 'koota'
|
|
18
|
-
|
|
19
17
|
import { untrack } from 'svelte'
|
|
20
18
|
import { onDestroy } from 'svelte'
|
|
21
19
|
|
|
22
20
|
import type { Snapshot as SnapshotProto } from '../buf/draw/v1/snapshot_pb'
|
|
23
21
|
|
|
24
|
-
import { useWorld } from '../ecs'
|
|
22
|
+
import { traits, useWorld } from '../ecs'
|
|
25
23
|
import { useCameraControls } from '../hooks/useControls.svelte'
|
|
24
|
+
import { useRelationships } from '../hooks/useRelationships.svelte'
|
|
26
25
|
import { useSettings } from '../hooks/useSettings.svelte'
|
|
27
|
-
import { applySceneMetadata, spawnSnapshotEntities } from '../snapshot'
|
|
26
|
+
import { applySceneMetadata, type SnapshotEntity, spawnSnapshotEntities } from '../snapshot'
|
|
28
27
|
|
|
29
28
|
interface Props {
|
|
30
29
|
snapshot: SnapshotProto
|
|
@@ -35,8 +34,9 @@ Renders a Snapshot protobuf by spawning its transforms and drawings as entities
|
|
|
35
34
|
const world = useWorld()
|
|
36
35
|
const settings = useSettings()
|
|
37
36
|
const cameraControls = useCameraControls()
|
|
37
|
+
const relationships = useRelationships()
|
|
38
38
|
|
|
39
|
-
let entities:
|
|
39
|
+
let entities: SnapshotEntity[] = []
|
|
40
40
|
|
|
41
41
|
$effect(() => {
|
|
42
42
|
world.id.toString()
|
|
@@ -44,6 +44,11 @@ Renders a Snapshot protobuf by spawning its transforms and drawings as entities
|
|
|
44
44
|
|
|
45
45
|
untrack(() => {
|
|
46
46
|
entities = spawnSnapshotEntities(world, snapshot)
|
|
47
|
+
for (const spawned of entities) {
|
|
48
|
+
relationships.apply(spawned.entity, spawned.relationships)
|
|
49
|
+
const uuid = spawned.entity.get(traits.UUID)
|
|
50
|
+
if (uuid) relationships.flush(uuid)
|
|
51
|
+
}
|
|
47
52
|
})
|
|
48
53
|
})
|
|
49
54
|
|
|
@@ -78,8 +83,8 @@ Renders a Snapshot protobuf by spawning its transforms and drawings as entities
|
|
|
78
83
|
})
|
|
79
84
|
|
|
80
85
|
onDestroy(() => {
|
|
81
|
-
for (const
|
|
82
|
-
if (world.has(entity)) entity.destroy()
|
|
86
|
+
for (const spawned of entities) {
|
|
87
|
+
if (world.has(spawned.entity)) spawned.entity.destroy()
|
|
83
88
|
}
|
|
84
89
|
})
|
|
85
90
|
</script>
|
|
@@ -4,20 +4,30 @@
|
|
|
4
4
|
|
|
5
5
|
import { relations, traits, useQuery, useTrait } from '../../ecs'
|
|
6
6
|
import { SubEntityLinkType } from '../../ecs/relations'
|
|
7
|
+
import { useDrawService } from '../../hooks/useDrawService.svelte'
|
|
7
8
|
|
|
8
9
|
interface Props {
|
|
9
10
|
entity: Entity | undefined
|
|
10
11
|
}
|
|
11
12
|
|
|
12
13
|
const { entity }: Props = $props()
|
|
14
|
+
const drawService = useDrawService()
|
|
13
15
|
|
|
14
16
|
const allEntities = useQuery(traits.Name)
|
|
15
17
|
const name = useTrait(() => entity, traits.Name)
|
|
18
|
+
const drawServiceAPI = useTrait(() => entity, traits.DrawServiceAPI)
|
|
19
|
+
const isServiceManaged = $derived(!!drawServiceAPI.current)
|
|
20
|
+
|
|
16
21
|
const entityNames = $derived.by(() => {
|
|
17
22
|
const currentEntityName = name.current
|
|
18
23
|
return allEntities.current
|
|
19
|
-
.
|
|
20
|
-
|
|
24
|
+
.filter((e: Entity) => {
|
|
25
|
+
const entityName = e.get(traits.Name)
|
|
26
|
+
if (!entityName || entityName === currentEntityName) return false
|
|
27
|
+
if (isServiceManaged) return !!e.get(traits.DrawServiceAPI)
|
|
28
|
+
return true
|
|
29
|
+
})
|
|
30
|
+
.map((e: Entity) => e.get(traits.Name)!)
|
|
21
31
|
.toSorted()
|
|
22
32
|
})
|
|
23
33
|
|
|
@@ -43,7 +53,19 @@
|
|
|
43
53
|
const selectedEntity = allEntities.current.find(
|
|
44
54
|
(e: Entity) => e.get(traits.Name) === selectedRelationshipEntity
|
|
45
55
|
)
|
|
46
|
-
if (selectedEntity)
|
|
56
|
+
if (!selectedEntity) return
|
|
57
|
+
|
|
58
|
+
if (isServiceManaged) {
|
|
59
|
+
const sourceUuid = entity.get(traits.UUID)
|
|
60
|
+
const targetUuid = selectedEntity.get(traits.UUID)
|
|
61
|
+
if (!sourceUuid || !targetUuid) return
|
|
62
|
+
void drawService.createRelationship(
|
|
63
|
+
sourceUuid,
|
|
64
|
+
targetUuid,
|
|
65
|
+
linkType ?? '',
|
|
66
|
+
relationshipFormula
|
|
67
|
+
)
|
|
68
|
+
} else {
|
|
47
69
|
entity.add(
|
|
48
70
|
relations.SubEntityLink(selectedEntity, {
|
|
49
71
|
indexMapping: relationshipFormula,
|