Spaces:
Running
Running
File size: 2,457 Bytes
ca4340e 18b0fa5 ca4340e 18b0fa5 ca4340e 18b0fa5 ca4340e 18b0fa5 ca4340e 18b0fa5 ca4340e 18b0fa5 ca4340e 18b0fa5 ca4340e 18b0fa5 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
<script lang="ts">
import { T } from "@threlte/core";
import { TransformControls, interactivity } from "@threlte/extras";
import type { Snippet } from "svelte";
import { Spring } from "svelte/motion";
import { useCursor } from "@threlte/extras";
import { setContext } from "svelte";
interface Props {
content: Snippet<[{ isHighlighted: boolean }]>; // renderable
enableEdit?: boolean;
hoverColor?: string;
defaultColor?: string;
hoverOpacity?: number;
}
let {
content,
enableEdit = $bindable(true),
hoverColor = "#ffa348",
hoverOpacity = 0.5
}: Props = $props();
interactivity();
const scale = new Spring(1);
// Position state to persist transforms
let position = $state<[number, number, number]>([0, 0, 0]);
let rotation = $state<[number, number, number]>([0, 0, 0]);
// Hover state
let isHovered = $state(false);
let isSelected = $state(false);
let isHighlighted = $derived(enableEdit && (isSelected || isHovered));
$effect(() => {
// If isHighlighted is true, set the color to hoverColor and opacity to hoverOpacity
if (isHighlighted) {
scale.target = 1.05;
} else {
scale.target = 1;
}
});
const { onPointerEnter, onPointerLeave } = useCursor();
// Handle keyboard events for deselection
$effect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape" && isSelected) {
isSelected = false;
}
};
if (isSelected) {
document.addEventListener("keydown", handleKeyDown);
return () => {
document.removeEventListener("keydown", handleKeyDown);
};
}
});
// Handle transform changes
const handleTransform = (ref: any) => {
ref.updateMatrix();
// Update our position state from the object's current position
position = ref.position.toArray();
rotation = ref.rotation.toArray();
};
</script>
<T.Group
{position}
{rotation}
onclick={() => {
isSelected = true;
}}
onpointerenter={() => {
onPointerEnter();
isHovered = true;
}}
onpointerleave={() => {
onPointerLeave();
isHovered = false;
}}
scale={scale.current}
>
{#snippet children({ ref })}
{@render content({ isHighlighted })}
{#if isSelected && enableEdit}
<TransformControls
object={ref}
mode="translate"
showY={false}
axis="XZ"
space="world"
on:objectChange={() => handleTransform(ref)}
on:mouseUp={() => handleTransform(ref)}
/>
{/if}
{/snippet}
</T.Group>
<!-- From https://github.com/brean/urdf-viewer -->
|