aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-11-20 09:53:58 -0500
committerbobzel <zzzman@gmail.com>2023-11-20 09:53:58 -0500
commit4d15bf1cf2e37d15214c3c57fbb59da5465f30c8 (patch)
treec6847518913e915c063df8cb61da39ac42d42ad3 /src
parente4a3b962f8de00f5bc0463bed886d9f8f526ff89 (diff)
added rotation to transforms (partially done)
Diffstat (limited to 'src')
-rw-r--r--src/client/util/Transform.ts73
-rw-r--r--src/client/views/DocumentDecorations.tsx4
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx6
-rw-r--r--src/client/views/nodes/VideoBox.tsx2
4 files changed, 64 insertions, 21 deletions
diff --git a/src/client/util/Transform.ts b/src/client/util/Transform.ts
index e9170ec36..dca37c960 100644
--- a/src/client/util/Transform.ts
+++ b/src/client/util/Transform.ts
@@ -2,65 +2,105 @@ export class Transform {
private _translateX: number = 0;
private _translateY: number = 0;
private _scale: number = 1;
+ private _rotate: number = 0;
static Identity(): Transform {
return new Transform(0, 0, 1);
}
- get TranslateX(): number { return this._translateX; }
- get TranslateY(): number { return this._translateY; }
- get Scale(): number { return this._scale; }
+ get TranslateX(): number {
+ return this._translateX;
+ }
+ get TranslateY(): number {
+ return this._translateY;
+ }
+ get Scale(): number {
+ return this._scale;
+ }
+ get Rotate(): number {
+ return this._rotate;
+ }
+ get RotateDeg(): number {
+ return (this._rotate * 180) / Math.PI;
+ }
- constructor(x: number, y: number, scale: number) {
+ /**
+ * Represents a transformation/scale matrix (can contain a rotation value, but it is not used when transforming points)
+ * @param x
+ * @param y
+ * @param scale
+ * @param rotation NOTE: this is passed along but is NOT used by any of the transformation functionsStores
+ */
+ constructor(x: number, y: number, scale: number, rotationRadians?: number) {
this._translateX = x;
this._translateY = y;
this._scale = scale;
+ this._rotate = rotationRadians ?? 0;
}
+ /**
+ * Rotate in radians
+ * @param rot
+ * @returns the modified transformation
+ */
+ rotate = (rot: number): this => {
+ this._rotate += rot;
+ return this;
+ };
+ /**
+ * Rotation in degrees
+ * @param rot
+ * @returns the modified transformation
+ */
+ rotateDeg = (rot: number): this => {
+ this._rotate += (rot * Math.PI) / 180;
+ return this;
+ };
+
translate = (x: number, y: number): this => {
this._translateX += x;
this._translateY += y;
return this;
- }
+ };
scale = (scale: number): this => {
this._scale *= scale;
this._translateX *= scale;
this._translateY *= scale;
return this;
- }
+ };
scaleAbout = (scale: number, x: number, y: number): this => {
this._translateX += x * this._scale - x * this._scale * scale;
this._translateY += y * this._scale - y * this._scale * scale;
this._scale *= scale;
return this;
- }
+ };
transform = (transform: Transform): this => {
this._translateX = transform._translateX + transform._scale * this._translateX;
this._translateY = transform._translateY + transform._scale * this._translateY;
this._scale *= transform._scale;
return this;
- }
+ };
preTranslate = (x: number, y: number): this => {
this._translateX += this._scale * x;
this._translateY += this._scale * y;
return this;
- }
+ };
preScale = (scale: number): this => {
this._scale *= scale;
return this;
- }
+ };
preTransform = (transform: Transform): this => {
this._translateX += transform._translateX * this._scale;
this._translateY += transform._translateY * this._scale;
this._scale *= transform._scale;
return this;
- }
+ };
translated = (x: number, y: number): Transform => this.copy().translate(x, y);
@@ -82,18 +122,17 @@ export class Transform {
y *= this._scale;
y += this._translateY;
return [x, y];
- }
+ };
transformDirection = (x: number, y: number): [number, number] => [x * this._scale, y * this._scale];
- transformBounds(x: number, y: number, width: number, height: number): { x: number, y: number, width: number, height: number } {
+ transformBounds(x: number, y: number, width: number, height: number): { x: number; y: number; width: number; height: number } {
[x, y] = this.transformPoint(x, y);
[width, height] = this.transformDirection(width, height);
return { x, y, width, height };
}
- inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale);
-
- copy = () => new Transform(this._translateX, this._translateY, this._scale);
+ inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale, -this._rotate);
-} \ No newline at end of file
+ copy = () => new Transform(this._translateX, this._translateY, this._scale, this._rotate);
+}
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 6663c5ee8..dc5839bdd 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -69,7 +69,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
const center = {x: (this.Bounds.x+this.Bounds.r)/2, y: (this.Bounds.y+this.Bounds.b)/2};
const {x,y} = Utils.rotPt(e.clientX - center.x,
e.clientY - center.y,
- -NumCast(SelectionManager.Docs().lastElement()?.rotation)/180*Math.PI);
+ -NumCast(SelectionManager.Views().lastElement()?.screenToLocalTransform().RotateDeg));
(this._showNothing = !(this.Bounds.x !== Number.MAX_VALUE && //
(this.Bounds.x > center.x+x + this._resizeBorderWidth / 2 ||
this.Bounds.r < center.x+x - this._resizeBorderWidth / 2 ||
@@ -698,7 +698,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
const bounds = this.ClippedBounds;
const useLock = bounds.r - bounds.x > 135 && seldocview.CollectionFreeFormDocumentView;
const useRotation = !hideResizers && seldocview.rootDoc.type !== DocumentType.EQUATION && seldocview.CollectionFreeFormDocumentView; // when do we want an object to not rotate?
- const rotation = SelectionManager.Views().length == 1 ? seldocview.docViewPath.reduce((rot, view) => rot + NumCast(view.rootDoc._rotation), 0) : 0;
+ const rotation = SelectionManager.Views().length == 1 ? seldocview.screenToLocalTransform().RotateDeg : 0;
// Radius constants
const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 5fbe5d0e3..ab124eede 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -226,7 +226,11 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
this.props.Document.x = this.props.w_X() + x;
this.props.Document.y = this.props.w_Y() + y;
};
- screenToLocalTransform = () => this.props.ScreenToLocalTransform().translate(-this.props.w_X(), -this.props.w_Y());
+ screenToLocalTransform = () =>
+ this.props
+ .ScreenToLocalTransform()
+ .translate(-this.props.w_X(), -this.props.w_Y())
+ .rotateDeg(this.props.w_Rotation?.() || 0);
returnThis = () => this;
/// this indicates whether the doc view is activated because of its relationshop to a group
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 459b3036d..6ebf84738 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -938,7 +938,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
className="videoBox-ui"
style={{
transformOrigin: 'top left',
- transform: `rotate(${NumCast(this.rootDoc.rotation)}deg) translate(${-(xRight - xPos) + 10}px, ${yBot - yMid - uiHeight - uiMargin}px)`,
+ transform: `rotate(${this.props.ScreenToLocalTransform().RotateDeg}deg) translate(${-(xRight - xPos) + 10}px, ${yBot - yMid - uiHeight - uiMargin}px)`,
left: xPos,
top: yMid,
height: uiHeight,