move objects

This commit is contained in:
Skyler Lehmkuhl 2024-11-20 02:41:14 -05:00
parent 380fcf0c32
commit 551993bc16
1 changed files with 160 additions and 52 deletions

View File

@ -79,6 +79,7 @@ let context = {
lineWidth: 5,
simplifyMode: "smooth",
fillShape: true,
strokeShape: true,
dragging: false,
selectionRect: undefined,
selection: [],
@ -95,6 +96,8 @@ let config = {
// Pointers to all objects
let pointerList = {}
// Keeping track of initial values of variables when we edit them continuously
let startProps = {}
let actions = {
addShape: {
@ -138,6 +141,7 @@ let actions = {
},
editShape: {
create: (shape, newCurves) => {
redoStack.length = 0; // Clear redo stack
let serializableNewCurves = []
for (let curve of newCurves) {
serializableNewCurves.push({ points: curve.points })
@ -183,19 +187,79 @@ let actions = {
))
}}
},
addObject: {
create: () => {},
execute: (action) => {
addImageObject: {
create: (x, y, img, parent) => {
redoStack.length = 0; // Clear redo stack
let action = {
shapeUuid: uuidv4(),
objectUuid: uuidv4(),
x: x,
y: y,
width: img.width,
height: img.height,
ix: img.ix,
img: img.idx,
parent: parent.idx
}
undoStack.push({name: "addImageObject", action: action})
actions.addImageObject.execute(action)
},
rollback: (action) => {}
execute: (action) => {
let imageObject = new GraphicsObject(action.objectUuid)
let img = pointerList[action.img]
let ct = {
...context,
fillImage: img,
strokeShape: false,
}
let imageShape = new Shape(0, 0, ct, action.shapeUuid)
imageShape.addLine(action.width, 0)
imageShape.addLine(action.width, action.height)
imageShape.addLine(0, action.height)
imageShape.addLine(0, 0)
imageShape.recalculateBoundingBox()
imageObject.addShape(imageShape)
let parent = pointerList[action.parent]
parent.addObject(
imageObject,
action.x-action.width/2 + (20*action.ix),
action.y-action.height/2 + (20*action.ix)
)
},
rollback: (action) => {
let shape = pointerList[action.shapeUuid]
let object = pointerList[action.objectUuid]
let parent = pointerList[action.parent]
object.removeShape(shape)
delete pointerList[action.shapeUuid]
parent.removeChild(object)
delete pointerList[action.objectUuid]
let selectIndex = context.selection.indexOf(object)
if (selectIndex >= 0) {
context.selection.splice(selectIndex, 1)
}
}
},
editObject: {
create: () => {},
execute: (action) => {
editFrame: {
create: (frame) => {
redoStack.length = 0; // Clear redo stack
let action = {
newState: structuredClone(frame.keys),
oldState: startProps[frame.idx],
frame: frame.idx
}
undoStack.push({name: "editFrame", action: action})
actions.editFrame.execute(action)
},
rollback: (action) => {}
execute: (action) => {
let frame = pointerList[action.frame]
frame.keys = structuredClone(action.newState)
},
rollback: (action) => {
let frame = pointerList[action.frame]
frame.keys = structuredClone(action.oldState)
console.log(frame)
}
},
}
@ -482,6 +546,9 @@ class Frame {
}
pointerList[this.idx] = this
}
saveState() {
startProps[this.idx] = structuredClone(this.keys)
}
}
class Layer {
@ -507,7 +574,7 @@ class Shape {
this.strokeStyle = context.strokeStyle;
this.lineWidth = context.lineWidth
this.filled = context.fillShape;
this.stroked = context.strokeShape || true;
this.stroked = context.strokeShape;
this.boundingBox = {
x: {min: startx, max: starty},
y: {min: starty, max: starty}
@ -707,6 +774,7 @@ class GraphicsObject {
for (let item of context.selection) {
ctx.save()
ctx.strokeStyle = "#00ffff"
ctx.lineWidth = 1;
ctx.translate(item.x, item.y)
ctx.beginPath()
let bbox = item.bbox()
@ -717,6 +785,7 @@ class GraphicsObject {
if (context.selectionRect) {
ctx.save()
ctx.strokeStyle = "#00ffff"
ctx.lineWidth = 1;
ctx.beginPath()
ctx.rect(
context.selectionRect.x1, context.selectionRect.y1,
@ -751,6 +820,23 @@ class GraphicsObject {
}
}
}
removeChild(childObject) {
let idx = childObject.idx
for (let layer of this.layers) {
for (let frame of layer.frames) {
delete frame[idx]
}
}
this.children.splice(this.children.indexOf(childObject), 1)
}
saveState() {
startProps[this.idx] = {
x: this.x,
y: this.y,
rotation: this.rotation,
scale: this.scale
}
}
}
let root = new GraphicsObject();
@ -814,25 +900,29 @@ function stage() {
let img = new Image()
img.src = window.URL.createObjectURL(file)
img.ix = i
img.idx = uuidv4()
pointerList[img.idx] = img
img.onload = function() {
let width = img.width
let height = img.height
let imageObject = new GraphicsObject()
let ct = {
...context,
fillImage: img,
}
let imageShape = new Shape(0, 0, ct, false)
imageShape.addLine(width, 0)
imageShape.addLine(width, height)
imageShape.addLine(0, height)
imageShape.addLine(0, 0)
imageShape.recalculateBoundingBox()
imageObject.addShape(imageShape)
context.activeObject.addObject(
imageObject,
mouse.x-width/2 + (20*img.ix),
mouse.y-height/2 + (20*img.ix))
actions.addImageObject.create(
mouse.x, mouse.y, img, context.activeObject)
// let width = img.width
// let height = img.height
// let imageObject = new GraphicsObject()
// let ct = {
// ...context,
// fillImage: img,
// }
// let imageShape = new Shape(0, 0, ct, false)
// imageShape.addLine(width, 0)
// imageShape.addLine(width, height)
// imageShape.addLine(0, height)
// imageShape.addLine(0, 0)
// imageShape.recalculateBoundingBox()
// imageObject.addShape(imageShape)
// context.activeObject.addObject(
// imageObject,
// mouse.x-width/2 + (20*img.ix),
// mouse.y-height/2 + (20*img.ix))
updateUI()
}
}
@ -871,22 +961,37 @@ function stage() {
} else {
let selected = false
let child;
// Have to iterate in reverse order to grab the frontmost object when two overlap
for (let i=context.activeObject.children.length-1; i>=0; i--) {
child = context.activeObject.children[i]
// let bbox = child.bbox()
if (hitTest(mouse, child)) {
if (context.selection.indexOf(child) != -1) {
// dragging = true
}
context.selection = [child]
selected = true
if (context.selection.length) {
for (child of context.selection) {
if (hitTest(mouse, child)) {
context.dragging = true
context.lastMouse = mouse
context.activeObject.currentFrame.saveState()
break
}
}
}
if (!selected) {
context.selection = []
context.selectionRect = {x1: mouse.x, x2: mouse.x, y1: mouse.y, y2:mouse.y}
if (!context.dragging) {
// Have to iterate in reverse order to grab the frontmost object when two overlap
for (let i=context.activeObject.children.length-1; i>=0; i--) {
child = context.activeObject.children[i]
// let bbox = child.bbox()
if (hitTest(mouse, child)) {
if (context.selection.indexOf(child) != -1) {
// dragging = true
}
child.saveState()
context.selection = [child]
context.dragging = true
selected = true
context.activeObject.currentFrame.saveState()
break
}
}
if (!selected) {
context.selection = []
context.selectionRect = {x1: mouse.x, x2: mouse.x, y1: mouse.y, y2:mouse.y}
}
}
}
break;
@ -925,6 +1030,9 @@ function stage() {
}
}
actions.editShape.create(context.activeCurve.shape, newCurves)
} else if (context.selection.length) {
console.log("sopjngf")
actions.editFrame.create(context.activeObject.currentFrame)
}
break;
default:
@ -959,16 +1067,16 @@ function stage() {
break;
case "select":
if (context.dragging) {
// let dist = vectorDist(mouse, context.activeCurve.points[1])
// let cpoint = context.activeCurve.points[1]
// if (vectorDist(mouse, context.activeCurve.points[2]) < dist) {
// cpoint = context.activeCurve.points[2]
// }
// cpoint.x += (mouse.x - context.lastMouse.x)
// cpoint.y += (mouse.y - context.lastMouse.y)
context.activeCurve.current.points = moldCurve(
context.activeCurve.initial, mouse, context.activeCurve.startmouse
).points
if (context.activeCurve) {
context.activeCurve.current.points = moldCurve(
context.activeCurve.initial, mouse, context.activeCurve.startmouse
).points
} else {
for (let child of context.selection) {
context.activeObject.currentFrame.keys[child.idx].x += (mouse.x - context.lastMouse.x)
context.activeObject.currentFrame.keys[child.idx] .y += (mouse.y - context.lastMouse.y)
}
}
} else if (context.selectionRect) {
context.selectionRect.x2 = mouse.x
context.selectionRect.y2 = mouse.y