@viamrobotics/motion-tools 1.9.0 → 1.10.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/HoverUpdater.svelte.d.ts +19 -0
- package/dist/HoverUpdater.svelte.js +120 -0
- package/dist/components/App.svelte +34 -35
- package/dist/components/CameraControls.svelte +1 -1
- package/dist/components/Focus.svelte +1 -1
- package/dist/components/Frame.svelte +1 -1
- package/dist/components/Geometry2.svelte +8 -5
- package/dist/components/Label.svelte +1 -1
- package/dist/components/MeasureTool/MeasurePoint.svelte +5 -3
- package/dist/components/MeasureTool/MeasureTool.svelte +11 -11
- package/dist/components/SceneProviders.svelte +2 -0
- package/dist/components/hover/HoveredEntities.svelte +23 -0
- package/dist/components/hover/HoveredEntity.svelte +15 -0
- package/dist/components/hover/HoveredEntity.svelte.d.ts +3 -0
- package/dist/components/hover/HoveredEntityTooltip.svelte +70 -0
- package/dist/components/{HoveredEntityTooltip.svelte.d.ts → hover/HoveredEntityTooltip.svelte.d.ts} +2 -2
- package/dist/components/hover/LinkedHoveredEntity.svelte +55 -0
- package/dist/components/hover/LinkedHoveredEntity.svelte.d.ts +9 -0
- package/dist/components/overlay/AddRelationship.svelte +131 -0
- package/dist/components/overlay/AddRelationship.svelte.d.ts +7 -0
- package/dist/components/{Details.svelte → overlay/Details.svelte} +44 -11
- package/dist/components/overlay/FloatingPanel.svelte +78 -0
- package/dist/components/overlay/FloatingPanel.svelte.d.ts +13 -0
- package/dist/components/{LiveUpdatesBanner.svelte → overlay/LiveUpdatesBanner.svelte} +2 -2
- package/dist/components/{RefreshRate.svelte → overlay/RefreshRate.svelte} +1 -1
- package/dist/components/overlay/ToggleGroup.svelte +56 -0
- package/dist/components/{Overlay → overlay}/ToggleGroup.svelte.d.ts +6 -7
- package/dist/components/{__tests__ → overlay/__tests__}/__fixtures__/entity.js +1 -1
- package/dist/components/{dashboard → overlay/dashboard}/Button.svelte +1 -1
- package/dist/components/{dashboard → overlay/dashboard}/Dashboard.svelte +2 -2
- package/dist/components/{Tree → overlay/left-pane}/AddFrames.svelte +2 -2
- package/dist/components/{Tree → overlay/left-pane}/Logs.svelte +1 -1
- package/dist/components/{Tree → overlay/left-pane}/Tree.svelte +3 -3
- package/dist/components/{Tree → overlay/left-pane}/TreeContainer.svelte +8 -10
- package/dist/components/{Tree → overlay/left-pane}/Widgets.svelte +3 -3
- package/dist/components/{Tree → overlay/left-pane}/buildTree.js +1 -1
- package/dist/components/overlay/settings/Settings.svelte +279 -0
- package/dist/components/overlay/settings/Tabs.svelte +54 -0
- package/dist/components/overlay/settings/Tabs.svelte.d.ts +12 -0
- package/dist/components/{widgets → overlay/widgets}/ArmPositions.svelte +4 -4
- package/dist/components/{widgets → overlay/widgets}/Camera.svelte +5 -5
- package/dist/ecs/index.d.ts +1 -0
- package/dist/ecs/index.js +1 -0
- package/dist/ecs/relations.d.ts +7 -0
- package/dist/ecs/relations.js +7 -0
- package/dist/ecs/traits.d.ts +8 -2
- package/dist/ecs/traits.js +11 -5
- package/dist/hooks/useDrawAPI.svelte.js +1 -1
- package/dist/hooks/useFrames.svelte.js +1 -0
- package/dist/hooks/useGeometries.svelte.js +1 -1
- package/dist/hooks/useLinked.svelte.d.ts +7 -0
- package/dist/hooks/useLinked.svelte.js +35 -0
- package/dist/hooks/useObjectEvents.svelte.js +35 -16
- package/dist/hooks/usePointcloudObjects.svelte.js +1 -1
- package/dist/hooks/usePointclouds.svelte.js +30 -43
- package/dist/hooks/usePose.svelte.js +1 -1
- package/dist/hooks/useWorldState.svelte.js +1 -1
- package/package.json +4 -1
- package/dist/components/DotSprite.svelte +0 -59
- package/dist/components/DotSprite.svelte.d.ts +0 -10
- package/dist/components/HoveredEntities.svelte +0 -19
- package/dist/components/HoveredEntityTooltip.svelte +0 -241
- package/dist/components/MeasureTool.svelte +0 -123
- package/dist/components/MeasureTool.svelte.d.ts +0 -3
- package/dist/components/Overlay/ToggleGroup.svelte +0 -60
- package/dist/components/Tree/Settings.svelte +0 -221
- package/dist/components/null-states/Connection.svelte +0 -0
- package/dist/components/null-states/Connection.svelte.d.ts +0 -26
- /package/dist/components/{HoveredEntities.svelte.d.ts → hover/HoveredEntities.svelte.d.ts} +0 -0
- /package/dist/components/{Details.svelte.d.ts → overlay/Details.svelte.d.ts} +0 -0
- /package/dist/components/{LiveUpdatesBanner.svelte.d.ts → overlay/LiveUpdatesBanner.svelte.d.ts} +0 -0
- /package/dist/components/{Overlay → overlay}/Popover.svelte +0 -0
- /package/dist/components/{Overlay → overlay}/Popover.svelte.d.ts +0 -0
- /package/dist/components/{RefreshRate.svelte.d.ts → overlay/RefreshRate.svelte.d.ts} +0 -0
- /package/dist/components/{shared → overlay}/Table.svelte +0 -0
- /package/dist/components/{shared → overlay}/Table.svelte.d.ts +0 -0
- /package/dist/components/{__tests__ → overlay/__tests__}/__fixtures__/entity.d.ts +0 -0
- /package/dist/components/{__tests__ → overlay/__tests__}/__fixtures__/resource.d.ts +0 -0
- /package/dist/components/{__tests__ → overlay/__tests__}/__fixtures__/resource.js +0 -0
- /package/dist/components/{dashboard → overlay/dashboard}/Button.svelte.d.ts +0 -0
- /package/dist/components/{dashboard → overlay/dashboard}/Dashboard.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/AddFrames.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/Drawer.svelte +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/Drawer.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/Logs.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/Tree.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/TreeContainer.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/Widgets.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/buildTree.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/useExpanded.svelte.d.ts +0 -0
- /package/dist/components/{Tree → overlay/left-pane}/useExpanded.svelte.js +0 -0
- /package/dist/components/{Tree → overlay/settings}/Settings.svelte.d.ts +0 -0
- /package/dist/components/{widgets → overlay/widgets}/ArmPositions.svelte.d.ts +0 -0
- /package/dist/components/{widgets → overlay/widgets}/Camera.svelte.d.ts +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Vector3 } from 'three';
|
|
2
|
+
import type { Entity } from 'koota';
|
|
3
|
+
import type { IntersectionEvent } from '@threlte/extras';
|
|
4
|
+
export interface HoverInfo {
|
|
5
|
+
index: number;
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
z: number;
|
|
9
|
+
oX: number;
|
|
10
|
+
oY: number;
|
|
11
|
+
oZ: number;
|
|
12
|
+
theta: number;
|
|
13
|
+
}
|
|
14
|
+
export declare const getClosestArrow: (positions: Float32Array, point: Vector3) => HoverInfo;
|
|
15
|
+
export declare const getClosestPoint: (positions: Float32Array, point: Vector3) => HoverInfo;
|
|
16
|
+
export declare const getPointAtIndex: (positions: Float32Array, index: number) => HoverInfo | null;
|
|
17
|
+
export declare const getArrowAtIndex: (positions: Float32Array, index: number) => HoverInfo | null;
|
|
18
|
+
export declare const updateHoverInfo: (entity: Entity, hoverEvent: IntersectionEvent<MouseEvent>) => HoverInfo | null;
|
|
19
|
+
export declare const getLinkedHoverInfo: (index: number, linkedEntity: Entity) => HoverInfo | null;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Vector3 } from 'three';
|
|
2
|
+
import { traits } from './ecs';
|
|
3
|
+
const hoverPosition = new Vector3();
|
|
4
|
+
export const getClosestArrow = (positions, point) => {
|
|
5
|
+
let smallestDistance = Infinity;
|
|
6
|
+
let index = -1;
|
|
7
|
+
for (let i = 0; i < positions.length; i += 6) {
|
|
8
|
+
const x = positions[i] / 1000;
|
|
9
|
+
const y = positions[i + 1] / 1000;
|
|
10
|
+
const z = positions[i + 2] / 1000;
|
|
11
|
+
const distance = point.distanceToSquared({ x, y, z });
|
|
12
|
+
if (distance < smallestDistance) {
|
|
13
|
+
smallestDistance = distance;
|
|
14
|
+
index = i;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
index: Math.floor(index / 6),
|
|
19
|
+
x: positions[index] / 1000,
|
|
20
|
+
y: positions[index + 1] / 1000,
|
|
21
|
+
z: positions[index + 2] / 1000,
|
|
22
|
+
oX: positions[index + 3],
|
|
23
|
+
oY: positions[index + 4],
|
|
24
|
+
oZ: positions[index + 5],
|
|
25
|
+
theta: 0,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export const getClosestPoint = (positions, point) => {
|
|
29
|
+
let smallestDistance = Infinity;
|
|
30
|
+
let index = -1;
|
|
31
|
+
for (let i = 0; i < positions.length; i += 3) {
|
|
32
|
+
const x = positions[i];
|
|
33
|
+
const y = positions[i + 1];
|
|
34
|
+
const z = positions[i + 2];
|
|
35
|
+
const distance = point.distanceToSquared({ x, y, z });
|
|
36
|
+
if (distance < smallestDistance) {
|
|
37
|
+
smallestDistance = distance;
|
|
38
|
+
index = i;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
index: Math.floor(index / 3),
|
|
43
|
+
x: positions[index],
|
|
44
|
+
y: positions[index + 1],
|
|
45
|
+
z: positions[index + 2],
|
|
46
|
+
oX: 0,
|
|
47
|
+
oY: 0,
|
|
48
|
+
oZ: 0,
|
|
49
|
+
theta: 0,
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
export const getPointAtIndex = (positions, index) => {
|
|
53
|
+
if (index < 0 || index >= positions.length / 3) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
index,
|
|
58
|
+
x: positions[index * 3],
|
|
59
|
+
y: positions[index * 3 + 1],
|
|
60
|
+
z: positions[index * 3 + 2],
|
|
61
|
+
oX: 0,
|
|
62
|
+
oY: 0,
|
|
63
|
+
oZ: 0,
|
|
64
|
+
theta: 0,
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
export const getArrowAtIndex = (positions, index) => {
|
|
68
|
+
if (index < 0 || index >= positions.length / 6) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return {
|
|
72
|
+
index,
|
|
73
|
+
x: positions[index * 6] / 1000,
|
|
74
|
+
y: positions[index * 6 + 1] / 1000,
|
|
75
|
+
z: positions[index * 6 + 2] / 1000,
|
|
76
|
+
oX: positions[index * 6 + 3],
|
|
77
|
+
oY: positions[index * 6 + 4],
|
|
78
|
+
oZ: positions[index * 6 + 5],
|
|
79
|
+
theta: 0,
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
export const updateHoverInfo = (entity, hoverEvent) => {
|
|
83
|
+
const { index, point } = hoverEvent;
|
|
84
|
+
if (index === -1) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
hoverPosition.set(point.x, point.y, point.z);
|
|
88
|
+
let hoverInfo = null;
|
|
89
|
+
if (entity.has(traits.Arrows)) {
|
|
90
|
+
const closestArrow = getClosestArrow(entity.get(traits.Positions), hoverPosition);
|
|
91
|
+
if (closestArrow) {
|
|
92
|
+
hoverInfo = closestArrow;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else if (entity.has(traits.Points)) {
|
|
96
|
+
const positions = entity.get(traits.BufferGeometry)?.attributes.position.array;
|
|
97
|
+
const closestPoint = getClosestPoint(positions, hoverPosition);
|
|
98
|
+
if (closestPoint) {
|
|
99
|
+
hoverInfo = closestPoint;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return hoverInfo;
|
|
103
|
+
};
|
|
104
|
+
export const getLinkedHoverInfo = (index, linkedEntity) => {
|
|
105
|
+
if (linkedEntity.has(traits.Arrows)) {
|
|
106
|
+
const closestArrow = getArrowAtIndex(linkedEntity.get(traits.Positions), index);
|
|
107
|
+
if (closestArrow) {
|
|
108
|
+
return closestArrow;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
else if (linkedEntity.has(traits.Points)) {
|
|
112
|
+
const positions = linkedEntity.get(traits.BufferGeometry)?.attributes.position
|
|
113
|
+
.array;
|
|
114
|
+
const closestPoint = getPointAtIndex(positions, index);
|
|
115
|
+
if (closestPoint) {
|
|
116
|
+
return closestPoint;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return null;
|
|
120
|
+
};
|
|
@@ -5,20 +5,20 @@
|
|
|
5
5
|
import { provideToast, ToastContainer } from '@viamrobotics/prime-core'
|
|
6
6
|
import type { Struct } from '@viamrobotics/sdk'
|
|
7
7
|
import Scene from './Scene.svelte'
|
|
8
|
-
import TreeContainer from './
|
|
9
|
-
import Details from './Details.svelte'
|
|
8
|
+
import TreeContainer from './overlay/left-pane/TreeContainer.svelte'
|
|
9
|
+
import Details from './overlay/Details.svelte'
|
|
10
10
|
import SceneProviders from './SceneProviders.svelte'
|
|
11
11
|
import XR from './xr/XR.svelte'
|
|
12
12
|
import { createPartIDContext } from '../hooks/usePartID.svelte'
|
|
13
|
-
import Dashboard from './dashboard/Dashboard.svelte'
|
|
13
|
+
import Dashboard from './overlay/dashboard/Dashboard.svelte'
|
|
14
14
|
import { domPortal } from '../portal'
|
|
15
15
|
import { provideSettings } from '../hooks/useSettings.svelte'
|
|
16
16
|
import FileDrop from './FileDrop/FileDrop.svelte'
|
|
17
17
|
import { provideWeblabs } from '../hooks/useWeblabs.svelte'
|
|
18
18
|
import { providePartConfig } from '../hooks/usePartConfig.svelte'
|
|
19
19
|
import { useViamClient } from '@viamrobotics/svelte-sdk'
|
|
20
|
-
import LiveUpdatesBanner from './LiveUpdatesBanner.svelte'
|
|
21
|
-
import ArmPositions from './widgets/ArmPositions.svelte'
|
|
20
|
+
import LiveUpdatesBanner from './overlay/LiveUpdatesBanner.svelte'
|
|
21
|
+
import ArmPositions from './overlay/widgets/ArmPositions.svelte'
|
|
22
22
|
import { provideEnvironment } from '../hooks/useEnvironment.svelte'
|
|
23
23
|
import type { CameraPose } from '../hooks/useControls.svelte'
|
|
24
24
|
import { provideWorld } from '../ecs'
|
|
@@ -26,8 +26,9 @@
|
|
|
26
26
|
provideDrawConnectionConfig,
|
|
27
27
|
type DrawConnectionConfig,
|
|
28
28
|
} from '../hooks/useDrawConnectionConfig.svelte'
|
|
29
|
-
import Camera from './widgets/Camera.svelte'
|
|
30
|
-
import HoveredEntities from './HoveredEntities.svelte'
|
|
29
|
+
import Camera from './overlay/widgets/Camera.svelte'
|
|
30
|
+
import HoveredEntities from './hover/HoveredEntities.svelte'
|
|
31
|
+
import Settings from './overlay/settings/Settings.svelte'
|
|
31
32
|
|
|
32
33
|
interface LocalConfigProps {
|
|
33
34
|
getLocalPartConfig: () => Struct
|
|
@@ -125,37 +126,35 @@
|
|
|
125
126
|
|
|
126
127
|
<XR {@attach domPortal(root)} />
|
|
127
128
|
|
|
128
|
-
<Dashboard
|
|
129
|
-
{@attach domPortal(root)}
|
|
130
|
-
{dashboard}
|
|
131
|
-
/>
|
|
132
|
-
|
|
133
129
|
{#if settings.current.renderSubEntityHoverDetail}
|
|
134
|
-
<HoveredEntities
|
|
135
|
-
{/if}
|
|
136
|
-
<Details {@attach domPortal(root)} />
|
|
137
|
-
{#if environment.current.isStandalone}
|
|
138
|
-
<LiveUpdatesBanner {@attach domPortal(root)} />
|
|
139
|
-
{/if}
|
|
140
|
-
|
|
141
|
-
{#if !focus}
|
|
142
|
-
<TreeContainer {@attach domPortal(root)} />
|
|
143
|
-
{/if}
|
|
144
|
-
|
|
145
|
-
{#if !focus && settings.current.enableArmPositionsWidget}
|
|
146
|
-
<ArmPositions {@attach domPortal(root)} />
|
|
147
|
-
{/if}
|
|
148
|
-
|
|
149
|
-
{#if !focus}
|
|
150
|
-
{#each currentRobotCameraWidgets as cameraName (cameraName)}
|
|
151
|
-
<Camera
|
|
152
|
-
name={cameraName}
|
|
153
|
-
{@attach domPortal(root)}
|
|
154
|
-
/>
|
|
155
|
-
{/each}
|
|
130
|
+
<HoveredEntities />
|
|
156
131
|
{/if}
|
|
157
132
|
|
|
158
|
-
|
|
133
|
+
<!-- Overlays that need Threlte context -->
|
|
134
|
+
<div {@attach domPortal(root)}>
|
|
135
|
+
<FileDrop />
|
|
136
|
+
<Dashboard {dashboard} />
|
|
137
|
+
<Details />
|
|
138
|
+
<Settings />
|
|
139
|
+
|
|
140
|
+
{#if environment.current.isStandalone}
|
|
141
|
+
<LiveUpdatesBanner />
|
|
142
|
+
{/if}
|
|
143
|
+
|
|
144
|
+
{#if !focus}
|
|
145
|
+
<TreeContainer />
|
|
146
|
+
{/if}
|
|
147
|
+
|
|
148
|
+
{#if !focus && settings.current.enableArmPositionsWidget}
|
|
149
|
+
<ArmPositions />
|
|
150
|
+
{/if}
|
|
151
|
+
|
|
152
|
+
{#if !focus}
|
|
153
|
+
{#each currentRobotCameraWidgets as cameraName (cameraName)}
|
|
154
|
+
<Camera name={cameraName} />
|
|
155
|
+
{/each}
|
|
156
|
+
{/if}
|
|
157
|
+
</div>
|
|
159
158
|
{/snippet}
|
|
160
159
|
</SceneProviders>
|
|
161
160
|
</Canvas>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { CameraControls, type CameraControlsRef, Gizmo, Portal } from '@threlte/extras'
|
|
4
4
|
import { useCameraControls, useTransformControls } from '../hooks/useControls.svelte'
|
|
5
5
|
import KeyboardControls from './KeyboardControls.svelte'
|
|
6
|
-
import Button from './dashboard/Button.svelte'
|
|
6
|
+
import Button from './overlay/dashboard/Button.svelte'
|
|
7
7
|
import { useSettings } from '../hooks/useSettings.svelte'
|
|
8
8
|
|
|
9
9
|
const cameraControls = useCameraControls()
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { Box3, type Object3D, Vector3 } from 'three'
|
|
5
5
|
import { TrackballControls as ThreeTrackballControls } from 'three/examples/jsm/controls/TrackballControls.js'
|
|
6
6
|
import Camera from './Camera.svelte'
|
|
7
|
-
import Button from './dashboard/Button.svelte'
|
|
7
|
+
import Button from './overlay/dashboard/Button.svelte'
|
|
8
8
|
|
|
9
9
|
interface Props {
|
|
10
10
|
object3d: Object3D
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
const linePositions = useTrait(() => entity, traits.LinePositions)
|
|
47
47
|
const lineWidth = useTrait(() => entity, traits.LineWidth)
|
|
48
48
|
const center = useTrait(() => entity, traits.Center)
|
|
49
|
+
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
|
|
49
50
|
|
|
50
51
|
const geometryType = $derived.by(() => {
|
|
51
52
|
if (box.current) return 'box'
|
|
@@ -124,10 +125,12 @@
|
|
|
124
125
|
{...rest}
|
|
125
126
|
>
|
|
126
127
|
{#if geometryType}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
{#if showAxesHelper.current}
|
|
129
|
+
<AxesHelper
|
|
130
|
+
width={3}
|
|
131
|
+
length={0.1}
|
|
132
|
+
/>
|
|
133
|
+
{/if}
|
|
131
134
|
|
|
132
135
|
<T
|
|
133
136
|
is={mesh}
|
|
@@ -196,7 +199,7 @@
|
|
|
196
199
|
{/if}
|
|
197
200
|
{/if}
|
|
198
201
|
</T>
|
|
199
|
-
{:else}
|
|
202
|
+
{:else if showAxesHelper.current}
|
|
200
203
|
<AxesHelper
|
|
201
204
|
name={name.current}
|
|
202
205
|
width={3}
|
|
@@ -17,30 +17,32 @@
|
|
|
17
17
|
>
|
|
18
18
|
<HTML
|
|
19
19
|
center
|
|
20
|
+
zIndexRange={[3, 0]}
|
|
20
21
|
class="h-2.5 w-2.5 rounded-full bg-black/70"
|
|
21
22
|
/>
|
|
22
23
|
|
|
23
24
|
<HTML
|
|
24
25
|
class="pointer-events-none mb-2 w-16 -translate-x-1/2 -translate-y-[calc(100%+10px)] border border-black bg-white px-1 py-0.5 text-xs text-wrap"
|
|
26
|
+
zIndexRange={[3, 0]}
|
|
25
27
|
>
|
|
26
28
|
<div class="flex justify-between">
|
|
27
29
|
<span class="text-subtle-2">x</span>
|
|
28
30
|
<div>
|
|
29
|
-
{position[0].toFixed(
|
|
31
|
+
{position[0].toFixed(3)}<span class="text-subtle-2">m</span>
|
|
30
32
|
</div>
|
|
31
33
|
</div>
|
|
32
34
|
|
|
33
35
|
<div class="flex justify-between">
|
|
34
36
|
<span class="text-subtle-2">y</span>
|
|
35
37
|
<div>
|
|
36
|
-
{position[1].toFixed(
|
|
38
|
+
{position[1].toFixed(3)}<span class="text-subtle-2">m</span>
|
|
37
39
|
</div>
|
|
38
40
|
</div>
|
|
39
41
|
|
|
40
42
|
<div class="flex justify-between">
|
|
41
43
|
<span class="text-subtle-2">z</span>
|
|
42
44
|
<div>
|
|
43
|
-
{position[2].toFixed(
|
|
45
|
+
{position[2].toFixed(3)}<span class="text-subtle-2">m</span>
|
|
44
46
|
</div>
|
|
45
47
|
</div>
|
|
46
48
|
</HTML>
|
|
@@ -4,20 +4,19 @@
|
|
|
4
4
|
import { T } from '@threlte/core'
|
|
5
5
|
import { HTML, MeshLineGeometry, MeshLineMaterial, Portal } from '@threlte/extras'
|
|
6
6
|
import { useSettings } from '../../hooks/useSettings.svelte'
|
|
7
|
-
import Button from '../dashboard/Button.svelte'
|
|
7
|
+
import Button from '../overlay/dashboard/Button.svelte'
|
|
8
8
|
import MeasurePoint from './MeasurePoint.svelte'
|
|
9
9
|
import { useMouseRaycaster } from '../../hooks/useMouseRaycaster.svelte'
|
|
10
10
|
import { useFocusedEntity } from '../../hooks/useSelection.svelte'
|
|
11
|
-
import ToggleGroup from '../
|
|
12
|
-
import Popover from '../
|
|
11
|
+
import ToggleGroup from '../overlay/ToggleGroup.svelte'
|
|
12
|
+
import Popover from '../overlay/Popover.svelte'
|
|
13
13
|
|
|
14
14
|
const focusedEntity = useFocusedEntity()
|
|
15
15
|
const settings = useSettings()
|
|
16
16
|
|
|
17
17
|
const htmlPosition = new Vector3()
|
|
18
18
|
|
|
19
|
-
let step
|
|
20
|
-
|
|
19
|
+
let step = $state<'idle' | 'p1' | 'p2'>('idle')
|
|
21
20
|
let intersection = $state<Intersection>()
|
|
22
21
|
let p1 = $state.raw<Vector3>()
|
|
23
22
|
let p2 = $state.raw<Vector3>()
|
|
@@ -105,12 +104,12 @@
|
|
|
105
104
|
Enabled axes
|
|
106
105
|
<ToggleGroup
|
|
107
106
|
multiple
|
|
108
|
-
|
|
109
|
-
{
|
|
110
|
-
{
|
|
111
|
-
{
|
|
107
|
+
options={[
|
|
108
|
+
{ label: 'x', selected: settings.current.enableMeasureAxisX },
|
|
109
|
+
{ label: 'y', selected: settings.current.enableMeasureAxisY },
|
|
110
|
+
{ label: 'z', selected: settings.current.enableMeasureAxisZ },
|
|
112
111
|
]}
|
|
113
|
-
|
|
112
|
+
onSelect={(details) => {
|
|
114
113
|
settings.current.enableMeasureAxisX = details.includes('x')
|
|
115
114
|
settings.current.enableMeasureAxisY = details.includes('y')
|
|
116
115
|
settings.current.enableMeasureAxisZ = details.includes('z')
|
|
@@ -166,9 +165,10 @@
|
|
|
166
165
|
<HTML
|
|
167
166
|
center
|
|
168
167
|
position={htmlPosition.lerpVectors(p1, p2, 0.5).toArray()}
|
|
168
|
+
zIndexRange={[3, 0]}
|
|
169
169
|
>
|
|
170
170
|
<div class="border border-black bg-white px-1 py-0.5 text-xs">
|
|
171
|
-
{p1.distanceTo(p2).toFixed(
|
|
171
|
+
{p1.distanceTo(p2).toFixed(3)}<span class="text-subtle-2">m</span>
|
|
172
172
|
</div>
|
|
173
173
|
</HTML>
|
|
174
174
|
{/if}
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
import { provideResourceByName } from '../hooks/useResourceByName.svelte'
|
|
22
22
|
import { provide3DModels } from '../hooks/use3DModels.svelte'
|
|
23
23
|
import { providePointcloudObjects } from '../hooks/usePointcloudObjects.svelte'
|
|
24
|
+
import { provideLinkedEntities } from '../hooks/useLinked.svelte'
|
|
24
25
|
|
|
25
26
|
interface Props {
|
|
26
27
|
cameraPose?: CameraPose
|
|
@@ -51,6 +52,7 @@
|
|
|
51
52
|
provideFramelessComponents()
|
|
52
53
|
|
|
53
54
|
const { focus } = provideSelection()
|
|
55
|
+
provideLinkedEntities()
|
|
54
56
|
</script>
|
|
55
57
|
|
|
56
58
|
{@render children({ focus: focus.current !== undefined })}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { traits, useTrait } from '../../ecs'
|
|
3
|
+
import { useSelectedEntity } from '../../hooks/useSelection.svelte'
|
|
4
|
+
import { useFocusedEntity } from '../../hooks/useSelection.svelte'
|
|
5
|
+
import HoveredEntity from './HoveredEntity.svelte'
|
|
6
|
+
import LinkedHoveredEntity from './LinkedHoveredEntity.svelte'
|
|
7
|
+
import { useLinkedEntities } from '../../hooks/useLinked.svelte'
|
|
8
|
+
|
|
9
|
+
const selectedEntity = useSelectedEntity()
|
|
10
|
+
const focusedEntity = useFocusedEntity()
|
|
11
|
+
const linkedEntities = useLinkedEntities()
|
|
12
|
+
|
|
13
|
+
const displayEntity = $derived(selectedEntity.current ?? focusedEntity.current)
|
|
14
|
+
const isHovered = useTrait(() => displayEntity, traits.Hovered)
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
{#if isHovered}
|
|
18
|
+
<HoveredEntity />
|
|
19
|
+
|
|
20
|
+
{#each linkedEntities.current as entity (entity)}
|
|
21
|
+
<LinkedHoveredEntity linkedEntity={entity} />
|
|
22
|
+
{/each}
|
|
23
|
+
{/if}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { traits, useTrait } from '../../ecs'
|
|
3
|
+
import HoveredEntityTooltip from './HoveredEntityTooltip.svelte'
|
|
4
|
+
import { useFocusedEntity, useSelectedEntity } from '../../hooks/useSelection.svelte'
|
|
5
|
+
|
|
6
|
+
const selectedEntity = useSelectedEntity()
|
|
7
|
+
const focusedEntity = useFocusedEntity()
|
|
8
|
+
|
|
9
|
+
const displayEntity = $derived(selectedEntity.current ?? focusedEntity.current)
|
|
10
|
+
const hoverInfo = useTrait(() => displayEntity, traits.InstancedPose)
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
{#if hoverInfo.current}
|
|
14
|
+
<HoveredEntityTooltip hoverInfo={hoverInfo.current} />
|
|
15
|
+
{/if}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { HTML } from '@threlte/extras'
|
|
3
|
+
import { type HoverInfo } from '../../HoverUpdater.svelte'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
hoverInfo: HoverInfo
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let { hoverInfo }: Props = $props()
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
{#if hoverInfo}
|
|
13
|
+
<HTML
|
|
14
|
+
position={[hoverInfo.x, hoverInfo.y, hoverInfo.z]}
|
|
15
|
+
class="pointer-events-none"
|
|
16
|
+
zIndexRange={[3, 0]}
|
|
17
|
+
>
|
|
18
|
+
<div
|
|
19
|
+
class="border-medium pointer-events-none relative -mb-2 -translate-x-1/2 -translate-y-full border bg-white px-3 py-2.5 text-xs shadow-md"
|
|
20
|
+
>
|
|
21
|
+
<!-- Arrow -->
|
|
22
|
+
<div
|
|
23
|
+
class="border-medium absolute -bottom-[5px] left-1/2 size-2.5 -translate-x-1/2 rotate-45 border-r border-b bg-white"
|
|
24
|
+
></div>
|
|
25
|
+
|
|
26
|
+
<div class="flex flex-col gap-2.5">
|
|
27
|
+
<div>
|
|
28
|
+
<div class="mb-1"><strong class="font-semibold">index</strong></div>
|
|
29
|
+
<div>{hoverInfo.index}</div>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<div>
|
|
33
|
+
<div class="mb-1">
|
|
34
|
+
<strong class="font-semibold">world position</strong>
|
|
35
|
+
<span class="text-subtle-2"> (m)</span>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="flex gap-3">
|
|
38
|
+
<div>
|
|
39
|
+
<span class="text-subtle-2 mr-1">x </span>{hoverInfo.x.toFixed(2)}
|
|
40
|
+
</div>
|
|
41
|
+
<div>
|
|
42
|
+
<span class="text-subtle-2 mr-1">y </span>{hoverInfo.y.toFixed(2)}
|
|
43
|
+
</div>
|
|
44
|
+
<div>
|
|
45
|
+
<span class="text-subtle-2 mr-1">z </span>{hoverInfo.z.toFixed(2)}
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div>
|
|
51
|
+
<div class="mb-1">
|
|
52
|
+
<strong class="font-semibold">world orientation</strong>
|
|
53
|
+
<span class="text-subtle-2"> (deg)</span>
|
|
54
|
+
</div>
|
|
55
|
+
<div class="flex gap-3">
|
|
56
|
+
<div>
|
|
57
|
+
<span class="text-subtle-2 mr-1">x </span>{hoverInfo.oX.toFixed(2)}
|
|
58
|
+
</div>
|
|
59
|
+
<div>
|
|
60
|
+
<span class="text-subtle-2 mr-1">y </span>{hoverInfo.oY.toFixed(2)}
|
|
61
|
+
</div>
|
|
62
|
+
<div>
|
|
63
|
+
<span class="text-subtle-2 mr-1">z </span>{hoverInfo.oZ.toFixed(2)}
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</HTML>
|
|
70
|
+
{/if}
|
package/dist/components/{HoveredEntityTooltip.svelte.d.ts → hover/HoveredEntityTooltip.svelte.d.ts}
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type HoverInfo } from '../../HoverUpdater.svelte';
|
|
2
2
|
interface Props {
|
|
3
|
-
|
|
3
|
+
hoverInfo: HoverInfo;
|
|
4
4
|
}
|
|
5
5
|
declare const HoveredEntityTooltip: import("svelte").Component<Props, {}, "">;
|
|
6
6
|
type HoveredEntityTooltip = ReturnType<typeof HoveredEntityTooltip>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
module
|
|
4
|
+
>
|
|
5
|
+
import { Parser } from 'expr-eval'
|
|
6
|
+
|
|
7
|
+
export const parser = new Parser()
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import { relations, traits } from '../../ecs'
|
|
12
|
+
import type { Entity } from 'koota'
|
|
13
|
+
import HoveredEntityTooltip from './HoveredEntityTooltip.svelte'
|
|
14
|
+
import { getLinkedHoverInfo, type HoverInfo } from '../../HoverUpdater.svelte'
|
|
15
|
+
import { useSelectedEntity } from '../../hooks/useSelection.svelte'
|
|
16
|
+
import { useFocusedEntity } from '../../hooks/useSelection.svelte'
|
|
17
|
+
import { useTrait } from '../../ecs'
|
|
18
|
+
import { SubEntityLinkType } from '../../ecs/relations'
|
|
19
|
+
|
|
20
|
+
interface Props {
|
|
21
|
+
linkedEntity: Entity
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let { linkedEntity }: Props = $props()
|
|
25
|
+
|
|
26
|
+
const selectedEntity = useSelectedEntity()
|
|
27
|
+
const focusedEntity = useFocusedEntity()
|
|
28
|
+
const displayEntity = $derived(selectedEntity.current ?? focusedEntity.current)
|
|
29
|
+
|
|
30
|
+
const displayedHoverInfo = useTrait(() => displayEntity, traits.InstancedPose)
|
|
31
|
+
|
|
32
|
+
let hoverInfo = $state.raw<HoverInfo | null>(null)
|
|
33
|
+
|
|
34
|
+
$effect(() => {
|
|
35
|
+
if (displayEntity && displayedHoverInfo.current) {
|
|
36
|
+
const linkType = displayEntity?.get(relations.SubEntityLink(linkedEntity))?.type
|
|
37
|
+
if (linkType !== SubEntityLinkType.HoverLink) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
// Index Mapping is a formula with the variable 'index' in it, available operations can be found here: https://github.com/silentmatt/expr-eval/tree/master
|
|
41
|
+
const indexMapping =
|
|
42
|
+
displayEntity?.get(relations.SubEntityLink(linkedEntity))?.indexMapping ?? 'index'
|
|
43
|
+
const expression = parser.parse(indexMapping)
|
|
44
|
+
const resolvedIndex = expression.evaluate({ index: displayedHoverInfo.current.index })
|
|
45
|
+
const linkedHoverInfo = getLinkedHoverInfo(resolvedIndex, linkedEntity)
|
|
46
|
+
hoverInfo = linkedHoverInfo
|
|
47
|
+
} else {
|
|
48
|
+
hoverInfo = null
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
</script>
|
|
52
|
+
|
|
53
|
+
{#if hoverInfo}
|
|
54
|
+
<HoveredEntityTooltip {hoverInfo} />
|
|
55
|
+
{/if}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Parser } from 'expr-eval';
|
|
2
|
+
export declare const parser: Parser;
|
|
3
|
+
import type { Entity } from 'koota';
|
|
4
|
+
interface Props {
|
|
5
|
+
linkedEntity: Entity;
|
|
6
|
+
}
|
|
7
|
+
declare const LinkedHoveredEntity: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type LinkedHoveredEntity = ReturnType<typeof LinkedHoveredEntity>;
|
|
9
|
+
export default LinkedHoveredEntity;
|