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