Skip to content
Open
Show file tree
Hide file tree
Changes from 114 commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
faf59c0
Add shared ECS traits and helpers for entity pose plugins
DTCurrie Jun 1, 2026
9e637c6
Add changeset
DTCurrie Jun 1, 2026
02bc0d0
Refactor Details panel into focused subcomponents
DTCurrie Jun 1, 2026
bf49747
Add changeset
DTCurrie Jun 1, 2026
9bd8689
Small component tweaks to support per-entity pose mutators
DTCurrie Jun 1, 2026
030b969
Add changeset
DTCurrie Jun 1, 2026
585e9c2
Add Gizmos plugin (APP-16292)
DTCurrie Jun 1, 2026
50cffd7
Add changeset
DTCurrie Jun 1, 2026
77eed59
Address review feedback on writeMatrix and useMouseRaycaster
github-actions[bot] Jun 1, 2026
c18c0e7
Merge branch 'main' into app-16292/1-ecs-utils
DTCurrie Jun 2, 2026
f02fb53
Fix review findings in Gizmos plugin
github-actions[bot] Jun 2, 2026
6854ba0
Address review feedback: hierarchy comment, disableTooltip test
github-actions[bot] Jun 2, 2026
0d33dea
Address review feedback on Details refactor
github-actions[bot] Jun 2, 2026
dfef837
Address review feedback: writeMatrix early exit, undefined tests, fir…
github-actions[bot] Jun 2, 2026
4b68aae
Merge branch 'app-16292/1-ecs-utils' into app-16292/2-details-refactor
DTCurrie Jun 2, 2026
c00b48a
Update src/lib/ecs/traits.ts
DTCurrie Jun 2, 2026
2bcdba2
Merge branch 'app-16292/1-ecs-utils' into app-16292/2-details-refactor
DTCurrie Jun 2, 2026
b18c167
Add invalidate() to subcomponents and fix Details handleParentChange
github-actions[bot] Jun 2, 2026
fd1cd53
Apply suggestion from @claude[bot]
DTCurrie Jun 2, 2026
b890b95
fix claude's bad suggestion
DTCurrie Jun 2, 2026
82d5076
cleanup
DTCurrie Jun 2, 2026
51809f3
Address review feedback on Details refactor
github-actions[bot] Jun 2, 2026
3741933
Address review feedback on writeMatrix and useMouseRaycaster
github-actions[bot] Jun 1, 2026
fea6014
Make measure tool a plugin (#732)
micheal-parks Jun 1, 2026
8d67f43
Address review feedback: writeMatrix early exit, undefined tests, fir…
github-actions[bot] Jun 2, 2026
db5c541
Update src/lib/ecs/traits.ts
DTCurrie Jun 2, 2026
83b98a6
Add invalidate() to subcomponents and fix Details handleParentChange
github-actions[bot] Jun 2, 2026
3d6bf32
Apply suggestion from @claude[bot]
DTCurrie Jun 2, 2026
e1b0cbe
fix claude's bad suggestion
DTCurrie Jun 2, 2026
e25aa16
cleanup
DTCurrie Jun 2, 2026
f8c93fb
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 2, 2026
e08aa03
Make measure tool a plugin (#732)
micheal-parks Jun 1, 2026
b51e16b
Address review feedback: hierarchy comment, disableTooltip test
github-actions[bot] Jun 2, 2026
54eeeb7
Address review feedback on Details refactor
github-actions[bot] Jun 2, 2026
8868ae4
Address review feedback on writeMatrix and useMouseRaycaster
github-actions[bot] Jun 1, 2026
d58bb09
Address review feedback: writeMatrix early exit, undefined tests, fir…
github-actions[bot] Jun 2, 2026
33bf972
Update src/lib/ecs/traits.ts
DTCurrie Jun 2, 2026
c9b7864
Add invalidate() to subcomponents and fix Details handleParentChange
github-actions[bot] Jun 2, 2026
c4f4008
Apply suggestion from @claude[bot]
DTCurrie Jun 2, 2026
1d37aea
fix claude's bad suggestion
DTCurrie Jun 2, 2026
ac4ad94
cleanup
DTCurrie Jun 2, 2026
3c28edb
cleanup
DTCurrie Jun 2, 2026
a816a45
Merge branch 'app-16292/3-component-tweaks' of github.com:viam-labs/m…
DTCurrie Jun 2, 2026
b11891e
Add disableTooltip inactive test case to Button spec
github-actions[bot] Jun 2, 2026
6116b7d
Merge branch 'app-16292/3-component-tweaks' into app-16292/4-gizmos-p…
DTCurrie Jun 2, 2026
300e4d9
address review issues: GizmoDetails ordering, GizmoNormals type, Gizm…
github-actions[bot] Jun 2, 2026
df6af8a
address review nits: async, onAddNext comment, effect.pre, y-axis tes…
github-actions[bot] Jun 2, 2026
451c04e
rename gestures -> inputs
DTCurrie Jun 2, 2026
1c294c8
Merge branch 'app-16292/4-gizmos-plugin' of github.com:viam-labs/moti…
DTCurrie Jun 2, 2026
1bc584f
Merge branch 'main' into app-16292/1-ecs-utils
DTCurrie Jun 2, 2026
8e8bc5e
Merge branch 'app-16292/1-ecs-utils' into app-16292/2-details-refactor
DTCurrie Jun 2, 2026
12b8101
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 2, 2026
d3aeab2
Merge branch 'app-16292/3-component-tweaks' into app-16292/4-gizmos-p…
DTCurrie Jun 2, 2026
259e9b9
missed commit
DTCurrie Jun 2, 2026
ddd050a
add handlers for changes
DTCurrie Jun 2, 2026
e47694e
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 2, 2026
9ad63d7
use callbacks with no defaults
DTCurrie Jun 2, 2026
5061ec9
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 2, 2026
c6d4288
Merge branch 'app-16292/3-component-tweaks' into app-16292/4-gizmos-p…
DTCurrie Jun 2, 2026
7d8b902
use handlers
DTCurrie Jun 2, 2026
2450370
revert opacity behavior
DTCurrie Jun 2, 2026
1aeff3b
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 2, 2026
94f3b26
revert opacity fallbacks
DTCurrie Jun 2, 2026
406608a
Merge branch 'app-16292/3-component-tweaks' into app-16292/4-gizmos-p…
DTCurrie Jun 2, 2026
081f852
split out opacity and axes helper details
DTCurrie Jun 2, 2026
ad9d95d
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 2, 2026
058c077
Merge branch 'app-16292/3-component-tweaks' into app-16292/4-gizmos-p…
DTCurrie Jun 2, 2026
30ff3e0
update details
DTCurrie Jun 2, 2026
f2b8a19
line color updates
DTCurrie Jun 2, 2026
74456a0
update details layout for clarity
DTCurrie Jun 2, 2026
4c7ab2f
default to first hit
DTCurrie Jun 2, 2026
d076b3f
Merge branch 'main' into app-16292/1-ecs-utils
DTCurrie Jun 2, 2026
b7b7d7c
Refactor Details panel into focused subcomponents
DTCurrie Jun 1, 2026
168cd3e
Add changeset
DTCurrie Jun 1, 2026
473af2e
Address review feedback on Details refactor
github-actions[bot] Jun 2, 2026
873a67b
Add invalidate() to subcomponents and fix Details handleParentChange
github-actions[bot] Jun 2, 2026
72a6fce
Apply suggestion from @claude[bot]
DTCurrie Jun 2, 2026
a92007c
fix claude's bad suggestion
DTCurrie Jun 2, 2026
2d7c9c1
cleanup
DTCurrie Jun 2, 2026
d5a080e
add handlers for changes
DTCurrie Jun 2, 2026
17e814f
use callbacks with no defaults
DTCurrie Jun 2, 2026
76b80ef
revert opacity behavior
DTCurrie Jun 2, 2026
053d6e1
split out opacity and axes helper details
DTCurrie Jun 2, 2026
51d9b2b
line color updates
DTCurrie Jun 2, 2026
d3f4b78
Merge branch 'app-16292/2-details-refactor' of github.com:viam-labs/m…
DTCurrie Jun 2, 2026
70a5b6f
Merge branch 'app-16292/2-details-refactor' of github.com:viam-labs/m…
DTCurrie Jun 2, 2026
3fa8e62
Merge branch 'app-16292/3-component-tweaks' of github.com:viam-labs/m…
DTCurrie Jun 2, 2026
22b2dc9
Merge branch 'main' into app-16292/2-details-refactor
DTCurrie Jun 2, 2026
f552dd3
resolve selection plugin changes and add plane details
DTCurrie Jun 2, 2026
5626401
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 2, 2026
ce8a85c
Merge branch 'app-16292/3-component-tweaks' into app-16292/4-gizmos-p…
DTCurrie Jun 2, 2026
156feed
Apply suggestions from code review
DTCurrie Jun 3, 2026
299bed5
fix: correct useThrelte mock structure and remove duplicate guard
github-actions[bot] Jun 3, 2026
2cdca10
Apply suggestion from @claude[bot]
DTCurrie Jun 3, 2026
55f5596
set arrow tool opacity
DTCurrie Jun 3, 2026
7900e97
Merge branch 'app-16292/4-gizmos-plugin' of github.com:viam-labs/moti…
DTCurrie Jun 3, 2026
fb7f589
Apply suggestion from @claude[bot]
DTCurrie Jun 3, 2026
7d48588
claude is bad at suggesting code edits
DTCurrie Jun 3, 2026
5ccbd2b
remove outdated mock
DTCurrie Jun 3, 2026
16b6268
Merge branch 'app-16292/2-details-refactor' into app-16292/3-componen…
DTCurrie Jun 3, 2026
84b0156
test: remove duplicate 'keeps original array intact' test case
github-actions[bot] Jun 3, 2026
b85557c
Merge branch 'app-16292/2-details-refactor' of github.com:viam-labs/m…
DTCurrie Jun 3, 2026
e715f79
Merge branch 'app-16292/3-component-tweaks' of github.com:viam-labs/m…
DTCurrie Jun 3, 2026
b92ec38
Merge branch 'app-16292/3-component-tweaks' of github.com:viam-labs/m…
DTCurrie Jun 3, 2026
fec6d11
Merge branch 'main' of github.com:viam-labs/motion-tools into app-162…
DTCurrie Jun 4, 2026
6bc1fd6
cleanup
DTCurrie Jun 4, 2026
43ab2e9
cleanup and clarify
DTCurrie Jun 4, 2026
f376b4d
cleanup
DTCurrie Jun 4, 2026
0915f65
Merge branch 'main' of github.com:viam-labs/motion-tools into app-162…
DTCurrie Jun 4, 2026
d509e21
Merge branch 'app-16292/3-component-tweaks' of github.com:viam-labs/m…
DTCurrie Jun 4, 2026
425ba30
Merge branch 'main' into app-16292/4-gizmos-plugin
DTCurrie Jun 8, 2026
31a8473
Merge branch 'main' of github.com:viam-labs/motion-tools into app-162…
DTCurrie Jun 9, 2026
b4be1e2
fixes
DTCurrie Jun 9, 2026
4ab25a7
cleanup, combine plane and geometries into reference shape
DTCurrie Jun 9, 2026
b963b56
Merge branch 'main' into app-16292/4-gizmos-plugin
DTCurrie Jun 9, 2026
744e462
Merge branch 'main' into app-16292/4-gizmos-plugin
DTCurrie Jun 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/add-gizmos-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@viamrobotics/motion-tools': minor
---

Add `Gizmos` plugin for placing editable scene aids (coordinate systems, reference planes, reference geometries, polylines, arrows, vertex normals, and surface normals) with a `useGizmos` hook and `gizmoTraits` namespace
2 changes: 2 additions & 0 deletions .claude/rules/svelte.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ This project renders a 3D scene using [Threlte](https://threlte.xyz/llms-full.tx

The right question to ask for when to use `$effect` vs `$effect.pre` is "does anything downstream in the same flush need to read this before render/DOM-commit?" If yes,`.pre`; if it's a pure side-effect with nothing observing the result inside the same flush, plain $effect is correct.

**Do not reach for `.pre` to "avoid a one-frame render lag."** That reasoning applies to continuously-rendered scenes; it does **not** apply here. Because rendering is on-demand, a scene mutation is followed by `invalidate()`, which schedules a render for the _next_ `requestAnimationFrame`.

@micheal-parks Micheal Parks (micheal-parks) Jun 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense for continuously rendered scenes either. $effect.pre runs synchronously and immediately. $effect runs in a batched manner in a microtask. But the guaranteed order of operations for JS per frame is:

  1. Sync tasks
  2. Microtasks
  3. requestAnimationFrame

Microtasks always run before requestAnimationFrame. Therefore even in continuously running apps $effect() is fine. The only time it's not fine is when it's writing Three.js props that other effects will potentially read from. Then $effect.pre is more necessary to get ahead of the other reads. But this is rare and sort of dangerous.


**`dispose={false}`** — pass when you manage the Three.js object's lifecycle yourself (pooled or shared instances).

**BVH / raycasting** — opt out objects that don't need hit-testing: `bvh={{ enabled: false }}` or `raycast={() => null}` for display-only geometry.
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/claude-pr-assistant.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
- Do NOT run unrelated commands, they waste turns and time.
- If a lint or test command fails more than twice on the same issue, commit what you have, push, and note the unresolved issue in a PR comment.
- Before editing code, read 1-2 similar functions or components in the same file or package to follow existing patterns and conventions.
- Before reviewing OR editing a file, read the project conventions that apply to it in `.claude/rules/` (the table in `CLAUDE.md` maps file globs to rule files). These are path-scoped and may not auto-load during a diff-only review, so read them explicitly — e.g. `.claude/rules/svelte.md` for `.svelte`/`.svelte.ts`/`.svelte.js`, `.claude/rules/three.md` for `src/lib/three/`. They override generic best-practice priors.
- This repo uses Svelte 5 runes and SvelteKit. Consult the Svelte MCP server when editing or reviewing `.svelte` / `.svelte.ts` / `.svelte.js` files.
- NEVER use curl, python3, or WebFetch to submit GitHub reviews. Use ONLY `gh pr review` and `gh pr comment`.
extra_system_prompt: >-
Expand Down
11 changes: 10 additions & 1 deletion src/lib/components/overlay/Popover.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@

{@render trigger(api.getTriggerProps(), { isOpen: api.open })}

<!--
The menu is portalled to <body>, so it must out-stack scene-space entity labels and
panels. zag drives the positioner's z-index from `var(--z-index)`, which it copies from
the *content* element's computed z-index. So the z-index must live on the content, not
the positioner.
-->
<div
use:portal={{ disabled: !api.portalled }}
{...api.getPositionerProps()}
>
<div {...api.getContentProps()}>
<div
class="z-max"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need z-max? Can we use a less aggressive value? (I think we use around z-5) for other floating UI

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was hitting some weirdness but I can lower it. though IMO I think we may want to introduce some semantic z-layering classes to reduce having to go search the codebase for every z-x usage and determine how to layer. like z-popover, z-panel, z-label or something.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, all for this

{...api.getContentProps()}
>
{@render children({ close })}
</div>
</div>
110 changes: 110 additions & 0 deletions src/lib/plugins/Gizmos/ConfirmFloatingPanel.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<script lang="ts">
import type { Vector3Tuple } from 'three'

import { HTML } from '@threlte/extras'
import { Check, Plus, Undo2, X } from 'lucide-svelte'

interface Props {
position: Vector3Tuple
onConfirm: () => void
onCancel: () => void
onAddNext?: () => void
onUndo?: () => void
}

const { position, onConfirm, onCancel, onAddNext, onUndo }: Props = $props()

const stopPointerBubble = (el: HTMLElement) => {
const stop = (event: PointerEvent) => event.stopPropagation()
el.addEventListener('pointerdown', stop)
el.addEventListener('pointerup', stop)
el.addEventListener('pointermove', stop)
return {
destroy() {
el.removeEventListener('pointerdown', stop)
el.removeEventListener('pointerup', stop)
el.removeEventListener('pointermove', stop)
},
}
}

const buttonClass =
'hover:bg-light flex min-w-9 flex-col items-center justify-center gap-0.5 rounded px-1.5 py-1 focus:outline-none focus-visible:ring-2'
const hotkeyClass = 'font-mono text-[10px] leading-none opacity-60'
</script>

<HTML
center
{position}
zIndexRange={[100, 0]}
>
<div
class="border-medium pointer-events-auto flex -translate-y-10 gap-0.5 rounded border bg-white p-0.5 shadow-md"
use:stopPointerBubble
>
{#if onUndo}
<button
class={[buttonClass, 'text-blue-600 focus-visible:ring-blue-500']}
type="button"
title="Undo last (⌫)"
onclick={onUndo}
>
<Undo2
class="size-4"
aria-hidden="true"
/>
<span
class={hotkeyClass}
aria-hidden="true">⌫</span
>
</button>
{/if}
<button
class={[buttonClass, 'text-red-600 focus-visible:ring-red-500']}
type="button"
title="Cancel (esc)"
onclick={onCancel}
>
<X
class="size-4"
aria-hidden="true"
/>
<span
class={hotkeyClass}
aria-hidden="true">Esc</span
>
</button>
{#if onAddNext}
<button
class={[buttonClass, 'text-blue-600 focus-visible:ring-blue-500']}
type="button"
title="Commit and add another (space)"
onclick={onAddNext}
>
<Plus
class="size-4"
aria-hidden="true"
/>
<span
class={hotkeyClass}
aria-hidden="true">Space</span
>
</button>
{/if}
<button
class={[buttonClass, 'text-green-600 focus-visible:ring-green-500']}
type="button"
title="Confirm and exit (↵)"
onclick={onConfirm}
>
<Check
class="size-4"
aria-hidden="true"
/>
<span
class={hotkeyClass}
aria-hidden="true">↵</span
>
</button>
</div>
</HTML>
97 changes: 97 additions & 0 deletions src/lib/plugins/Gizmos/GizmoArrow.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script module>
import { Color } from 'three'

import { ARROW_LENGTH, createArrowGeometry } from '$lib/three/arrow'

const colorUtil = new Color()
const sharedArrowGeometry = createArrowGeometry()
</script>

<script lang="ts">
import type { Entity } from 'koota'
import type { Snippet } from 'svelte'

import { T, useThrelte } from '@threlte/core'
import { Group, Mesh } from 'three'

import { colors } from '$lib/color'
import AxesHelper from '$lib/components/AxesHelper.svelte'
import { useEntityEvents } from '$lib/components/Entities/hooks/useEntityEvents.svelte'
import { traits, useTrait } from '$lib/ecs'

interface Props {
entity: Entity
children?: Snippet
}

const { entity, children }: Props = $props()

const { invalidate } = useThrelte()
const name = useTrait(() => entity, traits.Name)
const worldMatrix = useTrait(() => entity, traits.WorldMatrix)
const entityColor = useTrait(() => entity, traits.Color)
const opacity = useTrait(() => entity, traits.Opacity)
const showAxesHelper = useTrait(() => entity, traits.ShowAxesHelper)
const invisible = useTrait(() => entity, traits.InheritedInvisible)
const events = useEntityEvents(() => entity)

const group = new Group()
group.matrixAutoUpdate = false

const mesh = new Mesh()
mesh.position.y = -ARROW_LENGTH

const color = $derived.by(() => {
if (entityColor.current) {
return `#${colorUtil
.setRGB(entityColor.current.r, entityColor.current.g, entityColor.current.b)
.getHexString()}`
}

return colors.default
})

const currentOpacity = $derived(opacity.current ?? 1)

$effect.pre(() => {
if (!worldMatrix.current) return

group.matrix.copy(worldMatrix.current)
group.matrix.decompose(group.position, group.quaternion, group.scale)
group.updateMatrixWorld()
invalidate()
})
</script>

<T
is={group}
visible={invisible.current !== true}
>
<T
is={mesh}
name={entity}
userData.name={name}
{...events}
>
<T
is={sharedArrowGeometry}
dispose={false}
/>
<T.MeshToonMaterial
{color}
transparent={currentOpacity < 1}
depthWrite={currentOpacity === 1}
opacity={currentOpacity}
/>
</T>

{#if showAxesHelper.current}
<AxesHelper
name={entity}
width={3}
length={0.1}
/>
{/if}

{@render children?.()}
</T>
94 changes: 94 additions & 0 deletions src/lib/plugins/Gizmos/GizmoDetails.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<script lang="ts">
import { Portal } from '@threlte/extras'
import { Shapes } from 'lucide-svelte'

import AxesHelperDetails from '$lib/components/overlay/details/AxesHelperDetails.svelte'
import ColorDetails from '$lib/components/overlay/details/ColorDetails.svelte'
import GeometryDetails from '$lib/components/overlay/details/GeometryDetails.svelte'
import LineDetails from '$lib/components/overlay/details/LineDetails/LineDetails.svelte'
import OpacityDetails from '$lib/components/overlay/details/OpacityDetails.svelte'
import PoseDetails from '$lib/components/overlay/details/PoseDetails.svelte'
import { hierarchy, traits, useQuery, useTag, useTrait } from '$lib/ecs'

import PlaneDetails from './PlaneDetails.svelte'
import { Gizmo, GizmoArrow, Plane } from './traits'

const selected = useQuery(traits.Selected)
const entity = $derived(selected.current[0])
const gizmo = useTag(() => entity, Gizmo)

const plane = useTrait(() => entity, Plane)
const box = useTrait(() => entity, traits.Box)
const sphere = useTrait(() => entity, traits.Sphere)
const capsule = useTrait(() => entity, traits.Capsule)
const linePositions = useTrait(() => entity, traits.LinePositions)
const gizmoArrow = useTag(() => entity, GizmoArrow)

const isReferencePlane = $derived(Boolean(plane.current))
const isReferenceGeometry = $derived(Boolean(box.current || sphere.current || capsule.current))
const isLine = $derived(Boolean(linePositions.current))
const isArrow = $derived(Boolean(gizmoArrow.current))

const entities = useQuery(traits.Name)

const gizmoName = $derived.by(() => {
if (!entity) return
return entity.get(traits.Name)
})

const parentOptions = $derived.by(() => {
const opts = [{ value: 'world', text: 'world' }]
for (const candidate of entities.current) {
const name = candidate.get(traits.Name)
if (!name || name === 'world' || name === gizmoName) continue
opts.push({ value: name, text: name })
}

return opts
})
</script>

{#if gizmo.current}
<Portal id="details-header-icon">
<span
class="text-info-dark px-1"
aria-label="gizmo"
>
<Shapes size="16" />
</span>
</Portal>
{/if}

{#if gizmo.current && entity}
<Portal id="details-extensions">
<div class="flex flex-col gap-2.5 text-xs">
<PoseDetails
{entity}
{parentOptions}
onPoseChange={(patch) => traits.writeMatrix(entity, patch)}
onParentChange={(next) => hierarchy.setParent(entity, next)}
/>
{#if isReferencePlane}
<PlaneDetails {entity} />
<ColorDetails {entity} />
<OpacityDetails {entity} />
<AxesHelperDetails {entity} />
{/if}
{#if isReferenceGeometry}
<GeometryDetails {entity} />
<ColorDetails {entity} />
<OpacityDetails {entity} />
<AxesHelperDetails {entity} />
{/if}
{#if isLine}
<LineDetails {entity} />
<OpacityDetails {entity} />
{/if}
{#if isArrow}
<ColorDetails {entity} />
<OpacityDetails {entity} />
<AxesHelperDetails {entity} />
{/if}
</div>
</Portal>
{/if}
46 changes: 46 additions & 0 deletions src/lib/plugins/Gizmos/GizmoEntities.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script lang="ts">
import Label from '$lib/components/Entities/Label.svelte'
import { useQuery } from '$lib/ecs'

import GizmoArrow from './GizmoArrow.svelte'
import GizmoNormals from './GizmoNormals.svelte'
import GizmoPlane from './GizmoPlane.svelte'
import GizmoPolylineMeasure from './GizmoPolylineMeasure.svelte'
import * as gizmoTraits from './traits'

const planeGizmos = useQuery(gizmoTraits.Plane)
const arrowGizmos = useQuery(gizmoTraits.GizmoArrow)
const polylineMeasures = useQuery(gizmoTraits.PolylineMeasure)
const vertexNormals = useQuery(gizmoTraits.VertexNormals)
const surfaceNormals = useQuery(gizmoTraits.SurfaceNormals)
</script>

{#each planeGizmos.current as entity (entity)}
<GizmoPlane {entity}>
<Label {entity} />
</GizmoPlane>
{/each}

{#each arrowGizmos.current as entity (entity)}
<GizmoArrow {entity}>
<Label {entity} />
</GizmoArrow>
{/each}

{#each polylineMeasures.current as entity (entity)}
<GizmoPolylineMeasure {entity} />
{/each}

{#each vertexNormals.current as entity (entity)}
<GizmoNormals
{entity}
kind="vertex"
/>
{/each}

{#each surfaceNormals.current as entity (entity)}
<GizmoNormals
{entity}
kind="surface"
/>
{/each}
Loading
Loading