draw transform from action instead of stage
This commit is contained in:
parent
f0e0546a66
commit
c2e99866cf
283
src/main.js
283
src/main.js
|
|
@ -769,10 +769,167 @@ let actions = {
|
|||
updateLayers()
|
||||
}
|
||||
},
|
||||
transformObjects: {
|
||||
initialize: (frame, _selection, direction, mouse, transform=undefined) => {
|
||||
let bbox = undefined
|
||||
const selection = {}
|
||||
for (let item of _selection) {
|
||||
if (bbox==undefined) {
|
||||
bbox = getRotatedBoundingBox(item)
|
||||
} else {
|
||||
growBoundingBox(bbox, getRotatedBoundingBox(item))
|
||||
}
|
||||
selection[item.idx] = {x: item.x, y: item.y, scale_x: item.scale_x, scale_y: item.scale_y, rotation: item.rotation}
|
||||
}
|
||||
let action = {
|
||||
type: "transformObjects",
|
||||
oldState: structuredClone(frame.keys),
|
||||
frame: frame.idx,
|
||||
transform: {
|
||||
initial: {
|
||||
x: {min: bbox.x.min, max: bbox.x.max},
|
||||
y: {min: bbox.y.min, max: bbox.y.max},
|
||||
rotation: 0,
|
||||
mouse: {x: mouse.x, y: mouse.y},
|
||||
selection: selection
|
||||
},
|
||||
current: {
|
||||
x: {min: bbox.x.min, max: bbox.x.max},
|
||||
y: {min: bbox.y.min, max: bbox.y.max},
|
||||
scale_x: 1,
|
||||
scale_y: 1,
|
||||
rotation: 0,
|
||||
mouse: {x: mouse.x, y: mouse.y},
|
||||
selection: structuredClone(selection)
|
||||
}
|
||||
},
|
||||
selection: selection,
|
||||
direction: direction
|
||||
}
|
||||
if (transform) {
|
||||
action.transform = transform
|
||||
}
|
||||
return action
|
||||
},
|
||||
update: (action, mouse) => {
|
||||
const initial = action.transform.initial
|
||||
const current = action.transform.current
|
||||
console.log(action.direction)
|
||||
if (action.direction.indexOf('n') != -1) {
|
||||
current.y.min = mouse.y
|
||||
} else if (action.direction.indexOf('s') != -1) {
|
||||
current.y.max = mouse.y
|
||||
}
|
||||
if (action.direction.indexOf('w') != -1) {
|
||||
current.x.min = mouse.x
|
||||
} else if (action.direction.indexOf('e') != -1) {
|
||||
current.x.max = mouse.x
|
||||
}
|
||||
if (context.dragDirection == 'r') {
|
||||
const pivot = {
|
||||
x: (initial.x.min+initial.x.max)/2,
|
||||
y: (initial.y.min+initial.y.max)/2,
|
||||
}
|
||||
current.rotation = signedAngleBetweenVectors(pivot, initial.mouse, mouse)
|
||||
const {dx, dy} = rotateAroundPointIncremental(current.x.min, current.y.min, pivot, current.rotation)
|
||||
}
|
||||
|
||||
// Calculate the scaling factor based on the difference between current and initial values
|
||||
action.transform.current.scale_x = (current.x.max - current.x.min) / (initial.x.max - initial.x.min);
|
||||
action.transform.current.scale_y = (current.y.max - current.y.min) / (initial.y.max - initial.y.min);
|
||||
return action
|
||||
},
|
||||
render: (action, ctx) => {
|
||||
const initial = action.transform.initial
|
||||
const current = action.transform.current
|
||||
ctx.save()
|
||||
ctx.translate((current.x.max+current.x.min)/2, (current.y.max - current.y.min)/2)
|
||||
ctx.rotate(current.rotation)
|
||||
ctx.translate(-(current.x.max+current.x.min)/2, -(current.y.max - current.y.min)/2)
|
||||
console.log(action.selection)
|
||||
const cxt = {
|
||||
ctx: ctx,
|
||||
selection: [],
|
||||
shapeselection: []
|
||||
}
|
||||
for (let obj in action.selection) {
|
||||
const object = pointerList[obj]
|
||||
object.draw(cxt)
|
||||
}
|
||||
ctx.strokeStyle = '#00ffff'
|
||||
ctx.lineWidth = 1
|
||||
ctx.beginPath()
|
||||
ctx.rect(current.x.min, current.y.min, current.x.max-current.x.min, current.y.max-current.y.min)
|
||||
ctx.stroke()
|
||||
ctx.fillStyle = "#000000"
|
||||
const rectRadius = 5
|
||||
const xdiff = current.x.max - current.x.min
|
||||
const ydiff = current.y.max - current.y.min
|
||||
for (let i of [[0,0],[0.5,0],[1,0],[1,0.5],[1,1],[0.5,1],[0,1],[0,0.5]]) {
|
||||
ctx.beginPath()
|
||||
ctx.rect(
|
||||
current.x.min + xdiff * i[0] - rectRadius,
|
||||
current.y.min + ydiff * i[1] - rectRadius,
|
||||
rectRadius*2, rectRadius*2
|
||||
)
|
||||
ctx.fill()
|
||||
}
|
||||
ctx.restore()
|
||||
},
|
||||
finalize: (action) => {
|
||||
undoStack.push({name: "transformObjects", action: action})
|
||||
actions.transformObjects.execute(action)
|
||||
context.activeAction = undefined
|
||||
updateMenu()
|
||||
},
|
||||
execute: (action) => {
|
||||
const frame = pointerList[action.frame]
|
||||
const initial = action.transform.initial
|
||||
const current = action.transform.current
|
||||
const delta_x = current.x.min - initial.x.min;
|
||||
const delta_y = current.y.min - initial.y.min;
|
||||
const delta_rot = current.rotation - initial.rotation
|
||||
// frame.keys = structuredClone(action.newState)
|
||||
console.log(action)
|
||||
for (let idx in action.selection) {
|
||||
const item = frame.keys[idx]
|
||||
const xoffset = action.selection[idx].x - initial.x.min
|
||||
const yoffset = action.selection[idx].y - initial.y.min
|
||||
item.x = initial.x.min + delta_x + xoffset * current.scale_x
|
||||
item.y = initial.y.min + delta_y + yoffset * current.scale_y
|
||||
item.scale_x = action.selection[idx].scale_x * current.scale_x
|
||||
item.scale_y = action.selection[idx].scale_y * current.scale_y
|
||||
item.rotation = action.selection[idx].rotation + delta_rot
|
||||
}
|
||||
updateUI()
|
||||
},
|
||||
rollback: (action) => {
|
||||
let frame = pointerList[action.frame]
|
||||
frame.keys = structuredClone(action.oldState)
|
||||
updateUI()
|
||||
}
|
||||
},
|
||||
editFrame: {
|
||||
initialize: (frame) => {
|
||||
let action = {
|
||||
type: "editFrame",
|
||||
oldState: structuredClone(frame.keys),
|
||||
frame: frame.idx
|
||||
}
|
||||
return action
|
||||
},
|
||||
finalize: (action, frame) => {
|
||||
action.newState = structuredClone(frame.keys)
|
||||
undoStack.push({name: "editFrame", action: action})
|
||||
actions.editFrame.execute(action)
|
||||
context.activeAction = undefined
|
||||
updateMenu()
|
||||
},
|
||||
render: (action, ctx) => {
|
||||
|
||||
},
|
||||
create: (frame) => {
|
||||
redoStack.length = 0; // Clear redo stack
|
||||
console.log(frame.idx in startProps)
|
||||
if (!(frame.idx in startProps)) return;
|
||||
let action = {
|
||||
newState: structuredClone(frame.keys),
|
||||
|
|
@ -2652,12 +2809,14 @@ class GraphicsObject {
|
|||
}
|
||||
draw(context) {
|
||||
let ctx = context.ctx;
|
||||
ctx.save()
|
||||
ctx.translate(this.x, this.y)
|
||||
ctx.rotate(this.rotation)
|
||||
ctx.scale(this.scale_x, this.scale_y)
|
||||
// if (this.currentFrameNum>=this.maxFrame) {
|
||||
// this.currentFrameNum = 0;
|
||||
// }
|
||||
if (context.activeAction && this.idx in context.activeAction.selection) return;
|
||||
for (let layer of this.layers) {
|
||||
if (context.activeObject==this && !layer.visible) continue;
|
||||
let frame = layer.getFrame(this.currentFrameNum)
|
||||
|
|
@ -2790,6 +2949,7 @@ class GraphicsObject {
|
|||
}
|
||||
}
|
||||
}
|
||||
ctx.restore()
|
||||
}
|
||||
transformMouse(mouse) {
|
||||
if (this.parent) {
|
||||
|
|
@ -3754,7 +3914,7 @@ function stage() {
|
|||
if (hitTest(mouse, child)) {
|
||||
context.dragging = true
|
||||
context.lastMouse = mouse
|
||||
context.activeObject.currentFrame.saveState()
|
||||
context.activeAction = actions.editFrame.initialize(context.activeObject.currentFrame)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -3777,7 +3937,7 @@ function stage() {
|
|||
}
|
||||
context.dragging = true
|
||||
selected = true
|
||||
context.activeObject.currentFrame.saveState()
|
||||
context.activeAction = actions.editFrame.initialize(context.activeObject.currentFrame)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
@ -3825,7 +3985,12 @@ function stage() {
|
|||
selection: structuredClone(selection)
|
||||
}
|
||||
}
|
||||
context.activeObject.currentFrame.saveState()
|
||||
context.activeAction = actions.transformObjects.initialize(
|
||||
context.activeObject.currentFrame,
|
||||
context.selection,
|
||||
transformPoint,
|
||||
mouse
|
||||
)
|
||||
} else {
|
||||
transformPoint = getPointNearBox(bbox, mouse, 30, false)
|
||||
if (transformPoint) {
|
||||
|
|
@ -3847,7 +4012,12 @@ function stage() {
|
|||
selection: structuredClone(selection)
|
||||
}
|
||||
}
|
||||
context.activeObject.currentFrame.saveState()
|
||||
context.activeAction = actions.transformObjects.initialize(
|
||||
context.activeObject.currentFrame,
|
||||
context.selection,
|
||||
'r',
|
||||
mouse
|
||||
)
|
||||
} else {
|
||||
stage.style.cursor = "default"
|
||||
}
|
||||
|
|
@ -3950,7 +4120,9 @@ function stage() {
|
|||
context.activeShape = undefined
|
||||
break;
|
||||
case "select":
|
||||
if (context.activeVertex) {
|
||||
if (context.activeAction) {
|
||||
actions[context.activeAction.type].finalize(context.activeAction, context.activeObject.currentFrame)
|
||||
} else if (context.activeVertex) {
|
||||
let newCurves = []
|
||||
for (let i in context.activeVertex.shape.curves) {
|
||||
if (i in context.activeVertex.current.startCurves) {
|
||||
|
|
@ -3974,13 +4146,16 @@ function stage() {
|
|||
actions.editShape.create(context.activeCurve.shape, newCurves)
|
||||
} else if (context.selection.length) {
|
||||
actions.select.create()
|
||||
actions.editFrame.create(context.activeObject.currentFrame)
|
||||
// actions.editFrame.create(context.activeObject.currentFrame)
|
||||
} else if (context.shapeselection.length) {
|
||||
actions.select.create()
|
||||
}
|
||||
break;
|
||||
case "transform":
|
||||
actions.editFrame.create(context.activeObject.currentFrame)
|
||||
if (context.activeAction) {
|
||||
actions[context.activeAction.type].finalize(context.activeAction, context.activeObject.currentFrame)
|
||||
}
|
||||
// actions.editFrame.create(context.activeObject.currentFrame)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -4166,53 +4341,56 @@ function stage() {
|
|||
stage.style.cursor = "default"
|
||||
}
|
||||
}
|
||||
if (context.dragDirection) {
|
||||
let initial = context.activeTransform.initial
|
||||
let current = context.activeTransform.current
|
||||
let initialSelection = context.activeTransform.initial.selection
|
||||
if (context.dragDirection.indexOf('n') != -1) {
|
||||
current.y.min = mouse.y
|
||||
} else if (context.dragDirection.indexOf('s') != -1) {
|
||||
current.y.max = mouse.y
|
||||
}
|
||||
if (context.dragDirection.indexOf('w') != -1) {
|
||||
current.x.min = mouse.x
|
||||
} else if (context.dragDirection.indexOf('e') != -1) {
|
||||
current.x.max = mouse.x
|
||||
}
|
||||
// Calculate the translation difference between current and initial values
|
||||
let delta_x = current.x.min - initial.x.min;
|
||||
let delta_y = current.y.min - initial.y.min;
|
||||
// if (context.dragDirection) {
|
||||
// let initial = context.activeTransform.initial
|
||||
// let current = context.activeTransform.current
|
||||
// let initialSelection = context.activeTransform.initial.selection
|
||||
// if (context.dragDirection.indexOf('n') != -1) {
|
||||
// current.y.min = mouse.y
|
||||
// } else if (context.dragDirection.indexOf('s') != -1) {
|
||||
// current.y.max = mouse.y
|
||||
// }
|
||||
// if (context.dragDirection.indexOf('w') != -1) {
|
||||
// current.x.min = mouse.x
|
||||
// } else if (context.dragDirection.indexOf('e') != -1) {
|
||||
// current.x.max = mouse.x
|
||||
// }
|
||||
// // Calculate the translation difference between current and initial values
|
||||
// let delta_x = current.x.min - initial.x.min;
|
||||
// let delta_y = current.y.min - initial.y.min;
|
||||
|
||||
if (context.dragDirection == 'r') {
|
||||
let pivot = {
|
||||
x: (initial.x.min+initial.x.max)/2,
|
||||
y: (initial.y.min+initial.y.max)/2,
|
||||
}
|
||||
current.rotation = signedAngleBetweenVectors(pivot, initial.mouse, mouse)
|
||||
const {dx, dy} = rotateAroundPointIncremental(current.x.min, current.y.min, pivot, current.rotation)
|
||||
// delta_x -= dx
|
||||
// delta_y -= dy
|
||||
// console.log(dx, dy)
|
||||
}
|
||||
// if (context.dragDirection == 'r') {
|
||||
// let pivot = {
|
||||
// x: (initial.x.min+initial.x.max)/2,
|
||||
// y: (initial.y.min+initial.y.max)/2,
|
||||
// }
|
||||
// current.rotation = signedAngleBetweenVectors(pivot, initial.mouse, mouse)
|
||||
// const {dx, dy} = rotateAroundPointIncremental(current.x.min, current.y.min, pivot, current.rotation)
|
||||
// // delta_x -= dx
|
||||
// // delta_y -= dy
|
||||
// // console.log(dx, dy)
|
||||
// }
|
||||
|
||||
// This is probably unnecessary since initial rotation is 0
|
||||
const delta_rot = current.rotation - initial.rotation
|
||||
// // This is probably unnecessary since initial rotation is 0
|
||||
// const delta_rot = current.rotation - initial.rotation
|
||||
|
||||
// Calculate the scaling factor based on the difference between current and initial values
|
||||
const scale_x_ratio = (current.x.max - current.x.min) / (initial.x.max - initial.x.min);
|
||||
const scale_y_ratio = (current.y.max - current.y.min) / (initial.y.max - initial.y.min);
|
||||
// // Calculate the scaling factor based on the difference between current and initial values
|
||||
// const scale_x_ratio = (current.x.max - current.x.min) / (initial.x.max - initial.x.min);
|
||||
// const scale_y_ratio = (current.y.max - current.y.min) / (initial.y.max - initial.y.min);
|
||||
|
||||
for (let idx in initialSelection) {
|
||||
let item = context.activeObject.currentFrame.keys[idx]
|
||||
let xoffset = initialSelection[idx].x - initial.x.min
|
||||
let yoffset = initialSelection[idx].y - initial.y.min
|
||||
item.x = initial.x.min + delta_x + xoffset * scale_x_ratio
|
||||
item.y = initial.y.min + delta_y + yoffset * scale_y_ratio
|
||||
item.scale_x = initialSelection[idx].scale_x * scale_x_ratio
|
||||
item.scale_y = initialSelection[idx].scale_y * scale_y_ratio
|
||||
item.rotation = initialSelection[idx].rotation + delta_rot
|
||||
}
|
||||
// for (let idx in initialSelection) {
|
||||
// let item = context.activeObject.currentFrame.keys[idx]
|
||||
// let xoffset = initialSelection[idx].x - initial.x.min
|
||||
// let yoffset = initialSelection[idx].y - initial.y.min
|
||||
// item.x = initial.x.min + delta_x + xoffset * scale_x_ratio
|
||||
// item.y = initial.y.min + delta_y + yoffset * scale_y_ratio
|
||||
// item.scale_x = initialSelection[idx].scale_x * scale_x_ratio
|
||||
// item.scale_y = initialSelection[idx].scale_y * scale_y_ratio
|
||||
// item.rotation = initialSelection[idx].rotation + delta_rot
|
||||
// }
|
||||
// }
|
||||
if (context.activeAction) {
|
||||
actions[context.activeAction.type].update(context.activeAction, mouse)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
@ -5224,6 +5402,9 @@ function renderUI() {
|
|||
ctx.arc(point.x, point.y, 3, 0, 2*Math.PI)
|
||||
ctx.fill()
|
||||
}
|
||||
if (context.activeAction) {
|
||||
actions[context.activeAction.type].render(context.activeAction, ctx)
|
||||
}
|
||||
|
||||
}
|
||||
for (let selectionRect of document.querySelectorAll(".selectionRect")) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue