faster selection in editor

This commit is contained in:
azykov@mail.ru 2026-06-03 18:38:22 +03:00
parent 4e7b44dc57
commit 8575327af8
No known key found for this signature in database
2 changed files with 39 additions and 14 deletions

View File

@ -13,24 +13,51 @@ type ObjectEditorViewProps = {
object: Runtime<ObjectInstance>;
}
export const ObjectEditorView = observer(function ({ object }: ObjectEditorViewProps) {
const groupRef = useRef<Group>(null);
const objectType = state.world.getObjectTypeById(object.typeId);
type SelectionOverlayProps = {
objectId: string;
groupRef: RefObject<Group | null>;
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 (
<TransformControls
object={groupRef as RefObject<Group>}
mode={selectionMode}
onMouseUp={onTransformEnd}
/>
);
});
export const ObjectEditorView = observer(function ({ object }: ObjectEditorViewProps) {
const groupRef = useRef<Group>(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<MouseEvent>) {
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) &&
<TransformControls
object={groupRef as RefObject<Group>}
mode={selectionMode}
onMouseUp={handleTransformEnd}
<SelectionOverlay
objectId={object.id}
groupRef={groupRef}
onTransformEnd={handleTransformEnd}
/>
}
<ObjectViewInternal
ref={groupRef}
object={object}

View File

@ -16,7 +16,7 @@ type ObjectViewInternalProps = {
onClick?: (e: ThreeEvent<MouseEvent>) => void;
}
export const ObjectViewInternal = observer(forwardRef<Group, ObjectViewInternalProps>(
export const ObjectViewInternal = observer(forwardRef<Group | null, ObjectViewInternalProps>(
function ({ object, objectType, onClick }, ref) {
const trimeshArgs = useMemo(
() => buildObjectTrimesh(objectType, state.world.data.voxelTypes),