فهرست منبع

Added more variable types

flabbet 1 ماه پیش
والد
کامیت
833ad13085
19فایلهای تغییر یافته به همراه342 افزوده شده و 26 حذف شده
  1. 3 3
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Utility/SwitchNode.cs
  2. 9 1
      src/PixiEditor.ChangeableDocument/Changes/NodeGraph/Blackboard/SetBlackboardVariable_Change.cs
  3. 17 1
      src/PixiEditor/Data/Localization/Languages/en.json
  4. 3 0
      src/PixiEditor/ViewLocator.cs
  5. 30 4
      src/PixiEditor/ViewModels/Document/Blackboard/VariableViewModel.cs
  6. 9 1
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/ColorSettingViewModel.cs
  7. 13 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/GenericSettingViewModel.cs
  8. 52 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/PaintableSettingViewModel.cs
  9. 15 0
      src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/TextureSettingViewModel.cs
  10. 35 15
      src/PixiEditor/Views/Blackboard/BlackboardView.axaml.cs
  11. 32 0
      src/PixiEditor/Views/Input/TexturePicker.axaml
  12. 55 0
      src/PixiEditor/Views/Input/TexturePicker.axaml.cs
  13. 1 0
      src/PixiEditor/Views/Input/ToolSettingColorPicker.axaml
  14. 9 0
      src/PixiEditor/Views/Input/ToolSettingColorPicker.axaml.cs
  15. 3 1
      src/PixiEditor/Views/Tools/ToolSettings/Settings/ColorSettingView.axaml
  16. 11 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/GenericSettingView.axaml
  17. 15 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/GenericSettingView.axaml.cs
  18. 15 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/TextureSettingView.axaml
  19. 15 0
      src/PixiEditor/Views/Tools/ToolSettings/Settings/TextureSettingView.axaml.cs

+ 3 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Utility/SwitchNode.cs

@@ -16,9 +16,9 @@ public class SwitchNode : Node
     public SwitchNode()
     {
         Condition = CreateInput<bool>("Condition", "CONDITION", false);
-        InputTrue = CreateInput<object>("InputTrue", "IN_TRUE", null);
-        InputFalse = CreateInput<object>("InputFalse", "IN_FALSE", null);
-        Output = CreateOutput<object>("Output", "OUT", null);
+        InputTrue = CreateInput<object>("InputTrue", "ON_TRUE", null);
+        InputFalse = CreateInput<object>("InputFalse", "ON_FALSE", null);
+        Output = CreateOutput<object>("Output", "RESULT", null);
     }
 
     protected override void OnExecute(RenderContext context)

+ 9 - 1
src/PixiEditor.ChangeableDocument/Changes/NodeGraph/Blackboard/SetBlackboardVariable_Change.cs

@@ -37,7 +37,7 @@ internal class SetBlackboardVariable_Change : Change
             return false;
 
         if (target.NodeGraph.Blackboard.Variables.TryGetValue(variable, out var blackboardVariable) &&
-            blackboardVariable?.Type != value?.GetType() && !TryConvert(blackboardVariable?.Type, ref value))
+            !IsTypeAssignable(blackboardVariable) && !TryConvert(blackboardVariable?.Type, ref value))
             return false;
 
         if (blackboardVariable == null && value == null)
@@ -49,6 +49,14 @@ internal class SetBlackboardVariable_Change : Change
         return true;
     }
 
+    private bool IsTypeAssignable(Variable blackboardVariable)
+    {
+        if (blackboardVariable?.Type == null || value == null)
+            return false;
+        
+        return value.GetType().IsAssignableTo(blackboardVariable.Type);
+    }
+
     private bool TryConvert(Type targetType, ref object val)
     {
         try

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

@@ -1186,5 +1186,21 @@
   "BRUSH_SETTING": "Brush",
   "ABSOLUTE_COORDINATES": "Absolute Coordinates",
   "ALWAYS_CLEAR": "Always Clear",
-  "BILINEAR_SAMPLING": "Bilinear Sampling"
+  "BILINEAR_SAMPLING": "Bilinear Sampling",
+  "EXPOSE_VALUE_NODE": "Expose Value",
+  "NESTED_DOCUMENT": "Nested Document",
+  "PIXEL_PERFECT_ELLIPSE_NODE": "Pixel Perfect Ellipse",
+  "UTILITY": "Utility",
+  "SWITCH_NODE": "Switch",
+  "KEYBOARD_INFO_NODE": "Keyboard Info",
+  "DOCUMENT": "Document",
+  "IS_CTRL_PRESSED": "Is Ctrl Pressed",
+  "IS_SHIFT_PRESSED": "Is Shift Pressed",
+  "IS_ALT_PRESSED": "Is Alt Pressed",
+  "IS_META_PRESSED": "Is Meta Pressed",
+  "CONDITION": "Condition",
+  "ON_FALSE": "On False",
+  "ON_TRUE": "On True",
+  "GRAPH": "Graph",
+  "BRUSH": "Brush"
 }

+ 3 - 0
src/PixiEditor/ViewLocator.cs

@@ -6,9 +6,11 @@ using PixiDocks.Core.Docking;
 using PixiEditor.ViewModels.Dock;
 using PixiEditor.ViewModels.Nodes.Properties;
 using PixiEditor.ViewModels.SubViewModels;
+using PixiEditor.ViewModels.Tools.ToolSettings.Settings;
 using PixiEditor.Views.Dock;
 using PixiEditor.Views.Layers;
 using PixiEditor.Views.Nodes.Properties;
+using PixiEditor.Views.Tools.ToolSettings.Settings;
 
 namespace PixiEditor;
 
@@ -20,6 +22,7 @@ public class ViewLocator : IDataTemplate
         [typeof(LazyViewportWindowViewModel)] = typeof(LazyDocumentTemplate),
         [typeof(LayersDockViewModel)] = typeof(LayersManager),
         [typeof(SinglePropertyViewModel)] = typeof(DoublePropertyView),
+        [typeof(PaintableSettingViewModel)] = typeof(ColorSettingView)
     };
 
     public Control Build(object? data)

+ 30 - 4
src/PixiEditor/ViewModels/Document/Blackboard/VariableViewModel.cs

@@ -1,5 +1,8 @@
 using System.Windows.Input;
 using CommunityToolkit.Mvvm.Input;
+using Drawie.Backend.Core;
+using Drawie.Backend.Core.ColorsImpl;
+using Drawie.Backend.Core.ColorsImpl.Paintables;
 using PixiEditor.ChangeableDocument.Actions.Generated;
 using PixiEditor.ChangeableDocument.Changeables.Brushes;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
@@ -44,7 +47,8 @@ internal class VariableViewModel : ViewModelBase, IVariableHandler
     private DocumentInternalParts internals { get; }
     public ICommand RemoveCommand { get; }
 
-    public VariableViewModel(string name, Type type, object value, string? unit, double min, double max, DocumentInternalParts internals)
+    public VariableViewModel(string name, Type type, object value, string? unit, double min, double max,
+        DocumentInternalParts internals)
     {
         this.type = type;
         this.name = name;
@@ -89,10 +93,16 @@ internal class VariableViewModel : ViewModelBase, IVariableHandler
 
             if (unit == null)
             {
-                return new FloatSettingViewModel("Variable", 0, "Variable") { DecimalPlaces = 0, Min = intMin, Max = intMax };
+                return new FloatSettingViewModel("Variable", 0, "Variable")
+                {
+                    DecimalPlaces = 0, Min = intMin, Max = intMax
+                };
             }
 
-            return new SizeSettingViewModel("Variable", "Variable") { DecimalPlaces = 0, Min = min, Max = max, Unit = unit };
+            return new SizeSettingViewModel("Variable", "Variable")
+            {
+                DecimalPlaces = 0, Min = min, Max = max, Unit = unit
+            };
         }
 
         if (type == typeof(double) || type == typeof(float))
@@ -110,7 +120,23 @@ internal class VariableViewModel : ViewModelBase, IVariableHandler
             return new BrushSettingViewModel("Variable", "Variable");
         }
 
-        throw new NotSupportedException($"Type {type} is not supported for VariableViewModel.");
+        if (type == typeof(Paintable))
+        {
+            return new PaintableSettingViewModel("Variable", "Variable");
+        }
+        
+        
+        if (type == typeof(Color))
+        {
+            return new ColorSettingViewModel("Variable", "Variable") { AllowGradient = false };
+        }
+
+        if (type.IsAssignableTo(typeof(Texture)))
+        {
+            return new TextureSettingViewModel("Variable", "Variable");
+        }
+
+        return new GenericSettingViewModel("Variable");
     }
 
     public void SetValueInternal(object newValue)

+ 9 - 1
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/ColorSettingViewModel.cs

@@ -1,10 +1,12 @@
 using Avalonia.Media;
+using Drawie.Backend.Core.ColorsImpl.Paintables;
+using PixiEditor.Helpers.Extensions;
 
 namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
 
 internal sealed class ColorSettingViewModel : Setting<IBrush>
 {
-
+    private bool allowGradient = true;
     public IBrush BrushValue
     {
         get => base.Value;
@@ -24,6 +26,12 @@ internal sealed class ColorSettingViewModel : Setting<IBrush>
         }
     }
 
+    public bool AllowGradient
+    {
+        get => allowGradient;
+        set => SetProperty(ref allowGradient, value);
+    }
+
     public ColorSettingViewModel(string name, string label = "") : this(name, Brushes.White, label)
     { }
     

+ 13 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/GenericSettingViewModel.cs

@@ -0,0 +1,13 @@
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+internal class GenericSettingViewModel : Setting
+{
+    public GenericSettingViewModel(string name) : base(name)
+    {
+    }
+
+    public override Type GetSettingType()
+    {
+        return typeof(object);
+    }
+}

+ 52 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/PaintableSettingViewModel.cs

@@ -0,0 +1,52 @@
+using Avalonia.Media;
+using Drawie.Backend.Core.ColorsImpl.Paintables;
+using PixiEditor.Helpers.Extensions;
+using Colors = Drawie.Backend.Core.ColorsImpl.Colors;
+
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+internal sealed class PaintableSettingViewModel : Setting<Paintable>
+{
+    private IBrush brushValue;
+    public IBrush BrushValue
+    {
+        get => base.Value.ToBrush();
+        set
+        {
+            if (brushValue != null && brushValue is GradientBrush oldGradientBrush)
+            {
+                oldGradientBrush.GradientStops.CollectionChanged -= GradientStops_CollectionChanged;
+            }
+
+            brushValue = value;
+            base.Value = value.ToPaintable();
+
+            if (brushValue is GradientBrush gradientBrush)
+            {
+                gradientBrush.GradientStops.CollectionChanged += GradientStops_CollectionChanged;
+            }
+        }
+    }
+
+
+    public PaintableSettingViewModel(string name, string label = "") : this(name, new ColorPaintable(Colors.White), label)
+    { }
+    
+    public PaintableSettingViewModel(string name, Paintable defaultValue, string label = "")
+        : base(name)
+    {
+        Label = label;
+        Value = defaultValue;
+        ValueChanged += OnValueChanged;
+    }
+
+    private void OnValueChanged(object? sender, SettingValueChangedEventArgs<Paintable> e)
+    {
+        OnPropertyChanged(nameof(BrushValue));
+    }
+
+    private void GradientStops_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
+    {
+        InvokeValueChanged();
+    }
+}

+ 15 - 0
src/PixiEditor/ViewModels/Tools/ToolSettings/Settings/TextureSettingViewModel.cs

@@ -0,0 +1,15 @@
+using System.Collections.ObjectModel;
+using Drawie.Backend.Core;
+using PixiEditor.Models.BrushEngine;
+using PixiEditor.Models.Controllers;
+using PixiEditor.ViewModels.SubViewModels;
+
+namespace PixiEditor.ViewModels.Tools.ToolSettings.Settings;
+
+internal class TextureSettingViewModel : Setting<Texture>
+{
+    public TextureSettingViewModel(string name, string label) : base(name)
+    {
+        Label = label;
+    }
+}

+ 35 - 15
src/PixiEditor/Views/Blackboard/BlackboardView.axaml.cs

@@ -4,6 +4,13 @@ using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Interactivity;
 using Avalonia.Markup.Xaml;
+using Drawie.Backend.Core;
+using Drawie.Backend.Core.ColorsImpl;
+using Drawie.Backend.Core.ColorsImpl.Paintables;
+using Drawie.Backend.Core.Numerics;
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
+using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes.Shapes.Data;
 using PixiEditor.Models.Blackboard;
 using PixiEditor.Models.BrushEngine;
 using PixiEditor.ViewModels.Document.Blackboard;
@@ -12,8 +19,9 @@ namespace PixiEditor.Views.Blackboard;
 
 internal partial class BlackboardView : UserControl
 {
-    public static readonly StyledProperty<ObservableCollection<VariableViewModel>> VariablesProperty = AvaloniaProperty.Register<BlackboardView, ObservableCollection<VariableViewModel>>(
-        nameof(Variables));
+    public static readonly StyledProperty<ObservableCollection<VariableViewModel>> VariablesProperty =
+        AvaloniaProperty.Register<BlackboardView, ObservableCollection<VariableViewModel>>(
+            nameof(Variables));
 
     public ObservableCollection<VariableViewModel> Variables
     {
@@ -21,8 +29,9 @@ internal partial class BlackboardView : UserControl
         set => SetValue(VariablesProperty, value);
     }
 
-    public static readonly StyledProperty<ICommand> AddVariableCommandProperty = AvaloniaProperty.Register<BlackboardView, ICommand>(
-        nameof(AddVariableCommand));
+    public static readonly StyledProperty<ICommand> AddVariableCommandProperty =
+        AvaloniaProperty.Register<BlackboardView, ICommand>(
+            nameof(AddVariableCommand));
 
     public ICommand AddVariableCommand
     {
@@ -30,8 +39,9 @@ internal partial class BlackboardView : UserControl
         set => SetValue(AddVariableCommandProperty, value);
     }
 
-    public static readonly StyledProperty<VariableDefinition> SelectedVariableOptionProperty = AvaloniaProperty.Register<BlackboardView, VariableDefinition>(
-        nameof(SelectedVariableOption));
+    public static readonly StyledProperty<VariableDefinition> SelectedVariableOptionProperty =
+        AvaloniaProperty.Register<BlackboardView, VariableDefinition>(
+            nameof(SelectedVariableOption));
 
     public VariableDefinition SelectedVariableOption
     {
@@ -39,15 +49,25 @@ internal partial class BlackboardView : UserControl
         set => SetValue(SelectedVariableOptionProperty, value);
     }
 
-    public ObservableCollection<VariableDefinition> VariableOptions { get; } = new ObservableCollection<VariableDefinition>
-    {
-        new VariableDefinition("DECIMAL_NUMBER", typeof(double)) { Min = double.MinValue, Max = double.MaxValue },
-        new VariableDefinition("SIZE", typeof(double), "px"),
-        new VariableDefinition("PERCENTAGE", typeof(double), "%", 0, 100),
-        new VariableDefinition("WHOLE_NUMBER", typeof(int)),
-        new VariableDefinition("BOOLEAN", typeof(bool)),
-        new VariableDefinition("BRUSH", typeof(Brush)),
-    };
+    public ObservableCollection<VariableDefinition> VariableOptions { get; } =
+        new ObservableCollection<VariableDefinition>
+        {
+            new VariableDefinition("DECIMAL_NUMBER", typeof(double)) { Min = double.MinValue, Max = double.MaxValue },
+            new VariableDefinition("SIZE", typeof(double), "px"),
+            new VariableDefinition("PERCENTAGE", typeof(double), "%", 0, 100),
+            new VariableDefinition("WHOLE_NUMBER", typeof(int)),
+            new VariableDefinition("VECTOR", typeof(VecD)), // TODO: Picker
+            new VariableDefinition("WHOLE_NUM_VECTOR", typeof(VecI)), // TODO: Picker
+            new VariableDefinition("MATRIX", typeof(Matrix3X3)),
+            new VariableDefinition("BOOLEAN", typeof(bool)),
+            new VariableDefinition("BRUSH", typeof(Brush)),
+            new VariableDefinition("PAINTABLE", typeof(Paintable)),
+            new VariableDefinition("COLOR", typeof(Color)),
+            new VariableDefinition("TEXTURE", typeof(Texture)),
+            new VariableDefinition("PAINTER", typeof(Painter)),
+            new VariableDefinition("VECTOR_PATH", typeof(PathVectorData)),
+            new VariableDefinition("ANY", typeof(object)),
+        };
 
 
     public BlackboardView()

+ 32 - 0
src/PixiEditor/Views/Input/TexturePicker.axaml

@@ -0,0 +1,32 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:input="clr-namespace:PixiEditor.Views.Input"
+             xmlns:localization="clr-namespace:PixiEditor.UI.Common.Localization;assembly=PixiEditor.UI.Common"
+             xmlns:visuals="clr-namespace:PixiEditor.Views.Visuals"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:ClassModifier="internal"
+             x:Class="PixiEditor.Views.Input.TexturePicker">
+    <StackPanel Orientation="Horizontal" Spacing="6" VerticalAlignment="Center">
+        <Button localization:Translator.Key="SELECT"
+                MinWidth="80"
+                VerticalAlignment="Center"
+                Command="{Binding PickCommand, RelativeSource={RelativeSource AncestorType=input:TexturePicker, Mode=FindAncestor}}" />
+        
+        <visuals:TextureControl Texture="{Binding Texture, RelativeSource={RelativeSource AncestorType=input:TexturePicker, Mode=FindAncestor}}"
+                                 Width="32"
+                                 Height="32"
+                                 Margin="0,0,4,0"
+                                 VerticalAlignment="Center" />
+
+        <Button
+                Content="✕"
+                IsVisible="{Binding !!Texture, RelativeSource={RelativeSource AncestorType=input:TexturePicker, Mode=FindAncestor}}"
+                VerticalAlignment="Center"
+                Command="{Binding RemoveTextureCommand, RelativeSource={RelativeSource AncestorType=input:TexturePicker, Mode=FindAncestor}}"
+                localization:Translator.TooltipKey="REMOVE">
+        </Button>
+
+    </StackPanel>
+</UserControl>

+ 55 - 0
src/PixiEditor/Views/Input/TexturePicker.axaml.cs

@@ -0,0 +1,55 @@
+using System.Collections.ObjectModel;
+using System.Windows.Input;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Markup.Xaml;
+using Avalonia.Media;
+using Avalonia.Platform.Storage;
+using Avalonia.VisualTree;
+using CommunityToolkit.Mvvm.Input;
+using Drawie.Backend.Core;
+using Drawie.Numerics;
+using PixiEditor.ChangeableDocument.Changeables;
+using PixiEditor.Models.IO;
+using Brush = PixiEditor.Models.BrushEngine.Brush;
+
+namespace PixiEditor.Views.Input;
+
+internal partial class TexturePicker : UserControl
+{
+    public static readonly StyledProperty<Texture?> TextureProperty = AvaloniaProperty.Register<TexturePicker, Texture?>(
+        nameof(Texture));
+
+    public Texture? Texture
+    {
+        get => GetValue(TextureProperty);
+        set => SetValue(TextureProperty, value);
+    }
+
+    public ICommand PickCommand { get; }
+    public RelayCommand RemoveTextureCommand => new RelayCommand(() => Texture = null);
+
+    public TexturePicker()
+    {
+        InitializeComponent();
+        PickCommand = new AsyncRelayCommand(PickTextureFile);
+    }
+
+    private async Task PickTextureFile()
+    {
+        var any = new FileTypeDialogDataSet(FileTypeDialogDataSet.SetKind.Image).GetFormattedTypes(false);
+
+        if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
+        {
+            var dialog = await desktop.MainWindow.StorageProvider.OpenFilePickerAsync(
+                new FilePickerOpenOptions { FileTypeFilter = any.ToList() });
+
+            if (dialog.Count == 0 || !Importer.IsSupportedFile(dialog[0].Path.LocalPath))
+                return;
+
+            Texture?.Dispose();
+            Texture = Texture.Load(dialog[0].Path.LocalPath);
+        }
+    }
+}

+ 1 - 0
src/PixiEditor/Views/Input/ToolSettingColorPicker.axaml

@@ -10,6 +10,7 @@
              x:ClassModifier="internal"
              x:Class="PixiEditor.Views.Input.ToolSettingColorPicker">
     <colorPicker:PortableColorPicker Width="40" Height="20" x:Name="ColorPicker" UseHintColor="True"
+                                     EnableGradientsTab="{Binding EnableGradientsTab, ElementName=SettingColorPicker}"
                                      HintColor="{Binding DataContext.ColorsSubViewModel.PrimaryColor,
         RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type views:MainWindow}, AncestorLevel=1},
         Converter={converters:GenericColorToMediaColorConverter}}"

+ 9 - 0
src/PixiEditor/Views/Input/ToolSettingColorPicker.axaml.cs

@@ -10,6 +10,9 @@ namespace PixiEditor.Views.Input;
 
 internal partial class ToolSettingColorPicker : UserControl
 {
+    public static readonly StyledProperty<bool> EnableGradientsTabProperty = 
+        AvaloniaProperty.Register<ToolSettingColorPicker, bool>(nameof(EnableGradientsTab), true);
+
     public static readonly StyledProperty<IBrush> SelectedBrushProperty =
         AvaloniaProperty.Register<ToolSettingColorPicker, IBrush>(
             nameof(SelectedBrush));
@@ -20,6 +23,12 @@ internal partial class ToolSettingColorPicker : UserControl
         set => SetValue(SelectedBrushProperty, value);
     }
 
+    public bool EnableGradientsTab
+    {
+        get { return (bool)GetValue(EnableGradientsTabProperty); }
+        set { SetValue(EnableGradientsTabProperty, value); }
+    }
+
     public ToolSettingColorPicker()
     {
         InitializeComponent();

+ 3 - 1
src/PixiEditor/Views/Tools/ToolSettings/Settings/ColorSettingView.axaml

@@ -11,7 +11,9 @@
         <settings:ColorSettingViewModel/>
     </Design.DataContext>
     
-    <input:ToolSettingColorPicker SelectedBrush="{Binding BrushValue, Mode=TwoWay}">
+    <input:ToolSettingColorPicker 
+        EnableGradientsTab="{Binding AllowGradient}"
+        SelectedBrush="{Binding BrushValue, Mode=TwoWay}">
         <Interaction.Behaviors>
             <behaviours:GlobalShortcutFocusBehavior/>
         </Interaction.Behaviors>

+ 11 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/GenericSettingView.axaml

@@ -0,0 +1,11 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:settings="clr-namespace:PixiEditor.ViewModels.Tools.ToolSettings.Settings"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.Views.Tools.ToolSettings.Settings.GenericSettingView">
+    <Design.DataContext>
+        <settings:GenericSettingViewModel />
+    </Design.DataContext>
+</UserControl>

+ 15 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/GenericSettingView.axaml.cs

@@ -0,0 +1,15 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views.Tools.ToolSettings.Settings;
+
+public partial class GenericSettingView : UserControl
+{
+    public GenericSettingView()
+    {
+        InitializeComponent();
+    }
+}
+

+ 15 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/TextureSettingView.axaml

@@ -0,0 +1,15 @@
+<UserControl xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             xmlns:settings="clr-namespace:PixiEditor.ViewModels.Tools.ToolSettings.Settings"
+             xmlns:input="clr-namespace:PixiEditor.Views.Input"
+             mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+             x:Class="PixiEditor.Views.Tools.ToolSettings.Settings.TextureSettingView">
+    <Design.DataContext>
+        <settings:TextureSettingViewModel />
+    </Design.DataContext>
+
+    <input:TexturePicker Texture="{Binding Value, Mode=TwoWay}" />
+
+</UserControl>

+ 15 - 0
src/PixiEditor/Views/Tools/ToolSettings/Settings/TextureSettingView.axaml.cs

@@ -0,0 +1,15 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Markup.Xaml;
+
+namespace PixiEditor.Views.Tools.ToolSettings.Settings;
+
+public partial class TextureSettingView : UserControl
+{
+    public TextureSettingView()
+    {
+        InitializeComponent();
+    }
+}
+