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))
}
@ -66,12 +70,12 @@ export default function useKeyboardEvents() {
}
function handleKeyUp(e: KeyboardEvent) {
if (e.key === "Escape") {
state.send("CANCELLED")
if (e.key === "Shift") {
state.send("RELEASED_SHIFT_KEY", getKeyboardEventInfo(e))
}
if (e.altKey) {
state.send("RELEASED_ALT_KEY")
if (e.key === "Alt") {
state.send("RELEASED_ALT_KEY", getKeyboardEventInfo(e))
}
state.send("RELEASED_KEY", getKeyboardEventInfo(e))

View file

@ -19,16 +19,14 @@ export default function translateCommand(
if (initial) return
const { shapes } = data.document.pages[after.currentPageId]
const { initialShapes, clones } = after
const { initialShapes } = after
const { clones } = before // !
data.selectedIds.clear()
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)
}
},

View file

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

View file

@ -115,23 +115,16 @@ const state = createState({
"setPointedId",
{
if: "isPressingShiftKey",
then: {
if: "isPointedShapeSelected",
do: "pullPointedIdFromSelectedIds",
else: {
do: "pushPointedIdToSelectedIds",
to: "pointingBounds",
},
},
else: [
{
unless: "isPointedShapeSelected",
do: ["clearSelectedIds", "pushPointedIdToSelectedIds"],
},
{
to: "pointingBounds",
},
],
unless: "isPointedShapeSelected",
do: ["pushPointedIdToSelectedIds", "clearPointedId"],
to: "pointingBounds",
},
{
unless: "isPointedShapeSelected",
do: ["clearSelectedIds", "pushPointedIdToSelectedIds"],
},
{
to: "pointingBounds",
},
],
},
@ -140,8 +133,15 @@ const state = createState({
on: {
STOPPED_POINTING: [
{
unless: ["isPointingBounds", "isPressingShiftKey"],
do: ["clearSelectedIds", "pushPointedIdToSelectedIds"],
if: "isPressingShiftKey",
then: {
if: "isPointedShapeSelected",
do: "pullPointedIdFromSelectedIds",
},
else: {
if: "isPointingBounds",
do: ["clearSelectedIds", "pushPointedIdToSelectedIds"],
},
},
{ to: "notPointing" },
],
@ -175,8 +175,10 @@ const state = createState({
on: {
MOVED_POINTER: "updateTranslateSession",
PANNED_CAMERA: "updateTranslateSession",
PRESSED_ALT_KEY: "updateCloningTranslateSession",
RELEASED_ALT_KEY: "updateCloningTranslateSession",
PRESSED_SHIFT_KEY: "keyUpdateTranslateSession",
RELEASED_SHIFT_KEY: "keyUpdateTranslateSession",
PRESSED_ALT_KEY: "keyUpdateTranslateSession",
RELEASED_ALT_KEY: "keyUpdateTranslateSession",
STOPPED_POINTING: { do: "completeSession", to: "selecting" },
CANCELLED: { do: "cancelSession", to: "selecting" },
},
@ -525,18 +527,29 @@ const state = createState({
startTranslateSession(data, payload: PointerInfo) {
session = new Sessions.TranslateSession(
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(
data,
screenToWorld(inputs.pointer.point, data),
payload.shiftKey,
payload.altKey
)
},
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
@ -761,6 +774,12 @@ const state = createState({
if (selectedIds.size === 0) return null
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])
if (!shapeUtils.canTransform) return null
return shapeUtils.getBounds(shapes[0])