Browse Source

Added onion frame settings

flabbet 1 year ago
parent
commit
379fef99ee

+ 3 - 2
src/PixiEditor.UI.Common/Controls/FlyoutPresenter.axaml

@@ -4,9 +4,10 @@
                 TargetType="FlyoutPresenter">
                 TargetType="FlyoutPresenter">
     <Setter Property="HorizontalContentAlignment" Value="Stretch" />
     <Setter Property="HorizontalContentAlignment" Value="Stretch" />
     <Setter Property="VerticalContentAlignment" Value="Stretch" />
     <Setter Property="VerticalContentAlignment" Value="Stretch" />
-    <Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" />
-    <Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}" />
+    <Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush1}" />
+    <Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderHighBrush}" />
     <Setter Property="BorderThickness" Value="1" />
     <Setter Property="BorderThickness" Value="1" />
+    <Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}"/>
     <Setter Property="Padding" Value="4" />
     <Setter Property="Padding" Value="4" />
     <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
     <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
     <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
     <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />

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

@@ -721,5 +721,6 @@
   "SELECT_FILE_FORMAT": "Select file format",
   "SELECT_FILE_FORMAT": "Select file format",
   "SELECT_FILE_FORMAT_DESCRIPTION": "Multiple file types of the same format are supported. Please select the one you want to use.",
   "SELECT_FILE_FORMAT_DESCRIPTION": "Multiple file types of the same format are supported. Please select the one you want to use.",
   "NEW_PALETTE_FILE": "palette",
   "NEW_PALETTE_FILE": "palette",
-  "ISLAND_EXAMPLE": "Islands"
-}
+  "ISLAND_EXAMPLE": "Islands",
+  "ONION_FRAMES_COUNT": "Onion frames"
+}

+ 8 - 0
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -199,6 +199,9 @@ internal class DocumentUpdater
             case FrameRate_ChangeInfo info:
             case FrameRate_ChangeInfo info:
                 ProcessFrameRate(info);
                 ProcessFrameRate(info);
                 break;
                 break;
+            case SetOnionFrames_PassthroughAction info:
+                ProcessSetOnionFrames(info);
+                break;
         }
         }
     }
     }
 
 
@@ -614,4 +617,9 @@ internal class DocumentUpdater
     {
     {
         doc.AnimationHandler.SetFrameRate(info.NewFrameRate);
         doc.AnimationHandler.SetFrameRate(info.NewFrameRate);
     }
     }
+    
+    private void ProcessSetOnionFrames(SetOnionFrames_PassthroughAction info)
+    {
+        doc.AnimationHandler.SetOnionFrames(info.Frames);
+    }
 }
 }

+ 6 - 0
src/PixiEditor/Models/DocumentPassthroughActions/SetOnionFrames_PassthroughAction.cs

@@ -0,0 +1,6 @@
+using PixiEditor.ChangeableDocument.Actions;
+using PixiEditor.ChangeableDocument.ChangeInfos;
+
+namespace PixiEditor.Models.DocumentPassthroughActions;
+
+public record SetOnionFrames_PassthroughAction(int Frames) : IChangeInfo, IAction;

+ 2 - 0
src/PixiEditor/Models/Handlers/IAnimationHandler.cs

@@ -8,6 +8,7 @@ internal interface IAnimationHandler
     public int ActiveFrameBindable { get; set; }
     public int ActiveFrameBindable { get; set; }
     public KeyFrameTime ActiveFrameTime { get; }
     public KeyFrameTime ActiveFrameTime { get; }
     public bool OnionSkinningEnabledBindable { get; set; }
     public bool OnionSkinningEnabledBindable { get; set; }
+    public int OnionFramesBindable { get; set; }
     public void CreateRasterKeyFrame(Guid targetLayerGuid, int frame, Guid? toCloneFrom = null, int? frameToCopyFrom = null);
     public void CreateRasterKeyFrame(Guid targetLayerGuid, int frame, Guid? toCloneFrom = null, int? frameToCopyFrom = null);
     public void SetFrameRate(int newFrameRate);
     public void SetFrameRate(int newFrameRate);
     public void SetActiveFrame(int newFrame);
     public void SetActiveFrame(int newFrame);
@@ -22,4 +23,5 @@ internal interface IAnimationHandler
     public void SetOnionSkinning(bool enabled);
     public void SetOnionSkinning(bool enabled);
     public int FirstFrame { get; }
     public int FirstFrame { get; }
     public int LastFrame { get; }
     public int LastFrame { get; }
+    public void SetOnionFrames(int frames);
 }
 }

+ 3 - 0
src/PixiEditor/Models/Rendering/AffectedAreasGatherer.cs

@@ -140,6 +140,9 @@ internal class AffectedAreasGatherer
                 case ToggleOnionSkinning_PassthroughAction:
                 case ToggleOnionSkinning_PassthroughAction:
                     AddWholeCanvasToMainImage();
                     AddWholeCanvasToMainImage();
                     break;
                     break;
+                case SetOnionFrames_PassthroughAction:
+                    AddWholeCanvasToMainImage();
+                    break;
             }
             }
         }
         }
     }
     }

+ 37 - 18
src/PixiEditor/Models/Rendering/CanvasUpdater.cs

@@ -7,6 +7,7 @@ using ChunkyImageLib.Operations;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Core.Surfaces.ImageData;
 using PixiEditor.DrawingApi.Core.Surfaces.ImageData;
@@ -20,11 +21,14 @@ namespace PixiEditor.Models.Rendering;
 #nullable enable
 #nullable enable
 internal class CanvasUpdater
 internal class CanvasUpdater
 {
 {
+    private const int NearestOnionFrameAlpha = 129;
+
     private readonly IDocument doc;
     private readonly IDocument doc;
     private readonly DocumentInternalParts internals;
     private readonly DocumentInternalParts internals;
 
 
     private Dictionary<int, Texture> renderedFramesCache = new();
     private Dictionary<int, Texture> renderedFramesCache = new();
     private int lastRenderedFrameNumber = -1;
     private int lastRenderedFrameNumber = -1;
+    private int lastOnionKeyFrames = -1;
 
 
     private static readonly Paint ReplacingPaint = new() { BlendMode = BlendMode.Src };
     private static readonly Paint ReplacingPaint = new() { BlendMode = BlendMode.Src };
 
 
@@ -161,6 +165,9 @@ internal class CanvasUpdater
     {
     {
         Dictionary<ChunkResolution, HashSet<VecI>> chunksToRerender =
         Dictionary<ChunkResolution, HashSet<VecI>> chunksToRerender =
             FindGlobalChunksToRerender(chunkGatherer, rerenderDelayed);
             FindGlobalChunksToRerender(chunkGatherer, rerenderDelayed);
+        
+        ChunkResolution onionSkinResolution = chunksToRerender.Min(x => x.Key);
+        UpdateOnionSkinning(doc.Surfaces[onionSkinResolution]);
 
 
         bool updatingStoredChunks = false;
         bool updatingStoredChunks = false;
         foreach (var (res, stored) in affectedAndNonRerenderedChunks)
         foreach (var (res, stored) in affectedAndNonRerenderedChunks)
@@ -197,9 +204,6 @@ internal class CanvasUpdater
         if (chunksToRerender.Count == 0)
         if (chunksToRerender.Count == 0)
             return;
             return;
 
 
-        ChunkResolution onionSkinResolution = chunksToRerender.Min(x => x.Key);
-        UpdateOnionSkinning(doc.Surfaces[onionSkinResolution]);
-
         foreach (var (resolution, chunks) in chunksToRerender)
         foreach (var (resolution, chunks) in chunksToRerender)
         {
         {
             int chunkSize = resolution.PixelSize();
             int chunkSize = resolution.PixelSize();
@@ -235,10 +239,12 @@ internal class CanvasUpdater
                 UpdateLastRenderedFrame(lastRendered, lastRenderedFrameNumber);
                 UpdateLastRenderedFrame(lastRendered, lastRenderedFrameNumber);
             }
             }
 
 
-            if (lastRenderedFrameNumber != doc.AnimationHandler.ActiveFrameBindable)
+            if (lastRenderedFrameNumber != doc.AnimationHandler.ActiveFrameBindable || doc.AnimationHandler.OnionFramesBindable != lastOnionKeyFrames)
             {
             {
-                int previousFrameIndex = doc.AnimationHandler.ActiveFrameBindable - 1;
-                int nextFrameIndex = doc.AnimationHandler.ActiveFrameBindable + 1;
+                int framesToRender = doc.AnimationHandler.OnionFramesBindable;
+                using Paint onionPaint = new Paint();
+                onionPaint.Color = new Color(0, 0, 0, NearestOnionFrameAlpha);
+                onionPaint.BlendMode = BlendMode.SrcOver;
 
 
                 if (doc.Renderer.OnionSkinTexture == null || doc.Renderer.OnionSkinTexture.Size != doc.SizeBindable)
                 if (doc.Renderer.OnionSkinTexture == null || doc.Renderer.OnionSkinTexture.Size != doc.SizeBindable)
                 {
                 {
@@ -248,21 +254,34 @@ internal class CanvasUpdater
 
 
                 doc.Renderer.OnionSkinTexture.DrawingSurface.Canvas.Clear();
                 doc.Renderer.OnionSkinTexture.DrawingSurface.Canvas.Clear();
 
 
-                if (!renderedFramesCache.ContainsKey(previousFrameIndex))
-                {
-                    RenderNextOnionSkinningFrame(previousFrameIndex);
-                }
+                float alphaFaloffMultiplier = 1f / framesToRender;
 
 
-                if (!renderedFramesCache.ContainsKey(nextFrameIndex))
+                for (int i = 1; i <= framesToRender; i++)
                 {
                 {
-                    RenderNextOnionSkinningFrame(nextFrameIndex);
-                }
+                    int previousFrameIndex = doc.AnimationHandler.ActiveFrameBindable - i;
+                    int nextFrameIndex = doc.AnimationHandler.ActiveFrameBindable + i;
 
 
-                DrawOnionSkinningFrame(previousFrameIndex, doc.Renderer.OnionSkinTexture);
-                DrawOnionSkinningFrame(nextFrameIndex, doc.Renderer.OnionSkinTexture);
+                    if (!renderedFramesCache.ContainsKey(previousFrameIndex))
+                    {
+                        RenderNextOnionSkinningFrame(previousFrameIndex);
+                    }
+
+                    if (!renderedFramesCache.ContainsKey(nextFrameIndex))
+                    {
+                        RenderNextOnionSkinningFrame(nextFrameIndex);
+                    }
+
+                    DrawOnionSkinningFrame(previousFrameIndex, doc.Renderer.OnionSkinTexture, onionPaint);
+                    DrawOnionSkinningFrame(nextFrameIndex, doc.Renderer.OnionSkinTexture, onionPaint);
+
+                    onionPaint.Color = onionPaint.Color.WithAlpha((byte)(NearestOnionFrameAlpha -
+                                                                         (NearestOnionFrameAlpha *
+                                                                          alphaFaloffMultiplier * i)));
+                }
             }
             }
 
 
             lastRenderedFrameNumber = doc.AnimationHandler.ActiveFrameBindable;
             lastRenderedFrameNumber = doc.AnimationHandler.ActiveFrameBindable;
+            lastOnionKeyFrames = doc.AnimationHandler.OnionFramesBindable;
         }
         }
     }
     }
 
 
@@ -294,14 +313,14 @@ internal class CanvasUpdater
         }
         }
     }
     }
 
 
-    private void DrawOnionSkinningFrame(int frameIndex, Texture onionSkinTexture)
+    private void DrawOnionSkinningFrame(int frameIndex, Texture onionSkinTexture, Paint paint)
     {
     {
         if (frameIndex < 1 || frameIndex >= doc.AnimationHandler.LastFrame)
         if (frameIndex < 1 || frameIndex >= doc.AnimationHandler.LastFrame)
             return;
             return;
-        
+
         if (renderedFramesCache.TryGetValue(frameIndex, out var frame))
         if (renderedFramesCache.TryGetValue(frameIndex, out var frame))
         {
         {
-            onionSkinTexture.DrawingSurface.Canvas.DrawSurface(frame.DrawingSurface, 0, 0);
+            onionSkinTexture.DrawingSurface.Canvas.DrawSurface(frame.DrawingSurface, 0, 0, paint);
         }
         }
     }
     }
 
 

+ 32 - 11
src/PixiEditor/Styles/Templates/Timeline.axaml

@@ -25,11 +25,34 @@
                         <ColumnDefinition Width="*" />
                         <ColumnDefinition Width="*" />
                     </Grid.ColumnDefinitions>
                     </Grid.ColumnDefinitions>
 
 
-                    <Border Grid.Row="0" Grid.Column="0" BorderThickness="0 0 1 0"
+                    <Border DockPanel.Dock="Left" BorderThickness="0 0 1 0"
                             BorderBrush="{DynamicResource ThemeBorderMidBrush}">
                             BorderBrush="{DynamicResource ThemeBorderMidBrush}">
-                        <input:SizeInput Unit="FPS"
-                                         Width="80" Height="25" HorizontalAlignment="Left"
-                                         Size="{Binding Fps, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
+                        <DockPanel Grid.Row="0" Grid.Column="0" LastChildFill="False" Margin="5 0">
+                            <input:SizeInput Unit="FPS"
+                                             Width="80" Height="25" HorizontalAlignment="Left"
+                                             Size="{Binding Fps, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
+
+                            <Button Classes="pixi-icon" DockPanel.Dock="Right"
+                                    Content="{DynamicResource icon-settings}"
+                                    ui1:Translator.TooltipKey="SETTINGS">
+                                <Button.Flyout>
+                                    <Flyout Placement="Top">
+                                        <StackPanel>
+                                            <TextBlock Classes="h4" Margin="5" ui1:Translator.Key="SETTINGS" />
+                                            <StackPanel Orientation="Horizontal" Spacing="5">
+                                                <TextBlock VerticalAlignment="Center" ui1:Translator.Key="ONION_FRAMES_COUNT" />
+                                                <input:NumberInput
+                                                   HorizontalAlignment="Left" Width="50"
+                                                    Min="1" Decimals="0"
+                                                    Max="128"
+                                                    Value="{Binding OnionFrames, RelativeSource={RelativeSource TemplatedParent}, 
+                                                    Mode=TwoWay}" />
+                                            </StackPanel>
+                                        </StackPanel>
+                                    </Flyout>
+                                </Button.Flyout>
+                            </Button>
+                        </DockPanel>
                     </Border>
                     </Border>
                     <Border Grid.Row="0" Grid.Column="1">
                     <Border Grid.Row="0" Grid.Column="1">
                         <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
                         <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="5">
@@ -66,7 +89,7 @@
 
 
                     <Border Grid.Column="0" Grid.Row="1" BorderThickness="0 1 1 1"
                     <Border Grid.Column="0" Grid.Row="1" BorderThickness="0 1 1 1"
                             BorderBrush="{DynamicResource ThemeBorderMidBrush}">
                             BorderBrush="{DynamicResource ThemeBorderMidBrush}">
-                        <StackPanel Orientation="Horizontal" Height="40">
+                        <StackPanel Margin="5, 0" Orientation="Horizontal" Height="40">
                             <Button Classes="pixi-icon"
                             <Button Classes="pixi-icon"
                                     Content="{DynamicResource icon-plus-square}"
                                     Content="{DynamicResource icon-plus-square}"
                                     ui1:Translator.TooltipKey="ADD_EMPTY_FRAME"
                                     ui1:Translator.TooltipKey="ADD_EMPTY_FRAME"
@@ -76,11 +99,9 @@
                                     ui1:Translator.TooltipKey="DUPLICATE_FRAME"
                                     ui1:Translator.TooltipKey="DUPLICATE_FRAME"
                                     Command="{TemplateBinding DuplicateKeyFrameCommand}" />
                                     Command="{TemplateBinding DuplicateKeyFrameCommand}" />
                             <ToggleButton Classes="pixi-icon"
                             <ToggleButton Classes="pixi-icon"
-                                    Content="{DynamicResource icon-onion-skin}"
-                                    ui1:Translator.TooltipKey="TOGGLE_ONION_SKINNING"
-                                    Command="{TemplateBinding ToggleOnionSkinningCommand}" 
-                                    CommandParameter="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}}"
-                                    />
+                                          Content="{DynamicResource icon-onion-skin}"
+                                          ui1:Translator.TooltipKey="TOGGLE_ONION_SKINNING"
+                                          IsChecked="{Binding OnionSkinningEnabled, RelativeSource={RelativeSource TemplatedParent}}"/>
                             <Button Classes="pixi-icon"
                             <Button Classes="pixi-icon"
                                     Content="{DynamicResource icon-trash}"
                                     Content="{DynamicResource icon-trash}"
                                     ui1:Translator.TooltipKey="DELETE_FRAME"
                                     ui1:Translator.TooltipKey="DELETE_FRAME"
@@ -195,7 +216,7 @@
                                     <ItemsControl.DataTemplates>
                                     <ItemsControl.DataTemplates>
                                         <DataTemplate DataType="document:KeyFrameGroupViewModel">
                                         <DataTemplate DataType="document:KeyFrameGroupViewModel">
                                             <ItemsControl ClipToBounds="False"
                                             <ItemsControl ClipToBounds="False"
-                                                          BorderThickness="0, 0, 0, 1" 
+                                                          BorderThickness="0, 0, 0, 1"
                                                           BorderBrush="{DynamicResource ThemeBorderMidBrush}"
                                                           BorderBrush="{DynamicResource ThemeBorderMidBrush}"
                                                           ItemsSource="{Binding Children}">
                                                           ItemsSource="{Binding Children}">
                                                 <ItemsControl.ItemContainerTheme>
                                                 <ItemsControl.ItemContainerTheme>

+ 20 - 0
src/PixiEditor/ViewModels/Document/AnimationDataViewModel.cs

@@ -15,6 +15,8 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
 {
 {
     private int _activeFrameBindable = 1;
     private int _activeFrameBindable = 1;
     private int frameRateBindable = 60;
     private int frameRateBindable = 60;
+    private int onionFrames = 1;
+    
     public DocumentViewModel Document { get; }
     public DocumentViewModel Document { get; }
     protected DocumentInternalParts Internals { get; }
     protected DocumentInternalParts Internals { get; }
     public IReadOnlyCollection<IKeyFrameHandler> KeyFrames => keyFrames;
     public IReadOnlyCollection<IKeyFrameHandler> KeyFrames => keyFrames;
@@ -62,6 +64,18 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
             Internals.ActionAccumulator.AddFinishedActions(new ToggleOnionSkinning_PassthroughAction(value));
             Internals.ActionAccumulator.AddFinishedActions(new ToggleOnionSkinning_PassthroughAction(value));
         }
         }
     }
     }
+    
+    public int OnionFramesBindable
+    {
+        get => onionFrames;
+        set
+        {
+            if (Document.UpdateableChangeActive)
+                return;
+
+            Internals.ActionAccumulator.AddFinishedActions(new SetOnionFrames_PassthroughAction(value));
+        }
+    }
 
 
     public int FirstFrame => keyFrames.Count > 0 ? keyFrames.Min(x => x.StartFrameBindable) : 0;
     public int FirstFrame => keyFrames.Count > 0 ? keyFrames.Min(x => x.StartFrameBindable) : 0;
 
 
@@ -155,6 +169,12 @@ internal class AnimationDataViewModel : ObservableObject, IAnimationHandler
         onionSkinningEnabled = value;
         onionSkinningEnabled = value;
         OnPropertyChanged(nameof(OnionSkinningEnabledBindable));
         OnPropertyChanged(nameof(OnionSkinningEnabledBindable));
     }
     }
+    
+    public void SetOnionFrames(int frames)
+    {
+        onionFrames = frames;
+        OnPropertyChanged(nameof(OnionFramesBindable));
+    }
 
 
     public void SetFrameLength(Guid keyFrameId, int newStartFrame, int newDuration)
     public void SetFrameLength(Guid keyFrameId, int newStartFrame, int newDuration)
     {
     {

+ 15 - 6
src/PixiEditor/Views/Animations/Timeline.cs

@@ -50,6 +50,15 @@ internal class Timeline : TemplatedControl, INotifyPropertyChanged
     public static readonly StyledProperty<Vector> ScrollOffsetProperty = AvaloniaProperty.Register<Timeline, Vector>(
     public static readonly StyledProperty<Vector> ScrollOffsetProperty = AvaloniaProperty.Register<Timeline, Vector>(
         nameof(ScrollOffset));
         nameof(ScrollOffset));
 
 
+    public static readonly StyledProperty<int> OnionFramesProperty = AvaloniaProperty.Register<Timeline, int>(
+        nameof(OnionFrames), 1);
+
+    public int OnionFrames
+    {
+        get => GetValue(OnionFramesProperty);
+        set => SetValue(OnionFramesProperty, value);
+    }
+
     public Vector ScrollOffset
     public Vector ScrollOffset
     {
     {
         get => GetValue(ScrollOffsetProperty);
         get => GetValue(ScrollOffsetProperty);
@@ -85,13 +94,13 @@ internal class Timeline : TemplatedControl, INotifyPropertyChanged
     public static readonly StyledProperty<int> DefaultEndFrameProperty = AvaloniaProperty.Register<Timeline, int>(
     public static readonly StyledProperty<int> DefaultEndFrameProperty = AvaloniaProperty.Register<Timeline, int>(
         nameof(DefaultEndFrame));
         nameof(DefaultEndFrame));
 
 
-    public static readonly StyledProperty<ICommand> ToggleOnionSkinningCommandProperty = AvaloniaProperty.Register<Timeline, ICommand>(
-        nameof(ToggleOnionSkinningCommand));
+    public static readonly StyledProperty<bool> OnionSkinningEnabledProperty = AvaloniaProperty.Register<Timeline, bool>(
+        nameof(OnionSkinningEnabled));
 
 
-    public ICommand ToggleOnionSkinningCommand
+    public bool OnionSkinningEnabled
     {
     {
-        get => GetValue(ToggleOnionSkinningCommandProperty);
-        set => SetValue(ToggleOnionSkinningCommandProperty, value);
+        get => GetValue(OnionSkinningEnabledProperty);
+        set => SetValue(OnionSkinningEnabledProperty, value);
     }
     }
 
 
     public int DefaultEndFrame
     public int DefaultEndFrame
@@ -175,7 +184,7 @@ internal class Timeline : TemplatedControl, INotifyPropertyChanged
     private KeyFrameViewModel clickedKeyFrame;
     private KeyFrameViewModel clickedKeyFrame;
     private bool dragged;
     private bool dragged;
     private int dragStartFrame;
     private int dragStartFrame;
-    
+
     public event PropertyChangedEventHandler? PropertyChanged;
     public event PropertyChangedEventHandler? PropertyChanged;
 
 
     static Timeline()
     static Timeline()

+ 2 - 1
src/PixiEditor/Views/Dock/TimelineDockView.axaml

@@ -18,7 +18,8 @@
         NewKeyFrameCommand="{xaml:Command PixiEditor.Animation.CreateRasterKeyFrame}"
         NewKeyFrameCommand="{xaml:Command PixiEditor.Animation.CreateRasterKeyFrame}"
         Fps="{Binding DocumentManagerSubViewModel.ActiveDocument.AnimationDataViewModel.FrameRateBindable, Mode=TwoWay}"
         Fps="{Binding DocumentManagerSubViewModel.ActiveDocument.AnimationDataViewModel.FrameRateBindable, Mode=TwoWay}"
         DefaultEndFrame="{Binding DocumentManagerSubViewModel.ActiveDocument.AnimationDataViewModel.DefaultEndFrame}"
         DefaultEndFrame="{Binding DocumentManagerSubViewModel.ActiveDocument.AnimationDataViewModel.DefaultEndFrame}"
-        ToggleOnionSkinningCommand="{xaml:Command PixiEditor.Animation.ToggleOnionSkinning, UseProvided=True}"
+        OnionSkinningEnabled="{Binding DocumentManagerSubViewModel.ActiveDocument.AnimationDataViewModel.OnionSkinningEnabledBindable, Mode=TwoWay}"
+        OnionFrames="{Binding DocumentManagerSubViewModel.ActiveDocument.AnimationDataViewModel.OnionFramesBindable, Mode=TwoWay}"
         DuplicateKeyFrameCommand="{xaml:Command PixiEditor.Animation.DuplicateRasterKeyFrame}"
         DuplicateKeyFrameCommand="{xaml:Command PixiEditor.Animation.DuplicateRasterKeyFrame}"
         DeleteKeyFrameCommand="{xaml:Command PixiEditor.Animation.DeleteKeyFrames, UseProvided=True}"
         DeleteKeyFrameCommand="{xaml:Command PixiEditor.Animation.DeleteKeyFrames, UseProvided=True}"
         ChangeKeyFramesLengthCommand="{xaml:Command PixiEditor.Animation.ChangeKeyFramesStartPos, UseProvided=True}"/>
         ChangeKeyFramesLengthCommand="{xaml:Command PixiEditor.Animation.ChangeKeyFramesStartPos, UseProvided=True}"/>

+ 7 - 10
src/PixiEditor/Views/Rendering/Scene.cs

@@ -495,7 +495,7 @@ internal class DrawSceneOperation : SkiaDrawOperation
     public RectI SurfaceRectToRender { get; }
     public RectI SurfaceRectToRender { get; }
 
 
     private bool hardwareAccelerationAvailable = DrawingBackendApi.Current.IsHardwareAccelerated;
     private bool hardwareAccelerationAvailable = DrawingBackendApi.Current.IsHardwareAccelerated;
-    
+
     private double opacity;
     private double opacity;
 
 
     public DrawSceneOperation(Texture surface, DocumentViewModel document, VecD contentPosition, double scale,
     public DrawSceneOperation(Texture surface, DocumentViewModel document, VecD contentPosition, double scale,
@@ -531,13 +531,14 @@ internal class DrawSceneOperation : SkiaDrawOperation
 
 
         using var ctx = DrawingBackendApi.Current.RenderOnDifferentGrContext(lease.GrContext);
         using var ctx = DrawingBackendApi.Current.RenderOnDifferentGrContext(lease.GrContext);
 
 
-        RenderOnionSkin(canvas);
+        using SKPaint paint = new SKPaint();
+        paint.Color = paint.Color.WithAlpha((byte)(opacity * 255));
+        
+        RenderOnionSkin(canvas, paint);
 
 
         /*var matrixValues = new float[ColorMatrix.Width * ColorMatrix.Height];
         /*var matrixValues = new float[ColorMatrix.Width * ColorMatrix.Height];
         ColorMatrix.TryGetMembers(matrixValues);*/
         ColorMatrix.TryGetMembers(matrixValues);*/
 
 
-        using SKPaint paint = new SKPaint();
-        paint.Color = paint.Color.WithAlpha((byte)(opacity * 255));
 
 
         if (!hardwareAccelerationAvailable)
         if (!hardwareAccelerationAvailable)
         {
         {
@@ -554,7 +555,7 @@ internal class DrawSceneOperation : SkiaDrawOperation
         canvas.RestoreToCount(count);
         canvas.RestoreToCount(count);
     }
     }
 
 
-    private void RenderOnionSkin(SKCanvas canvas)
+    private void RenderOnionSkin(SKCanvas canvas, SKPaint paint)
     {
     {
         if (Document.AnimationDataViewModel.OnionSkinningEnabledBindable)
         if (Document.AnimationDataViewModel.OnionSkinningEnabledBindable)
         {
         {
@@ -564,16 +565,12 @@ internal class DrawSceneOperation : SkiaDrawOperation
             {
             {
                 return;
                 return;
             }
             }
-            
-            
-            using SKPaint onionSkinPaint = new SKPaint();
-            onionSkinPaint.Color = Colors.White.WithAlpha(128).ToSKColor();
 
 
             int count = canvas.Save();
             int count = canvas.Save();
 
 
             canvas.Scale(1f / (float)ResolutionScale, 1f / (float)ResolutionScale);
             canvas.Scale(1f / (float)ResolutionScale, 1f / (float)ResolutionScale);
 
 
-            canvas.DrawSurface(onionSkinTexture.DrawingSurface.Native as SKSurface, 0, 0, onionSkinPaint);
+            canvas.DrawSurface(onionSkinTexture.DrawingSurface.Native as SKSurface, 0, 0, paint);
 
 
             canvas.RestoreToCount(count);
             canvas.RestoreToCount(count);
         }
         }