Stop propagation of camera clicks after drags (#4257)
* Update CameraControls.ts
* fix static analyzer error
* A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)
* Revert "A snapshot a day keeps the bugs away! 📷🐛 (OS: windows-latest)"
This reverts commit 0b63016217
.
* Don't perform sketch click operations if a camera movement interaction also matches
* Don't `stopPropogation`, make selection listener early return if `wasDragging`
+ consolidate `wasDragging` set statements, add comments
* Codespell
---------
Co-authored-by: 49fl <ircsurfer33@gmail.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Frank Noirot <frank@kittycad.io>
Co-authored-by: Frank Noirot <frank@zoo.dev>
This commit is contained in:
@ -92,6 +92,7 @@ export class CameraControls {
|
|||||||
target: Vector3
|
target: Vector3
|
||||||
domElement: HTMLCanvasElement
|
domElement: HTMLCanvasElement
|
||||||
isDragging: boolean
|
isDragging: boolean
|
||||||
|
wasDragging: boolean
|
||||||
mouseDownPosition: Vector2
|
mouseDownPosition: Vector2
|
||||||
mouseNewPosition: Vector2
|
mouseNewPosition: Vector2
|
||||||
rotationSpeed = 0.3
|
rotationSpeed = 0.3
|
||||||
@ -233,6 +234,7 @@ export class CameraControls {
|
|||||||
this.target = new Vector3()
|
this.target = new Vector3()
|
||||||
this.domElement = domElement
|
this.domElement = domElement
|
||||||
this.isDragging = false
|
this.isDragging = false
|
||||||
|
this.wasDragging = false
|
||||||
this.mouseDownPosition = new Vector2()
|
this.mouseDownPosition = new Vector2()
|
||||||
this.mouseNewPosition = new Vector2()
|
this.mouseNewPosition = new Vector2()
|
||||||
|
|
||||||
@ -363,6 +365,8 @@ export class CameraControls {
|
|||||||
onMouseDown = (event: PointerEvent) => {
|
onMouseDown = (event: PointerEvent) => {
|
||||||
this.domElement.setPointerCapture(event.pointerId)
|
this.domElement.setPointerCapture(event.pointerId)
|
||||||
this.isDragging = true
|
this.isDragging = true
|
||||||
|
// Reset the wasDragging flag to false when starting a new drag
|
||||||
|
this.wasDragging = false
|
||||||
this.mouseDownPosition.set(event.clientX, event.clientY)
|
this.mouseDownPosition.set(event.clientX, event.clientY)
|
||||||
let interaction = this.getInteractionType(event)
|
let interaction = this.getInteractionType(event)
|
||||||
if (interaction === 'none') return
|
if (interaction === 'none') return
|
||||||
@ -392,6 +396,10 @@ export class CameraControls {
|
|||||||
const interaction = this.getInteractionType(event)
|
const interaction = this.getInteractionType(event)
|
||||||
if (interaction === 'none') return
|
if (interaction === 'none') return
|
||||||
|
|
||||||
|
// If there's a valid interaction and the mouse is moving,
|
||||||
|
// our past (and current) interaction was a drag.
|
||||||
|
this.wasDragging = true
|
||||||
|
|
||||||
if (this.syncDirection === 'engineToClient') {
|
if (this.syncDirection === 'engineToClient') {
|
||||||
this.moveSender.send(() => {
|
this.moveSender.send(() => {
|
||||||
this.doMove(interaction, [event.clientX, event.clientY])
|
this.doMove(interaction, [event.clientX, event.clientY])
|
||||||
@ -399,6 +407,7 @@ export class CameraControls {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// else "clientToEngine" (Sketch Mode) or forceUpdate
|
||||||
// Implement camera movement logic here based on deltaMove
|
// Implement camera movement logic here based on deltaMove
|
||||||
// For example, for rotating the camera around the target:
|
// For example, for rotating the camera around the target:
|
||||||
if (interaction === 'rotate') {
|
if (interaction === 'rotate') {
|
||||||
@ -427,6 +436,9 @@ export class CameraControls {
|
|||||||
* under the cursor. This recently moved from being handled in App.tsx.
|
* under the cursor. This recently moved from being handled in App.tsx.
|
||||||
* This might not be the right spot, but it is more consolidated.
|
* This might not be the right spot, but it is more consolidated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// Clear any previous drag state
|
||||||
|
this.wasDragging = false
|
||||||
if (this.syncDirection === 'engineToClient') {
|
if (this.syncDirection === 'engineToClient') {
|
||||||
const newCmdId = uuidv4()
|
const newCmdId = uuidv4()
|
||||||
|
|
||||||
|
@ -338,6 +338,11 @@ export class SceneEntities {
|
|||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
if (!args) return
|
if (!args) return
|
||||||
|
// If there is a valid camera interaction that matches, do that instead
|
||||||
|
const interaction = sceneInfra.camControls.getInteractionType(
|
||||||
|
args.mouseEvent
|
||||||
|
)
|
||||||
|
if (interaction !== 'none') return
|
||||||
if (args.mouseEvent.which !== 1) return
|
if (args.mouseEvent.which !== 1) return
|
||||||
const { intersectionPoint } = args
|
const { intersectionPoint } = args
|
||||||
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode) return
|
if (!intersectionPoint?.twoD || !sketchDetails?.sketchPathToNode) return
|
||||||
@ -645,7 +650,13 @@ export class SceneEntities {
|
|||||||
sceneInfra.setCallbacks({
|
sceneInfra.setCallbacks({
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
if (!args) return
|
if (!args) return
|
||||||
|
// If there is a valid camera interaction that matches, do that instead
|
||||||
|
const interaction = sceneInfra.camControls.getInteractionType(
|
||||||
|
args.mouseEvent
|
||||||
|
)
|
||||||
|
if (interaction !== 'none') return
|
||||||
if (args.mouseEvent.which !== 1) return
|
if (args.mouseEvent.which !== 1) return
|
||||||
|
|
||||||
const { intersectionPoint } = args
|
const { intersectionPoint } = args
|
||||||
let intersection2d = intersectionPoint?.twoD
|
let intersection2d = intersectionPoint?.twoD
|
||||||
const profileStart = args.intersects
|
const profileStart = args.intersects
|
||||||
@ -826,6 +837,11 @@ export class SceneEntities {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
|
// If there is a valid camera interaction that matches, do that instead
|
||||||
|
const interaction = sceneInfra.camControls.getInteractionType(
|
||||||
|
args.mouseEvent
|
||||||
|
)
|
||||||
|
if (interaction !== 'none') return
|
||||||
// Commit the rectangle to the full AST/code and return to sketch.idle
|
// Commit the rectangle to the full AST/code and return to sketch.idle
|
||||||
const cornerPoint = args.intersectionPoint?.twoD
|
const cornerPoint = args.intersectionPoint?.twoD
|
||||||
if (!cornerPoint || args.mouseEvent.button !== 0) return
|
if (!cornerPoint || args.mouseEvent.button !== 0) return
|
||||||
@ -994,6 +1010,11 @@ export class SceneEntities {
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
onClick: async (args) => {
|
onClick: async (args) => {
|
||||||
|
// If there is a valid camera interaction that matches, do that instead
|
||||||
|
const interaction = sceneInfra.camControls.getInteractionType(
|
||||||
|
args.mouseEvent
|
||||||
|
)
|
||||||
|
if (interaction !== 'none') return
|
||||||
// Commit the rectangle to the full AST/code and return to sketch.idle
|
// Commit the rectangle to the full AST/code and return to sketch.idle
|
||||||
const cornerPoint = args.intersectionPoint?.twoD
|
const cornerPoint = args.intersectionPoint?.twoD
|
||||||
if (!cornerPoint || args.mouseEvent.button !== 0) return
|
if (!cornerPoint || args.mouseEvent.button !== 0) return
|
||||||
@ -1157,6 +1178,11 @@ export class SceneEntities {
|
|||||||
},
|
},
|
||||||
onMove: () => {},
|
onMove: () => {},
|
||||||
onClick: (args) => {
|
onClick: (args) => {
|
||||||
|
// If there is a valid camera interaction that matches, do that instead
|
||||||
|
const interaction = sceneInfra.camControls.getInteractionType(
|
||||||
|
args.mouseEvent
|
||||||
|
)
|
||||||
|
if (interaction !== 'none') return
|
||||||
if (args?.mouseEvent.which !== 1) return
|
if (args?.mouseEvent.which !== 1) return
|
||||||
if (!args || !args.selected) {
|
if (!args || !args.selected) {
|
||||||
sceneInfra.modelingSend({
|
sceneInfra.modelingSend({
|
||||||
|
@ -255,10 +255,14 @@ export const Stream = () => {
|
|||||||
}, [mediaStream])
|
}, [mediaStream])
|
||||||
|
|
||||||
const handleMouseUp: MouseEventHandler<HTMLDivElement> = (e) => {
|
const handleMouseUp: MouseEventHandler<HTMLDivElement> = (e) => {
|
||||||
|
// If we've got no stream or connection, don't do anything
|
||||||
if (!isNetworkOkay) return
|
if (!isNetworkOkay) return
|
||||||
if (!videoRef.current) return
|
if (!videoRef.current) return
|
||||||
|
// If we're in sketch mode, don't send a engine-side select event
|
||||||
if (state.matches('Sketch')) return
|
if (state.matches('Sketch')) return
|
||||||
if (state.matches({ idle: 'showPlanes' })) return
|
if (state.matches({ idle: 'showPlanes' })) return
|
||||||
|
// If we're mousing up from a camera drag, don't send a select event
|
||||||
|
if (sceneInfra.camControls.wasDragging === true) return
|
||||||
|
|
||||||
if (btnName(e.nativeEvent).left) {
|
if (btnName(e.nativeEvent).left) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
Reference in New Issue
Block a user