Browse Source

Merge pull request #934 from PixiEditor/fixes/09.05.2025

Fixes/09.05.2025
Krzysztof Krysiński 3 months ago
parent
commit
0320cf44fc

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit aa536e8bd572941f77c75755ad918eb09677712f
+Subproject commit c53ef1e999160717ec52c9149a74d41d86da721b

+ 4 - 7
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/Matrix3X3BaseNode.cs

@@ -13,8 +13,6 @@ public abstract class Matrix3X3BaseNode : RenderNode, IRenderInput
     public InputProperty<Matrix3X3> Input { get; }
     public InputProperty<Matrix3X3> Input { get; }
     public OutputProperty<Matrix3X3> Matrix { get; }
     public OutputProperty<Matrix3X3> Matrix { get; }
 
 
-    private Paint? paint;
-
     public Matrix3X3BaseNode()
     public Matrix3X3BaseNode()
     {
     {
         Background = CreateRenderInput("Background", "IMAGE");
         Background = CreateRenderInput("Background", "IMAGE");
@@ -30,19 +28,18 @@ public abstract class Matrix3X3BaseNode : RenderNode, IRenderInput
         if (Background.Value == null)
         if (Background.Value == null)
             return;
             return;
 
 
-        paint ??= new();
         base.OnExecute(context);
         base.OnExecute(context);
     }
     }
 
 
     protected override void OnPaint(RenderContext context, DrawingSurface surface)
     protected override void OnPaint(RenderContext context, DrawingSurface surface)
     {
     {
-        if (paint == null)
-            return;
-
         int layer = surface.Canvas.Save();
         int layer = surface.Canvas.Save();
 
 
         surface.Canvas.SetMatrix(surface.Canvas.TotalMatrix.Concat(Matrix.Value));
         surface.Canvas.SetMatrix(surface.Canvas.TotalMatrix.Concat(Matrix.Value));
-        Background.Value?.Paint(context, surface);
+        if (!surface.LocalClipBounds.IsZeroOrNegativeArea)
+        {
+            Background.Value?.Paint(context, surface);
+        }
 
 
         surface.Canvas.RestoreToCount(layer);
         surface.Canvas.RestoreToCount(layer);
     }
     }

+ 3 - 32
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Matrix/TransformNode.cs

@@ -7,40 +7,11 @@ using PixiEditor.ChangeableDocument.Rendering;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
 namespace PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Matrix;
 
 
 [NodeInfo("Transform")]
 [NodeInfo("Transform")]
-public class TransformNode : RenderNode, IRenderInput
+public class TransformNode : Matrix3X3BaseNode
 {
 {
-    public RenderInputProperty Background { get; }
-    public InputProperty<Matrix3X3> Matrix { get; }
-
-    public TransformNode()
-    {
-        Background = CreateRenderInput("Background", "IMAGE");
-        Matrix = CreateInput("Matrix", "INPUT_MATRIX", Matrix3X3.Identity);
-
-        Output.FirstInChain = null;
-    }
-
-    protected override void OnPaint(RenderContext context, DrawingSurface surface)
-    {
-        if (Background.Value == null)
-            return;
-
-        int layer = surface.Canvas.Save();
-
-        surface.Canvas.SetMatrix(surface.Canvas.TotalMatrix.PostConcat(Matrix.Value));
-        Background.Value?.Paint(context, surface);
-
-        surface.Canvas.RestoreToCount(layer);
-    }
-
-    public override RectD? GetPreviewBounds(int frame, string elementToRenderName = "")
-    {
-        return null;
-    }
-
-    public override bool RenderPreview(DrawingSurface renderOn, RenderContext context, string elementToRenderName)
+    protected override Matrix3X3 CalculateMatrix(Matrix3X3 input)
     {
     {
-        return false;
+        return Input.Value;
     }
     }
 
 
     public override Node CreateCopy()
     public override Node CreateCopy()

+ 17 - 2
src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs

@@ -5,10 +5,12 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core;
+using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.ImageData;
 using Drawie.Backend.Core.Surfaces.ImageData;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Text;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.ChangeableDocument.Rendering;
 namespace PixiEditor.ChangeableDocument.Rendering;
@@ -238,9 +240,22 @@ public class DocumentRenderer : IPreviewRenderable, IDisposable
             context.TargetOutput = customOutput;
             context.TargetOutput = customOutput;
         }
         }
 
 
-        graph.Execute(context);
+        try
+        {
+            graph.Execute(context);
+            toRenderOn.Canvas.DrawSurface(renderTexture.DrawingSurface, 0, 0);
+        }
+        catch (Exception e)
+        {
+            renderTexture.DrawingSurface.Canvas.Clear();
+            using Paint paint = new Paint { Color = Colors.White, IsAntiAliased = true };
+
+            using Font defaultSizedFont = Font.CreateDefault();
+            defaultSizedFont.Size = 24;
 
 
-        toRenderOn.Canvas.DrawSurface(renderTexture.DrawingSurface, 0, 0);
+            renderTexture.DrawingSurface.Canvas.DrawText("Graph Setup produced an error. Fix it the node graph",
+                renderTexture.Size / 2f, TextAlign.Center, defaultSizedFont, paint);
+        }
 
 
         renderTexture.DrawingSurface.Canvas.Restore();
         renderTexture.DrawingSurface.Canvas.Restore();
         toRenderOn.Canvas.Restore();
         toRenderOn.Canvas.Restore();

+ 2 - 1
src/PixiEditor/Data/Localization/Languages/en.json

@@ -1035,5 +1035,6 @@
   "RESET": "Reset",
   "RESET": "Reset",
   "AUTOSAVE_OPEN_FOLDER": "Open autosave folder",
   "AUTOSAVE_OPEN_FOLDER": "Open autosave folder",
    "AUTOSAVE_OPEN_FOLDER_DESCRIPTIVE": "Open the folder where autosaves are stored",
    "AUTOSAVE_OPEN_FOLDER_DESCRIPTIVE": "Open the folder where autosaves are stored",
-  "AUTOSAVE_TOGGLE_DESCRIPTIVE": "Enable/disable autosave"
+  "AUTOSAVE_TOGGLE_DESCRIPTIVE": "Enable/disable autosave",
+  "ERROR_GRAPH": "Graph Setup produced an error. Fix it the node graph"
 }
 }

+ 3 - 1
src/PixiEditor/Models/Rendering/SceneRenderer.cs

@@ -37,7 +37,8 @@ internal class SceneRenderer : IDisposable
 
 
     public void RenderScene(DrawingSurface target, ChunkResolution resolution, string? targetOutput = null)
     public void RenderScene(DrawingSurface target, ChunkResolution resolution, string? targetOutput = null)
     {
     {
-        if (Document.Renderer.IsBusy || DocumentViewModel.Busy || target.DeviceClipBounds.Size.ShortestAxis <= 0) return;
+        if (Document.Renderer.IsBusy || DocumentViewModel.Busy ||
+            target.DeviceClipBounds.Size.ShortestAxis <= 0) return;
         RenderOnionSkin(target, resolution, targetOutput);
         RenderOnionSkin(target, resolution, targetOutput);
 
 
         string adjustedTargetOutput = targetOutput ?? "";
         string adjustedTargetOutput = targetOutput ?? "";
@@ -80,6 +81,7 @@ internal class SceneRenderer : IDisposable
         else
         else
         {
         {
             renderTexture = Texture.ForProcessing(renderTarget.DeviceClipBounds.Size, Document.ProcessingColorSpace);
             renderTexture = Texture.ForProcessing(renderTarget.DeviceClipBounds.Size, Document.ProcessingColorSpace);
+
             renderTarget = renderTexture.DrawingSurface;
             renderTarget = renderTexture.DrawingSurface;
 
 
             target.Canvas.Save();
             target.Canvas.Save();

+ 3 - 3
src/PixiEditor/ViewModels/Document/AnimationDataViewModel.cs

@@ -108,7 +108,7 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
         }
         }
     }
     }
 
 
-    public int FirstFrame => cachedFirstFrame ??= keyFrames.Count > 0 ? keyFrames.Min(x => x.StartFrameBindable) : 0;
+    public int FirstFrame => cachedFirstFrame ??= keyFrames.Count > 0 ? keyFrames.Min(x => x.StartFrameBindable) : 1;
 
 
     public int LastFrame => cachedLastFrame ??= keyFrames.Count > 0
     public int LastFrame => cachedLastFrame ??= keyFrames.Count > 0
         ? keyFrames.Max(x => x.StartFrameBindable + x.DurationBindable)
         ? keyFrames.Max(x => x.StartFrameBindable + x.DurationBindable)
@@ -428,14 +428,14 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
 
 
     public int GetFirstVisibleFrame()
     public int GetFirstVisibleFrame()
     {
     {
-        return keyFrames.Count > 0 ? keyFrames.Where(x => x.IsVisible).Min(x => x.StartFrameBindable) : 0;
+        return keyFrames.Count > 0 ? keyFrames.Where(x => x.IsVisible).Min(x => x.StartFrameBindable) : 1;
     }
     }
 
 
     public int GetLastVisibleFrame()
     public int GetLastVisibleFrame()
     {
     {
         return keyFrames.Count > 0
         return keyFrames.Count > 0
             ? keyFrames.Where(x => x.IsVisible).Max(x => x.StartFrameBindable + x.DurationBindable)
             ? keyFrames.Where(x => x.IsVisible).Max(x => x.StartFrameBindable + x.DurationBindable)
-            : 0;
+            : DefaultEndFrame;
     }
     }
 
 
     public int GetVisibleFramesCount()
     public int GetVisibleFramesCount()

+ 4 - 18
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -966,9 +966,10 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
                 if (!includeNested)
                 if (!includeNested)
                 {
                 {
                     var parents = StructureHelper.GetParents(member.Id);
                     var parents = StructureHelper.GetParents(member.Id);
-                    if(parents.Any(x => selectedMembers.Contains(x.Id)))
+                    if (parents.Any(x => selectedMembers.Contains(x.Id)))
                         continue;
                         continue;
                 }
                 }
+
                 orderedMembers.Add(member.Id);
                 orderedMembers.Add(member.Id);
             }
             }
         }
         }
@@ -1035,9 +1036,6 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
 
 
     public Image[] RenderFrames(Func<Surface, Surface> processFrameAction = null, CancellationToken token = default)
     public Image[] RenderFrames(Func<Surface, Surface> processFrameAction = null, CancellationToken token = default)
     {
     {
-        if (AnimationDataViewModel.KeyFrames.Count == 0)
-            return [];
-
         if (token.IsCancellationRequested)
         if (token.IsCancellationRequested)
             return [];
             return [];
 
 
@@ -1081,9 +1079,6 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     /// <param name="token"></param>
     /// <param name="token"></param>
     public void RenderFramesProgressive(Action<Surface, int> processFrameAction, CancellationToken token)
     public void RenderFramesProgressive(Action<Surface, int> processFrameAction, CancellationToken token)
     {
     {
-        if (AnimationDataViewModel.KeyFrames.Count == 0)
-            return;
-
         int firstFrame = AnimationDataViewModel.GetFirstVisibleFrame();
         int firstFrame = AnimationDataViewModel.GetFirstVisibleFrame();
         int framesCount = AnimationDataViewModel.GetLastVisibleFrame();
         int framesCount = AnimationDataViewModel.GetLastVisibleFrame();
         int lastFrame = firstFrame + framesCount;
         int lastFrame = firstFrame + framesCount;
@@ -1110,17 +1105,8 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
 
 
     public bool RenderFrames(List<Image> frames, Func<Surface, Surface> processFrameAction = null)
     public bool RenderFrames(List<Image> frames, Func<Surface, Surface> processFrameAction = null)
     {
     {
-        var keyFrames = AnimationDataViewModel.KeyFrames;
-        int firstFrame = 0;
-        int lastFrame = AnimationDataViewModel.GetVisibleFramesCount();
-
-        lastFrame = Math.Max(1, lastFrame);
-
-        if (keyFrames.Count > 0)
-        {
-            firstFrame = AnimationDataViewModel.GetFirstVisibleFrame();
-            lastFrame = AnimationDataViewModel.GetLastVisibleFrame();
-        }
+        var firstFrame = AnimationDataViewModel.GetFirstVisibleFrame();
+        var lastFrame = AnimationDataViewModel.GetLastVisibleFrame();
 
 
         for (int i = firstFrame; i < lastFrame; i++)
         for (int i = firstFrame; i < lastFrame; i++)
         {
         {

+ 5 - 0
src/PixiEditor/ViewModels/SubViewModels/IoViewModel.cs

@@ -199,6 +199,11 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
             Owner.ToolsSubViewModel.HandleToolShortcutUp();
             Owner.ToolsSubViewModel.HandleToolShortcutUp();
         }
         }
 
 
+        if (shortcut.Key == queuedTransientKey)
+        {
+            queuedTransientKey = null;
+        }
+
         ShortcutController.UnblockShortcutExecution("ShortcutDown");
         ShortcutController.UnblockShortcutExecution("ShortcutDown");
     }
     }
 
 

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

@@ -567,7 +567,10 @@ public class VectorPathOverlay : Overlay
         {
         {
             Path = new VectorPath();
             Path = new VectorPath();
             Path.MoveTo((VecF)point);
             Path.MoveTo((VecF)point);
-            SelectAnchor(anchorHandles[0]);
+            if (anchorHandles.Count > 0)
+            {
+                SelectAnchor(anchorHandles[0]);
+            }
         }
         }
         else
         else
         {
         {

+ 23 - 2
src/PixiEditor/Views/Rendering/Scene.cs

@@ -19,6 +19,7 @@ using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Shaders;
 using Drawie.Backend.Core.Shaders;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Backend.Core.Text;
 using Drawie.Interop.Avalonia.Core;
 using Drawie.Interop.Avalonia.Core;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
@@ -27,12 +28,14 @@ using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Rendering;
 using PixiEditor.Models.Rendering;
 using Drawie.Numerics;
 using Drawie.Numerics;
 using Drawie.Skia;
 using Drawie.Skia;
+using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.ViewModels.Document;
 using PixiEditor.ViewModels.Document;
 using PixiEditor.Views.Overlays;
 using PixiEditor.Views.Overlays;
 using PixiEditor.Views.Overlays.Pointers;
 using PixiEditor.Views.Overlays.Pointers;
 using PixiEditor.Views.Visuals;
 using PixiEditor.Views.Visuals;
 using Bitmap = Drawie.Backend.Core.Surfaces.Bitmap;
 using Bitmap = Drawie.Backend.Core.Surfaces.Bitmap;
 using Color = Drawie.Backend.Core.ColorsImpl.Color;
 using Color = Drawie.Backend.Core.ColorsImpl.Color;
+using Colors = Drawie.Backend.Core.ColorsImpl.Colors;
 using Point = Avalonia.Point;
 using Point = Avalonia.Point;
 using TileMode = Drawie.Backend.Core.Surfaces.TileMode;
 using TileMode = Drawie.Backend.Core.Surfaces.TileMode;
 
 
@@ -297,8 +300,26 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
     {
     {
         DrawCheckerboard(renderTexture.DrawingSurface, bounds);
         DrawCheckerboard(renderTexture.DrawingSurface, bounds);
         DrawOverlays(renderTexture.DrawingSurface, bounds, OverlayRenderSorting.Background);
         DrawOverlays(renderTexture.DrawingSurface, bounds, OverlayRenderSorting.Background);
-        SceneRenderer.RenderScene(renderTexture.DrawingSurface, CalculateResolution(),
-            RenderOutput == "DEFAULT" ? null : RenderOutput);
+        try
+        {
+            SceneRenderer.RenderScene(renderTexture.DrawingSurface, CalculateResolution(),
+                RenderOutput == "DEFAULT" ? null : RenderOutput);
+        }
+        catch (Exception e)
+        {
+            renderTexture.DrawingSurface.Canvas.Clear();
+            using Paint paint = new Paint
+            {
+                Color = Colors.White,
+                IsAntiAliased = true
+            };
+
+            using Font defaultSizedFont = Font.CreateDefault();
+            defaultSizedFont.Size = 24;
+
+            renderTexture.DrawingSurface.Canvas.DrawText(new LocalizedString("ERROR_GRAPH"), renderTexture.Size / 2f, TextAlign.Center, defaultSizedFont, paint);
+        }
+
         DrawOverlays(renderTexture.DrawingSurface, bounds, OverlayRenderSorting.Foreground);
         DrawOverlays(renderTexture.DrawingSurface, bounds, OverlayRenderSorting.Foreground);
     }
     }