Jelajahi Sumber

Matrix shapes

flabbet 1 tahun lalu
induk
melakukan
516158168d

+ 2 - 2
src/ChunkyImageLib/ChunkyImageEx.cs

@@ -48,7 +48,7 @@ public static class IReadOnlyChunkyImageEx
         Func<VecI, ChunkResolution, DrawingSurface, VecI, Paint?, bool> drawingFunc,
         Paint? paint = null)
     {
-        surface.Canvas.Save();
+        int count = surface.Canvas.Save();
         surface.Canvas.ClipRect(RectD.Create(pos, fullResRegion.Size));
 
         VecI chunkTopLeft = OperationHelper.GetChunkPos(fullResRegion.TopLeft, ChunkyImage.FullChunkSize);
@@ -65,6 +65,6 @@ public static class IReadOnlyChunkyImageEx
             }
         }
 
-        surface.Canvas.Restore();
+        surface.Canvas.RestoreToCount(count);
     }
 }

+ 13 - 0
src/ChunkyImageLib/DataHolders/ShapeCorners.cs

@@ -245,4 +245,17 @@ public struct ShapeCorners
         // All projections overlap, so the shapes intersect
         return true;
     }
+
+    public ShapeCorners WithMatrix(Matrix3X3 transformationMatrix)
+    {
+        ShapeCorners corners = new ShapeCorners
+        {
+            TopLeft = transformationMatrix.MapPoint(TopLeft),
+            TopRight = transformationMatrix.MapPoint(TopRight),
+            BottomLeft = transformationMatrix.MapPoint(BottomLeft),
+            BottomRight = transformationMatrix.MapPoint(BottomRight)
+        };
+        
+        return corners;
+    }
 }

+ 3 - 15
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/ITransformableObject.cs

@@ -1,21 +1,9 @@
-using PixiEditor.Numerics;
+using PixiEditor.DrawingApi.Core.Numerics;
+using PixiEditor.Numerics;
 
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 
 public interface ITransformableObject
 {
-    /// <summary>
-    ///     Position in x and y.
-    /// </summary>
-    public VecD Position { get; set; }
-    
-    /// <summary>
-    ///     Scale in x and y.
-    /// </summary>
-    public VecD Size { get; set; }
-    
-    /// <summary>
-    ///     Rotation in radians.
-    /// </summary>
-    public double RotationRadians { get; set; }
+    public Matrix3X3 TransformationMatrix { get; set; }
 }

+ 26 - 17
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/EllipseVectorData.cs

@@ -6,27 +6,29 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 
 public class EllipseVectorData : ShapeVectorData
 {
-    public VecD Radius
-    {
-        get => Size / 2;
-        set => Size = value * 2;
-    } 
-
-    public override RectD AABB =>
-        new ShapeCorners(Position, Size).AsRotated(RotationRadians, Position)
-            .AABBBounds;
+    public VecD Radius { get; set; }
+    public VecD Center { get; set; }
     
+    public double RotationRadians { get; set; } = 0;
+
+    public override RectD GeometryAABB =>
+        new ShapeCorners(Center, Radius * 2).AsRotated(RotationRadians, Center).AABBBounds;
+
+    public override ShapeCorners TransformationCorners =>
+        new ShapeCorners(Center, Radius * 2).AsRotated(RotationRadians, Center).WithMatrix(TransformationMatrix);
+
+
     public EllipseVectorData(VecD center, VecD radius)
     {
-        Position = center;
+        Center = center;
         Radius = radius;
     }
 
     public override void Rasterize(DrawingSurface drawingSurface)
     {
-        var imageSize = (VecI)Size;
+        var imageSize = (VecI)(Radius * 2);
         
-        using ChunkyImage img = new ChunkyImage((VecI)AABB.Size);
+        using ChunkyImage img = new ChunkyImage((VecI)GeometryAABB.Size);
 
         RectD rotated = new ShapeCorners(RectD.FromTwoPoints(VecD.Zero, imageSize))
             .AsRotated(RotationRadians, imageSize / 2f).AABBBounds;
@@ -37,11 +39,16 @@ public class EllipseVectorData : ShapeVectorData
         img.EnqueueDrawEllipse(drawRect, StrokeColor, FillColor, StrokeWidth, RotationRadians);
         img.CommitChanges();
 
-        VecI topLeft = new VecI((int)Math.Round(Position.X - Radius.X), (int)Math.Round(Position.Y - Radius.Y)) - shift;
+        VecI topLeft = new VecI((int)Math.Round(Center.X - Radius.X), (int)Math.Round(Center.Y - Radius.Y)) - shift;
         
-        RectI region = new(VecI.Zero, (VecI)AABB.Size);
+        RectI region = new(VecI.Zero, (VecI)GeometryAABB.Size);
+
+        drawingSurface.Canvas.Save();
+        drawingSurface.Canvas.SetMatrix(TransformationMatrix);
 
         img.DrawMostUpToDateRegionOn(region, ChunkResolution.Full, drawingSurface, topLeft);
+        
+        drawingSurface.Canvas.Restore();
     }
 
     public override bool IsValid()
@@ -51,7 +58,7 @@ public class EllipseVectorData : ShapeVectorData
 
     public override int CalculateHash()
     {
-        return HashCode.Combine(Position, Radius);
+        return HashCode.Combine(Center, Radius, StrokeColor, FillColor, StrokeWidth, RotationRadians, TransformationMatrix);
     }
 
     public override int GetCacheHash()
@@ -61,11 +68,13 @@ public class EllipseVectorData : ShapeVectorData
 
     public override object Clone()
     {
-        return new EllipseVectorData(Position, Radius)
+        return new EllipseVectorData(Center, Radius)
         {
             StrokeColor = StrokeColor,
             FillColor = FillColor,
-            StrokeWidth = StrokeWidth
+            StrokeWidth = StrokeWidth,
+            RotationRadians = RotationRadians,
+            TransformationMatrix = TransformationMatrix
         };
     }
 }

+ 4 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/PointsVectorData.cs

@@ -13,7 +13,10 @@ public class PointsVectorData : ShapeVectorData
         Points = new List<VecD>(points);
     }
 
-    public override RectD AABB => new RectD(Points.Min(p => p.X), Points.Min(p => p.Y), Points.Max(p => p.X), Points.Max(p => p.Y));
+    public override RectD GeometryAABB => new RectD(Points.Min(p => p.X), Points.Min(p => p.Y), Points.Max(p => p.X),
+        Points.Max(p => p.Y));
+    public override ShapeCorners TransformationCorners => new ShapeCorners(
+        GeometryAABB).WithMatrix(TransformationMatrix); 
 
     public override void Rasterize(DrawingSurface drawingSurface)
     {

+ 5 - 8
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Shapes/Data/ShapeVectorData.cs

@@ -1,5 +1,6 @@
 using PixiEditor.Common;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.Numerics;
 
@@ -7,18 +8,14 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 
 public abstract class ShapeVectorData : ICacheable, ICloneable
 {
-    public VecD Position { get; set; }
-    public VecD Size { get; set; } 
-    
-    /// <summary>
-    ///     Rotation in radians.
-    /// </summary>
-    public double RotationRadians { get; set; }
+    public Matrix3X3 TransformationMatrix { get; set; } = Matrix3X3.Identity; 
     
     public Color StrokeColor { get; set; } = Colors.White;
     public Color FillColor { get; set; } = Colors.White;
     public int StrokeWidth { get; set; } = 1;
-    public abstract RectD AABB { get; }
+    public abstract RectD GeometryAABB { get; }
+    public RectD TransformedAABB => new ShapeCorners(GeometryAABB).WithMatrix(TransformationMatrix).AABBBounds;
+    public abstract ShapeCorners TransformationCorners { get; } 
 
     public abstract void Rasterize(DrawingSurface drawingSurface);
     public abstract bool IsValid();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/StructureNode.cs

@@ -29,7 +29,7 @@ public abstract class StructureNode : Node, IReadOnlyStructureNode, IBackgroundI
     public ChunkyImage? EmbeddedMask { get; set; }
     public virtual ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     {
-        return new ShapeCorners((RectD)GetTightBounds(frameTime).Value);
+        return new ShapeCorners((RectD)GetTightBounds(frameTime).GetValueOrDefault());
     }
 
     public string MemberName

+ 8 - 19
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/VectorLayerNode.cs

@@ -1,4 +1,5 @@
-using PixiEditor.ChangeableDocument.Changeables.Animations;
+using ChunkyImageLib.Operations;
+using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.ChangeableDocument.Rendering;
@@ -11,24 +12,12 @@ namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 [NodeInfo("VectorLayer")]
 public class VectorLayerNode : LayerNode, ITransformableObject
 {
-    public VecD Position
+    public Matrix3X3 TransformationMatrix
     {
-        get => ShapeData.Position;
-        set => ShapeData.Position = value;
+        get => ShapeData.TransformationMatrix;
+        set => ShapeData.TransformationMatrix = value;
     }
-
-    public VecD Size
-    {
-        get => ShapeData.Size;
-        set => ShapeData.Size = value;
-    }
-
-    public double RotationRadians
-    {
-        get => ShapeData.RotationRadians;
-        set => ShapeData.RotationRadians = value;
-    }
-
+    
     public ShapeVectorData ShapeData { get; } = new EllipseVectorData(new VecI(32), new VecI(32));
     
     private int lastCacheHash;
@@ -56,12 +45,12 @@ public class VectorLayerNode : LayerNode, ITransformableObject
 
     public override RectI? GetTightBounds(KeyFrameTime frameTime)
     {
-        return (RectI)ShapeData.AABB;
+        return (RectI)ShapeData.GeometryAABB;
     }
 
     public override ShapeCorners GetTransformationCorners(KeyFrameTime frameTime)
     {
-        return new ShapeCorners(ShapeData.Position, ShapeData.Size).AsRotated(RotationRadians, ShapeData.Position);
+        return ShapeData.TransformationCorners;
     }
 
     public override Node CreateCopy()

+ 49 - 34
src/PixiEditor.ChangeableDocument/Changes/Drawing/TransformSelected_UpdateableChange.cs

@@ -70,6 +70,7 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
         foreach (var member in memberData)
         {
             StructureNode layer = target.FindMemberOrThrow(member.MemberId);
+            originalMasterCornersSize = masterCorners.RectSize;
 
             if (layer is IReadOnlyImageNode)
             {
@@ -88,7 +89,7 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
 
                 member.OriginalPath = pathToExtract;
                 member.OriginalBounds = targetBounds;
-                member.GlobalMatrix = OperationHelper.CreateMatrixFromPoints(member.MemberCorners, targetBounds.Size);
+                member.LocalMatrix = OperationHelper.CreateMatrixFromPoints(member.MemberCorners, targetBounds.Size);
                 var extracted = ExtractArea(image, pathToExtract, member.RoundedOriginalBounds.Value);
                 if (extracted.IsT0)
                     continue;
@@ -97,13 +98,14 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
             }
             else if (layer is ITransformableObject transformable)
             {
-                member.AddTransformableObject(transformable,
-                    new ShapeCorners(transformable.Position, transformable.Size)
-                        .AsRotated(transformable.RotationRadians, transformable.Position));
+                member.LocalMatrix = transformable.TransformationMatrix;
+                RectI tightBounds = layer.GetTightBounds(frame).Value;
+                member.OriginalBounds = (RectD)tightBounds;
+                
+                member.AddTransformableObject(transformable, transformable.TransformationMatrix);
             }
         }
 
-        originalMasterCornersSize = masterCorners.RectSize;
         return true;
     }
 
@@ -113,14 +115,13 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
         this.keepOriginal = keepOriginal;
         lastCorners = this.masterCorners;
         this.masterCorners = masterCorners;
+        
+        Matrix3X3 masterMatrix = OperationHelper.CreateMatrixFromPoints(masterCorners, originalMasterCornersSize);
 
         foreach (var member in memberData)
         {
-            if (member.IsImage)
-            {
-                var corners = MasterToMemberCoords(member.MemberCorners);
-                member.GlobalMatrix = OperationHelper.CreateMatrixFromPoints(corners, member.OriginalBounds.Value.Size);
-            }
+            ShapeCorners localCorners = MasterToMemberCoords(member.MemberCorners);
+            member.LocalMatrix = OperationHelper.CreateMatrixFromPoints(localCorners, member.OriginalBounds!.Value.Size);
         }
     }
 
@@ -174,13 +175,14 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
             {
                 ShapeCorners localCorners = MasterToMemberCoords(member.MemberCorners);
 
-                member.TransformableObject.Position = localCorners.RectCenter;
-                member.TransformableObject.Size = localCorners.RectSize;
-                member.TransformableObject.RotationRadians = localCorners.RectRotation;
+                var localMatrix =
+                    OperationHelper.CreateMatrixFromPoints(localCorners, member.OriginalBounds!.Value.Size);
+                member.TransformableObject.TransformationMatrix = localMatrix;
 
                 member.MemberCorners = localCorners;
 
-                AffectedArea area = GetTranslationAffectedArea(member.OriginalCorners.Value);
+                // TODO: this is probably wrong
+                AffectedArea area = GetTranslationAffectedArea(localCorners);
                 infos.Add(new TransformObject_ChangeInfo(member.MemberId, area));
             }
         }
@@ -203,28 +205,28 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
         foreach (var member in memberData)
         {
             ShapeCorners localCorners = MasterToMemberCoords(member.MemberCorners);
-            
+
             if (member.IsImage)
             {
                 ChunkyImage targetImage =
                     DrawingChangeHelper.GetTargetImageOrThrow(target, member.MemberId, drawOnMask, frame);
-                
+
                 member.MemberCorners = localCorners;
-                
+
                 infos.Add(DrawingChangeHelper.CreateAreaChangeInfo(member.MemberId,
                         DrawImage(member, targetImage), drawOnMask)
                     .AsT1);
             }
             else if (member.IsTransformable)
             {
-                VecD translated = localCorners.RectCenter;
-                member.TransformableObject.Position = translated;
-                member.TransformableObject.Size = localCorners.RectSize;
-                member.TransformableObject.RotationRadians = localCorners.RectRotation; 
+                var localMatrix =
+                    OperationHelper.CreateMatrixFromPoints(localCorners, member.OriginalBounds!.Value.Size);
+                member.TransformableObject.TransformationMatrix = localMatrix;
 
                 member.MemberCorners = localCorners;
 
-                AffectedArea translationAffectedArea = GetTranslationAffectedArea(member.OriginalCorners.Value);
+                // TODO: this is probably wrong
+                AffectedArea translationAffectedArea = GetTranslationAffectedArea(localCorners);
                 infos.Add(new TransformObject_ChangeInfo(member.MemberId, translationAffectedArea));
             }
         }
@@ -245,12 +247,26 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
         VecD sizeDiff = masterCorners.RectSize - lastCorners.RectSize;
         double rotDiff = masterCorners.RectRotation - lastCorners.RectRotation;
 
-        ShapeCorners localCorners =
+        ShapeCorners rotatedCorners =
             new ShapeCorners(memberCorner.RectCenter + posDiff, memberCorner.RectSize + sizeDiff)
                 .AsRotated(memberCorner.RectRotation, memberCorner.RectCenter + posDiff)
                 .AsRotated(rotDiff, masterCorners.RectCenter);
 
-        return localCorners;
+        /*VecD[] cornersDiff = new VecD[]
+        {
+            masterCorners.TopLeft - lastCorners.TopLeft, masterCorners.TopRight - lastCorners.TopRight,
+            masterCorners.BottomLeft - lastCorners.BottomLeft, masterCorners.BottomRight - lastCorners.BottomRight
+        };
+        
+        ShapeCorners rotatedCorners = new ShapeCorners()
+        {
+            TopLeft = memberCorner.TopLeft + cornersDiff[0],
+            TopRight = memberCorner.TopRight + cornersDiff[1],
+            BottomLeft = memberCorner.BottomLeft + cornersDiff[2],
+            BottomRight = memberCorner.BottomRight + cornersDiff[3]
+        };*/
+
+        return rotatedCorners;
     }
 
     public override OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target)
@@ -271,11 +287,10 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
             }
             else if (member.IsTransformable)
             {
-                member.TransformableObject.Position = member.OriginalCorners.Value.RectCenter;
-                member.TransformableObject.Size = member.OriginalCorners.Value.RectSize;
-                member.TransformableObject.RotationRadians = member.OriginalCorners.Value.RectRotation;
+                member.TransformableObject.TransformationMatrix = member.OriginalMatrix!.Value;
 
-                AffectedArea area = GetTranslationAffectedArea(member.OriginalCorners.Value);
+                //TODO this is probably wrong
+                AffectedArea area = GetTranslationAffectedArea(member.MemberCorners);
                 infos.Add(new TransformObject_ChangeInfo(member.MemberId, area));
             }
         }
@@ -330,8 +345,8 @@ internal class TransformSelected_UpdateableChange : UpdateableChange
         var prevAffArea = memberImage.FindAffectedArea();
 
         memberImage.CancelChanges();
-        
-        Matrix3X3 globalMatrix = data.GlobalMatrix!.Value; 
+
+        Matrix3X3 globalMatrix = data.LocalMatrix!.Value;
 
         var originalPos = data.ImagePos!.Value;
 
@@ -355,7 +370,7 @@ class MemberTransformationData : IDisposable
     public ShapeCorners MemberCorners { get; set; }
 
     public ITransformableObject? TransformableObject { get; private set; }
-    public ShapeCorners? OriginalCorners { get; private set; }
+    public Matrix3X3? OriginalMatrix { get; private set; }
 
     public CommittedChunkStorage? SavedChunks { get; set; }
     public VectorPath? OriginalPath { get; set; }
@@ -365,17 +380,17 @@ class MemberTransformationData : IDisposable
     public bool IsImage => Image != null;
     public bool IsTransformable => TransformableObject != null;
     public RectI? RoundedOriginalBounds => (RectI?)OriginalBounds?.RoundOutwards();
-    public Matrix3X3? GlobalMatrix { get; set; }
+    public Matrix3X3? LocalMatrix { get; set; }
 
     public MemberTransformationData(Guid memberId)
     {
         MemberId = memberId;
     }
 
-    public void AddTransformableObject(ITransformableObject transformableObject, ShapeCorners originalCorners)
+    public void AddTransformableObject(ITransformableObject transformableObject, Matrix3X3 originalMatrix)
     {
         TransformableObject = transformableObject;
-        OriginalCorners = originalCorners;
+        OriginalMatrix = originalMatrix;
     }
 
     public void AddImage(Surface img, VecI extractedRectPos)

+ 1 - 0
src/PixiEditor.DrawingApi.Core/Bridge/NativeObjectsImpl/IMatrix3x3Implementation.cs

@@ -9,4 +9,5 @@ public interface IMatrix3X3Implementation
     public Matrix3X3 Concat(in Matrix3X3 first, in Matrix3X3 second);
     public Matrix3X3 PostConcat(in Matrix3X3 first, in Matrix3X3 second);
     public VecD MapPoint(Matrix3X3 matrix, int p0, int p1);
+    public VecD MapPoint(Matrix3X3 matrix, VecD point);
 }

+ 5 - 0
src/PixiEditor.DrawingApi.Core/Numerics/Matrix3X3.cs

@@ -361,6 +361,11 @@ public struct Matrix3X3 : IEquatable<Matrix3X3>
     {
         return DrawingBackendApi.Current.MatrixImplementation.MapPoint(this, p0, p1);
     }
+    
+    public VecD MapPoint(VecD point)
+    {
+        return DrawingBackendApi.Current.MatrixImplementation.MapPoint(this, point);
+    }
 
     private static void SetSinCos(ref Matrix3X3 matrix, float sin, float cos)
     {

+ 6 - 0
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaMatrixImplementation.cs

@@ -29,5 +29,11 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
             var mapped = matrix.ToSkMatrix().MapPoint(p0, p1);
             return new VecD(mapped.X, mapped.Y);
         }
+
+        public VecD MapPoint(Matrix3X3 matrix, VecD point)
+        {
+            var mapped = matrix.ToSkMatrix().MapPoint((float)point.X, (float)point.Y);
+            return new VecD(mapped.X, mapped.Y);
+        }
     }
 }

+ 1 - 1
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/TransformSelectedExecutor.cs

@@ -52,7 +52,7 @@ internal class TransformSelectedExecutor : UpdateableChangeExecutor
             memberCorners.Add(member.Id, targetCorners);
         }
         
-        ShapeCorners masterCorners = new ShapeCorners(memberCorners.Values.Select(static c => c.AABBBounds).Aggregate((a, b) => a.Union(b)));
+        ShapeCorners masterCorners = memberCorners.Count == 1 ? memberCorners.FirstOrDefault().Value : new ShapeCorners(memberCorners.Values.Select(static c => c.AABBBounds).Aggregate((a, b) => a.Union(b)));
         
         document.TransformHandler.ShowTransform(DocumentTransformMode.Scale_Rotate_Shear_Perspective, true, masterCorners, Type == ExecutorType.Regular);
         internals!.ActionAccumulator.AddActions(

+ 11 - 0
src/PixiEditor/Models/Serialization/Factories/ByteBuilder.cs

@@ -1,4 +1,5 @@
 using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.Models.Serialization.Factories;
@@ -17,6 +18,16 @@ public class ByteBuilder
         return this;
     }
     
+    public ByteBuilder AddMatrix3X3(Matrix3X3 matrix)
+    {
+        foreach (var value in matrix.Values)
+        {
+            _data.AddRange(BitConverter.GetBytes(value));
+        } 
+        
+        return this;
+    }
+    
     public ByteBuilder AddColor(Color color)
     {
         _data.Add(color.R);

+ 24 - 0
src/PixiEditor/Models/Serialization/Factories/ByteExtractor.cs

@@ -1,4 +1,5 @@
 using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.Models.Serialization.Factories;
@@ -57,4 +58,27 @@ public class ByteExtractor
         
         return points;
     }
+
+    public Matrix3X3 GetMatrix3X3()
+    {
+        double[] values = new double[9];
+        
+        for (int i = 0; i < 9; i++)
+        {
+            values[i] = BitConverter.ToDouble(_data, Position);
+            Position += sizeof(double);
+        }
+        
+        float[] valuesFloat = values.Select(x => (float)x).ToArray();
+        return new Matrix3X3(valuesFloat);
+    }
+
+    public double GetDouble()
+    {
+        double value = BitConverter.ToDouble(_data, Position);
+        
+        Position += sizeof(double);
+        
+        return value;
+    }
 }

+ 8 - 2
src/PixiEditor/Models/Serialization/Factories/EllipseSerializationFactory.cs

@@ -1,5 +1,6 @@
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
+using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Numerics;
 
 namespace PixiEditor.Models.Serialization.Factories;
@@ -10,8 +11,10 @@ public class EllipseSerializationFactory : SerializationFactory<byte[], EllipseV
     public override byte[] Serialize(EllipseVectorData original)
     {
         ByteBuilder builder = new ByteBuilder();
-        builder.AddVecD(original.Position);
+        builder.AddVecD(original.Center);
         builder.AddVecD(original.Radius);
+        builder.AddDouble(original.RotationRadians);
+        builder.AddMatrix3X3(original.TransformationMatrix);
         builder.AddColor(original.StrokeColor);
         builder.AddColor(original.FillColor);
         builder.AddInt(original.StrokeWidth);
@@ -31,6 +34,8 @@ public class EllipseSerializationFactory : SerializationFactory<byte[], EllipseV
         
         VecD center = extractor.GetVecD();
         VecD radius = extractor.GetVecD();
+        double rotationRadians = extractor.GetDouble();
+        Matrix3X3 matrix = extractor.GetMatrix3X3();
         Color strokeColor = extractor.GetColor();
         Color fillColor = extractor.GetColor();
         int strokeWidth = extractor.GetInt();
@@ -39,7 +44,8 @@ public class EllipseSerializationFactory : SerializationFactory<byte[], EllipseV
         {
             StrokeColor = strokeColor,
             FillColor = fillColor,
-            StrokeWidth = strokeWidth
+            StrokeWidth = strokeWidth,
+            TransformationMatrix = matrix
         };
         
         return true;