Quellcode durchsuchen

Merge pull request #985 from PixiEditor/fixes/22.07.2025

Fixes/22.07.2025
Krzysztof Krysiński vor 1 Monat
Ursprung
Commit
6f7e23fd26

+ 10 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Effects/OutlineNode.cs

@@ -86,11 +86,19 @@ public class OutlineNode : RenderNode, IRenderInput
             using Texture temp = Texture.ForProcessing(surface, context.ProcessingColorSpace);
             int saved = temp.DrawingSurface.Canvas.SaveLayer(paint);
 
-            Background.Value.Paint(context, temp.DrawingSurface);
+            var ctx = context.Clone();
+            ctx.ChunkResolution = ChunkResolution.Full;
+            ctx.RenderOutputSize = (VecI)(context.RenderOutputSize * context.ChunkResolution.InvertedMultiplier());
+
+            Background.Value.Paint(ctx, temp.DrawingSurface);
 
             temp.DrawingSurface.Canvas.RestoreToCount(saved);
 
-            for (int i = 1; i < (int)Thickness.Value; i++)
+            temp.DrawingSurface.Canvas.SetMatrix(Matrix3X3.Identity);
+
+            int thickness = (int)(Thickness.Value * context.ChunkResolution.Multiplier());
+
+            for (int i = 1; i < (int)thickness; i++)
             {
                 saved = temp.DrawingSurface.Canvas.SaveLayer(paint);
 

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

@@ -188,8 +188,8 @@ public class VectorLayerNode : LayerNode, ITransformableObject, IReadOnlyVectorN
     {
         int layer;
         // TODO: This can be further optimized by passing opacity, blend mode and filters directly to the rasterization method
-        if (paint.Color.A < 255 || paint.ColorFilter != null || paint.ImageFilter != null || paint.Shader != null ||
-            paint.BlendMode != Drawie.Backend.Core.Surfaces.BlendMode.SrcOver)
+        if (paint != null && (paint.Color.A < 255 || paint.ColorFilter != null || paint.ImageFilter != null || paint.Shader != null ||
+            paint.BlendMode != Drawie.Backend.Core.Surfaces.BlendMode.SrcOver))
         {
             layer = surface.Canvas.SaveLayer(paint);
         }

+ 10 - 1
src/PixiEditor.ChangeableDocument/Rendering/RenderContext.cs

@@ -12,7 +12,7 @@ public class RenderContext
     public double Opacity { get; set; }
 
     public KeyFrameTime FrameTime { get; }
-    public ChunkResolution ChunkResolution { get; }
+    public ChunkResolution ChunkResolution { get; set; }
     public VecI RenderOutputSize { get; set; }
 
     public VecI DocumentSize { get; set; }
@@ -60,4 +60,13 @@ public class RenderContext
             _ => DrawingApiBlendMode.SrcOver,
         };
     }
+
+    public RenderContext Clone()
+    {
+        return new RenderContext(RenderSurface, FrameTime, ChunkResolution, RenderOutputSize, DocumentSize, ProcessingColorSpace, Opacity)
+        {
+            FullRerender = FullRerender,
+            TargetOutput = TargetOutput
+        };
+    }
 }

+ 20 - 7
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/TransformSelectedExecutor.cs

@@ -166,17 +166,30 @@ internal class TransformSelectedExecutor : UpdateableChangeExecutor, ITransforma
             }
         }
 
-        var topMostWithinClick = QueryLayers<ILayerHandler>(args.PositionOnCanvas);
+        var topMostWithinClick = QueryLayers<IStructureMemberHandler>(args.PositionOnCanvas);
 
-        var nonSelected = topMostWithinClick.Where(x => x != document.SelectedStructureMember
-                                                        && !document.SoftSelectedStructureMembers.Contains(x))
-            .ToArray();
+        var orderedBySize = topMostWithinClick
+            .Where(x => x.TightBounds is not null)
+            .OrderByDescending(x => x.TightBounds?.Size.Length + (x is IFolderHandler ? 1 : 0) ?? double.MaxValue)
+            .ToList();
+
+        var nonSelected = orderedBySize.Where(x => x != document.SelectedStructureMember
+                                              && !document.SoftSelectedStructureMembers.Contains(x));
+
+        var smallestSizeDifferenceList = nonSelected
+            .Where(x => x.TightBounds is not null && (x.TightBounds.Value.Size.Length + (x is IFolderHandler ? 1 : 0)) <= (document.SelectedStructureMember?.TightBounds?.Size.Length ?? double.MaxValue))
+            .ToList();
+
+        if (!smallestSizeDifferenceList.Any() && orderedBySize.Count != 0)
+        {
+            smallestSizeDifferenceList.Add(orderedBySize.First());
+        }
 
         bool isHoldingShift = args.KeyModifiers.HasFlag(KeyModifiers.Shift);
 
-        if (nonSelected.Any())
+        if (smallestSizeDifferenceList.Any())
         {
-            var topMost = nonSelected.First();
+            var topMost = smallestSizeDifferenceList.First();
 
             if (!isHoldingShift)
             {
@@ -220,7 +233,7 @@ internal class TransformSelectedExecutor : UpdateableChangeExecutor, ITransforma
         DuplicateIfRequired();
     }
 
-    private void Deselect(List<ILayerHandler> topMostWithinClick)
+    private void Deselect(List<IStructureMemberHandler> topMostWithinClick)
     {
         var topMost = topMostWithinClick.FirstOrDefault();
         if (topMost is not null)

+ 5 - 5
src/PixiEditor/Models/DocumentModels/UpdateableChangeExecutors/UpdateableChangeExecutor.cs

@@ -63,9 +63,9 @@ internal abstract class UpdateableChangeExecutor
     public virtual void OnColorChanged(Color color, bool primary) { }
     public virtual void OnMembersSelected(List<Guid> memberGuids) { }
 
-    protected T[] QueryLayers<T>(VecD pos) where T : ILayerHandler
+    protected T[] QueryLayers<T>(VecD pos) where T : IStructureMemberHandler
     {
-        var allLayers = document.StructureHelper.GetAllLayers();
+        var allLayers = document.StructureHelper.GetAllMembers();
         FilterOutInvisible(allLayers);
         var topMostWithinClick = allLayers.Where(x =>
                 x is T { TightBounds: not null } &&
@@ -74,11 +74,11 @@ internal abstract class UpdateableChangeExecutor
         return topMostWithinClick.Cast<T>().ToArray();
     }
 
-    private void FilterOutInvisible(List<ILayerHandler> allLayers)
+    private void FilterOutInvisible(List<IStructureMemberHandler> allLayers)
     {
-        allLayers.RemoveAll(x => x is ILayerHandler { IsVisibleBindable: false });
+        allLayers.RemoveAll(x => x is IStructureMemberHandler { IsVisibleBindable: false });
 
-        List<ILayerHandler> toRemove = new List<ILayerHandler>();
+        List<IStructureMemberHandler> toRemove = new List<IStructureMemberHandler>();
         foreach (var layer in allLayers)
         {
             var parents = document.StructureHelper.GetParents(layer.Id);

+ 12 - 1
src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -369,7 +369,18 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         if (!typeof(ToolViewModel).IsAssignableFrom(toolType))
             throw new ArgumentException($"'{toolType}' does not inherit from {typeof(ToolViewModel)}");
         IToolHandler foundTool = ActiveToolSet!.Tools.FirstOrDefault(x => x.GetType().IsAssignableFrom(toolType));
-        if (foundTool == null) return;
+        if (foundTool == null)
+        {
+            foundTool = allTools.FirstOrDefault(x => x.GetType().IsAssignableFrom(toolType));
+            if(foundTool == null)
+                return;
+
+            var toolset = AllToolSets.FirstOrDefault(x => x.Tools.Contains(foundTool));
+            if (toolset is not null)
+            {
+                SetActiveToolSet(toolset);
+            }
+        }
 
         SetActiveTool(foundTool, transient, sourceInfo);
     }

+ 1 - 3
src/PixiEditor/Views/Overlays/PathOverlay/VectorPathOverlay.cs

@@ -148,11 +148,9 @@ public class VectorPathOverlay : Overlay
                 }
 
                 var handle = anchorHandles[anchorIndex];
-                var nextIndex = subPath.GetNextPoint(anchorIndex).Index;
+                var nextIndex = subPath.GetNextPoint(anchorIndex)?.Index ?? 0;
                 bool nextIsSelected = nextIndex < anchorHandles.Count &&
                                       anchorHandles[nextIndex].IsSelected;
-                bool previousIsSelected = anchorIndex - 1 >= 0 &&
-                                          anchorHandles[anchorIndex - 1].IsSelected;
                 bool drawControl1 = handle.IsSelected;
                 bool drawControl2 = nextIsSelected;