feat: implement editable wall length slider (#195)

feat: implement editable wall length slider #191
This commit is contained in:
Pascal
2026-03-28 18:24:14 -04:00
committed by GitHub
2 changed files with 37 additions and 10 deletions
@@ -6,7 +6,7 @@ import { markToolCancelConsumed } from '../../../hooks/use-keyboard'
import { EDITOR_LAYER } from '../../../lib/constants' import { EDITOR_LAYER } from '../../../lib/constants'
import { sfxEmitter } from '../../../lib/sfx-bus' import { sfxEmitter } from '../../../lib/sfx-bus'
import { CursorSphere } from '../shared/cursor-sphere' import { CursorSphere } from '../shared/cursor-sphere'
import { createWallOnCurrentLevel, snapWallDraftPoint, type WallPlanPoint } from './wall-drafting' import { createWallOnCurrentLevel, snapWallDraftPoint, WALL_MIN_LENGTH, type WallPlanPoint } from './wall-drafting'
const WALL_HEIGHT = 2.5 const WALL_HEIGHT = 2.5
@@ -18,7 +18,7 @@ const updateWallPreview = (mesh: Mesh, start: Vector3, end: Vector3) => {
const direction = new Vector3(end.x - start.x, 0, end.z - start.z) const direction = new Vector3(end.x - start.x, 0, end.z - start.z)
const length = direction.length() const length = direction.length()
if (length < 0.01) { if (length < WALL_MIN_LENGTH) {
mesh.visible = false mesh.visible = false
return return
} }
@@ -143,7 +143,7 @@ export const WallTool: React.FC = () => {
endingPoint.current.set(snappedEnd[0], event.position[1], snappedEnd[1]) endingPoint.current.set(snappedEnd[0], event.position[1], snappedEnd[1])
const dx = endingPoint.current.x - startingPoint.current.x const dx = endingPoint.current.x - startingPoint.current.x
const dz = endingPoint.current.z - startingPoint.current.z const dz = endingPoint.current.z - startingPoint.current.z
if (dx * dx + dz * dz < 0.01 * 0.01) return if (dx * dx + dz * dz < WALL_MIN_LENGTH * WALL_MIN_LENGTH) return
createWallOnCurrentLevel( createWallOnCurrentLevel(
[startingPoint.current.x, startingPoint.current.z], [startingPoint.current.x, startingPoint.current.z],
[endingPoint.current.x, endingPoint.current.z], [endingPoint.current.x, endingPoint.current.z],
@@ -25,6 +25,29 @@ export function WallPanel() {
[selectedId, updateNode], [selectedId, updateNode],
) )
// Função mágica para a Issue #191: Atualiza o comprimento via cálculo vetorial
const handleUpdateLength = useCallback((newLength: number) => {
if (!node || newLength <= 0) return
const dx = node.end[0] - node.start[0]
const dz = node.end[1] - node.start[1]
const currentLength = Math.sqrt(dx * dx + dz * dz)
if (currentLength === 0) return
// Calcula a direção (vetor unitário)
const dirX = dx / currentLength
const dirZ = dz / currentLength
// Define o novo ponto final baseado no novo comprimento
const newEnd: [number, number] = [
node.start[0] + dirX * newLength,
node.start[1] + dirZ * newLength
]
handleUpdate({ end: newEnd })
}, [node, handleUpdate])
const handleClose = useCallback(() => { const handleClose = useCallback(() => {
setSelection({ selectedIds: [] }) setSelection({ selectedIds: [] })
}, [setSelection]) }, [setSelection])
@@ -46,6 +69,17 @@ export function WallPanel() {
width={280} width={280}
> >
<PanelSection title="Dimensions"> <PanelSection title="Dimensions">
{/* Adicionando o controle de Length solicitado na Issue #191 */}
<SliderControl
label="Length"
max={20}
min={0.1}
onChange={handleUpdateLength}
precision={2}
step={0.01}
unit="m"
value={length}
/>
<SliderControl <SliderControl
label="Height" label="Height"
max={6} max={6}
@@ -67,13 +101,6 @@ export function WallPanel() {
value={Math.round(thickness * 1000) / 1000} value={Math.round(thickness * 1000) / 1000}
/> />
</PanelSection> </PanelSection>
<PanelSection title="Info">
<div className="flex items-center justify-between px-2 py-1 text-muted-foreground text-sm">
<span>Length</span>
<span className="font-mono text-white">{length.toFixed(2)} m</span>
</div>
</PanelSection>
</PanelWrapper> </PanelWrapper>
) )
} }