浏览代码

Improve kernel property UI and allow resizing

CPKreuz 1 年之前
父节点
当前提交
34a33a0824

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

@@ -633,5 +633,12 @@
   "EMPTY_IMAGE": "Empty image",
   "EMPTY_IMAGE": "Empty image",
   "NOISE": "Noise",
   "NOISE": "Noise",
   "SCALE": "Scale",
   "SCALE": "Scale",
-  "SEED": "Seed"
+  "SEED": "Seed",
+  "KERNEL": "Kernel",
+  "KERNEL_VIEW_SUM": "Sum:",
+  "KERNEL_VIEW_SUM_TOOLTIP": "The sum of all values. You likely want to aim for a value of 1 or 0",
+  "GAIN": "Gain",
+  "BIAS": "Bias",
+  "TILE_MODE": "Tile Mode",
+  "ON_ALPHA": "On Alpha"
 }
 }

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Nodes/NodePropertyViewModel.cs

@@ -139,7 +139,7 @@ internal abstract class NodePropertyViewModel : ViewModelBase, INodePropertyHand
         return (NodePropertyViewModel)Activator.CreateInstance(viewModelType, node, type);
         return (NodePropertyViewModel)Activator.CreateInstance(viewModelType, node, type);
     }
     }
 
 
-    public void InternalSetValue(object? value) => SetProperty(ref _value, value);
+    public void InternalSetValue(object? value) => SetProperty(ref _value, value, nameof(Value));
 }
 }
 
 
 internal abstract class NodePropertyViewModel<T> : NodePropertyViewModel
 internal abstract class NodePropertyViewModel<T> : NodePropertyViewModel

+ 26 - 8
src/PixiEditor.AvaloniaUI/ViewModels/Nodes/Properties/KernelPropertyViewModel.cs

@@ -1,37 +1,54 @@
 using System.Collections.ObjectModel;
 using System.Collections.ObjectModel;
 using System.ComponentModel;
 using System.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
 
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Nodes.Properties;
 namespace PixiEditor.AvaloniaUI.ViewModels.Nodes.Properties;
 
 
 internal class KernelPropertyViewModel : NodePropertyViewModel<Kernel?>
 internal class KernelPropertyViewModel : NodePropertyViewModel<Kernel?>
 {
 {
-    public ObservableCollection<List<KernelVmReference>> ReferenceCollections { get; }
+    public ObservableCollection<KernelVmReference> ReferenceCollections { get; }
+    
+    public RelayCommand<int> AdjustSizeCommand { get; }
     
     
     public KernelPropertyViewModel(NodeViewModel node, Type valueType) : base(node, valueType)
     public KernelPropertyViewModel(NodeViewModel node, Type valueType) : base(node, valueType)
     {
     {
-        ReferenceCollections = new ObservableCollection<List<KernelVmReference>>();
+        ReferenceCollections = new ObservableCollection<KernelVmReference>();
         PropertyChanged += OnPropertyChanged;
         PropertyChanged += OnPropertyChanged;
+        AdjustSizeCommand = new RelayCommand<int>(Execute, i => i > 0 && Width < 9 || i < 0 && Width > 3);
     }
     }
 
 
+    private void Execute(int by)
+    {
+        Value.Resize(Width + by * 2, Height + by * 2);
+        OnPropertyChanged(nameof(Value));
+        AdjustSizeCommand.NotifyCanExecuteChanged();
+    }
+
+    public int Width => Value.Width;
+    
+    public int Height => Value.Height;
+
+    public float Sum => Value.Sum;
+
     private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
     private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
     {
     {
-        if (e.PropertyName == nameof(Value) || Value == null)
+        if (e.PropertyName != nameof(Value) || Value == null)
             return;
             return;
 
 
         ReferenceCollections.Clear();
         ReferenceCollections.Clear();
         
         
         for (int y = -Value.RadiusY; y <= Value.RadiusY; y++)
         for (int y = -Value.RadiusY; y <= Value.RadiusY; y++)
         {
         {
-            var collection = new List<KernelVmReference>();
-            
             for (int x = -Value.RadiusX; x <= Value.RadiusX; x++)
             for (int x = -Value.RadiusX; x <= Value.RadiusX; x++)
             {
             {
-                collection.Add(new KernelVmReference(this, x, y));
+                ReferenceCollections.Add(new KernelVmReference(this, x, y));
             }
             }
-
-            ReferenceCollections.Add(collection);
         }
         }
+        
+        OnPropertyChanged(nameof(Width));
+        OnPropertyChanged(nameof(Height));
+        OnPropertyChanged(nameof(Sum));
     }
     }
 
 
     public class KernelVmReference(KernelPropertyViewModel viewModel, int x, int y) : PixiObservableObject
     public class KernelVmReference(KernelPropertyViewModel viewModel, int x, int y) : PixiObservableObject
@@ -43,6 +60,7 @@ internal class KernelPropertyViewModel : NodePropertyViewModel<Kernel?>
             {
             {
                 viewModel.Value[x, y] = value;
                 viewModel.Value[x, y] = value;
                 ViewModelMain.Current.NodeGraphManager.UpdatePropertyValue((viewModel.Node, viewModel.PropertyName, viewModel.Value));
                 ViewModelMain.Current.NodeGraphManager.UpdatePropertyValue((viewModel.Node, viewModel.PropertyName, viewModel.Value));
+                viewModel.OnPropertyChanged(nameof(Sum));
                 OnPropertyChanged();
                 OnPropertyChanged();
             }
             }
         }
         }

+ 35 - 18
src/PixiEditor.AvaloniaUI/Views/Nodes/Properties/KernelPropertyView.axaml

@@ -6,29 +6,46 @@
                              xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
                              xmlns:ui="clr-namespace:PixiEditor.Extensions.UI;assembly=PixiEditor.Extensions"
                              xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
                              xmlns:converters="clr-namespace:PixiEditor.AvaloniaUI.Helpers.Converters"
                              xmlns:input="clr-namespace:PixiEditor.AvaloniaUI.Views.Input"
                              xmlns:input="clr-namespace:PixiEditor.AvaloniaUI.Views.Input"
+                             xmlns:system="clr-namespace:System;assembly=System.Runtime"
                              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
                              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
                              x:Class="PixiEditor.AvaloniaUI.Views.Nodes.Properties.KernelPropertyView">
                              x:Class="PixiEditor.AvaloniaUI.Views.Nodes.Properties.KernelPropertyView">
-    
-    <StackPanel HorizontalAlignment="{Binding IsInput, Converter={converters:BoolToValueConverter FalseValue='Right', TrueValue='Stretch'}}">
-        <TextBlock ui:Translator.Key="{Binding DisplayName}" />
-        
-        <ItemsControl ItemsSource="{Binding ReferenceCollections}" HorizontalAlignment="Stretch">
+
+    <StackPanel Margin="0,2">
+        <Grid ColumnDefinitions="*,*,*" Margin="0,0,0,2">
+            <TextBlock ui:Translator.Key="{Binding DisplayName}" VerticalAlignment="Center"/>
+            <StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
+                <Button Padding="0" Content="-" Width="35" Command="{Binding AdjustSizeCommand}">
+                    <Button.CommandParameter>
+                        <system:Int32>-1</system:Int32>
+                    </Button.CommandParameter>
+                </Button>
+                <Button Padding="0" Content="+" Width="35" Command="{Binding AdjustSizeCommand}">
+                    <Button.CommandParameter>
+                        <system:Int32>1</system:Int32>
+                    </Button.CommandParameter>
+                </Button>
+            </StackPanel>
+            <StackPanel Grid.Column="2" Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Right">
+                <TextBlock ui:Translator.Key="KERNEL_VIEW_SUM" Padding="0,0,2,0"
+                           ui:Translator.TooltipKey="KERNEL_VIEW_SUM_TOOLTIP"
+                           TextAlignment="Right"/>
+                <TextBlock Text="{Binding Sum, StringFormat='0.###'}"
+                           ui:Translator.TooltipKey="KERNEL_VIEW_SUM_TOOLTIP"
+                           TextAlignment="Right"/>
+            </StackPanel>
+        </Grid>
+
+        <ItemsControl ItemsSource="{Binding ReferenceCollections}" Margin="0,1">
             <ItemsControl.ItemTemplate>
             <ItemsControl.ItemTemplate>
                 <DataTemplate>
                 <DataTemplate>
-                    <ItemsControl ItemsSource="{Binding .}">
-                        <ItemsControl.ItemTemplate>
-                            <DataTemplate>
-                                <input:NumberInput Value="{Binding Value, Mode=TwoWay}"/>
-                            </DataTemplate>
-                        </ItemsControl.ItemTemplate>
-                        <ItemsControl.ItemsPanel>
-                            <ItemsPanelTemplate>
-                                <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch"/>
-                            </ItemsPanelTemplate>
-                        </ItemsControl.ItemsPanel>
-                    </ItemsControl>
+                    <input:NumberInput Value="{Binding Value, Mode=TwoWay}" Decimals="4" />
                 </DataTemplate>
                 </DataTemplate>
             </ItemsControl.ItemTemplate>
             </ItemsControl.ItemTemplate>
+            <ItemsControl.ItemsPanel>
+                <ItemsPanelTemplate>
+                    <UniformGrid Columns="{Binding Width}" Rows="{Binding Height}" />
+                </ItemsPanelTemplate>
+            </ItemsControl.ItemsPanel>
         </ItemsControl>
         </ItemsControl>
     </StackPanel>
     </StackPanel>
-</properties:NodePropertyView>
+</properties:NodePropertyView>

+ 2 - 0
src/PixiEditor.Numerics/Kernel.cs

@@ -18,6 +18,8 @@ public class Kernel
         set => _buffer[x, y] = value;
         set => _buffer[x, y] = value;
     }
     }
 
 
+    public float Sum => _buffer.Sum;
+    
     public Kernel(int width, int height)
     public Kernel(int width, int height)
     {
     {
         if (width % 2 == 0)
         if (width % 2 == 0)

+ 2 - 0
src/PixiEditor.Numerics/KernelArray.cs

@@ -11,6 +11,8 @@ public class KernelArray
     public int RadiusX => Width / 2;
     public int RadiusX => Width / 2;
     
     
     public int RadiusY => Height / 2;
     public int RadiusY => Height / 2;
+
+    public float Sum => _buffer.Sum();
     
     
     public KernelArray(int width, int height)
     public KernelArray(int width, int height)
     {
     {