clean branch-scoped code quality issues

This commit is contained in:
Tom Boullay
2026-04-28 14:23:37 +02:00
parent 9818e719ce
commit 64b53a762d
15 changed files with 218 additions and 242 deletions
+32 -47
View File
@@ -31,6 +31,20 @@ interface EditorControlsProps {
isPlayerMode?: boolean;
}
const TRANSFORM_OPTIONS = [
{ mode: "translate", label: "Translate", shortcut: "T", Icon: Move3D },
{ mode: "rotate", label: "Rotate", shortcut: "R", Icon: RotateCw },
{ mode: "scale", label: "Scale", shortcut: "S", Icon: Expand },
] as const;
const EDITOR_SHORTCUTS = [
["Click", "Select object"],
["T / R / S", "Transform mode"],
["Ctrl Z / Y", "Undo / redo"],
["Esc", "Deselect"],
["WASD", "Move when locked"],
] as const;
export function EditorControls({
transformMode,
onTransformModeChange,
@@ -69,33 +83,18 @@ export function EditorControls({
</div>
<div className="editor-transform-buttons">
<button
className={`editor-transform-button ${transformMode === "translate" ? "active" : ""}`}
onClick={() => onTransformModeChange("translate")}
aria-pressed={transformMode === "translate"}
>
<Move3D size={16} aria-hidden="true" />
<span>Translate</span>
<kbd>T</kbd>
</button>
<button
className={`editor-transform-button ${transformMode === "rotate" ? "active" : ""}`}
onClick={() => onTransformModeChange("rotate")}
aria-pressed={transformMode === "rotate"}
>
<RotateCw size={16} aria-hidden="true" />
<span>Rotate</span>
<kbd>R</kbd>
</button>
<button
className={`editor-transform-button ${transformMode === "scale" ? "active" : ""}`}
onClick={() => onTransformModeChange("scale")}
aria-pressed={transformMode === "scale"}
>
<Expand size={16} aria-hidden="true" />
<span>Scale</span>
<kbd>S</kbd>
</button>
{TRANSFORM_OPTIONS.map(({ mode, label, shortcut, Icon }) => (
<button
key={mode}
className={`editor-transform-button ${transformMode === mode ? "active" : ""}`}
onClick={() => onTransformModeChange(mode)}
aria-pressed={transformMode === mode}
>
<Icon size={16} aria-hidden="true" />
<span>{label}</span>
<kbd>{shortcut}</kbd>
</button>
))}
</div>
<div className="editor-history-buttons">
@@ -203,26 +202,12 @@ export function EditorControls({
</div>
<dl className="editor-shortcuts-list">
<div>
<dt>Click</dt>
<dd>Select object</dd>
</div>
<div>
<dt>T / R / S</dt>
<dd>Transform mode</dd>
</div>
<div>
<dt>Ctrl Z / Y</dt>
<dd>Undo / redo</dd>
</div>
<div>
<dt>Esc</dt>
<dd>Deselect</dd>
</div>
<div>
<dt>WASD</dt>
<dd>Move when locked</dd>
</div>
{EDITOR_SHORTCUTS.map(([keys, description]) => (
<div key={keys}>
<dt>{keys}</dt>
<dd>{description}</dd>
</div>
))}
</dl>
</section>
+50 -30
View File
@@ -29,6 +29,12 @@ interface EditorNodeCommonProps {
onHoverNode: (index: number | null) => void;
}
interface EditorNodePointerHandlers {
onClick: (event: ThreeEvent<MouseEvent>) => void;
onPointerEnter: (event: ThreeEvent<PointerEvent>) => void;
onPointerLeave: (event: ThreeEvent<PointerEvent>) => void;
}
function applyNodeTransform(object: THREE.Object3D, node: MapNode): void {
object.position.set(...node.position);
object.rotation.set(...node.rotation);
@@ -88,6 +94,36 @@ function cloneHighlightedMaterial(
return clone;
}
function getNodeHighlightColor(
isSelected: boolean,
isHovered: boolean,
): string | null {
if (isSelected) return "#ffffff";
if (isHovered) return "#b8b8b8";
return null;
}
function createEditorNodePointerHandlers(
index: number,
onSelectNode: (index: number | null) => void,
onHoverNode: (index: number | null) => void,
): EditorNodePointerHandlers {
return {
onClick: (event) => {
event.stopPropagation();
onSelectNode(index);
},
onPointerEnter: (event) => {
event.stopPropagation();
onHoverNode(index);
},
onPointerLeave: (event) => {
event.stopPropagation();
onHoverNode(null);
},
};
}
export function EditorMap({
sceneData,
selectedNodeIndex,
@@ -224,15 +260,16 @@ function EditorModelNode({
const { scene } = useGLTF(modelUrl);
const sceneInstance = useMemo(() => scene.clone(true), [scene]);
const pointerHandlers = createEditorNodePointerHandlers(
index,
onSelectNode,
onHoverNode,
);
useRegisteredEditorNode(groupRef, index, node, objectsMapRef);
useEffect(() => {
if (!groupRef.current) return;
const highlightColor = isSelected
? "#ffffff"
: isHovered
? "#b8b8b8"
: null;
const highlightColor = getNodeHighlightColor(isSelected, isHovered);
groupRef.current.traverse((child) => {
if (!(child instanceof THREE.Mesh)) {
@@ -288,18 +325,7 @@ function EditorModelNode({
position={node.position}
rotation={node.rotation}
scale={node.scale}
onClick={(e: ThreeEvent<MouseEvent>) => {
e.stopPropagation();
onSelectNode(index);
}}
onPointerEnter={(e: ThreeEvent<PointerEvent>) => {
e.stopPropagation();
onHoverNode(index);
}}
onPointerLeave={(e: ThreeEvent<PointerEvent>) => {
e.stopPropagation();
onHoverNode(null);
}}
{...pointerHandlers}
/>
);
}
@@ -314,9 +340,14 @@ function EditorFallbackNode({
onHoverNode,
}: EditorNodeCommonProps) {
const meshRef = useRef<THREE.Mesh>(null);
const pointerHandlers = createEditorNodePointerHandlers(
index,
onSelectNode,
onHoverNode,
);
useRegisteredEditorNode(meshRef, index, node, objectsMapRef);
const color = isSelected ? "#ffffff" : isHovered ? "#b8b8b8" : "#6f6f6f";
const color = getNodeHighlightColor(isSelected, isHovered) ?? "#6f6f6f";
return (
<mesh
@@ -324,18 +355,7 @@ function EditorFallbackNode({
position={node.position}
rotation={node.rotation}
scale={node.scale}
onClick={(e: ThreeEvent<MouseEvent>) => {
e.stopPropagation();
onSelectNode(index);
}}
onPointerEnter={(e: ThreeEvent<PointerEvent>) => {
e.stopPropagation();
onHoverNode(index);
}}
onPointerLeave={(e: ThreeEvent<PointerEvent>) => {
e.stopPropagation();
onHoverNode(null);
}}
{...pointerHandlers}
>
<boxGeometry args={[1, 1, 1]} />
<meshStandardMaterial color={color} />