From 5af6b43b9fc3af2c57c82cf826ef35723103de91 Mon Sep 17 00:00:00 2001 From: funny bot Date: Fri, 30 Jan 2026 13:12:16 -0800 Subject: [PATCH 1/2] Add skew properties --- engine/src/Transformation.js | 54 +++++++++++++++++++++++++++++++++++ engine/src/base/Clip.js | 13 +++++++++ engine/src/base/Tween.js | 2 +- engine/src/view/View.Clip.js | 12 ++------ engine/src/view/View.Frame.js | 11 ++----- 5 files changed, 72 insertions(+), 20 deletions(-) diff --git a/engine/src/Transformation.js b/engine/src/Transformation.js index 21e97e9db..d3b6d8345 100644 --- a/engine/src/Transformation.js +++ b/engine/src/Transformation.js @@ -26,6 +26,7 @@ Wick.Transformation = class { * @param {number} scaleX - The amount of scaling on the x-axis * @param {number} scaleY - The amount of scaling on the y-axis * @param {number} rotation - Rotation, in degrees + * @param {number} skew - Skew, in degrees * @param {number} opacity - Opacity, ranging from 0.0 - 1.0 */ constructor (args) { @@ -36,6 +37,7 @@ Wick.Transformation = class { this.scaleX = args.scaleX === undefined ? 1 : args.scaleX; this.scaleY = args.scaleY === undefined ? 1 : args.scaleY; this.rotation = args.rotation === undefined ? 0 : args.rotation; + this.skew = args.skew === undefined ? 0 : args.skew; this.opacity = args.opacity === undefined ? 1 : args.opacity; } @@ -49,6 +51,7 @@ Wick.Transformation = class { scaleX: this.scaleX, scaleY: this.scaleY, rotation: this.rotation, + skew: this.skew, opacity: this.opacity, } } @@ -60,4 +63,55 @@ Wick.Transformation = class { copy () { return new Wick.Transformation(this.values); } + + /** + * Creates a transformation using a 2D matrix. + * @param {Array} values A list of matrix values as passed to a paper.js Matrix object. + * @returns {Wick.Transformation} + */ + fromMatrix (values) { + const [a, b, c, d, tx, ty] = values; + const rotationX = Math.atan2(b, a) * 180 / Math.PI, + rotationY = Math.atan2(-c, d) * 180 / Math.PI, + scaleX = Math.sqrt(a * a + b * b), + scaleY = Math.sqrt(c * c + d * d); + return new Wick.Transformation({ + x: tx, + y: ty, + scaleX, + scaleY, + rotation: rotationX, + skew: rotationY - rotationX, + opacity: 1 + }); + } + + /** + * Creates a 2D matrix using this transformation. + * @returns {Array} A list of matrix values as passed to a paper.js Matrix object. + */ + toMatrix () { + const {x, y, scaleX, scaleY, rotation, skew} = this; + const rotationX = rotation * Math.PI / 180, + rotationY = (skew + rotation) * Math.PI / 180; + + let a, b, c, d; + if (Math.abs(rotationX) === Math.PI / 2) { + a = 0; + b = Math.sign(rotationX) * scaleX; + } + else { + a = scaleX * Math.cos(rotationX); + b = scaleX * Math.sin(rotationX); + } + if (Math.abs(rotationY) === Math.PI / 2) { + d = 0; + c = -Math.sign(rotationX) * scaleY; + } + else { + d = scaleY * Math.cos(rotationY); + c = -scaleY * Math.sin(rotationY); + } + return [a, b, c, d, x, y]; + } } diff --git a/engine/src/base/Clip.js b/engine/src/base/Clip.js index b5ec382b6..8310f4056 100644 --- a/engine/src/base/Clip.js +++ b/engine/src/base/Clip.js @@ -1319,6 +1319,19 @@ let avgIntersection = { this._onDirtyTransform(); } + /** + * The skew of the clip. + * @type {number} + */ + get skew() { + return this.transformation.skew; + } + + set skew(skew) { + this.transformation.skew = skew; + + this._onDirtyTransform(); + } /** * The opacity of the clip. diff --git a/engine/src/base/Tween.js b/engine/src/base/Tween.js index 9c0fa994d..48a620cc0 100644 --- a/engine/src/base/Tween.js +++ b/engine/src/base/Tween.js @@ -72,7 +72,7 @@ Wick.Tween = class extends Wick.Base { var t = Wick.Tween._calculateTimeValue(tweenA, tweenB, playheadPosition); // Interpolate every transformation attribute using the t value - ["x", "y", "scaleX", "scaleY", "rotation", "opacity"].forEach(propName => { + ["x", "y", "scaleX", "scaleY", "rotation", "skew", "opacity"].forEach(propName => { var tweenFn = tweenA._getTweenFunction(); var tt = tweenFn(t); var valA = tweenA.transformation[propName]; diff --git a/engine/src/view/View.Clip.js b/engine/src/view/View.Clip.js index d423ab48c..3b9b039ac 100644 --- a/engine/src/view/View.Clip.js +++ b/engine/src/view/View.Clip.js @@ -173,11 +173,7 @@ Wick.View.Clip = class extends Wick.View { //this._radius = null; this.group.pivot = new this.paper.Point(0,0); - this.group.position.x = this.model.transformation.x; - this.group.position.y = this.model.transformation.y; - this.group.scaling.x = this.model.transformation.scaleX; - this.group.scaling.y = this.model.transformation.scaleY; - this.group.rotation = this.model.transformation.rotation; + this.group.matrix.set(this.model.transformation.toMatrix()); this.group.opacity = this.model.transformation.opacity; } @@ -207,11 +203,7 @@ Wick.View.Clip = class extends Wick.View { group.addChild(border); group.pivot = new this.paper.Point(0,0); - group.position.x = this.model.transformation.x; - group.position.y = this.model.transformation.y; - group.scaling.x = this.model.transformation.scaleX; - group.scaling.y = this.model.transformation.scaleY; - group.rotation = this.model.transformation.rotation; + group.matrix.set(this.model.transformation.toMatrix()); return group; } diff --git a/engine/src/view/View.Frame.js b/engine/src/view/View.Frame.js index bb714415a..d0a08c4e5 100644 --- a/engine/src/view/View.Frame.js +++ b/engine/src/view/View.Frame.js @@ -129,15 +129,8 @@ Wick.View.Frame = class extends Wick.View { }).forEach(child => { if (child instanceof paper.Group || child instanceof Wick.Clip) { var wickClip = Wick.ObjectCache.getObjectByUUID(child.data.wickUUID); - wickClip.transformation = new Wick.Transformation({ - x: child.position.x, - y: child.position.y, - scaleX: child.scaling.x, - scaleY: child.scaling.y, - rotation: child.rotation, - opacity: child.opacity - - }); + wickClip.transformation = Wick.Transformation.prototype.fromMatrix(child.matrix.values); + wickClip.transformation.opacity = child.opacity; } }); From 32a8ab2e1da470bee131a249eb45376cdf67ce7c Mon Sep 17 00:00:00 2001 From: StickmanRed <100049599+StickmanRed@users.noreply.github.com> Date: Thu, 5 Feb 2026 20:22:54 -0800 Subject: [PATCH 2/2] Simplify matrix calculation in toMatrix function idk what I was thinking, this code should work just as well --- engine/src/Transformation.js | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/engine/src/Transformation.js b/engine/src/Transformation.js index d3b6d8345..d08273c39 100644 --- a/engine/src/Transformation.js +++ b/engine/src/Transformation.js @@ -94,24 +94,10 @@ Wick.Transformation = class { const {x, y, scaleX, scaleY, rotation, skew} = this; const rotationX = rotation * Math.PI / 180, rotationY = (skew + rotation) * Math.PI / 180; - - let a, b, c, d; - if (Math.abs(rotationX) === Math.PI / 2) { - a = 0; - b = Math.sign(rotationX) * scaleX; - } - else { - a = scaleX * Math.cos(rotationX); - b = scaleX * Math.sin(rotationX); - } - if (Math.abs(rotationY) === Math.PI / 2) { - d = 0; - c = -Math.sign(rotationX) * scaleY; - } - else { - d = scaleY * Math.cos(rotationY); - c = -scaleY * Math.sin(rotationY); - } + const a = scaleX * Math.cos(rotationX), + b = scaleX * Math.sin(rotationX), + d = scaleY * Math.cos(rotationY), + c = -scaleY * Math.sin(rotationY); return [a, b, c, d, x, y]; } }