Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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/rare-aliens-visit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@viamrobotics/motion-tools': minor
---

feat: have select plugin emit multiple entities per selection (one per source entity)
39 changes: 23 additions & 16 deletions src/lib/plugins/Selection/Ellipse.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,17 @@
max.set(ellipseBox.maxX, ellipseBox.maxY, Number.POSITIVE_INFINITY)
box3.set(min, max)

const enclosedPoints: number[] = []
const enclosedPoints: Record<string, number[]> = {}

for (const pointsEntity of world.query(
traits.Points,
traits.SelectToolInteractionLayer,
Not(selectionTraits.SelectionEnclosedPoints)
)) {
const geometry = pointsEntity.get(traits.BufferGeometry)
const name = pointsEntity.get(traits.Name)

if (!geometry) return
if (!geometry || !name) return

const points = scene.getObjectByName(pointsEntity as unknown as string)

Expand All @@ -202,7 +203,8 @@
getTriangleFromIndex(i, indices, positions, triangle)

if (triangle.containsPoint(point)) {
enclosedPoints.push(point.x, point.y, point.z)
enclosedPoints[name] ??= []
enclosedPoints[name].push(point.x, point.y, point.z)
}
}
}
Expand All @@ -211,19 +213,24 @@
} as ShapecastCallbacks)
}

const ellipseResultGeometry = createBufferGeometry(new Float32Array(enclosedPoints))

world.spawn(
traits.Name('Ellipse result'),
traits.BufferGeometry(ellipseResultGeometry),
traits.Color({ r: 1, g: 0, b: 0 }),
traits.RenderOrder(999),
traits.Material({ depthTest: false }),
traits.Points,
traits.Removable,
selectionTraits.SelectionEnclosedPoints,
selectionTraits.PointsCapturedBy(ellipse)
)
const selectionInstanceId = crypto.randomUUID()
for (const [name, points] of Object.entries(enclosedPoints)) {
const ellipseResultGeometry = createBufferGeometry(new Float32Array(points))

world.spawn(
traits.Name('Ellipse result'),
traits.BufferGeometry(ellipseResultGeometry),
traits.Color({ r: 1, g: 0, b: 0 }),
traits.RenderOrder(999),
traits.Material({ depthTest: false }),
traits.Points,
traits.Removable,
selectionTraits.SelectionEnclosedPoints,
selectionTraits.PointsCapturedBy(ellipse),
selectionTraits.SelectedFrom(name),
selectionTraits.SelectionInstance(selectionInstanceId)
)
}
}

const onkeydown = (event: KeyboardEvent) => {
Expand Down
39 changes: 23 additions & 16 deletions src/lib/plugins/Selection/Lasso.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -149,16 +149,17 @@
max.set(lassoBox.maxX, lassoBox.maxY, Number.POSITIVE_INFINITY)
box3.set(min, max)

const enclosedPoints: number[] = []
const enclosedPoints: Record<string, number[]> = {}

for (const pointsEntity of world.query(
traits.Points,
traits.SelectToolInteractionLayer,
Not(selectionTraits.SelectionEnclosedPoints)
)) {
const geometry = pointsEntity.get(traits.BufferGeometry)
const name = pointsEntity.get(traits.Name)

if (!geometry) return
if (!geometry || !name) return

const points = scene.getObjectByName(pointsEntity as unknown as string)

Expand All @@ -183,7 +184,8 @@
getTriangleFromIndex(i, indices, positions, triangle)

if (triangle.containsPoint(point)) {
enclosedPoints.push(point.x, point.y, point.z)
enclosedPoints[name] ??= []
enclosedPoints[name].push(point.x, point.y, point.z)
}
}
}
Expand All @@ -192,19 +194,24 @@
} as ShapecastCallbacks)
}

const lassoResultGeometry = createBufferGeometry(new Float32Array(enclosedPoints))

world.spawn(
traits.Name('Lasso result'),
traits.BufferGeometry(lassoResultGeometry),
traits.Color({ r: 1, g: 0, b: 0 }),
traits.RenderOrder(999),
traits.Material({ depthTest: false }),
traits.Points,
traits.Removable,
selectionTraits.SelectionEnclosedPoints,
selectionTraits.PointsCapturedBy(lasso)
)
const selectionInstanceId = crypto.randomUUID()
for (const [name, points] of Object.entries(enclosedPoints)) {
const lassoResultGeometry = createBufferGeometry(new Float32Array(points))

world.spawn(
traits.Name('Lasso result'),
traits.BufferGeometry(lassoResultGeometry),
traits.Color({ r: 1, g: 0, b: 0 }),
traits.RenderOrder(999),
traits.Material({ depthTest: false }),
traits.Points,
traits.Removable,
selectionTraits.SelectionEnclosedPoints,
selectionTraits.PointsCapturedBy(lasso),
selectionTraits.SelectedFrom(name),
selectionTraits.SelectionInstance(selectionInstanceId)
)
}
}

const onkeydown = (event: KeyboardEvent) => {
Expand Down
2 changes: 2 additions & 0 deletions src/lib/plugins/Selection/traits.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { relation, trait } from 'koota'
export const Lasso = trait(() => true)
export const Ellipse = trait(() => true)
export const SelectionEnclosedPoints = trait(() => true)
export const SelectedFrom = trait(() => '')
export const SelectionInstance = trait(() => '')

/**
* Captured points are removable, so we want to also destroy
Expand Down
11 changes: 10 additions & 1 deletion src/routes/lib/components/selectDemoPage/SelectionOverlay.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@
import { FloatingPanel } from '$lib'
import { traits } from '$lib/ecs'
import { useSelectionPlugin } from '$lib/plugins'
import { SelectedFrom, SelectionInstance } from '$lib/plugins/Selection/traits'

const { dom } = useThrelte()
const selectionCtx = useSelectionPlugin()

const rect = new ElementRect(() => dom)

$effect(() => {
const entity = selectionCtx.current.at(-1)
if (entity) {
entity.set(traits.Color, { r: 0, g: 1, b: 0 })
const selectionInstanceId = entity.get(SelectionInstance)
const selectionInstanceEntities = selectionCtx.current.filter(
(entity) => entity.get(SelectionInstance) === selectionInstanceId
)
for (const selectionEntity of selectionInstanceEntities) {
const name = selectionEntity.get(traits.Name)
const selectedFrom = selectionEntity.get(SelectedFrom)
selectionEntity.set(traits.Name, `${name} (selected from ${selectedFrom})`)
}
}
})
</script>
Expand Down
9 changes: 9 additions & 0 deletions src/routes/select/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@

{#await createRandomPcdBinary(10_000, 1) then data}
<PCD
name="Points 1"
{data}
interactionLayers={['selectTool']}
/>
{/await}

{#await createRandomPcdBinary(1_000, 1) then data}
<PCD
name="Points 2"
{data}
interactionLayers={['selectTool']}
/>
Expand Down
Loading