| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- "use client";
- import { useRef, useEffect, useCallback } from "react";
- import { useThree } from "@react-three/fiber";
- import { TransformControls, OrbitControls } from "@react-three/drei";
- import * as THREE from "three";
- import { useEditorStore } from "@/lib/store";
- export function EditorControls() {
- const isPlaying = useEditorStore((s) => s.isPlaying);
- if (isPlaying) return null;
- return (
- <>
- <EditorOrbitControls />
- <TransformGizmo />
- </>
- );
- }
- function EditorOrbitControls() {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const orbitRef = useRef<any>(null);
- useEffect(() => {
- const enable = () => {
- if (orbitRef.current) orbitRef.current.enabled = false;
- };
- const disable = () => {
- if (orbitRef.current) orbitRef.current.enabled = true;
- };
- window.addEventListener("transform-start", enable);
- window.addEventListener("transform-end", disable);
- return () => {
- window.removeEventListener("transform-start", enable);
- window.removeEventListener("transform-end", disable);
- };
- }, []);
- return (
- <OrbitControls
- ref={orbitRef}
- makeDefault
- enableDamping
- dampingFactor={0.1}
- minDistance={1}
- maxDistance={200}
- />
- );
- }
- function TransformGizmo() {
- const {
- selectedObjectId,
- transformMode,
- isPlaying,
- updateObjectTransform,
- saveToHistory,
- } = useEditorStore();
- const { scene } = useThree();
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- const controlsRef = useRef<any>(null);
- const findObjectById = useCallback(
- (id: string): THREE.Object3D | null => {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- let found: any = null;
- scene.traverse((child) => {
- if (child.userData?.id === id || child.userData?.objectId === id) {
- found = child;
- }
- });
- return found;
- },
- [scene],
- );
- useEffect(() => {
- if (
- !controlsRef.current ||
- !selectedObjectId ||
- isPlaying ||
- transformMode === "select"
- ) {
- if (controlsRef.current) {
- try {
- controlsRef.current.detach();
- } catch {
- /* may not be attached */
- }
- }
- return;
- }
- const timer = setTimeout(() => {
- const obj = findObjectById(selectedObjectId);
- if (obj && controlsRef.current) {
- try {
- controlsRef.current.attach(obj);
- } catch {
- /* object may not be ready */
- }
- }
- }, 50);
- return () => clearTimeout(timer);
- }, [selectedObjectId, transformMode, isPlaying, findObjectById]);
- useEffect(() => {
- const controls = controlsRef.current;
- if (!controls) return;
- const onDragStart = () =>
- window.dispatchEvent(new CustomEvent("transform-start"));
- const onDragEnd = () =>
- window.dispatchEvent(new CustomEvent("transform-end"));
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- controls.addEventListener("dragging-changed", (e: any) => {
- if (e.value) onDragStart();
- else onDragEnd();
- });
- return () => {
- controls.removeEventListener("dragging-changed", onDragStart);
- };
- }, []);
- const handleChange = useCallback(() => {
- if (!controlsRef.current || !selectedObjectId) return;
- const obj = controlsRef.current.object;
- if (!obj) return;
- updateObjectTransform(selectedObjectId, {
- position: [obj.position.x, obj.position.y, obj.position.z],
- rotation: [obj.rotation.x, obj.rotation.y, obj.rotation.z],
- scale: [obj.scale.x, obj.scale.y, obj.scale.z],
- });
- }, [selectedObjectId, updateObjectTransform]);
- const handleMouseUp = useCallback(() => {
- saveToHistory();
- }, [saveToHistory]);
- if (!selectedObjectId || isPlaying || transformMode === "select") return null;
- const mode =
- transformMode === "translate"
- ? "translate"
- : transformMode === "rotate"
- ? "rotate"
- : "scale";
- return (
- <TransformControls
- ref={controlsRef}
- mode={mode}
- onObjectChange={handleChange}
- onMouseUp={handleMouseUp}
- />
- );
- }
|