@tldraw/editor 4.3.0-next.7f179bd04d6c → 4.3.0-next.842fb21476f2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +441 -120
- package/dist-cjs/index.js +6 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
- package/dist-cjs/lib/components/GeometryDebuggingView.js +1 -17
- package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +3 -3
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/constants.js +1 -3
- package/dist-cjs/lib/constants.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +288 -275
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +18 -17
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js +12 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -1
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +5 -6
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +591 -0
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -22
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +31 -23
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js +1 -1
- package/dist-cjs/lib/editor/shapes/group/DashedOutlineBox.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +3 -3
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/exports/parseCss.js +1 -1
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +45 -9
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/useCoarsePointer.js +14 -29
- package/dist-cjs/lib/hooks/useCoarsePointer.js.map +2 -2
- package/dist-cjs/lib/hooks/useEvent.js +1 -1
- package/dist-cjs/lib/hooks/useEvent.js.map +2 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
- package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
- package/dist-cjs/lib/hooks/useStateAttribute.js +4 -1
- package/dist-cjs/lib/hooks/useStateAttribute.js.map +2 -2
- package/dist-cjs/lib/hooks/useTransform.js.map +1 -1
- package/dist-cjs/lib/hooks/useZoomCss.js +4 -8
- package/dist-cjs/lib/hooks/useZoomCss.js.map +2 -2
- package/dist-cjs/lib/options.js +6 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +3 -0
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/utils/rotation.js +1 -1
- package/dist-cjs/lib/utils/rotation.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +441 -120
- package/dist-esm/index.mjs +7 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
- package/dist-esm/lib/components/GeometryDebuggingView.mjs +1 -17
- package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +3 -3
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/constants.mjs +1 -3
- package/dist-esm/lib/constants.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +289 -278
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +18 -17
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +13 -4
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +5 -6
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +573 -0
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -22
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +31 -23
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs +1 -1
- package/dist-esm/lib/editor/shapes/group/DashedOutlineBox.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +3 -3
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/exports/parseCss.mjs +1 -1
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +45 -9
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCoarsePointer.mjs +15 -30
- package/dist-esm/lib/hooks/useCoarsePointer.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEvent.mjs +1 -1
- package/dist-esm/lib/hooks/useEvent.mjs.map +2 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useGestureEvents.mjs +1 -1
- package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useStateAttribute.mjs +4 -1
- package/dist-esm/lib/hooks/useStateAttribute.mjs.map +2 -2
- package/dist-esm/lib/hooks/useTransform.mjs.map +1 -1
- package/dist-esm/lib/hooks/useZoomCss.mjs +4 -8
- package/dist-esm/lib/hooks/useZoomCss.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +6 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +3 -0
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/utils/rotation.mjs +1 -1
- package/dist-esm/lib/utils/rotation.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +14 -12
- package/package.json +18 -16
- package/src/index.ts +4 -1
- package/src/lib/components/ErrorBoundary.tsx +1 -1
- package/src/lib/components/GeometryDebuggingView.tsx +1 -19
- package/src/lib/components/default-components/DefaultCanvas.tsx +3 -3
- package/src/lib/config/TLUserPreferences.test.ts +40 -0
- package/src/lib/constants.ts +0 -2
- package/src/lib/editor/Editor.test.ts +140 -0
- package/src/lib/editor/Editor.ts +374 -321
- package/src/lib/editor/derivations/notVisibleShapes.ts +37 -23
- package/src/lib/editor/derivations/parentsToChildren.ts +18 -7
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +17 -31
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +129 -79
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +10 -6
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +566 -0
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -4
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +12 -0
- package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +40 -107
- package/src/lib/editor/managers/TickManager/TickManager.ts +2 -32
- package/src/lib/editor/shapes/ShapeUtil.ts +67 -24
- package/src/lib/editor/shapes/group/DashedOutlineBox.tsx +1 -1
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +3 -3
- package/src/lib/exports/parseCss.test.ts +1 -0
- package/src/lib/exports/parseCss.ts +1 -1
- package/src/lib/globals/environment.ts +65 -10
- package/src/lib/hooks/useCoarsePointer.ts +16 -59
- package/src/lib/hooks/useEvent.tsx +1 -1
- package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -1
- package/src/lib/hooks/useGestureEvents.ts +2 -2
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +1 -1
- package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -1
- package/src/lib/hooks/useScreenBounds.ts +1 -1
- package/src/lib/hooks/useStateAttribute.ts +4 -1
- package/src/lib/hooks/useTransform.ts +1 -1
- package/src/lib/hooks/useZoomCss.ts +3 -8
- package/src/lib/options.ts +32 -0
- package/src/lib/primitives/Box.ts +9 -0
- package/src/lib/primitives/geometry/Geometry2d.ts +1 -0
- package/src/lib/utils/rotation.ts +1 -1
- package/src/version.ts +3 -3
|
@@ -2,29 +2,7 @@ import { computed, isUninitialized } from '@tldraw/state'
|
|
|
2
2
|
import { TLShapeId } from '@tldraw/tlschema'
|
|
3
3
|
import { Editor } from '../Editor'
|
|
4
4
|
|
|
5
|
-
function fromScratch(editor: Editor): Set<TLShapeId> {
|
|
6
|
-
const shapesIds = editor.getCurrentPageShapeIds()
|
|
7
|
-
const viewportPageBounds = editor.getViewportPageBounds()
|
|
8
|
-
const notVisibleShapes = new Set<TLShapeId>()
|
|
9
|
-
shapesIds.forEach((id) => {
|
|
10
|
-
const shape = editor.getShape(id)
|
|
11
|
-
if (!shape) return
|
|
12
|
-
|
|
13
|
-
const canCull = editor.getShapeUtil(shape.type).canCull(shape)
|
|
14
|
-
if (!canCull) return
|
|
15
|
-
|
|
16
|
-
// If the shape is fully outside of the viewport page bounds, add it to the set.
|
|
17
|
-
// We'll ignore masks here, since they're more expensive to compute and the overhead is not worth it.
|
|
18
|
-
const pageBounds = editor.getShapePageBounds(id)
|
|
19
|
-
if (pageBounds === undefined || !viewportPageBounds.includes(pageBounds)) {
|
|
20
|
-
notVisibleShapes.add(id)
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
return notVisibleShapes
|
|
24
|
-
}
|
|
25
|
-
|
|
26
5
|
/**
|
|
27
|
-
* Incremental derivation of not visible shapes.
|
|
28
6
|
* Non visible shapes are shapes outside of the viewport page bounds.
|
|
29
7
|
*
|
|
30
8
|
* @param editor - Instance of the tldraw Editor.
|
|
@@ -32,7 +10,43 @@ function fromScratch(editor: Editor): Set<TLShapeId> {
|
|
|
32
10
|
*/
|
|
33
11
|
export function notVisibleShapes(editor: Editor) {
|
|
34
12
|
return computed<Set<TLShapeId>>('notVisibleShapes', function updateNotVisibleShapes(prevValue) {
|
|
35
|
-
const
|
|
13
|
+
const shapeIds = editor.getCurrentPageShapeIds()
|
|
14
|
+
const nextValue = new Set<TLShapeId>()
|
|
15
|
+
|
|
16
|
+
// Extract viewport bounds once to avoid repeated property access
|
|
17
|
+
const viewportPageBounds = editor.getViewportPageBounds()
|
|
18
|
+
const viewMinX = viewportPageBounds.minX
|
|
19
|
+
const viewMinY = viewportPageBounds.minY
|
|
20
|
+
const viewMaxX = viewportPageBounds.maxX
|
|
21
|
+
const viewMaxY = viewportPageBounds.maxY
|
|
22
|
+
|
|
23
|
+
for (const id of shapeIds) {
|
|
24
|
+
const pageBounds = editor.getShapePageBounds(id)
|
|
25
|
+
|
|
26
|
+
// Hybrid check: if bounds exist and shape overlaps viewport, it's visible.
|
|
27
|
+
// This inlines Box.Collides to avoid function call overhead and the
|
|
28
|
+
// redundant Contains check that Box.Includes was doing.
|
|
29
|
+
if (
|
|
30
|
+
pageBounds !== undefined &&
|
|
31
|
+
pageBounds.maxX >= viewMinX &&
|
|
32
|
+
pageBounds.minX <= viewMaxX &&
|
|
33
|
+
pageBounds.maxY >= viewMinY &&
|
|
34
|
+
pageBounds.minY <= viewMaxY
|
|
35
|
+
) {
|
|
36
|
+
continue
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Shape is outside viewport or has no bounds - check if it can be culled.
|
|
40
|
+
// We defer getShape and canCull checks until here since most shapes are
|
|
41
|
+
// typically visible and we can skip these calls for them.
|
|
42
|
+
const shape = editor.getShape(id)
|
|
43
|
+
if (!shape) continue
|
|
44
|
+
|
|
45
|
+
const canCull = editor.getShapeUtil(shape.type).canCull(shape)
|
|
46
|
+
if (!canCull) continue
|
|
47
|
+
|
|
48
|
+
nextValue.add(id)
|
|
49
|
+
}
|
|
36
50
|
|
|
37
51
|
if (isUninitialized(prevValue)) {
|
|
38
52
|
return nextValue
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Computed, computed, isUninitialized, RESET_VALUE } from '@tldraw/state'
|
|
2
2
|
import { CollectionDiff, RecordsDiff } from '@tldraw/store'
|
|
3
|
-
import { isShape, TLParentId, TLRecord, TLShapeId, TLStore } from '@tldraw/tlschema'
|
|
4
|
-
import {
|
|
3
|
+
import { isShape, TLParentId, TLRecord, TLShape, TLShapeId, TLStore } from '@tldraw/tlschema'
|
|
4
|
+
import { sortByIndex } from '@tldraw/utils'
|
|
5
5
|
|
|
6
6
|
type ParentShapeIdsToChildShapeIds = Record<TLParentId, TLShapeId[]>
|
|
7
7
|
|
|
@@ -98,12 +98,23 @@ export const parentsToChildren = (store: TLStore) => {
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
// Sort the arrays that have been marked for sorting
|
|
101
|
+
// Sort the arrays that have been marked for sorting (in-place to avoid intermediate arrays)
|
|
102
102
|
for (const arr of toSort) {
|
|
103
|
-
//
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
// Filter out any deleted shapes in-place
|
|
104
|
+
let writeIdx = 0
|
|
105
|
+
for (let readIdx = 0; readIdx < arr.length; readIdx++) {
|
|
106
|
+
if (store.get(arr[readIdx])) {
|
|
107
|
+
arr[writeIdx++] = arr[readIdx]
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
arr.length = writeIdx
|
|
111
|
+
|
|
112
|
+
// Sort in-place by index
|
|
113
|
+
arr.sort((a, b) => {
|
|
114
|
+
const shapeA = store.get(a) as TLShape
|
|
115
|
+
const shapeB = store.get(b) as TLShape
|
|
116
|
+
return sortByIndex(shapeA, shapeB)
|
|
117
|
+
})
|
|
107
118
|
}
|
|
108
119
|
|
|
109
120
|
return newValue ?? lastValue
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Mocked, vi } from 'vitest'
|
|
2
|
+
import { Vec } from '../../../primitives/Vec'
|
|
2
3
|
import { Editor } from '../../Editor'
|
|
3
4
|
import { TLClickEventInfo, TLPointerEventInfo } from '../../types/event-types'
|
|
4
5
|
import { ClickManager } from './ClickManager'
|
|
@@ -35,6 +36,8 @@ describe('ClickManager', () => {
|
|
|
35
36
|
setTimeout: vi.fn((fn, delay) => setTimeout(fn, delay)),
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
const mockCurrentScreenPoint = new Vec(0, 0)
|
|
40
|
+
|
|
38
41
|
editor = {
|
|
39
42
|
timers: mockTimers,
|
|
40
43
|
dispatch: vi.fn(),
|
|
@@ -45,7 +48,8 @@ describe('ClickManager', () => {
|
|
|
45
48
|
coarseDragDistanceSquared: 36,
|
|
46
49
|
},
|
|
47
50
|
inputs: {
|
|
48
|
-
|
|
51
|
+
getCurrentScreenPoint: vi.fn(() => mockCurrentScreenPoint),
|
|
52
|
+
currentScreenPoint: mockCurrentScreenPoint, // deprecated getter for compatibility
|
|
49
53
|
},
|
|
50
54
|
getInstanceState: vi.fn(() => ({
|
|
51
55
|
isCoarsePointer: false,
|
|
@@ -321,8 +325,9 @@ describe('ClickManager', () => {
|
|
|
321
325
|
const downEvent = createPointerEvent('pointer_down', { x: 0, y: 0 })
|
|
322
326
|
const moveEvent = createPointerEvent('pointer_move', { x: 10, y: 10 })
|
|
323
327
|
|
|
324
|
-
editor.inputs.
|
|
325
|
-
|
|
328
|
+
const currentScreenPoint = editor.inputs.getCurrentScreenPoint()
|
|
329
|
+
currentScreenPoint.x = 10
|
|
330
|
+
currentScreenPoint.y = 10
|
|
326
331
|
|
|
327
332
|
clickManager.handlePointerEvent(downEvent)
|
|
328
333
|
expect(clickManager.clickState).toBe('pendingDouble')
|
|
@@ -347,13 +352,15 @@ describe('ClickManager', () => {
|
|
|
347
352
|
expect(clickManager.clickState).toBe('pendingDouble')
|
|
348
353
|
|
|
349
354
|
// Should not cancel for coarse pointer with small movement
|
|
350
|
-
editor.inputs.
|
|
351
|
-
|
|
355
|
+
const currentScreenPoint1 = editor.inputs.getCurrentScreenPoint()
|
|
356
|
+
currentScreenPoint1.x = 1
|
|
357
|
+
currentScreenPoint1.y = 1
|
|
352
358
|
clickManager.handlePointerEvent(moveEvent1)
|
|
353
359
|
expect(clickManager.clickState).toBe('pendingDouble')
|
|
354
360
|
|
|
355
|
-
editor.inputs.
|
|
356
|
-
|
|
361
|
+
const currentScreenPoint2 = editor.inputs.getCurrentScreenPoint()
|
|
362
|
+
currentScreenPoint2.x = 5
|
|
363
|
+
currentScreenPoint2.y = 5
|
|
357
364
|
clickManager.handlePointerEvent(moveEvent2)
|
|
358
365
|
|
|
359
366
|
expect(clickManager.clickState).toBe('idle')
|
|
@@ -362,8 +369,9 @@ describe('ClickManager', () => {
|
|
|
362
369
|
it('should not cancel in idle state', () => {
|
|
363
370
|
const moveEvent = createPointerEvent('pointer_move', { x: 100, y: 100 })
|
|
364
371
|
|
|
365
|
-
editor.inputs.
|
|
366
|
-
|
|
372
|
+
const currentScreenPoint = editor.inputs.getCurrentScreenPoint()
|
|
373
|
+
currentScreenPoint.x = 100
|
|
374
|
+
currentScreenPoint.y = 100
|
|
367
375
|
|
|
368
376
|
clickManager.handlePointerEvent(moveEvent)
|
|
369
377
|
|
|
@@ -401,28 +409,6 @@ describe('ClickManager', () => {
|
|
|
401
409
|
})
|
|
402
410
|
|
|
403
411
|
describe('edge cases', () => {
|
|
404
|
-
it('should handle null click state gracefully', () => {
|
|
405
|
-
// Force null state
|
|
406
|
-
;(clickManager as any)._clickState = null
|
|
407
|
-
|
|
408
|
-
const pointerEvent = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
409
|
-
const result = clickManager.handlePointerEvent(pointerEvent)
|
|
410
|
-
|
|
411
|
-
expect(result).toBe(pointerEvent)
|
|
412
|
-
})
|
|
413
|
-
|
|
414
|
-
it('should handle missing previous screen point', () => {
|
|
415
|
-
const firstDown = createPointerEvent('pointer_down', { x: 0, y: 0 })
|
|
416
|
-
|
|
417
|
-
// Clear previous point
|
|
418
|
-
;(clickManager as any)._previousScreenPoint = undefined
|
|
419
|
-
|
|
420
|
-
const result = clickManager.handlePointerEvent(firstDown)
|
|
421
|
-
|
|
422
|
-
expect(result).toBe(firstDown)
|
|
423
|
-
expect(clickManager.clickState).toBe('pendingDouble')
|
|
424
|
-
})
|
|
425
|
-
|
|
426
412
|
it('should handle overflow state correctly', () => {
|
|
427
413
|
const pointerDown = createPointerEvent('pointer_down', { x: 100, y: 100 })
|
|
428
414
|
const pointerUp = createPointerEvent('pointer_up', { x: 100, y: 100 })
|
|
@@ -197,7 +197,7 @@ export class ClickManager {
|
|
|
197
197
|
if (
|
|
198
198
|
this._clickState !== 'idle' &&
|
|
199
199
|
this._clickScreenPoint &&
|
|
200
|
-
Vec.Dist2(this._clickScreenPoint, this.editor.inputs.
|
|
200
|
+
Vec.Dist2(this._clickScreenPoint, this.editor.inputs.getCurrentScreenPoint()) >
|
|
201
201
|
(this.editor.getInstanceState().isCoarsePointer
|
|
202
202
|
? this.editor.options.coarseDragDistanceSquared
|
|
203
203
|
: this.editor.options.dragDistanceSquared)
|
|
@@ -18,8 +18,56 @@ describe('EdgeScrollManager', () => {
|
|
|
18
18
|
}
|
|
19
19
|
>
|
|
20
20
|
let edgeScrollManager: EdgeScrollManager
|
|
21
|
+
let mockInputs: {
|
|
22
|
+
_currentScreenPoint: Vec
|
|
23
|
+
currentScreenPoint: Vec
|
|
24
|
+
getCurrentScreenPoint(): Vec
|
|
25
|
+
setCurrentScreenPoint(value: Vec): void
|
|
26
|
+
_isDragging: boolean
|
|
27
|
+
isDragging: boolean
|
|
28
|
+
getIsDragging(): boolean
|
|
29
|
+
setIsDragging(value: boolean): void
|
|
30
|
+
_isPanning: boolean
|
|
31
|
+
isPanning: boolean
|
|
32
|
+
getIsPanning(): boolean
|
|
33
|
+
setIsPanning(value: boolean): void
|
|
34
|
+
}
|
|
21
35
|
|
|
22
36
|
beforeEach(() => {
|
|
37
|
+
// Create a mock inputs object with writable properties and getters
|
|
38
|
+
mockInputs = {
|
|
39
|
+
_currentScreenPoint: new Vec(500, 300),
|
|
40
|
+
get currentScreenPoint() {
|
|
41
|
+
return this._currentScreenPoint
|
|
42
|
+
},
|
|
43
|
+
getCurrentScreenPoint() {
|
|
44
|
+
return this._currentScreenPoint
|
|
45
|
+
},
|
|
46
|
+
setCurrentScreenPoint(value: Vec) {
|
|
47
|
+
this._currentScreenPoint = value
|
|
48
|
+
},
|
|
49
|
+
_isDragging: true,
|
|
50
|
+
get isDragging() {
|
|
51
|
+
return this._isDragging
|
|
52
|
+
},
|
|
53
|
+
getIsDragging() {
|
|
54
|
+
return this._isDragging
|
|
55
|
+
},
|
|
56
|
+
setIsDragging(value: boolean) {
|
|
57
|
+
this._isDragging = value
|
|
58
|
+
},
|
|
59
|
+
_isPanning: false,
|
|
60
|
+
get isPanning() {
|
|
61
|
+
return this._isPanning
|
|
62
|
+
},
|
|
63
|
+
getIsPanning() {
|
|
64
|
+
return this._isPanning
|
|
65
|
+
},
|
|
66
|
+
setIsPanning(value: boolean) {
|
|
67
|
+
this._isPanning = value
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
23
71
|
editor = {
|
|
24
72
|
options: {
|
|
25
73
|
edgeScrollDelay: 200,
|
|
@@ -28,22 +76,15 @@ describe('EdgeScrollManager', () => {
|
|
|
28
76
|
edgeScrollDistance: 8,
|
|
29
77
|
coarsePointerWidth: 12,
|
|
30
78
|
},
|
|
31
|
-
inputs:
|
|
32
|
-
currentScreenPoint: new Vec(500, 300),
|
|
33
|
-
isDragging: true,
|
|
34
|
-
isPanning: false,
|
|
35
|
-
},
|
|
79
|
+
inputs: mockInputs as unknown as Editor['inputs'],
|
|
36
80
|
user: {
|
|
37
81
|
getEdgeScrollSpeed: vi.fn(() => 1),
|
|
38
82
|
},
|
|
39
83
|
getViewportScreenBounds: vi.fn(() => new Box(0, 0, 1000, 600)),
|
|
40
|
-
getInstanceState: vi.fn(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
insets: [false, false, false, false], // [top, right, bottom, left]
|
|
45
|
-
}) as any
|
|
46
|
-
),
|
|
84
|
+
getInstanceState: vi.fn(() => ({
|
|
85
|
+
isCoarsePointer: false,
|
|
86
|
+
insets: [false, false, false, false], // [top, right, bottom, left]
|
|
87
|
+
})),
|
|
47
88
|
getCameraOptions: vi.fn(() => ({
|
|
48
89
|
isLocked: false,
|
|
49
90
|
panSpeed: 1,
|
|
@@ -54,9 +95,17 @@ describe('EdgeScrollManager', () => {
|
|
|
54
95
|
getZoomLevel: vi.fn(() => 1),
|
|
55
96
|
getCamera: vi.fn(() => new Vec(0, 0, 1)),
|
|
56
97
|
setCamera: vi.fn(),
|
|
57
|
-
} as
|
|
98
|
+
} as unknown as Mocked<
|
|
99
|
+
Editor & {
|
|
100
|
+
user: { getEdgeScrollSpeed: Mock }
|
|
101
|
+
getCamera: Mock
|
|
102
|
+
getCameraOptions: Mock
|
|
103
|
+
getZoomLevel: Mock
|
|
104
|
+
getViewportScreenBounds: Mock
|
|
105
|
+
}
|
|
106
|
+
>
|
|
58
107
|
|
|
59
|
-
edgeScrollManager = new EdgeScrollManager(editor
|
|
108
|
+
edgeScrollManager = new EdgeScrollManager(editor)
|
|
60
109
|
})
|
|
61
110
|
|
|
62
111
|
afterEach(() => {
|
|
@@ -67,49 +116,45 @@ describe('EdgeScrollManager', () => {
|
|
|
67
116
|
it('should initialize with editor reference', () => {
|
|
68
117
|
expect(edgeScrollManager.editor).toBe(editor)
|
|
69
118
|
})
|
|
70
|
-
|
|
71
|
-
it('should initialize edge scrolling state as false', () => {
|
|
72
|
-
// Access private properties for testing
|
|
73
|
-
expect((edgeScrollManager as any)._isEdgeScrolling).toBe(false)
|
|
74
|
-
expect((edgeScrollManager as any)._edgeScrollDuration).toBe(-1)
|
|
75
|
-
})
|
|
76
119
|
})
|
|
77
120
|
|
|
78
121
|
describe('basic edge scrolling behavior', () => {
|
|
79
122
|
it('should not trigger edge scrolling when pointer is in center', () => {
|
|
80
|
-
|
|
123
|
+
mockInputs.setCurrentScreenPoint(new Vec(500, 300))
|
|
81
124
|
|
|
82
125
|
edgeScrollManager.updateEdgeScrolling(16)
|
|
83
126
|
|
|
84
|
-
expect((edgeScrollManager as any)._isEdgeScrolling).toBe(false)
|
|
85
127
|
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
86
128
|
})
|
|
87
129
|
|
|
88
130
|
it('should start edge scrolling when pointer is near edge', () => {
|
|
89
|
-
|
|
131
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
90
132
|
|
|
133
|
+
// Should not scroll immediately due to delay
|
|
91
134
|
edgeScrollManager.updateEdgeScrolling(16)
|
|
135
|
+
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
92
136
|
|
|
93
|
-
|
|
94
|
-
|
|
137
|
+
// Should scroll after delay
|
|
138
|
+
edgeScrollManager.updateEdgeScrolling(200)
|
|
139
|
+
expect(editor.setCamera).toHaveBeenCalled()
|
|
95
140
|
})
|
|
96
141
|
|
|
97
142
|
it('should stop edge scrolling when pointer moves away from edge', () => {
|
|
98
|
-
// Start edge scrolling
|
|
99
|
-
|
|
100
|
-
edgeScrollManager.updateEdgeScrolling(
|
|
101
|
-
expect(
|
|
143
|
+
// Start edge scrolling near edge
|
|
144
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
145
|
+
edgeScrollManager.updateEdgeScrolling(300)
|
|
146
|
+
expect(editor.setCamera).toHaveBeenCalled()
|
|
102
147
|
|
|
103
|
-
// Move pointer to center
|
|
104
|
-
editor.
|
|
148
|
+
// Move pointer to center - should stop scrolling
|
|
149
|
+
editor.setCamera.mockClear()
|
|
150
|
+
mockInputs.setCurrentScreenPoint(new Vec(500, 300))
|
|
105
151
|
edgeScrollManager.updateEdgeScrolling(16)
|
|
106
152
|
|
|
107
|
-
expect(
|
|
108
|
-
expect((edgeScrollManager as any)._edgeScrollDuration).toBe(0)
|
|
153
|
+
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
109
154
|
})
|
|
110
155
|
|
|
111
156
|
it('should respect edge scroll delay', () => {
|
|
112
|
-
|
|
157
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
113
158
|
|
|
114
159
|
// First update - should not scroll yet due to delay
|
|
115
160
|
edgeScrollManager.updateEdgeScrolling(100)
|
|
@@ -123,7 +168,7 @@ describe('EdgeScrollManager', () => {
|
|
|
123
168
|
|
|
124
169
|
describe('edge proximity detection', () => {
|
|
125
170
|
it('should detect left edge proximity', () => {
|
|
126
|
-
|
|
171
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
127
172
|
edgeScrollManager.updateEdgeScrolling(300) // Enough to trigger after delay
|
|
128
173
|
|
|
129
174
|
expect(editor.setCamera).toHaveBeenCalled()
|
|
@@ -132,7 +177,7 @@ describe('EdgeScrollManager', () => {
|
|
|
132
177
|
})
|
|
133
178
|
|
|
134
179
|
it('should detect right edge proximity', () => {
|
|
135
|
-
|
|
180
|
+
mockInputs.setCurrentScreenPoint(new Vec(995, 300))
|
|
136
181
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
137
182
|
|
|
138
183
|
expect(editor.setCamera).toHaveBeenCalled()
|
|
@@ -141,7 +186,7 @@ describe('EdgeScrollManager', () => {
|
|
|
141
186
|
})
|
|
142
187
|
|
|
143
188
|
it('should detect top edge proximity', () => {
|
|
144
|
-
|
|
189
|
+
mockInputs.setCurrentScreenPoint(new Vec(500, 5))
|
|
145
190
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
146
191
|
|
|
147
192
|
expect(editor.setCamera).toHaveBeenCalled()
|
|
@@ -150,7 +195,7 @@ describe('EdgeScrollManager', () => {
|
|
|
150
195
|
})
|
|
151
196
|
|
|
152
197
|
it('should detect bottom edge proximity', () => {
|
|
153
|
-
|
|
198
|
+
mockInputs.setCurrentScreenPoint(new Vec(500, 595))
|
|
154
199
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
155
200
|
|
|
156
201
|
expect(editor.setCamera).toHaveBeenCalled()
|
|
@@ -159,7 +204,7 @@ describe('EdgeScrollManager', () => {
|
|
|
159
204
|
})
|
|
160
205
|
|
|
161
206
|
it('should handle corner proximity (both x and y)', () => {
|
|
162
|
-
|
|
207
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 5))
|
|
163
208
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
164
209
|
|
|
165
210
|
expect(editor.setCamera).toHaveBeenCalled()
|
|
@@ -172,11 +217,11 @@ describe('EdgeScrollManager', () => {
|
|
|
172
217
|
describe('coarse pointer handling', () => {
|
|
173
218
|
it('should account for coarse pointer width', () => {
|
|
174
219
|
editor.getInstanceState.mockReturnValue({
|
|
220
|
+
...editor.getInstanceState(),
|
|
175
221
|
isCoarsePointer: true,
|
|
176
222
|
insets: [false, false, false, false],
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
editor.inputs.currentScreenPoint = new Vec(15, 300)
|
|
223
|
+
})
|
|
224
|
+
mockInputs.setCurrentScreenPoint(new Vec(15, 300))
|
|
180
225
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
181
226
|
|
|
182
227
|
expect(editor.setCamera).toHaveBeenCalled()
|
|
@@ -184,11 +229,11 @@ describe('EdgeScrollManager', () => {
|
|
|
184
229
|
|
|
185
230
|
it('should not trigger edge scrolling for fine pointer at same position', () => {
|
|
186
231
|
editor.getInstanceState.mockReturnValue({
|
|
232
|
+
...editor.getInstanceState(),
|
|
187
233
|
isCoarsePointer: false,
|
|
188
234
|
insets: [false, false, false, false],
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
editor.inputs.currentScreenPoint = new Vec(15, 300)
|
|
235
|
+
})
|
|
236
|
+
mockInputs.setCurrentScreenPoint(new Vec(15, 300))
|
|
192
237
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
193
238
|
|
|
194
239
|
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
@@ -197,8 +242,8 @@ describe('EdgeScrollManager', () => {
|
|
|
197
242
|
|
|
198
243
|
describe('camera movement conditions', () => {
|
|
199
244
|
it('should not move camera when not dragging', () => {
|
|
200
|
-
editor.inputs.
|
|
201
|
-
|
|
245
|
+
editor.inputs.setIsDragging(false)
|
|
246
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
202
247
|
|
|
203
248
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
204
249
|
|
|
@@ -206,8 +251,8 @@ describe('EdgeScrollManager', () => {
|
|
|
206
251
|
})
|
|
207
252
|
|
|
208
253
|
it('should not move camera when panning', () => {
|
|
209
|
-
editor.inputs.
|
|
210
|
-
|
|
254
|
+
editor.inputs.setIsPanning(true)
|
|
255
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
211
256
|
|
|
212
257
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
213
258
|
|
|
@@ -222,7 +267,7 @@ describe('EdgeScrollManager', () => {
|
|
|
222
267
|
zoomSteps: [1],
|
|
223
268
|
wheelBehavior: 'pan' as const,
|
|
224
269
|
})
|
|
225
|
-
|
|
270
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
226
271
|
|
|
227
272
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
228
273
|
|
|
@@ -233,7 +278,7 @@ describe('EdgeScrollManager', () => {
|
|
|
233
278
|
describe('camera movement calculation', () => {
|
|
234
279
|
it('should calculate scroll speed based on user preference', () => {
|
|
235
280
|
editor.user.getEdgeScrollSpeed.mockReturnValue(2)
|
|
236
|
-
|
|
281
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
237
282
|
|
|
238
283
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
239
284
|
|
|
@@ -244,7 +289,7 @@ describe('EdgeScrollManager', () => {
|
|
|
244
289
|
|
|
245
290
|
it('should apply screen size factor for small screens', () => {
|
|
246
291
|
editor.getViewportScreenBounds.mockReturnValue(new Box(0, 0, 800, 600))
|
|
247
|
-
|
|
292
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
248
293
|
|
|
249
294
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
250
295
|
|
|
@@ -253,7 +298,7 @@ describe('EdgeScrollManager', () => {
|
|
|
253
298
|
|
|
254
299
|
it('should adjust scroll speed based on zoom level', () => {
|
|
255
300
|
editor.getZoomLevel.mockReturnValue(2)
|
|
256
|
-
|
|
301
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
257
302
|
|
|
258
303
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
259
304
|
|
|
@@ -266,7 +311,7 @@ describe('EdgeScrollManager', () => {
|
|
|
266
311
|
it('should add scroll delta to current camera position', () => {
|
|
267
312
|
const currentCamera = new Vec(100, 200, 1)
|
|
268
313
|
editor.getCamera.mockReturnValue(currentCamera)
|
|
269
|
-
|
|
314
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 5))
|
|
270
315
|
|
|
271
316
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
272
317
|
|
|
@@ -280,14 +325,14 @@ describe('EdgeScrollManager', () => {
|
|
|
280
325
|
|
|
281
326
|
describe('proximity factor calculation', () => {
|
|
282
327
|
it('should return 0 when not near any edge', () => {
|
|
283
|
-
|
|
328
|
+
mockInputs.setCurrentScreenPoint(new Vec(500, 300))
|
|
284
329
|
edgeScrollManager.updateEdgeScrolling(16)
|
|
285
330
|
|
|
286
331
|
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
287
332
|
})
|
|
288
333
|
|
|
289
334
|
it('should cap proximity factor at 1', () => {
|
|
290
|
-
|
|
335
|
+
mockInputs.setCurrentScreenPoint(new Vec(0, 300))
|
|
291
336
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
292
337
|
|
|
293
338
|
expect(editor.setCamera).toHaveBeenCalled()
|
|
@@ -297,20 +342,20 @@ describe('EdgeScrollManager', () => {
|
|
|
297
342
|
|
|
298
343
|
describe('edge cases and error handling', () => {
|
|
299
344
|
it('should handle negative elapsed time', () => {
|
|
300
|
-
|
|
345
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
301
346
|
|
|
302
347
|
expect(() => edgeScrollManager.updateEdgeScrolling(-16)).not.toThrow()
|
|
303
348
|
})
|
|
304
349
|
|
|
305
350
|
it('should handle very large elapsed time', () => {
|
|
306
|
-
|
|
351
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
307
352
|
|
|
308
353
|
expect(() => edgeScrollManager.updateEdgeScrolling(100000)).not.toThrow()
|
|
309
354
|
})
|
|
310
355
|
|
|
311
356
|
it('should handle zero user edge scroll speed', () => {
|
|
312
357
|
editor.user.getEdgeScrollSpeed.mockReturnValue(0)
|
|
313
|
-
|
|
358
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
314
359
|
|
|
315
360
|
edgeScrollManager.updateEdgeScrolling(300)
|
|
316
361
|
|
|
@@ -322,7 +367,7 @@ describe('EdgeScrollManager', () => {
|
|
|
322
367
|
})
|
|
323
368
|
|
|
324
369
|
it('should handle extreme zoom levels', () => {
|
|
325
|
-
|
|
370
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
326
371
|
|
|
327
372
|
editor.getZoomLevel.mockReturnValue(0.01) // Very zoomed out
|
|
328
373
|
expect(() => edgeScrollManager.updateEdgeScrolling(300)).not.toThrow()
|
|
@@ -335,41 +380,46 @@ describe('EdgeScrollManager', () => {
|
|
|
335
380
|
describe('state transitions', () => {
|
|
336
381
|
it('should properly transition from not scrolling to scrolling', () => {
|
|
337
382
|
// Start with no edge scrolling
|
|
338
|
-
|
|
383
|
+
mockInputs.setCurrentScreenPoint(new Vec(500, 300))
|
|
339
384
|
edgeScrollManager.updateEdgeScrolling(16)
|
|
340
|
-
expect(
|
|
385
|
+
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
341
386
|
|
|
342
|
-
// Move to edge
|
|
343
|
-
|
|
387
|
+
// Move to edge - should start scrolling after delay
|
|
388
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
344
389
|
edgeScrollManager.updateEdgeScrolling(16)
|
|
345
|
-
expect(
|
|
346
|
-
|
|
390
|
+
expect(editor.setCamera).not.toHaveBeenCalled() // Not yet, due to delay
|
|
391
|
+
|
|
392
|
+
edgeScrollManager.updateEdgeScrolling(200)
|
|
393
|
+
expect(editor.setCamera).toHaveBeenCalled()
|
|
347
394
|
})
|
|
348
395
|
|
|
349
396
|
it('should accumulate edge scroll duration over multiple updates', () => {
|
|
350
|
-
|
|
397
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
351
398
|
|
|
399
|
+
// First update - not enough time
|
|
352
400
|
edgeScrollManager.updateEdgeScrolling(50)
|
|
353
|
-
expect(
|
|
401
|
+
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
354
402
|
|
|
355
|
-
|
|
356
|
-
|
|
403
|
+
// Second update - still not enough
|
|
404
|
+
edgeScrollManager.updateEdgeScrolling(50)
|
|
405
|
+
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
357
406
|
|
|
358
|
-
|
|
359
|
-
|
|
407
|
+
// Third update - now should trigger (50 + 50 + 101 = 201ms > 200ms delay)
|
|
408
|
+
edgeScrollManager.updateEdgeScrolling(101)
|
|
409
|
+
expect(editor.setCamera).toHaveBeenCalled()
|
|
360
410
|
})
|
|
361
411
|
|
|
362
412
|
it('should reset duration when stopping edge scroll', () => {
|
|
363
413
|
// Start edge scrolling
|
|
364
|
-
|
|
365
|
-
edgeScrollManager.updateEdgeScrolling(
|
|
366
|
-
expect(
|
|
414
|
+
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
415
|
+
edgeScrollManager.updateEdgeScrolling(300)
|
|
416
|
+
expect(editor.setCamera).toHaveBeenCalled()
|
|
367
417
|
|
|
368
|
-
// Stop edge scrolling
|
|
369
|
-
editor.
|
|
418
|
+
// Stop edge scrolling - move away
|
|
419
|
+
editor.setCamera.mockClear()
|
|
420
|
+
mockInputs.setCurrentScreenPoint(new Vec(500, 300))
|
|
370
421
|
edgeScrollManager.updateEdgeScrolling(16)
|
|
371
|
-
expect(
|
|
372
|
-
expect((edgeScrollManager as any)._edgeScrollDuration).toBe(0)
|
|
422
|
+
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
373
423
|
})
|
|
374
424
|
})
|
|
375
425
|
})
|
|
@@ -9,6 +9,10 @@ export class EdgeScrollManager {
|
|
|
9
9
|
private _isEdgeScrolling = false
|
|
10
10
|
private _edgeScrollDuration = -1
|
|
11
11
|
|
|
12
|
+
getIsEdgeScrolling() {
|
|
13
|
+
return this._isEdgeScrolling
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
/**
|
|
13
17
|
* Update the camera position when the mouse is close to the edge of the screen.
|
|
14
18
|
* Run this on every tick when in a state where edge scrolling is enabled.
|
|
@@ -81,11 +85,7 @@ export class EdgeScrollManager {
|
|
|
81
85
|
|
|
82
86
|
private getEdgeScroll() {
|
|
83
87
|
const { editor } = this
|
|
84
|
-
const {
|
|
85
|
-
inputs: {
|
|
86
|
-
currentScreenPoint: { x, y },
|
|
87
|
-
},
|
|
88
|
-
} = editor
|
|
88
|
+
const { x, y } = editor.inputs.getCurrentScreenPoint()
|
|
89
89
|
const screenBounds = editor.getViewportScreenBounds()
|
|
90
90
|
|
|
91
91
|
const {
|
|
@@ -107,7 +107,11 @@ export class EdgeScrollManager {
|
|
|
107
107
|
*/
|
|
108
108
|
private moveCameraWhenCloseToEdge(proximityFactor: { x: number; y: number }) {
|
|
109
109
|
const { editor } = this
|
|
110
|
-
if (
|
|
110
|
+
if (
|
|
111
|
+
!editor.inputs.getIsDragging() ||
|
|
112
|
+
editor.inputs.getIsPanning() ||
|
|
113
|
+
editor.getCameraOptions().isLocked
|
|
114
|
+
)
|
|
111
115
|
return
|
|
112
116
|
|
|
113
117
|
if (proximityFactor.x === 0 && proximityFactor.y === 0) return
|