From 8575327af8a6a5e78f2463b631108133ceaa5134 Mon Sep 17 00:00:00 2001 From: "azykov@mail.ru" Date: Wed, 3 Jun 2026 18:38:22 +0300 Subject: [PATCH] faster selection in editor --- src/components/ObjectEditorView.tsx | 51 ++++++++++++++++++++------- src/components/ObjectViewInternal.tsx | 2 +- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/components/ObjectEditorView.tsx b/src/components/ObjectEditorView.tsx index af8dae3..0528c9d 100644 --- a/src/components/ObjectEditorView.tsx +++ b/src/components/ObjectEditorView.tsx @@ -13,24 +13,51 @@ type ObjectEditorViewProps = { object: Runtime; } -export const ObjectEditorView = observer(function ({ object }: ObjectEditorViewProps) { - const groupRef = useRef(null); - - const objectType = state.world.getObjectTypeById(object.typeId); +type SelectionOverlayProps = { + objectId: string; + groupRef: RefObject; + onTransformEnd: () => void; +} +// Separate observer so only the 2 affected instances (selected/deselected) +// re-render on selection change, not all N objects in the scene. +const SelectionOverlay = observer(function ({ objectId, groupRef, onTransformEnd }: SelectionOverlayProps) { const isSelected = state.worldEditor.isEnabled && - state.worldEditor.selectedObjectId === object.id; + state.worldEditor.selectedObjectId === objectId; const selectionMode = isSelected ? state.worldEditor.selectedObjectMode : undefined; useHelper(isSelected ? groupRef : { current: null } as any, BoxHelper, 'white'); + if (!isSelected || selectionMode === undefined || !groupRef.current) + return null; + + return ( + } + mode={selectionMode} + onMouseUp={onTransformEnd} + /> + ); +}); + +export const ObjectEditorView = observer(function ({ object }: ObjectEditorViewProps) { + const groupRef = useRef(null); + + // Only observes world object types — not selection state — so won't + // re-render when a different object is selected. + const objectType = state.world.getObjectTypeById(object.typeId); if (!objectType) return null; function handleClick(e: ThreeEvent) { if (e.delta > 5) return; e.stopPropagation(); - state.worldEditor.setSelectedObject(object.id, nextSelectionEditMode(selectionMode)); + // Reading selection state inside an event handler: not tracked by observer. + const currentMode = state.worldEditor.isEnabled && + state.worldEditor.selectedObjectId === object.id + ? state.worldEditor.selectedObjectMode + : undefined; + state.worldEditor.setSelectedObject(object.id, nextSelectionEditMode(currentMode)); } function handleTransformEnd() { @@ -45,13 +72,11 @@ export const ObjectEditorView = observer(function ({ object }: ObjectEditorViewP } return (<> - {(isSelected && selectionMode !== undefined && groupRef.current) && - } - mode={selectionMode} - onMouseUp={handleTransformEnd} - /> - } + ) => void; } -export const ObjectViewInternal = observer(forwardRef( +export const ObjectViewInternal = observer(forwardRef( function ({ object, objectType, onClick }, ref) { const trimeshArgs = useMemo( () => buildObjectTrimesh(objectType, state.world.data.voxelTypes),