fix raycaster layers, polygon drag, slider undo, and grid events
- Enable EDITOR_LAYER on R3F raycaster for proper hit detection - Fix polygon editor drag using refs and direct position passing - Handle pointercancel events and fix pointerId access in polygon editor - Fix slider undo by reverting to start value before resuming temporal state - Allow grid:move during camera drag so polygon editor works while panning - Bump better-auth to ^1.5.2 and turbo to ^2.8.12 - Remove explicit return type on createAuth for better inference Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
efeea1719c
commit
48979ec014
@@ -16,9 +16,11 @@ export const CustomCameraControls = () => {
|
||||
const firstLoad = useRef(true)
|
||||
|
||||
const camera = useThree((state) => state.camera)
|
||||
const raycaster = useThree((state) => state.raycaster)
|
||||
useEffect(() => {
|
||||
camera.layers.enable(EDITOR_LAYER)
|
||||
}, [camera])
|
||||
raycaster.layers.enable(EDITOR_LAYER)
|
||||
}, [camera, raycaster])
|
||||
|
||||
useEffect(() => {
|
||||
let targetY = 0
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { emitter, type GridEvent, sceneRegistry } from '@pascal-app/core'
|
||||
import { useViewer } from '@pascal-app/viewer'
|
||||
import { createPortal } from '@react-three/fiber'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { BufferGeometry, Float32BufferAttribute, type Mesh } from 'three'
|
||||
@@ -49,6 +50,13 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
|
||||
// Local state for dragging
|
||||
const [dragState, setDragState] = useState<DragState | null>(null)
|
||||
const [previewPolygon, setPreviewPolygon] = useState<Array<[number, number]> | null>(null)
|
||||
const previewPolygonRef = useRef<Array<[number, number]> | null>(null)
|
||||
|
||||
// Keep ref in sync
|
||||
useEffect(() => {
|
||||
previewPolygonRef.current = previewPolygon
|
||||
}, [previewPolygon])
|
||||
|
||||
const [hoveredVertex, setHoveredVertex] = useState<number | null>(null)
|
||||
const [hoveredMidpoint, setHoveredMidpoint] = useState<number | null>(null)
|
||||
const [cursorPosition, setCursorPosition] = useState<[number, number]>([0, 0])
|
||||
@@ -80,23 +88,25 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
|
||||
|
||||
// Update vertex position using grid cursor position
|
||||
const handleVertexDrag = useCallback(
|
||||
(vertexIndex: number) => {
|
||||
const basePolygon = previewPolygon ?? polygon
|
||||
const newPolygon = [...basePolygon]
|
||||
newPolygon[vertexIndex] = cursorPosition
|
||||
setPreviewPolygon(newPolygon)
|
||||
(vertexIndex: number, position: [number, number]) => {
|
||||
setPreviewPolygon((prev) => {
|
||||
const basePolygon = prev ?? polygon
|
||||
const newPolygon = [...basePolygon]
|
||||
newPolygon[vertexIndex] = position
|
||||
return newPolygon
|
||||
})
|
||||
},
|
||||
[cursorPosition, previewPolygon, polygon],
|
||||
[polygon],
|
||||
)
|
||||
|
||||
// Commit polygon changes
|
||||
const commitPolygonChange = useCallback(() => {
|
||||
if (previewPolygon) {
|
||||
onPolygonChange(previewPolygon)
|
||||
if (previewPolygonRef.current) {
|
||||
onPolygonChange(previewPolygonRef.current)
|
||||
}
|
||||
setPreviewPolygon(null)
|
||||
setDragState(null)
|
||||
}, [previewPolygon, onPolygonChange])
|
||||
}, [onPolygonChange])
|
||||
|
||||
// Handle adding a new vertex at midpoint
|
||||
const handleAddVertex = useCallback(
|
||||
@@ -145,7 +155,7 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
|
||||
|
||||
// Update vertex position during drag
|
||||
if (dragState?.isDragging) {
|
||||
handleVertexDrag(dragState.vertexIndex)
|
||||
handleVertexDrag(dragState.vertexIndex, newPosition)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,9 +169,9 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
|
||||
useEffect(() => {
|
||||
if (!dragState?.isDragging) return
|
||||
|
||||
const handlePointerUp = (e: PointerEvent) => {
|
||||
// Only handle the specific pointer that started the drag
|
||||
if (e.pointerId !== dragState.pointerId) return
|
||||
const handlePointerUp = (e: PointerEvent | MouseEvent) => {
|
||||
// Only handle the specific pointer that started the drag, if it's a PointerEvent
|
||||
if ('pointerId' in e && dragState.pointerId !== undefined && e.pointerId !== dragState.pointerId) return
|
||||
|
||||
// Stop the event from propagating to prevent grid click
|
||||
e.stopImmediatePropagation()
|
||||
@@ -183,9 +193,11 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
|
||||
commitPolygonChange()
|
||||
}
|
||||
|
||||
window.addEventListener('pointerup', handlePointerUp, true)
|
||||
window.addEventListener('pointerup', handlePointerUp as EventListener, true)
|
||||
window.addEventListener('pointercancel', handlePointerUp as EventListener, true)
|
||||
return () => {
|
||||
window.removeEventListener('pointerup', handlePointerUp, true)
|
||||
window.removeEventListener('pointerup', handlePointerUp as EventListener, true)
|
||||
window.removeEventListener('pointercancel', handlePointerUp as EventListener, true)
|
||||
}
|
||||
}, [dragState, commitPolygonChange])
|
||||
|
||||
@@ -256,7 +268,7 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
|
||||
isDragging: true,
|
||||
vertexIndex: index,
|
||||
initialPosition: [x!, z!],
|
||||
pointerId: e.nativeEvent.pointerId,
|
||||
pointerId: e.pointerId,
|
||||
})
|
||||
}}
|
||||
onClick={(e) => {
|
||||
@@ -308,7 +320,7 @@ export const PolygonEditor: React.FC<PolygonEditorProps> = ({
|
||||
isDragging: true,
|
||||
vertexIndex: newVertexIndex,
|
||||
initialPosition: [x!, z!],
|
||||
pointerId: e.nativeEvent.pointerId,
|
||||
pointerId: e.pointerId,
|
||||
})
|
||||
setHoveredMidpoint(null)
|
||||
}
|
||||
|
||||
@@ -147,12 +147,26 @@ export function SliderControl({
|
||||
}
|
||||
|
||||
setIsDragging(false)
|
||||
const startVal = dragStartValue
|
||||
const finalVal = valueRef.current
|
||||
|
||||
setDragStartValue(null)
|
||||
setDragMin(null)
|
||||
setDragMax(null)
|
||||
document.removeEventListener('pointermove', handlePointerMove)
|
||||
document.removeEventListener('pointerup', handlePointerUp)
|
||||
useScene.temporal.getState().resume()
|
||||
|
||||
if (startVal !== null && startVal !== finalVal) {
|
||||
// Revert to start value while paused so the undo baseline is clean
|
||||
onChange(startVal)
|
||||
|
||||
useScene.temporal.getState().resume()
|
||||
|
||||
// Apply final value while recording
|
||||
onChange(finalVal)
|
||||
} else {
|
||||
useScene.temporal.getState().resume()
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('pointermove', handlePointerMove)
|
||||
|
||||
@@ -72,7 +72,7 @@ export function useGridEvents(gridY: number) {
|
||||
}
|
||||
|
||||
const handlePointerMove = (e: PointerEvent) => {
|
||||
if (useViewer.getState().cameraDragging) return
|
||||
// Emit move even if camera is dragging, so tools like PolygonEditor still work
|
||||
emit('move', e)
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"@vercel/speed-insights": "^1.3.1",
|
||||
"@vercel/toolbar": "^0.2.2",
|
||||
"@visual-json/react": "latest",
|
||||
"better-auth": "^1.4.19",
|
||||
"better-auth": "^1.5.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"howler": "^2.2.4",
|
||||
|
||||
Reference in New Issue
Block a user