@viamrobotics/motion-tools 1.30.0 → 1.32.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/components/App.svelte +51 -46
- package/dist/components/App.svelte.d.ts +1 -1
- package/dist/components/Entities/Arrows/Arrows.svelte +4 -7
- package/dist/components/Entities/hooks/useEntityEvents.svelte.d.ts +0 -1
- package/dist/components/Entities/hooks/useEntityEvents.svelte.js +30 -16
- package/dist/components/InputBindings.svelte +0 -43
- package/dist/components/KeyboardBindings.svelte +38 -0
- package/dist/components/KeyboardBindings.svelte.d.ts +18 -0
- package/dist/components/PointerMissBox.svelte +6 -3
- package/dist/components/Scene.svelte +34 -45
- package/dist/components/SceneProviders.svelte +2 -4
- package/dist/components/SceneProviders.svelte.d.ts +1 -3
- package/dist/components/Selected.svelte +20 -27
- package/dist/components/SelectedTransformControls.svelte +10 -8
- package/dist/components/StaticGeometries.svelte +3 -5
- package/dist/components/hover/HoveredEntities.svelte +15 -14
- package/dist/components/hover/HoveredEntities.svelte.d.ts +17 -2
- package/dist/components/hover/HoveredEntity.svelte +8 -5
- package/dist/components/hover/HoveredEntity.svelte.d.ts +5 -1
- package/dist/components/hover/LinkedHoveredEntity.svelte +7 -11
- package/dist/components/hover/LinkedHoveredEntity.svelte.d.ts +1 -0
- package/dist/components/overlay/Details.svelte +24 -38
- package/dist/components/overlay/Details.svelte.d.ts +3 -1
- package/dist/components/overlay/controls/Controls.svelte +0 -2
- package/dist/components/overlay/dashboard/Button.svelte +5 -3
- package/dist/components/overlay/dashboard/Button.svelte.d.ts +1 -1
- package/dist/components/overlay/left-pane/Tree.svelte +13 -10
- package/dist/components/overlay/left-pane/TreeContainer.svelte +9 -4
- package/dist/components/overlay/left-pane/TreeNode.svelte +6 -4
- package/dist/draw.d.ts +1 -0
- package/dist/draw.js +1 -1
- package/dist/ecs/index.d.ts +1 -0
- package/dist/ecs/index.js +1 -0
- package/dist/ecs/traits.d.ts +22 -5
- package/dist/ecs/traits.js +33 -4
- package/dist/ecs/useTag.svelte.d.ts +5 -0
- package/dist/ecs/useTag.svelte.js +43 -0
- package/dist/hooks/useConfigFrames.svelte.js +1 -1
- package/dist/hooks/useEnvironment.svelte.d.ts +1 -1
- package/dist/hooks/useLinked.svelte.js +7 -8
- package/dist/hooks/useMouseRaycaster.svelte.d.ts +4 -3
- package/dist/hooks/useMouseRaycaster.svelte.js +1 -0
- package/dist/hooks/useSettings.svelte.d.ts +1 -1
- package/dist/lib.d.ts +1 -0
- package/dist/lib.js +1 -0
- package/dist/loaders/pcd/worker.inline.d.ts +1 -1
- package/dist/loaders/pcd/worker.inline.js +1 -1
- package/dist/loaders/pcd/worker.js +3 -1
- package/dist/plugins/Focus/Focus.svelte +45 -0
- package/dist/plugins/Focus/Focus.svelte.d.ts +3 -0
- package/dist/plugins/Focus/FocusBox.svelte +75 -0
- package/dist/plugins/Focus/FocusBox.svelte.d.ts +3 -0
- package/dist/plugins/Focus/provideFocus.svelte.d.ts +1 -0
- package/dist/plugins/Focus/provideFocus.svelte.js +61 -0
- package/dist/{components → plugins}/MeasureTool/MeasureTool.svelte +6 -8
- package/dist/plugins/Selection/Ellipse.svelte +21 -16
- package/dist/plugins/Selection/Lasso.svelte +21 -16
- package/dist/plugins/Selection/SelectionTool.svelte +10 -3
- package/dist/plugins/Selection/relations.d.ts +6 -0
- package/dist/plugins/Selection/relations.js +7 -0
- package/dist/plugins/Selection/traits.d.ts +0 -5
- package/dist/plugins/Selection/traits.js +1 -6
- package/dist/plugins/index.d.ts +3 -0
- package/dist/plugins/index.js +3 -0
- package/dist/snapshot.d.ts +14 -0
- package/dist/snapshot.js +23 -0
- package/dist/three/arrow.d.ts +2 -0
- package/dist/three/arrow.js +3 -1
- package/package.json +17 -5
- package/dist/components/Focus.svelte +0 -46
- package/dist/components/Focus.svelte.d.ts +0 -7
- package/dist/hooks/useSelection.svelte.d.ts +0 -33
- package/dist/hooks/useSelection.svelte.js +0 -94
- /package/dist/{components → plugins}/MeasureTool/MeasurePoint.svelte +0 -0
- /package/dist/{components → plugins}/MeasureTool/MeasurePoint.svelte.d.ts +0 -0
- /package/dist/{components → plugins}/MeasureTool/MeasureTool.svelte.d.ts +0 -0
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import { useThrelte } from '@threlte/core'
|
|
2
3
|
import { TransformControls } from '@threlte/extras'
|
|
3
4
|
import { Matrix4, Quaternion, Vector3 } from 'three'
|
|
4
5
|
|
|
5
6
|
import type { FrameEditSession } from '../editing/FrameEditSession'
|
|
6
7
|
|
|
7
|
-
import { relations, traits, useTrait } from '../ecs'
|
|
8
|
+
import { relations, traits, useQuery, useTrait } from '../ecs'
|
|
8
9
|
import { useTransformControls } from '../hooks/useControls.svelte'
|
|
9
10
|
import { useEnvironment } from '../hooks/useEnvironment.svelte'
|
|
10
11
|
import { useFrameEditSession } from '../hooks/useFrameEditSession.svelte'
|
|
11
12
|
import { usePartConfig } from '../hooks/usePartConfig.svelte'
|
|
12
|
-
import { useSelectedEntity, useSelectedObject3d } from '../hooks/useSelection.svelte'
|
|
13
13
|
import { useSettings } from '../hooks/useSettings.svelte'
|
|
14
14
|
import {
|
|
15
15
|
createPose,
|
|
@@ -20,16 +20,17 @@
|
|
|
20
20
|
vector3ToPose,
|
|
21
21
|
} from '../transform'
|
|
22
22
|
|
|
23
|
+
const { scene } = useThrelte()
|
|
23
24
|
const settings = useSettings()
|
|
24
25
|
const environment = useEnvironment()
|
|
25
26
|
const partConfig = usePartConfig()
|
|
26
27
|
const transformControls = useTransformControls()
|
|
27
|
-
const selectedEntity = useSelectedEntity()
|
|
28
|
-
const selectedObject3d = useSelectedObject3d()
|
|
29
28
|
const sessions = useFrameEditSession()
|
|
29
|
+
const selected = useQuery(traits.Selected)
|
|
30
30
|
|
|
31
31
|
const mode = $derived(settings.current.transformMode)
|
|
32
|
-
const entity = $derived(
|
|
32
|
+
const entity = $derived(selected.current[0])
|
|
33
|
+
const object3d = $derived(scene.getObjectByName(entity as unknown as string))
|
|
33
34
|
const transformable = useTrait(() => entity, traits.Transformable)
|
|
34
35
|
const invisible = useTrait(() => entity, traits.InheritedInvisible)
|
|
35
36
|
const configMatrix = useTrait(() => entity, traits.Matrix)
|
|
@@ -43,14 +44,15 @@
|
|
|
43
44
|
)
|
|
44
45
|
const isFragmentComponentWithVariables = $derived(
|
|
45
46
|
name.current &&
|
|
46
|
-
Object.keys(partConfig.componentNameToFragmentInfo[name.current]?.variables ?? {}).length >
|
|
47
|
+
Object.keys(partConfig.componentNameToFragmentInfo?.[name.current]?.variables ?? {}).length >
|
|
48
|
+
0
|
|
47
49
|
)
|
|
48
50
|
|
|
49
|
-
// Mesh sets name={entity} on its inner mesh, so
|
|
51
|
+
// Mesh sets name={entity} on its inner mesh, so getObjectByName resolves
|
|
50
52
|
// to that mesh — not the parent Frame Group we actually want to drive. Walk
|
|
51
53
|
// up to the Group so translate/rotate/scale apply to the whole frame, not
|
|
52
54
|
// the geometry inside it.
|
|
53
|
-
const ref = $derived(
|
|
55
|
+
const ref = $derived(object3d?.parent ?? object3d)
|
|
54
56
|
|
|
55
57
|
const activeMode = $derived.by<'translate' | 'rotate' | 'scale' | undefined>(() => {
|
|
56
58
|
if (mode === 'none' || !transformable.current) return
|
|
@@ -11,17 +11,16 @@
|
|
|
11
11
|
import { PressedKeys } from 'runed'
|
|
12
12
|
import { SvelteSet } from 'svelte/reactivity'
|
|
13
13
|
|
|
14
|
-
import { traits, useWorld } from '../ecs'
|
|
15
|
-
import { useSelectedEntity } from '../hooks/useSelection.svelte'
|
|
14
|
+
import { traits, useQuery, useWorld } from '../ecs'
|
|
16
15
|
|
|
17
16
|
import Frame from './Entities/Frame.svelte'
|
|
18
17
|
|
|
19
18
|
const world = useWorld()
|
|
20
|
-
const
|
|
19
|
+
const selected = useQuery(traits.Selected)
|
|
21
20
|
|
|
22
21
|
const entities = new SvelteSet<Entity>()
|
|
23
22
|
const selectedCustomGeometry = $derived(
|
|
24
|
-
[...entities].find((entity) => entity ===
|
|
23
|
+
[...entities].find((entity) => entity === selected.current[0])
|
|
25
24
|
)
|
|
26
25
|
|
|
27
26
|
const keys = new PressedKeys()
|
|
@@ -43,7 +42,6 @@
|
|
|
43
42
|
const entity = selectedCustomGeometry
|
|
44
43
|
entity.destroy()
|
|
45
44
|
entities.delete(entity)
|
|
46
|
-
selectedEntity.set()
|
|
47
45
|
}
|
|
48
46
|
})
|
|
49
47
|
</script>
|
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { traits, useTrait } from '../../ecs'
|
|
2
|
+
import { traits, useQuery, useTrait } from '../../ecs'
|
|
3
3
|
import { useLinkedEntities } from '../../hooks/useLinked.svelte'
|
|
4
|
-
import { useSelectedEntity } from '../../hooks/useSelection.svelte'
|
|
5
|
-
import { useFocusedEntity } from '../../hooks/useSelection.svelte'
|
|
6
4
|
|
|
7
5
|
import HoveredEntity from './HoveredEntity.svelte'
|
|
8
6
|
import LinkedHoveredEntity from './LinkedHoveredEntity.svelte'
|
|
9
7
|
|
|
10
|
-
const selectedEntity = useSelectedEntity()
|
|
11
|
-
const focusedEntity = useFocusedEntity()
|
|
12
8
|
const linkedEntities = useLinkedEntities()
|
|
13
|
-
|
|
14
|
-
const displayEntity = $derived(selectedEntity.current ?? focusedEntity.current)
|
|
15
|
-
const isHovered = useTrait(() => displayEntity, traits.Hovered)
|
|
9
|
+
const selected = useQuery(traits.Selected)
|
|
16
10
|
</script>
|
|
17
11
|
|
|
18
|
-
{#
|
|
19
|
-
|
|
12
|
+
{#each selected.current as entity (entity)}
|
|
13
|
+
{@const isHovered = useTrait(() => entity, traits.Hovered)}
|
|
14
|
+
|
|
15
|
+
{#if isHovered}
|
|
16
|
+
<HoveredEntity {entity} />
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
{
|
|
18
|
+
{#each linkedEntities.current as linkedEntity (linkedEntity)}
|
|
19
|
+
<LinkedHoveredEntity
|
|
20
|
+
{linkedEntity}
|
|
21
|
+
{entity}
|
|
22
|
+
/>
|
|
23
|
+
{/each}
|
|
24
|
+
{/if}
|
|
25
|
+
{/each}
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
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> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const HoveredEntities: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type HoveredEntities = InstanceType<typeof HoveredEntities>;
|
|
3
18
|
export default HoveredEntities;
|
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import type { Entity } from 'koota'
|
|
3
|
+
|
|
2
4
|
import { MathUtils, Quaternion, Vector3 } from 'three'
|
|
3
5
|
|
|
4
6
|
import type { HoverInfo } from '../../HoverUpdater.svelte'
|
|
5
7
|
|
|
6
8
|
import { traits, useTrait } from '../../ecs'
|
|
7
|
-
import { useFocusedEntity, useSelectedEntity } from '../../hooks/useSelection.svelte'
|
|
8
9
|
import { OrientationVector } from '../../three/OrientationVector'
|
|
9
10
|
|
|
10
11
|
import HoveredEntityTooltip from './HoveredEntityTooltip.svelte'
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
interface Props {
|
|
14
|
+
entity: Entity
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let { entity }: Props = $props()
|
|
14
18
|
|
|
15
|
-
const
|
|
16
|
-
const instancedMatrix = useTrait(() => displayEntity, traits.InstancedMatrix)
|
|
19
|
+
const instancedMatrix = useTrait(() => entity, traits.InstancedMatrix)
|
|
17
20
|
|
|
18
21
|
// Pool: InstancedMatrix's `Matrix4` is in metres (matches Three.js).
|
|
19
22
|
// Decompose for the tooltip's display, which expects metres for position
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Entity } from 'koota';
|
|
2
|
+
interface Props {
|
|
3
|
+
entity: Entity;
|
|
4
|
+
}
|
|
5
|
+
declare const HoveredEntity: import("svelte").Component<Props, {}, "">;
|
|
2
6
|
type HoveredEntity = ReturnType<typeof HoveredEntity>;
|
|
3
7
|
export default HoveredEntity;
|
|
@@ -5,36 +5,32 @@
|
|
|
5
5
|
|
|
6
6
|
import { relations, traits, useTrait } from '../../ecs'
|
|
7
7
|
import { SubEntityLinkType } from '../../ecs/relations'
|
|
8
|
-
import { useSelectedEntity } from '../../hooks/useSelection.svelte'
|
|
9
|
-
import { useFocusedEntity } from '../../hooks/useSelection.svelte'
|
|
10
8
|
import { getLinkedHoverInfo, type HoverInfo } from '../../HoverUpdater.svelte'
|
|
11
9
|
|
|
12
10
|
import HoveredEntityTooltip from './HoveredEntityTooltip.svelte'
|
|
13
11
|
|
|
14
12
|
interface Props {
|
|
15
13
|
linkedEntity: Entity
|
|
14
|
+
entity: Entity
|
|
16
15
|
}
|
|
17
16
|
|
|
18
|
-
let { linkedEntity }: Props = $props()
|
|
17
|
+
let { linkedEntity, entity }: Props = $props()
|
|
19
18
|
|
|
20
|
-
const
|
|
21
|
-
const focusedEntity = useFocusedEntity()
|
|
22
|
-
const displayEntity = $derived(selectedEntity.current ?? focusedEntity.current)
|
|
23
|
-
|
|
24
|
-
const displayedHoverInfo = useTrait(() => displayEntity, traits.InstancedMatrix)
|
|
19
|
+
const displayedHoverInfo = useTrait(() => entity, traits.InstancedMatrix)
|
|
25
20
|
|
|
26
21
|
let hoverInfo = $state.raw<HoverInfo | null>(null)
|
|
27
22
|
|
|
28
23
|
$effect(() => {
|
|
29
|
-
if (
|
|
30
|
-
const linkType =
|
|
24
|
+
if (entity && displayedHoverInfo.current) {
|
|
25
|
+
const linkType = entity?.get(relations.SubEntityLink(linkedEntity))?.type
|
|
31
26
|
if (linkType !== SubEntityLinkType.HoverLink) {
|
|
32
27
|
return
|
|
33
28
|
}
|
|
29
|
+
|
|
34
30
|
// Index mapping is a formula with the variable 'index' in it.
|
|
35
31
|
// Supported operations: https://github.com/cshaa/filtrex#expressions
|
|
36
32
|
const indexMapping =
|
|
37
|
-
|
|
33
|
+
entity?.get(relations.SubEntityLink(linkedEntity))?.indexMapping ?? 'index'
|
|
38
34
|
const evaluate = compileExpression(indexMapping)
|
|
39
35
|
const resolvedIndex = evaluate({ index: displayedHoverInfo.current.index })
|
|
40
36
|
const linkedHoverInfo = getLinkedHoverInfo(resolvedIndex, linkedEntity)
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import type { Pose } from '@viamrobotics/sdk'
|
|
16
16
|
import type { Entity } from 'koota'
|
|
17
17
|
import type { Snippet } from 'svelte'
|
|
18
|
+
import type { HTMLAttributes } from 'svelte/elements'
|
|
18
19
|
|
|
19
20
|
import { draggable } from '@neodrag/svelte'
|
|
20
21
|
import { isInstanceOf, useThrelte } from '@threlte/core'
|
|
@@ -46,38 +47,28 @@
|
|
|
46
47
|
import { usePartConfig } from '../../hooks/usePartConfig.svelte'
|
|
47
48
|
import { usePartID } from '../../hooks/usePartID.svelte'
|
|
48
49
|
import { useResourceByName } from '../../hooks/useResourceByName.svelte'
|
|
49
|
-
import {
|
|
50
|
-
useFocusedEntity,
|
|
51
|
-
useFocusedObject3d,
|
|
52
|
-
useSelectedEntity,
|
|
53
|
-
useSelectedObject3d,
|
|
54
|
-
} from '../../hooks/useSelection.svelte'
|
|
55
50
|
import { useSettings } from '../../hooks/useSettings.svelte'
|
|
56
51
|
import { createPose, matrixToPose } from '../../transform'
|
|
57
52
|
|
|
58
|
-
interface Props {
|
|
53
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
54
|
+
entity: Entity
|
|
59
55
|
details?: Snippet<[{ entity: Entity }]>
|
|
60
56
|
}
|
|
61
57
|
|
|
62
|
-
const { details }: Props = $props()
|
|
58
|
+
const { entity, details, ...rest }: Props = $props()
|
|
63
59
|
|
|
64
60
|
const world = useWorld()
|
|
65
|
-
const { invalidate } = useThrelte()
|
|
61
|
+
const { scene, invalidate } = useThrelte()
|
|
66
62
|
const controls = useCameraControls()
|
|
67
63
|
const resourceByName = useResourceByName()
|
|
68
64
|
const configFrames = useConfigFrames()
|
|
69
65
|
const partConfig = usePartConfig()
|
|
70
66
|
const partID = usePartID()
|
|
71
67
|
const settings = useSettings()
|
|
72
|
-
const selectedEntity = useSelectedEntity()
|
|
73
|
-
const selectedObject3d = useSelectedObject3d()
|
|
74
68
|
const environment = useEnvironment()
|
|
75
|
-
const focusedEntity = useFocusedEntity()
|
|
76
|
-
const focusedObject3d = useFocusedObject3d()
|
|
77
69
|
const linkedEntities = useLinkedEntities()
|
|
78
70
|
|
|
79
|
-
const
|
|
80
|
-
const object3d = $derived(focusedObject3d.current ?? selectedObject3d.current)
|
|
71
|
+
const object3d = $derived(scene.getObjectByName(entity as unknown as string))
|
|
81
72
|
|
|
82
73
|
const name = useTrait(() => entity, traits.Name)
|
|
83
74
|
const parent = useParentName(() => entity)
|
|
@@ -111,7 +102,8 @@
|
|
|
111
102
|
const isGeometry = $derived(!!geometriesAPI.current)
|
|
112
103
|
const isFragmentComponentWithVariables = $derived(
|
|
113
104
|
name.current &&
|
|
114
|
-
Object.keys(partConfig.componentNameToFragmentInfo[name.current]?.variables ?? {}).length >
|
|
105
|
+
Object.keys(partConfig.componentNameToFragmentInfo?.[name.current]?.variables ?? {}).length >
|
|
106
|
+
0
|
|
115
107
|
)
|
|
116
108
|
const showEditFrameOptions = $derived(
|
|
117
109
|
isFrameNode && partConfig.hasEditPermissions && !isFragmentComponentWithVariables
|
|
@@ -128,8 +120,7 @@
|
|
|
128
120
|
})
|
|
129
121
|
|
|
130
122
|
const geometryTypes = ['none', 'box', 'sphere', 'capsule'] as const
|
|
131
|
-
|
|
132
|
-
// can write a transient override that lasts until the trait re-derives.
|
|
123
|
+
|
|
133
124
|
let geometryTabIndex = $derived(geometryTypes.indexOf(geometryType))
|
|
134
125
|
|
|
135
126
|
$effect(() => {
|
|
@@ -155,6 +146,10 @@
|
|
|
155
146
|
|
|
156
147
|
const detailConfigUpdater = new FrameConfigUpdater(partConfig.updateFrame, partConfig.deleteFrame)
|
|
157
148
|
|
|
149
|
+
const stopKeyboardPropagation = (event: KeyboardEvent) => {
|
|
150
|
+
event.stopPropagation()
|
|
151
|
+
}
|
|
152
|
+
|
|
158
153
|
const handlePositionChange = (event: PointChangeEvent) => {
|
|
159
154
|
if (event.detail.origin !== 'internal' || !entity) return
|
|
160
155
|
const next = event.detail.value as PointValue3dObject
|
|
@@ -311,13 +306,21 @@
|
|
|
311
306
|
{/snippet}
|
|
312
307
|
|
|
313
308
|
{#if entity}
|
|
309
|
+
<!-- tabindex makes the whole panel focusable so a click anywhere in it (not
|
|
310
|
+
just the inputs) raises it via `focus-within:z-5`. -->
|
|
314
311
|
<div
|
|
315
312
|
id="details-panel"
|
|
316
|
-
class="border-medium bg-extralight absolute top-0 right-0 z-4 m-2 w-70 border p-2 text-xs"
|
|
313
|
+
class="border-medium bg-extralight absolute top-0 right-0 z-4 m-2 w-70 border p-2 text-xs focus-within:z-5"
|
|
314
|
+
role="region"
|
|
315
|
+
aria-label="Details panel"
|
|
316
|
+
tabindex="-1"
|
|
317
|
+
onkeydown={stopKeyboardPropagation}
|
|
318
|
+
onkeyup={stopKeyboardPropagation}
|
|
317
319
|
use:draggable={{
|
|
318
320
|
bounds: 'body',
|
|
319
321
|
handle: dragElement,
|
|
320
322
|
}}
|
|
323
|
+
{...rest}
|
|
321
324
|
>
|
|
322
325
|
<div
|
|
323
326
|
class="flex cursor-move items-center justify-between gap-2 pb-2"
|
|
@@ -767,25 +770,8 @@
|
|
|
767
770
|
|
|
768
771
|
{@render details?.({ entity })}
|
|
769
772
|
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
{#if focusedEntity.current}
|
|
773
|
-
<Button
|
|
774
|
-
class="w-full"
|
|
775
|
-
icon="arrow-left"
|
|
776
|
-
variant="dark"
|
|
777
|
-
onclick={() => focusedEntity.set()}
|
|
778
|
-
>
|
|
779
|
-
Exit object view
|
|
780
|
-
</Button>
|
|
781
|
-
{:else}
|
|
782
|
-
<Button
|
|
783
|
-
class="w-full"
|
|
784
|
-
icon="image-filter-center-focus"
|
|
785
|
-
onclick={() => focusedEntity.set(entity)}
|
|
786
|
-
>
|
|
787
|
-
Enter object view
|
|
788
|
-
</Button>
|
|
773
|
+
{#if showRelationshipOptions || (showEditFrameOptions && environment.current.isStandalone)}
|
|
774
|
+
<h3 class="text-subtle-2 pt-3 pb-2">Actions</h3>
|
|
789
775
|
{/if}
|
|
790
776
|
|
|
791
777
|
{#if showRelationshipOptions}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { Entity } from 'koota';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
-
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
entity: Entity;
|
|
4
6
|
details?: Snippet<[{
|
|
5
7
|
entity: Entity;
|
|
6
8
|
}]>;
|
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
|
|
17
17
|
<fieldset class="flex flex-col">
|
|
18
18
|
<Button
|
|
19
|
-
active
|
|
20
19
|
class="rounded-b-none"
|
|
21
20
|
icon="camera-outline"
|
|
22
21
|
description="Reset camera"
|
|
@@ -26,7 +25,6 @@
|
|
|
26
25
|
}}
|
|
27
26
|
/>
|
|
28
27
|
<Button
|
|
29
|
-
active
|
|
30
28
|
class="-my-0.5 rounded-t-none"
|
|
31
29
|
icon={isOrthographic ? 'grid-orthographic' : 'grid-perspective'}
|
|
32
30
|
description={isOrthographic ? 'Switch to perspective view' : 'Switch to orthographic view'}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import type { ClassValue, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements'
|
|
3
3
|
|
|
4
4
|
import { Icon, type IconName, Tooltip } from '@viamrobotics/prime-core'
|
|
5
|
-
import { MousePointer2, Ruler } from 'lucide-svelte'
|
|
5
|
+
import { Focus, MousePointer2, Ruler } from 'lucide-svelte'
|
|
6
6
|
|
|
7
7
|
interface Props extends HTMLButtonAttributes {
|
|
8
|
-
icon: IconName | 'ruler' | 'mouse-pointer'
|
|
8
|
+
icon: IconName | 'ruler' | 'mouse-pointer' | 'focus'
|
|
9
9
|
active?: boolean
|
|
10
10
|
description: string
|
|
11
11
|
hotkey?: string
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<label
|
|
34
34
|
class={[
|
|
35
35
|
className,
|
|
36
|
-
'relative block rounded-md border',
|
|
36
|
+
'relative block rounded-md border active:z-4 active:border-[#666] active:bg-[#666] active:text-white',
|
|
37
37
|
active ? 'z-4 border-[#666] bg-[#666] text-white' : 'border-gray-5 text-gray-8 bg-white',
|
|
38
38
|
]}
|
|
39
39
|
aria-describedby={tooltipID}
|
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
<Ruler size="16" />
|
|
51
51
|
{:else if icon === 'mouse-pointer'}
|
|
52
52
|
<MousePointer2 size="16" />
|
|
53
|
+
{:else if icon === 'focus'}
|
|
54
|
+
<Focus size="16" />
|
|
53
55
|
{:else}
|
|
54
56
|
<Icon name={icon} />
|
|
55
57
|
{/if}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClassValue, HTMLButtonAttributes, MouseEventHandler } from 'svelte/elements';
|
|
2
2
|
import { type IconName } from '@viamrobotics/prime-core';
|
|
3
3
|
interface Props extends HTMLButtonAttributes {
|
|
4
|
-
icon: IconName | 'ruler' | 'mouse-pointer';
|
|
4
|
+
icon: IconName | 'ruler' | 'mouse-pointer' | 'focus';
|
|
5
5
|
active?: boolean;
|
|
6
6
|
description: string;
|
|
7
7
|
hotkey?: string;
|
|
@@ -6,15 +6,12 @@
|
|
|
6
6
|
import { VirtualList } from 'svelte-virtuallists'
|
|
7
7
|
import { SvelteSet } from 'svelte/reactivity'
|
|
8
8
|
|
|
9
|
-
import { relations, traits } from '../../../ecs'
|
|
10
|
-
import { useSelectedEntity } from '../../../hooks/useSelection.svelte'
|
|
9
|
+
import { relations, traits, useQuery } from '../../../ecs'
|
|
11
10
|
|
|
12
11
|
import type { TreeNode as TreeNodeType } from './useTree.svelte'
|
|
13
12
|
|
|
14
13
|
import TreeNode from './TreeNode.svelte'
|
|
15
14
|
|
|
16
|
-
const selected = useSelectedEntity()
|
|
17
|
-
|
|
18
15
|
interface Props {
|
|
19
16
|
rootNode: TreeNodeType
|
|
20
17
|
dragElement?: HTMLElement
|
|
@@ -31,14 +28,18 @@
|
|
|
31
28
|
})
|
|
32
29
|
)
|
|
33
30
|
|
|
34
|
-
const
|
|
31
|
+
const selected = useQuery(traits.Selected)
|
|
32
|
+
|
|
33
|
+
const selectedValue = $derived(selected.current.map((entity) => `${entity}`))
|
|
35
34
|
const expandedValues = new SvelteSet<string>()
|
|
36
35
|
|
|
37
36
|
$effect(() => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
for (const entity of selected.current) {
|
|
38
|
+
let ancestor: Entity | undefined = entity.targetFor(relations.ChildOf)
|
|
39
|
+
while (ancestor) {
|
|
40
|
+
expandedValues.add(`${ancestor}`)
|
|
41
|
+
ancestor = ancestor.targetFor(relations.ChildOf)
|
|
42
|
+
}
|
|
42
43
|
}
|
|
43
44
|
})
|
|
44
45
|
|
|
@@ -46,6 +47,8 @@
|
|
|
46
47
|
const service = useMachine(tree.machine, () => ({
|
|
47
48
|
id,
|
|
48
49
|
collection,
|
|
50
|
+
selectionMode: 'multiple' as const,
|
|
51
|
+
expandOnClick: false,
|
|
49
52
|
selectedValue,
|
|
50
53
|
expandedValue: [...expandedValues],
|
|
51
54
|
onSelectionChange(details) {
|
|
@@ -64,7 +67,7 @@
|
|
|
64
67
|
|
|
65
68
|
$effect(() => {
|
|
66
69
|
const element = document.querySelector(
|
|
67
|
-
`[data-scope="tree-view"][data-value="${selected.current}"]`
|
|
70
|
+
`[data-scope="tree-view"][data-value="${selected.current.at(-1)}"]`
|
|
68
71
|
)
|
|
69
72
|
|
|
70
73
|
requestAnimationFrame(() => {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { type Entity, IsExcluded } from 'koota'
|
|
3
3
|
|
|
4
4
|
import { traits, useWorld } from '../../../ecs'
|
|
5
|
-
import { useSelectedEntity } from '../../../hooks/useSelection.svelte'
|
|
6
5
|
|
|
7
6
|
import FloatingPanel from '../FloatingPanel.svelte'
|
|
8
7
|
import Tree from './Tree.svelte'
|
|
@@ -11,7 +10,6 @@
|
|
|
11
10
|
|
|
12
11
|
provideTreeExpandedContext()
|
|
13
12
|
|
|
14
|
-
const selectedEntity = useSelectedEntity()
|
|
15
13
|
const world = useWorld()
|
|
16
14
|
|
|
17
15
|
const worldEntity = world.spawn(IsExcluded, traits.Name('World'))
|
|
@@ -35,9 +33,16 @@
|
|
|
35
33
|
<Tree
|
|
36
34
|
{rootNode}
|
|
37
35
|
onSelectionChange={(event) => {
|
|
38
|
-
const
|
|
36
|
+
const next = new Set(event.selectedValue.map(Number))
|
|
39
37
|
|
|
40
|
-
|
|
38
|
+
for (const entity of world.query(traits.Selected)) {
|
|
39
|
+
if (!next.has(entity as number)) entity.remove(traits.Selected)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (const id of next) {
|
|
43
|
+
const entity = id as Entity
|
|
44
|
+
if (!entity.has(traits.Selected)) entity.add(traits.Selected)
|
|
45
|
+
}
|
|
41
46
|
}}
|
|
42
47
|
/>
|
|
43
48
|
</FloatingPanel>
|
|
@@ -63,12 +63,14 @@
|
|
|
63
63
|
]}
|
|
64
64
|
>
|
|
65
65
|
<div {...api.getBranchControlProps(nodeProps)}>
|
|
66
|
-
<
|
|
67
|
-
|
|
68
|
-
|
|
66
|
+
<button
|
|
67
|
+
type="button"
|
|
68
|
+
aria-label={expanded ? 'Collapse' : 'Expand'}
|
|
69
|
+
{...api.getBranchTriggerProps(nodeProps)}
|
|
70
|
+
class={['flex items-center', { 'rotate-90': expanded }]}
|
|
69
71
|
>
|
|
70
72
|
<ChevronRight size={14} />
|
|
71
|
-
</
|
|
73
|
+
</button>
|
|
72
74
|
<span
|
|
73
75
|
class="flex items-center overflow-hidden text-ellipsis"
|
|
74
76
|
{...api.getBranchTextProps(nodeProps)}
|
package/dist/draw.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { Transform as TransformProto } from './buf/common/v1/common_pb';
|
|
|
4
4
|
import type { Drawing } from './buf/draw/v1/drawing_pb';
|
|
5
5
|
import type { Relationship } from './metadata';
|
|
6
6
|
import { type Metadata } from './metadata';
|
|
7
|
+
export declare const DEFAULT_LINE_WIDTH = 5;
|
|
7
8
|
export type Transform = TransformWithUUID | TransformProto;
|
|
8
9
|
export declare const uuidBytesToString: (bytes: Uint8Array | undefined) => string | undefined;
|
|
9
10
|
export declare const uuidStringToBytes: (uuid: string) => Uint8Array<ArrayBuffer>;
|
package/dist/draw.js
CHANGED
|
@@ -11,7 +11,7 @@ import { ColorFormat } from './buf/draw/v1/metadata_pb';
|
|
|
11
11
|
import { isPointCloud } from './geometry';
|
|
12
12
|
const vec3 = new Vector3();
|
|
13
13
|
const rgb = { r: 0, g: 0, b: 0 };
|
|
14
|
-
const DEFAULT_LINE_WIDTH = 5;
|
|
14
|
+
export const DEFAULT_LINE_WIDTH = 5;
|
|
15
15
|
const DEFAULT_POINT_SIZE = 10;
|
|
16
16
|
const DEFAULT_NURBS_DEGREE = 3;
|
|
17
17
|
const DEFAULT_NURBS_WEIGHT = 1;
|
package/dist/ecs/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { provideWorld, useWorld } from './useWorld';
|
|
2
2
|
export { useQuery } from './useQuery.svelte';
|
|
3
3
|
export { useTrait } from './useTrait.svelte';
|
|
4
|
+
export { useTag } from './useTag.svelte';
|
|
4
5
|
export { useTarget } from './useTarget.svelte';
|
|
5
6
|
export { useParentName } from './useParentName.svelte';
|
|
6
7
|
export { provideHierarchy } from './provideHierarchy.svelte';
|
package/dist/ecs/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { provideWorld, useWorld } from './useWorld';
|
|
2
2
|
export { useQuery } from './useQuery.svelte';
|
|
3
3
|
export { useTrait } from './useTrait.svelte';
|
|
4
|
+
export { useTag } from './useTag.svelte';
|
|
4
5
|
export { useTarget } from './useTarget.svelte';
|
|
5
6
|
export { useParentName } from './useParentName.svelte';
|
|
6
7
|
export { provideHierarchy } from './provideHierarchy.svelte';
|
package/dist/ecs/traits.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { GLTF as ThreeGltf } from 'three/examples/jsm/loaders/GLTFLoader.js';
|
|
2
|
-
import { Geometry as ViamGeometry } from '@viamrobotics/sdk';
|
|
2
|
+
import { type Pose, Geometry as ViamGeometry } from '@viamrobotics/sdk';
|
|
3
3
|
import { type Entity } from 'koota';
|
|
4
4
|
import { Matrix4, BufferGeometry as ThreeBufferGeometry } from 'three';
|
|
5
5
|
export declare const Name: import("koota").Trait<() => string>;
|
|
@@ -65,6 +65,13 @@ export declare const InstancedMatrix: import("koota").Trait<() => {
|
|
|
65
65
|
}>;
|
|
66
66
|
export declare const Hovered: import("koota").Trait<() => boolean>;
|
|
67
67
|
export declare const Invisible: import("koota").Trait<() => boolean>;
|
|
68
|
+
/**
|
|
69
|
+
* Suppresses the default frame-style world/local pose and parent-frame blocks
|
|
70
|
+
* in the details panel. Entities that render their own pose UI via the
|
|
71
|
+
* `details-extensions` portal target (e.g. gizmo plugin entities) opt in by
|
|
72
|
+
* adding this trait.
|
|
73
|
+
*/
|
|
74
|
+
export declare const CustomDetails: import("koota").Trait<() => boolean>;
|
|
68
75
|
/**
|
|
69
76
|
* True when the entity itself, or any of its parents up the `ChildOf`
|
|
70
77
|
* chain, has `Invisible`. Maintained by `provideInheritedInvisible`;
|
|
@@ -76,11 +83,14 @@ export declare const InheritedInvisible: import("koota").Trait<() => boolean>;
|
|
|
76
83
|
* Represents that an entity is composed of many instances, so that the treeview and
|
|
77
84
|
* details panel may display all instances
|
|
78
85
|
*/
|
|
79
|
-
export declare const
|
|
86
|
+
export declare const InstanceId: import("koota").Trait<() => number>;
|
|
80
87
|
export declare const Instance: import("koota").Trait<{
|
|
81
88
|
meshID: number;
|
|
82
89
|
instanceID: number;
|
|
83
90
|
}>;
|
|
91
|
+
export declare const Instances: import("koota").Trait<{
|
|
92
|
+
count: number;
|
|
93
|
+
}>;
|
|
84
94
|
export declare const RenderOrder: import("koota").Trait<() => number>;
|
|
85
95
|
export declare const Opacity: import("koota").Trait<() => number>;
|
|
86
96
|
/**
|
|
@@ -108,9 +118,6 @@ export declare const Colors: import("koota").Trait<() => Uint8Array<ArrayBufferL
|
|
|
108
118
|
* Per-vertex opacity values packed as uint8 (0-255).
|
|
109
119
|
*/
|
|
110
120
|
export declare const Opacities: import("koota").Trait<() => Uint8Array<ArrayBuffer>>;
|
|
111
|
-
export declare const Instances: import("koota").Trait<{
|
|
112
|
-
count: number;
|
|
113
|
-
}>;
|
|
114
121
|
export declare const Arrows: import("koota").Trait<{
|
|
115
122
|
headAtPose: boolean;
|
|
116
123
|
}>;
|
|
@@ -205,6 +212,10 @@ export declare const ChunkProgress: import("koota").Trait<{
|
|
|
205
212
|
*/
|
|
206
213
|
export type InteractionLayerValue = 'selectTool';
|
|
207
214
|
export declare const SelectToolInteractionLayer: import("koota").Trait<() => boolean>;
|
|
215
|
+
/**
|
|
216
|
+
* This entity is selected by the user
|
|
217
|
+
*/
|
|
218
|
+
export declare const Selected: import("koota").TagTrait;
|
|
208
219
|
/**
|
|
209
220
|
* This entity can be safely removed from the scene by the user
|
|
210
221
|
*/
|
|
@@ -229,3 +240,9 @@ export declare const Geometry: (geometry: ViamGeometry) => import("koota").Trait
|
|
|
229
240
|
r: number;
|
|
230
241
|
}>] | [import("koota").Trait<() => ThreeBufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>>, ThreeBufferGeometry<import("three").NormalBufferAttributes, import("three").BufferGeometryEventMap>];
|
|
231
242
|
export declare const updateGeometryTrait: (entity: Entity, geometry?: ViamGeometry) => void;
|
|
243
|
+
/**
|
|
244
|
+
* Patches an entity's `Matrix` trait in-place via the `Pose` round-trip
|
|
245
|
+
* (`matrixToPose` → merge → `poseToMatrix`), then signals `entity.changed(Matrix)`.
|
|
246
|
+
* No-ops silently if the entity has no `Matrix` trait.
|
|
247
|
+
*/
|
|
248
|
+
export declare const writeMatrix: (entity: Entity, patch: Partial<Pose>) => void;
|