Browse Source

Pixel perfect pen fully implemented, delete junk folder

Equbuxu 3 years ago
parent
commit
9c7abb0779
37 changed files with 87 additions and 333 deletions
  1. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Change.cs
  2. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ApplyLayerMask_Change.cs
  3. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ClearSelectedArea_Change.cs
  4. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ClearSelection_Change.cs
  5. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs
  6. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawEllipse_UpdateableChange.cs
  7. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRectangle_UpdateableChange.cs
  8. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFill_Change.cs
  9. 1 5
      src/PixiEditor.ChangeableDocument/Changes/Drawing/LineBasedPen_UpdateableChange.cs
  10. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/PasteImage_UpdateableChange.cs
  11. 1 4
      src/PixiEditor.ChangeableDocument/Changes/Drawing/PathBasedPen_UpdateableChange.cs
  12. 49 22
      src/PixiEditor.ChangeableDocument/Changes/Drawing/PixelPerfectPen_UpdateableChange.cs
  13. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayer_UpdateableChange.cs
  14. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/CreateStructureMemberMask_Change.cs
  15. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/DeleteStructureMemberMask_Change.cs
  16. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/LayerLockTransparency_Change.cs
  17. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberBlendMode_Change.cs
  18. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberClipToMemberBelow_Change.cs
  19. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberIsVisible_Change.cs
  20. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberMaskIsVisible_Change.cs
  21. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberName_Change.cs
  22. 2 2
      src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberOpacity_UpdateableChange.cs
  23. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Root/ResizeCanvas_Change.cs
  24. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Root/SymmetryAxisPosition_UpdateableChange.cs
  25. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Root/SymmetryAxisState_Change.cs
  26. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Selection/SelectLasso_UpdateableChange.cs
  27. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Selection/SelectRectangle_UpdateableChange.cs
  28. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Selection/TransformSelectionPath_UpdateableChange.cs
  29. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs
  30. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Structure/DeleteStructureMember_Change.cs
  31. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Structure/MoveStructureMember_Change.cs
  32. 3 3
      src/PixiEditor.ChangeableDocument/DocumentChangeTracker.cs
  33. 4 0
      src/PixiEditorPrototype.sln.DotSettings
  34. 0 16
      src/StructureRenderer/RenderInfos/DirtyRect_RenderInfo.cs
  35. 0 6
      src/StructureRenderer/RenderInfos/IRenderInfo.cs
  36. 0 234
      src/StructureRenderer/Renderer.cs
  37. 0 14
      src/StructureRenderer/StructureRenderer.csproj

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Change.cs

@@ -4,7 +4,7 @@ internal abstract class Change : IDisposable
 {
     public virtual bool IsMergeableWith(Change other) => false;
     public abstract OneOf<Success, Error> InitializeAndValidate(Document target);
-    public abstract OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo);
+    public abstract OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo);
     public abstract OneOf<None, IChangeInfo, List<IChangeInfo>> Revert(Document target);
     public virtual void Dispose() { }
 };

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/ApplyLayerMask_Change.cs

@@ -24,7 +24,7 @@ internal class ApplyLayerMask_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var layer = (Layer)target.FindMemberOrThrow(layerGuid);
         if (layer.Mask is null)

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/ClearSelectedArea_Change.cs

@@ -23,7 +23,7 @@ internal class ClearSelectedArea_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         if (savedChunks is not null)
             throw new InvalidOperationException("trying to save chunks while they are already saved");

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/ClearSelection_Change.cs

@@ -17,7 +17,7 @@ internal class ClearSelection_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         (var toDispose, target.Selection.SelectionPath) = (target.Selection.SelectionPath, new SKPath());
         toDispose.Dispose();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs

@@ -46,7 +46,7 @@ internal class CombineStructureMembersOnto_Change : Change
         }
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         Layer toDrawOn = (Layer)target.FindMemberOrThrow(targetLayer);
 

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawEllipse_UpdateableChange.cs

@@ -50,7 +50,7 @@ internal class DrawEllipse_UpdateableChange : UpdateableChange
         return affectedChunks;
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
         var chunks = UpdateEllipse(target, image);

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/DrawRectangle_UpdateableChange.cs

@@ -49,7 +49,7 @@ internal class DrawRectangle_UpdateableChange : UpdateableChange
         return DrawingChangeHelper.CreateChunkChangeInfo(memberGuid, chunks, drawOnMask);
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
         var affectedChunks = UpdateRectangle(target, targetImage);

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFill_Change.cs

@@ -27,7 +27,7 @@ internal class FloodFill_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
 

+ 1 - 5
src/PixiEditor.ChangeableDocument/Changes/Drawing/LineBasedPen_UpdateableChange.cs

@@ -9,8 +9,6 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
     private readonly bool replacing;
     private readonly bool drawOnMask;
 
-    bool firstApply = true;
-
     private CommittedChunkStorage? storedChunks;
     private readonly List<VecI> points = new();
 
@@ -80,7 +78,7 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
         }
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         if (storedChunks is not null)
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
@@ -89,8 +87,6 @@ internal class LineBasedPen_UpdateableChange : UpdateableChange
         ignoreInUndo = false;
         if (firstApply)
         {
-            firstApply = false;
-
             var affChunks = image.FindAffectedChunks();
             storedChunks = new CommittedChunkStorage(image, affChunks);
             image.CommitChanges();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/PasteImage_UpdateableChange.cs

@@ -51,7 +51,7 @@ internal class PasteImage_UpdateableChange : UpdateableChange
         return affectedChunks;
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         ChunkyImage targetImage = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
         var chunks = DrawImage(target, targetImage);

+ 1 - 4
src/PixiEditor.ChangeableDocument/Changes/Drawing/PathBasedPen_UpdateableChange.cs

@@ -8,8 +8,6 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
     private readonly float strokeWidth;
     private readonly bool drawOnMask;
 
-    bool firstApply = true;
-
     private CommittedChunkStorage? storedChunks;
     private SKPath tempPath = new();
 
@@ -98,7 +96,7 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
         tempPath.CubicTo((SKPoint)mid1, (SKPoint)mid2, (SKPoint)points[pointsCount - 2]);
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         if (storedChunks is not null)
             throw new InvalidOperationException("Trying to save chunks while there are saved chunks already");
@@ -107,7 +105,6 @@ internal class PathBasedPen_UpdateableChange : UpdateableChange
         ignoreInUndo = false;
         if (firstApply)
         {
-            firstApply = false;
             UpdateTempPathFinish();
 
             image.EnqueueDrawPath(tempPath, color, strokeWidth, SKStrokeCap.Round, SKBlendMode.Src);

+ 49 - 22
src/PixiEditor.ChangeableDocument/Changes/Drawing/PixelPerfectPen_UpdateableChange.cs

@@ -1,4 +1,6 @@
-using SkiaSharp;
+using System.ComponentModel.Design;
+using ChunkyImageLib.Operations;
+using SkiaSharp;
 
 namespace PixiEditor.ChangeableDocument.Changes.Drawing;
 
@@ -7,7 +9,10 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
     private readonly SKColor color;
     private readonly bool drawOnMask;
     private readonly Guid memberGuid;
-    private readonly List<VecI> points = new();
+    private readonly HashSet<VecI> confirmedPixels = new();
+    private HashSet<VecI> pixelsToConfirm = new();
+    private HashSet<VecI> pixelsToConfirm2 = new();
+    private List<VecI>? incomingPoints = new();
     private CommittedChunkStorage? chunkStorage;
 
     [GenerateUpdateableChangeActions]
@@ -16,14 +21,13 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
         this.memberGuid = memberGuid;
         this.color = color;
         this.drawOnMask = drawOnMask;
-        points.Add(pos);
+        incomingPoints!.Add(pos);
     }
 
     [UpdateChangeMethod]
     public void Update(VecI pos)
     {
-        if (points[^1] != pos)
-            points.Add(pos);
+        incomingPoints!.Add(pos);
     }
 
     public override OneOf<Success, Error> InitializeAndValidate(Document target)
@@ -36,13 +40,13 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
         return new Success();
     }
 
-    private bool IsAngle(int lastPixelIndex)
+    private bool IsLShape(int lastPixelIndex)
     {
         if (lastPixelIndex < 3)
             return false;
-        VecI first = points[lastPixelIndex - 2];
-        VecI second = points[lastPixelIndex - 1];
-        VecI third = points[lastPixelIndex];
+        VecI first = incomingPoints![lastPixelIndex - 2];
+        VecI second = incomingPoints[lastPixelIndex - 1];
+        VecI third = incomingPoints[lastPixelIndex];
         return first.X != third.X && first.Y != third.Y && (second - first).TaxicabLength == 1 && (second - third).TaxicabLength == 1;
     }
 
@@ -50,15 +54,35 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
     {
         if (pointsCount == 1)
         {
-            image.EnqueueDrawPixel(points[0], color, SKBlendMode.Src);
+            image.EnqueueDrawPixel(incomingPoints![0], color, SKBlendMode.Src);
             return;
         }
 
-        image.EnqueueDrawBresenhamLine(points[pointsCount - 2], points[pointsCount - 1], color, SKBlendMode.Src);
-        if (pointsCount == 3 && IsAngle(pointsCount - 1) ||
-            pointsCount >= 4 && IsAngle(pointsCount - 1) && !IsAngle(pointsCount - 2))
+        if (incomingPoints![^1] == incomingPoints[^2])
         {
-            image.EnqueueDrawPixel(points[pointsCount - 2], SKColors.Transparent, SKBlendMode.Src);
+            incomingPoints.RemoveAt(incomingPoints.Count - 1);
+            return;
+        }
+
+        
+        confirmedPixels!.UnionWith(pixelsToConfirm2!);
+        (pixelsToConfirm2, pixelsToConfirm) = (pixelsToConfirm, pixelsToConfirm2);
+        pixelsToConfirm!.Clear();
+        
+        SKPoint[] line = BresenhamLineHelper.GetBresenhamLine(incomingPoints[pointsCount - 2], incomingPoints[pointsCount - 1]);
+        foreach (VecI pixel in line)
+        {
+            pixelsToConfirm.Add(pixel);
+        }
+        image.EnqueueDrawPixels(line.Select(point => (VecI)point), color, SKBlendMode.Src);
+        
+        if (pointsCount >= 3 && IsLShape(pointsCount - 1) && !confirmedPixels.Contains(incomingPoints[pointsCount - 2]))
+        {
+            VecI pixelToErase = incomingPoints[pointsCount - 2];
+            image.EnqueueDrawPixel(pixelToErase, SKColors.Transparent, SKBlendMode.Src);
+            pixelsToConfirm.Remove(pixelToErase);
+            pixelsToConfirm2.Remove(pixelToErase);
+            incomingPoints.RemoveAt(pointsCount - 2);
         }
     }
 
@@ -67,26 +91,29 @@ internal class PixelPerfectPen_UpdateableChange : UpdateableChange
         ChunkyImage image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
 
         int changeCount = image.QueueLength;
-        DoDrawingIteration(image, points.Count);
+        DoDrawingIteration(image, incomingPoints!.Count);
         HashSet<VecI> affChunks = image.FindAffectedChunks(changeCount);
         return DrawingChangeHelper.CreateChunkChangeInfo(memberGuid, affChunks, drawOnMask);
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         if (chunkStorage is not null)
-            throw new InvalidOperationException("Trying to save chunks while saved one already exist");
+            throw new InvalidOperationException("Trying to save chunks while a saved one already exist");
 
         ignoreInUndo = false;
         var image = DrawingChangeHelper.GetTargetImageOrThrow(target, memberGuid, drawOnMask);
-        if (image.QueueLength == 0)
+        if (firstApply)
+        {
+            incomingPoints = null;
+            confirmedPixels!.UnionWith(pixelsToConfirm!);
+            confirmedPixels.UnionWith(pixelsToConfirm2!);
+        }
+        else
         {
             image.SetBlendMode(SKBlendMode.SrcOver);
             DrawingChangeHelper.ApplyClipsSymmetriesEtc(target, image, memberGuid, drawOnMask);
-            for (int i = 1; i <= points.Count; i++)
-            {
-                DoDrawingIteration(image, i);
-            }
+            image.EnqueueDrawPixels(confirmedPixels, color, SKBlendMode.Src);
         }
 
         var affChunks = image.FindAffectedChunks();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/ShiftLayer_UpdateableChange.cs

@@ -38,7 +38,7 @@ internal class ShiftLayer_UpdateableChange : UpdateableChange
         return curChunks;
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var chunks = DrawShiftedLayer(target);
         var image = ((Layer)target.FindMemberOrThrow(layerGuid)).LayerImage;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/CreateStructureMemberMask_Change.cs

@@ -20,7 +20,7 @@ internal class CreateStructureMemberMask_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var member = target.FindMemberOrThrow(targetMember);
         if (member.Mask is not null)

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/DeleteStructureMemberMask_Change.cs

@@ -22,7 +22,7 @@ internal class DeleteStructureMemberMask_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var member = target.FindMemberOrThrow(memberGuid);
         if (member.Mask is null)

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/LayerLockTransparency_Change.cs

@@ -25,7 +25,7 @@ internal class LayerLockTransparency_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         ((Layer)target.FindMemberOrThrow(layerGuid)).LockTransparency = newValue;
         ignoreInUndo = false;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberBlendMode_Change.cs

@@ -24,7 +24,7 @@ internal class StructureMemberBlendMode_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var member = target.FindMemberOrThrow(targetGuid);
         member.BlendMode = newBlendMode;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberClipToMemberBelow_Change.cs

@@ -23,7 +23,7 @@ internal class StructureMemberClipToMemberBelow_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var member = target.FindMemberOrThrow(memberGuid);
         member.ClipToMemberBelow = newValue;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberIsVisible_Change.cs

@@ -23,7 +23,7 @@ internal class StructureMemberIsVisible_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         // don't record layer/folder visibility changes - it's just more convenient this way
         ignoreInUndo = true;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberMaskIsVisible_Change.cs

@@ -25,7 +25,7 @@ internal class StructureMemberMaskIsVisible_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var member = target.FindMemberOrThrow(memberGuid);
         member.MaskIsVisible = newMaskIsVisible;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberName_Change.cs

@@ -24,7 +24,7 @@ internal class StructureMemberName_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         target.FindMemberOrThrow(targetMember).Name = newName;
 

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Properties/StructureMemberOpacity_UpdateableChange.cs

@@ -31,9 +31,9 @@ internal class StructureMemberOpacity_UpdateableChange : UpdateableChange
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target) => Apply(target, out _);
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> ApplyTemporarily(Document target) => Apply(target, false, out _);
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document document, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document document, bool firstApply, out bool ignoreInUndo)
     {
         if (originalOpacity == newOpacity)
         {

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Root/ResizeCanvas_Change.cs

@@ -39,7 +39,7 @@ internal class ResizeCanvas_Change : Change
         }
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         target.Size = newSize;
         target.VerticalSymmetryAxisX = Math.Clamp(originalVerAxisX, 0, target.Size.X);

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Root/SymmetryAxisPosition_UpdateableChange.cs

@@ -42,7 +42,7 @@ internal class SymmetryAxisPosition_UpdateableChange : UpdateableChange
             throw new NotImplementedException();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         ignoreInUndo = originalPos == newPos;
         SetPosition(target, newPos);

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Root/SymmetryAxisState_Change.cs

@@ -38,7 +38,7 @@ internal class SymmetryAxisState_Change : Change
             throw new NotImplementedException();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         SetState(target, newEnabled);
         ignoreInUndo = false;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectLasso_UpdateableChange.cs

@@ -44,7 +44,7 @@ internal class SelectLasso_UpdateableChange : UpdateableChange
 
         return new Selection_ChangeInfo(new SKPath(target.Selection.SelectionPath));
     }
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         ignoreInUndo = false;
         return CommonApply(target);

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Selection/SelectRectangle_UpdateableChange.cs

@@ -51,7 +51,7 @@ internal class SelectRectangle_UpdateableChange : UpdateableChange
         return CommonApply(target);
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         var changes = CommonApply(target);
         ignoreInUndo = false;

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Selection/TransformSelectionPath_UpdateableChange.cs

@@ -45,7 +45,7 @@ internal class TransformSelectionPath_UpdateableChange : UpdateableChange
         return new Selection_ChangeInfo(new SKPath(target.Selection.SelectionPath));
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         ignoreInUndo = false;
         return CommonApply(target);

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Structure/CreateStructureMember_Change.cs

@@ -27,7 +27,7 @@ internal class CreateStructureMember_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document document, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document document, bool firstApply, out bool ignoreInUndo)
     {
         var folder = (Folder)document.FindMemberOrThrow(parentFolderGuid);
 

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Structure/DeleteStructureMember_Change.cs

@@ -27,7 +27,7 @@ internal class DeleteStructureMember_Change : Change
         return new Success();
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document document, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document document, bool firstApply, out bool ignoreInUndo)
     {
         var (member, parent) = document.FindChildAndParentOrThrow(memberGuid);
         parent.Children = parent.Children.Remove(member);

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Structure/MoveStructureMember_Change.cs

@@ -40,7 +40,7 @@ internal class MoveStructureMember_Change : Change
         targetFolder.Children = targetFolder.Children.Insert(targetIndex, member);
     }
 
-    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, out bool ignoreInUndo)
+    public override OneOf<None, IChangeInfo, List<IChangeInfo>> Apply(Document target, bool firstApply, out bool ignoreInUndo)
     {
         Move(target, memberGuid, targetFolderGuid, targetFolderIndex);
         ignoreInUndo = false;

+ 3 - 3
src/PixiEditor.ChangeableDocument/DocumentChangeTracker.cs

@@ -130,7 +130,7 @@ public class DocumentChangeTracker : IDisposable
 
         for (int i = 0; i < changePacket.Count; i++)
         {
-            changePacket[i].Apply(document, out _).Switch(
+            changePacket[i].Apply(document, false, out _).Switch(
                 (None _) => { },
                 (IChangeInfo info) => changeInfos.Add(info),
                 (List<IChangeInfo> infos) => changeInfos.AddRange(infos));
@@ -173,7 +173,7 @@ public class DocumentChangeTracker : IDisposable
             return new None();
         }
 
-        var info = change.Apply(document, out bool ignoreInUndo);
+        var info = change.Apply(document, true, out bool ignoreInUndo);
         if (!ignoreInUndo)
             AddToUndo(change);
         else
@@ -217,7 +217,7 @@ public class DocumentChangeTracker : IDisposable
             return new None();
         }
 
-        var info = activeUpdateableChange.Apply(document, out bool ignoreInUndo);
+        var info = activeUpdateableChange.Apply(document, true, out bool ignoreInUndo);
         if (!ignoreInUndo)
             AddToUndo(activeUpdateableChange);
         else

+ 4 - 0
src/PixiEditorPrototype.sln.DotSettings

@@ -8,6 +8,10 @@
 	<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=Xaml_002ERedundantNamespaceAlias/@EntryIndexedValue">SUGGESTION</s:String>
 	<s:Int64 x:Key="/Default/CodeStyle/CodeFormatting/CSharpFormat/BLANK_LINES_AFTER_BLOCK_STATEMENTS/@EntryValue">0</s:Int64>
 	<s:String x:Key="/Default/CodeStyle/Naming/XamlNaming/UserRules/=XAML_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
+	<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean>
 	<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=2CAB0A567F30704CA99AA3EC249E3153/Text/@EntryValue">$HEADER$namespace $NAMESPACE$
 {
   internal class $CLASS$ {$END$}

+ 0 - 16
src/StructureRenderer/RenderInfos/DirtyRect_RenderInfo.cs

@@ -1,16 +0,0 @@
-using ChunkyImageLib.DataHolders;
-
-namespace StructureRenderer.RenderInfos
-{
-    public record struct DirtyRect_RenderInfo : IRenderInfo
-    {
-        public DirtyRect_RenderInfo(Vector2i pos, Vector2i size)
-        {
-            Pos = pos;
-            Size = size;
-        }
-
-        public Vector2i Pos { get; }
-        public Vector2i Size { get; }
-    }
-}

+ 0 - 6
src/StructureRenderer/RenderInfos/IRenderInfo.cs

@@ -1,6 +0,0 @@
-namespace StructureRenderer.RenderInfos
-{
-    public interface IRenderInfo
-    {
-    }
-}

+ 0 - 234
src/StructureRenderer/Renderer.cs

@@ -1,234 +0,0 @@
-using ChangeableDocument;
-using ChangeableDocument.Changeables.Interfaces;
-using ChangeableDocument.ChangeInfos;
-using ChunkyImageLib;
-using ChunkyImageLib.DataHolders;
-using SkiaSharp;
-using StructureRenderer.RenderInfos;
-
-namespace StructureRenderer
-{
-    public class Renderer
-    {
-        private DocumentChangeTracker tracker;
-        private List<Surface> temporarySurfaces = new();
-        private Surface? backSurface;
-        private static SKPaint PaintToDrawChunksWith = new SKPaint() { BlendMode = SKBlendMode.SrcOver };
-        private static SKPaint BlendingPaint = new SKPaint() { BlendMode = SKBlendMode.SrcOver };
-        private static SKPaint ReplacingPaint = new SKPaint() { BlendMode = SKBlendMode.Src };
-        private static SKPaint SelectionPaint = new SKPaint() { BlendMode = SKBlendMode.SrcOver, Color = new(0xa0FFFFFF) };
-        private static SKPaint ClearPaint = new SKPaint() { BlendMode = SKBlendMode.Src, Color = SKColors.Transparent };
-
-        private bool highlightUpdatedChunks = false;
-        private SKPaint highlightPaint = new SKPaint() { BlendMode = SKBlendMode.SrcOver, Color = new(0x30FF0000) };
-
-        public Renderer(DocumentChangeTracker tracker)
-        {
-            this.tracker = tracker;
-        }
-
-        public async Task<List<IRenderInfo>> ProcessChanges(IReadOnlyList<IChangeInfo> changes, SKSurface screenSurface, Vector2i screenSize)
-        {
-            return await Task.Run(() => Render(changes, screenSurface, screenSize)).ConfigureAwait(true);
-        }
-
-        private HashSet<Vector2i>? FindChunksToRerender(IReadOnlyList<IChangeInfo> changes)
-        {
-            HashSet<Vector2i> chunks = new();
-            foreach (var change in changes)
-            {
-                switch (change)
-                {
-                    case LayerImageChunks_ChangeInfo layerImageChunks:
-                        if (layerImageChunks.Chunks == null)
-                            throw new Exception("Chunks must not be null");
-                        chunks.UnionWith(layerImageChunks.Chunks);
-                        break;
-                    case Selection_ChangeInfo selection:
-                        if (tracker.Document.ReadOnlySelection.ReadOnlyIsEmptyAndInactive)
-                        {
-                            return null;
-                        }
-                        else
-                        {
-                            if (selection.Chunks == null)
-                                throw new Exception("Chunks must not be null");
-                            chunks.UnionWith(selection.Chunks);
-                        }
-                        break;
-                    case CreateStructureMember_ChangeInfo:
-                    case DeleteStructureMember_ChangeInfo:
-                    case MoveStructureMember_ChangeInfo:
-                    case Size_ChangeInfo:
-                        return null;
-                    case StructureMemberOpacity_ChangeInfo opacityChangeInfo:
-                        var memberWithOpacity = tracker.Document.FindMemberOrThrow(opacityChangeInfo.GuidValue);
-                        if (memberWithOpacity is IReadOnlyLayer layerWithOpacity)
-                            chunks.UnionWith(layerWithOpacity.ReadOnlyLayerImage.FindAllChunks());
-                        else
-                            return null;
-                        break;
-                    case StructureMemberProperties_ChangeInfo propertiesChangeInfo:
-                        if (!propertiesChangeInfo.IsVisibleChanged)
-                            break;
-                        var memberWithVisibility = tracker.Document.FindMemberOrThrow(propertiesChangeInfo.GuidValue);
-                        if (memberWithVisibility is IReadOnlyLayer layerWithVisibility)
-                            chunks.UnionWith(layerWithVisibility.ReadOnlyLayerImage.FindAllChunks());
-                        else
-                            return null;
-                        break;
-                }
-            }
-            return chunks;
-        }
-
-        private List<IRenderInfo> Render(IReadOnlyList<IChangeInfo> changes, SKSurface screenSurface, Vector2i screenSize)
-        {
-            bool redrawEverything = false;
-            if (backSurface == null || backSurface.Size != screenSize)
-            {
-                backSurface?.Dispose();
-                backSurface = new(screenSize);
-                redrawEverything = true;
-            }
-            HashSet<Vector2i>? chunks = null;
-            if (!redrawEverything)
-                chunks = FindChunksToRerender(changes);
-            if (chunks == null)
-                redrawEverything = true;
-
-            AllocateTempSurfaces(tracker.Document.ReadOnlyStructureRoot);
-
-            List<IRenderInfo> infos = new();
-
-            // draw to back surface
-            if (redrawEverything)
-            {
-                RenderScreen(screenSize, backSurface.SkiaSurface, tracker.Document.ReadOnlyStructureRoot);
-                infos.Add(new DirtyRect_RenderInfo(new Vector2i(0, 0), screenSize));
-            }
-            else
-            {
-                if (highlightUpdatedChunks)
-                {
-                    backSurface.SkiaSurface.Canvas.Clear();
-                    infos.Add(new DirtyRect_RenderInfo(new(0, 0), screenSize));
-                }
-                foreach (var chunkPos in chunks!)
-                {
-                    backSurface.SkiaSurface.Canvas.DrawRect(SKRect.Create(chunkPos * ChunkyImage.ChunkSize, new(ChunkyImage.ChunkSize, ChunkyImage.ChunkSize)), ClearPaint);
-                    RenderChunk(chunkPos, backSurface.SkiaSurface);
-                    infos.Add(new DirtyRect_RenderInfo(
-                        chunkPos * ChunkyImage.ChunkSize,
-                        new(ChunkyImage.ChunkSize, ChunkyImage.ChunkSize)
-                        ));
-                }
-            }
-
-            // transfer the back surface to the screen surface
-
-            foreach (var info in infos)
-            {
-                if (info is DirtyRect_RenderInfo dirtyRect)
-                {
-                    screenSurface.Canvas.Save();
-                    screenSurface.Canvas.ClipRect(SKRect.Create(dirtyRect.Pos, dirtyRect.Size));
-                    screenSurface.Canvas.DrawSurface(backSurface.SkiaSurface, 0, 0, ReplacingPaint);
-                    screenSurface.Canvas.Restore();
-                }
-            }
-
-            return infos;
-        }
-
-        private void RenderScreen(Vector2i screenSize, SKSurface screenSurface, IReadOnlyFolder structureRoot)
-        {
-            int chunksWidth = (int)Math.Ceiling(screenSize.X / (float)ChunkyImage.ChunkSize);
-            int chunksHeight = (int)Math.Ceiling(screenSize.Y / (float)ChunkyImage.ChunkSize);
-            screenSurface.Canvas.Clear();
-            for (int x = 0; x < chunksWidth; x++)
-            {
-                for (int y = 0; y < chunksHeight; y++)
-                {
-                    RenderChunk(new(x, y), screenSurface);
-                }
-            }
-        }
-
-        private void AllocateTempSurfaces(IReadOnlyFolder structureRoot)
-        {
-            int depth = FindDeepestLayerDepth(structureRoot, 0);
-            while (temporarySurfaces.Count < depth)
-            {
-                temporarySurfaces.Add(new Surface(new Vector2i(ChunkyImage.ChunkSize, ChunkyImage.ChunkSize)));
-            }
-        }
-
-        private int FindDeepestLayerDepth(IReadOnlyFolder folder, int folderDepth)
-        {
-            int deepestLayer = -1;
-            foreach (var child in folder.ReadOnlyChildren)
-            {
-                if (child is IReadOnlyLayer layer)
-                {
-                    deepestLayer = folderDepth + 1;
-                }
-                else if (child is IReadOnlyFolder innerFolder)
-                {
-                    deepestLayer = FindDeepestLayerDepth(innerFolder, folderDepth + 1);
-                }
-            }
-            return deepestLayer;
-        }
-
-        private void RenderChunk(Vector2i chunkPos, SKSurface screenSurface)
-        {
-            var renderedSurface = RenderChunkRecursively(chunkPos, 0, tracker.Document.ReadOnlyStructureRoot);
-            if (renderedSurface != null)
-            {
-                if (highlightUpdatedChunks)
-                    renderedSurface.SkiaSurface.Canvas.DrawPaint(highlightPaint);
-                screenSurface.Canvas.DrawSurface(renderedSurface.SkiaSurface, chunkPos * ChunkyImage.ChunkSize, BlendingPaint);
-            }
-
-            if (tracker.Document.ReadOnlySelection.ReadOnlyIsEmptyAndInactive)
-                return;
-            var selectionChunk = tracker.Document.ReadOnlySelection.ReadOnlySelectionImage.GetLatestChunk(chunkPos);
-            if (selectionChunk != null)
-                selectionChunk.DrawOnSurface(screenSurface, chunkPos * ChunkyImage.ChunkSize, SelectionPaint);
-
-        }
-
-        private Surface? RenderChunkRecursively(Vector2i chunkPos, int depth, IReadOnlyFolder folder)
-        {
-            Surface? surface = temporarySurfaces.Count > depth ? temporarySurfaces[depth] : null;
-            surface?.SkiaSurface.Canvas.Clear();
-            foreach (var child in folder.ReadOnlyChildren)
-            {
-                if (!child.IsVisible)
-                    continue;
-                if (child is IReadOnlyLayer layer)
-                {
-                    var chunk = layer.ReadOnlyLayerImage.GetLatestChunk(chunkPos);
-                    if (chunk == null)
-                        continue;
-                    if (surface == null)
-                        throw new Exception("Not enough surfaces have been allocated to draw the entire layer tree");
-                    PaintToDrawChunksWith.Color = new SKColor(255, 255, 255, (byte)Math.Round(child.Opacity * 255));
-                    chunk.DrawOnSurface(surface.SkiaSurface, new(0, 0), PaintToDrawChunksWith);
-                }
-                else if (child is IReadOnlyFolder innerFolder)
-                {
-                    var renderedSurface = RenderChunkRecursively(chunkPos, depth + 1, innerFolder);
-                    if (renderedSurface == null)
-                        continue;
-                    if (surface == null)
-                        throw new Exception("Not enough surfaces have been allocated to draw the entire layer tree");
-                    PaintToDrawChunksWith.Color = new SKColor(255, 255, 255, (byte)Math.Round(child.Opacity * 255));
-                    surface.SkiaSurface.Canvas.DrawSurface(renderedSurface.SkiaSurface, 0, 0, PaintToDrawChunksWith);
-                }
-            }
-            return surface;
-        }
-    }
-}

+ 0 - 14
src/StructureRenderer/StructureRenderer.csproj

@@ -1,14 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net6.0</TargetFramework>
-    <ImplicitUsings>enable</ImplicitUsings>
-    <Nullable>enable</Nullable>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <ProjectReference Include="..\ChangeableDocument\ChangeableDocument.csproj" />
-    <ProjectReference Include="..\ChunkyImageLib\ChunkyImageLib.csproj" />
-  </ItemGroup>
-
-</Project>