adds aligned dragging / cloning
This commit is contained in:
parent
e8b13103ac
commit
b126b1af65
4 changed files with 80 additions and 66 deletions
|
@ -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))
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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])
|
||||||
|
|
Loading…
Reference in a new issue