adds aligned dragging / cloning

This commit is contained in:
Steve Ruiz 2021-05-20 09:19:13 +01:00
parent e8b13103ac
commit b126b1af65
4 changed files with 80 additions and 66 deletions

View file

@ -15,7 +15,11 @@ export default function useKeyboardEvents() {
} }
} }
if (e.altKey) { if (e.key === "Shift") {
state.send("PRESSED_SHIFT_KEY", getKeyboardEventInfo(e))
}
if (e.key === "Alt") {
state.send("PRESSED_ALT_KEY", getKeyboardEventInfo(e)) state.send("PRESSED_ALT_KEY", getKeyboardEventInfo(e))
} }
@ -66,12 +70,12 @@ export default function useKeyboardEvents() {
} }
function handleKeyUp(e: KeyboardEvent) { function handleKeyUp(e: KeyboardEvent) {
if (e.key === "Escape") { if (e.key === "Shift") {
state.send("CANCELLED") state.send("RELEASED_SHIFT_KEY", getKeyboardEventInfo(e))
} }
if (e.altKey) { if (e.key === "Alt") {
state.send("RELEASED_ALT_KEY") state.send("RELEASED_ALT_KEY", getKeyboardEventInfo(e))
} }
state.send("RELEASED_KEY", getKeyboardEventInfo(e)) state.send("RELEASED_KEY", getKeyboardEventInfo(e))

View file

@ -19,16 +19,14 @@ export default function translateCommand(
if (initial) return if (initial) return
const { shapes } = data.document.pages[after.currentPageId] const { shapes } = data.document.pages[after.currentPageId]
const { initialShapes, clones } = after const { initialShapes } = after
const { clones } = before // !
data.selectedIds.clear() data.selectedIds.clear()
for (let id in initialShapes) { for (let id in initialShapes) {
if (isCloning) {
shapes[id] = initialShapes[id]
} else {
shapes[id].point = initialShapes[id].point shapes[id].point = initialShapes[id].point
} shapes[clones[id].id] = clones[id]
data.selectedIds.add(id) data.selectedIds.add(id)
} }
}, },

View file

@ -11,54 +11,47 @@ export default class TranslateSession extends BaseSession {
snapshot: TranslateSnapshot snapshot: TranslateSnapshot
isCloning = false isCloning = false
constructor(data: Data, point: number[]) { constructor(data: Data, point: number[], isCloning = false) {
super(data) super(data)
this.origin = point this.origin = point
this.snapshot = getTranslateSnapshot(data) this.snapshot = getTranslateSnapshot(data)
} }
update(data: Data, point: number[], isCloning: boolean) { update(data: Data, point: number[], isAligned: boolean, isCloning: boolean) {
const { currentPageId, clones, initialShapes } = this.snapshot const { currentPageId, clones, initialShapes } = this.snapshot
const { document } = data const { shapes } = data.document.pages[currentPageId]
const { shapes } = document.pages[this.snapshot.currentPageId]
const delta = vec.vec(this.origin, point) const delta = vec.vec(this.origin, point)
if (isCloning && !this.isCloning) { if (isAligned) {
// Enter cloning state, create clones at shape points and move shapes if (Math.abs(delta[0]) < Math.abs(delta[1])) {
// back to initial point. delta[0] = 0
this.isCloning = true } else {
data.selectedIds.clear() delta[1] = 0
for (let id in clones) { }
const clone = clones[id] }
data.selectedIds.add(clone.id)
shapes[id].point = initialShapes[id].point if (isCloning && !this.isCloning) {
data.document.pages[currentPageId].shapes[clone.id] = clone this.isCloning = true
} for (let id in clones) {
} else if (!isCloning && this.isCloning) { const clone = clones[id]
// Exit cloning state, delete up clones and move shapes to clone points shapes[clone.id] = clone
this.isCloning = false }
data.selectedIds.clear() } else if (!isCloning && this.isCloning) {
for (let id in clones) { this.isCloning = false
const clone = clones[id] for (let id in clones) {
data.selectedIds.add(id) const clone = clones[id]
delete data.document.pages[currentPageId].shapes[clone.id] delete shapes[clone.id]
} }
} }
// Calculate the new points and update data
for (let id in initialShapes) { for (let id in initialShapes) {
const point = vec.add(initialShapes[id].point, delta) shapes[id].point = vec.add(initialShapes[id].point, delta)
const targetId = this.isCloning ? clones[id].id : id
document.pages[currentPageId].shapes[targetId].point = point
} }
} }
cancel(data: Data) { cancel(data: Data) {
const { document } = data
const { initialShapes, clones, currentPageId } = this.snapshot const { initialShapes, clones, currentPageId } = this.snapshot
const { shapes } = data.document.pages[currentPageId]
const { shapes } = document.pages[currentPageId]
for (let id in initialShapes) { for (let id in initialShapes) {
shapes[id].point = initialShapes[id].point shapes[id].point = initialShapes[id].point

View file

@ -115,15 +115,10 @@ const state = createState({
"setPointedId", "setPointedId",
{ {
if: "isPressingShiftKey", if: "isPressingShiftKey",
then: { unless: "isPointedShapeSelected",
if: "isPointedShapeSelected", do: ["pushPointedIdToSelectedIds", "clearPointedId"],
do: "pullPointedIdFromSelectedIds",
else: {
do: "pushPointedIdToSelectedIds",
to: "pointingBounds", to: "pointingBounds",
}, },
},
else: [
{ {
unless: "isPointedShapeSelected", unless: "isPointedShapeSelected",
do: ["clearSelectedIds", "pushPointedIdToSelectedIds"], do: ["clearSelectedIds", "pushPointedIdToSelectedIds"],
@ -133,16 +128,21 @@ const state = createState({
}, },
], ],
}, },
],
},
}, },
pointingBounds: { pointingBounds: {
on: { on: {
STOPPED_POINTING: [ STOPPED_POINTING: [
{ {
unless: ["isPointingBounds", "isPressingShiftKey"], if: "isPressingShiftKey",
then: {
if: "isPointedShapeSelected",
do: "pullPointedIdFromSelectedIds",
},
else: {
if: "isPointingBounds",
do: ["clearSelectedIds", "pushPointedIdToSelectedIds"], do: ["clearSelectedIds", "pushPointedIdToSelectedIds"],
}, },
},
{ to: "notPointing" }, { to: "notPointing" },
], ],
MOVED_POINTER: { MOVED_POINTER: {
@ -175,8 +175,10 @@ const state = createState({
on: { on: {
MOVED_POINTER: "updateTranslateSession", MOVED_POINTER: "updateTranslateSession",
PANNED_CAMERA: "updateTranslateSession", PANNED_CAMERA: "updateTranslateSession",
PRESSED_ALT_KEY: "updateCloningTranslateSession", PRESSED_SHIFT_KEY: "keyUpdateTranslateSession",
RELEASED_ALT_KEY: "updateCloningTranslateSession", RELEASED_SHIFT_KEY: "keyUpdateTranslateSession",
PRESSED_ALT_KEY: "keyUpdateTranslateSession",
RELEASED_ALT_KEY: "keyUpdateTranslateSession",
STOPPED_POINTING: { do: "completeSession", to: "selecting" }, STOPPED_POINTING: { do: "completeSession", to: "selecting" },
CANCELLED: { do: "cancelSession", to: "selecting" }, CANCELLED: { do: "cancelSession", to: "selecting" },
}, },
@ -525,18 +527,29 @@ const state = createState({
startTranslateSession(data, payload: PointerInfo) { startTranslateSession(data, payload: PointerInfo) {
session = new Sessions.TranslateSession( session = new Sessions.TranslateSession(
data, data,
screenToWorld(payload.point, data) screenToWorld(payload.point, data),
payload.altKey
) )
}, },
updateCloningTranslateSession(data, payload: { altKey: boolean }) { keyUpdateTranslateSession(
data,
payload: { shiftKey: boolean; altKey: boolean }
) {
session.update( session.update(
data, data,
screenToWorld(inputs.pointer.point, data), screenToWorld(inputs.pointer.point, data),
payload.shiftKey,
payload.altKey payload.altKey
) )
}, },
updateTranslateSession(data, payload: PointerInfo) { updateTranslateSession(data, payload: PointerInfo) {
session.update(data, screenToWorld(payload.point, data), payload.altKey) console.log(payload.altKey)
session.update(
data,
screenToWorld(payload.point, data),
payload.shiftKey,
payload.altKey
)
}, },
// Dragging / Translating // Dragging / Translating
@ -761,6 +774,12 @@ const state = createState({
if (selectedIds.size === 0) return null if (selectedIds.size === 0) return null
if (selectedIds.size === 1) { if (selectedIds.size === 1) {
if (!shapes[0]) {
console.error("Could not find that shape! Clearing selected IDs.")
data.selectedIds.clear()
return null
}
const shapeUtils = getShapeUtils(shapes[0]) const shapeUtils = getShapeUtils(shapes[0])
if (!shapeUtils.canTransform) return null if (!shapeUtils.canTransform) return null
return shapeUtils.getBounds(shapes[0]) return shapeUtils.getBounds(shapes[0])