Browse Source

ToolSet config

flabbet 11 months ago
parent
commit
1b5007fec6

+ 22 - 0
src/PixiEditor/Data/Configs/ToolSetsConfig.json

@@ -0,0 +1,22 @@
+[
+  {
+    "Name": "PIXEL_ART_TOOLSET",
+    "Tools": [
+      "MoveViewport",
+      "RotateViewport",
+      "Move",
+      "Pen",
+      "Select",
+      "MagicWand",
+      "Lasso",
+      "FloodFill",
+      "Line",
+      "Ellipse",
+      "Rectangle",
+      "Eraser",
+      "ColorPicker",
+      "Brightness",
+      "Zoom"
+    ]
+  }
+]

+ 28 - 27
src/PixiEditor/Helpers/ServiceCollectionHelpers.cs

@@ -81,33 +81,21 @@ internal static class ServiceCollectionHelpers
             .AddSingleton<CommandController>()
             .AddSingleton<DocumentManagerViewModel>()
             // Tools
-            .AddSingleton<IToolHandler, MoveViewportToolViewModel>()
-            .AddSingleton<IToolHandler, RotateViewportToolViewModel>()
-            .AddSingleton<IMoveToolHandler, MoveToolViewModel>()
-            .AddSingleton<IToolHandler, MoveToolViewModel>(x => (MoveToolViewModel)x.GetService<IMoveToolHandler>())
-            .AddSingleton<IPenToolHandler, PenToolViewModel>()
-            .AddSingleton<IToolHandler, PenToolViewModel>(x => (PenToolViewModel)x.GetService<IPenToolHandler>())
-            .AddSingleton<ISelectToolHandler, SelectToolViewModel>()
-            .AddSingleton<IToolHandler, SelectToolViewModel>(x => (SelectToolViewModel)x.GetService<ISelectToolHandler>())
-            .AddSingleton<IMagicWandToolHandler, MagicWandToolViewModel>()
-            .AddSingleton<IToolHandler, MagicWandToolViewModel>(x => (MagicWandToolViewModel)x.GetService<IMagicWandToolHandler>())
-            .AddSingleton<ILassoToolHandler, LassoToolViewModel>()
-            .AddSingleton<IToolHandler, LassoToolViewModel>(x => (LassoToolViewModel)x.GetService<ILassoToolHandler>())
-            .AddSingleton<IFloodFillToolHandler, FloodFillToolViewModel>()
-            .AddSingleton<IToolHandler, FloodFillToolViewModel>(x => (FloodFillToolViewModel)x.GetService<IFloodFillToolHandler>())
-            .AddSingleton<ILineToolHandler, LineToolViewModel>()
-            .AddSingleton<IToolHandler, LineToolViewModel>(x => (LineToolViewModel)x.GetService<ILineToolHandler>())
-            .AddSingleton<IEllipseToolHandler, EllipseToolViewModel>()
-            .AddSingleton<IToolHandler, EllipseToolViewModel>(x => (EllipseToolViewModel)x.GetService<IEllipseToolHandler>())
-            .AddSingleton<IRectangleToolHandler, RectangleToolViewModel>()
-            .AddSingleton<IToolHandler, RectangleToolViewModel>(x => (RectangleToolViewModel)x.GetService<IRectangleToolHandler>())
-            .AddSingleton<IEraserToolHandler, EraserToolViewModel>()
-            .AddSingleton<IToolHandler, EraserToolViewModel>(x => (EraserToolViewModel)x.GetService<IEraserToolHandler>())
-            .AddSingleton<IColorPickerHandler, ColorPickerToolViewModel>()
-            .AddSingleton<IToolHandler, ColorPickerToolViewModel>(x => (ColorPickerToolViewModel)x.GetService<IColorPickerHandler>())
-            .AddSingleton<IBrightnessToolHandler, BrightnessToolViewModel>()
-            .AddSingleton<IToolHandler, BrightnessToolViewModel>(x => (BrightnessToolViewModel)x.GetService<IBrightnessToolHandler>())
-            .AddSingleton<IToolHandler, ZoomToolViewModel>()
+            .AddTool<MoveViewportToolViewModel>()
+            .AddTool<RotateViewportToolViewModel>()
+            .AddTool<IMoveToolHandler, MoveToolViewModel>()
+            .AddTool<IPenToolHandler, PenToolViewModel>()
+            .AddTool<ISelectToolHandler, SelectToolViewModel>()
+            .AddTool<IMagicWandToolHandler, MagicWandToolViewModel>()
+            .AddTool<ILassoToolHandler, LassoToolViewModel>()
+            .AddTool<IFloodFillToolHandler, FloodFillToolViewModel>()
+            .AddTool<ILineToolHandler, LineToolViewModel>()
+            .AddTool<IEllipseToolHandler, EllipseToolViewModel>()
+            .AddTool<IRectangleToolHandler, RectangleToolViewModel>()
+            .AddTool<IEraserToolHandler, EraserToolViewModel>()
+            .AddTool<IColorPickerHandler, ColorPickerToolViewModel>()
+            .AddTool<IBrightnessToolHandler, BrightnessToolViewModel>()
+            .AddTool<ZoomToolViewModel>()
             // File types
             .AddSingleton<IoFileType, PixiFileType>()
             .AddSingleton<IoFileType, PngFileType>()
@@ -167,6 +155,19 @@ internal static class ServiceCollectionHelpers
             url = Environment.GetEnvironmentVariable("PixiEditorAnalytics");
         }
     }
+    
+    private static IServiceCollection AddTool<T, T1>(this IServiceCollection collection)
+        where T : class, IToolHandler where T1 : class, T
+    {
+        return collection.AddSingleton<T, T1>()
+            .AddSingleton<IToolHandler, T1>(x => (T1)x.GetRequiredService<T>());
+    }
+    
+    private static IServiceCollection AddTool<T>(this IServiceCollection collection)
+        where T : class, IToolHandler
+    {
+        return collection.AddSingleton<IToolHandler, T>();
+    }
 
     private static IServiceCollection AddMenuBuilders(this IServiceCollection collection)
     {

+ 20 - 0
src/PixiEditor/Models/Config/ConfigManager.cs

@@ -0,0 +1,20 @@
+using System.Reflection;
+using Avalonia.Platform;
+using Newtonsoft.Json;
+using PixiEditor.Views;
+
+namespace PixiEditor.Models.Config;
+
+public class ConfigManager
+{
+    public T GetConfig<T>(string configName)
+    {
+        string path = $"avares://{Assembly.GetExecutingAssembly().GetName().Name}/Data/Configs/{configName}.json";
+
+        using Stream config = AssetLoader.Open(new Uri(path));
+        using StreamReader reader = new(config);
+        
+        string json = reader.ReadToEnd();
+        return JsonConvert.DeserializeObject<T>(json);
+    }
+}

+ 13 - 0
src/PixiEditor/Models/Config/ToolSetConfig.cs

@@ -0,0 +1,13 @@
+using Newtonsoft.Json;
+
+namespace PixiEditor.Models.Config;
+
+public class ToolSetsConfig : List<ToolSetConfig>
+{
+}
+
+public class ToolSetConfig
+{
+    public string Name { get; set; }
+    public List<string> Tools { get; set; }
+}

+ 6 - 0
src/PixiEditor/Models/Handlers/IToolSetHandler.cs

@@ -0,0 +1,6 @@
+namespace PixiEditor.Models.Handlers;
+
+internal interface IToolSetHandler : IHandler
+{
+    public ICollection<IToolHandler> Tools { get; }
+}

+ 4 - 2
src/PixiEditor/Models/Handlers/IToolsHandler.cs

@@ -3,6 +3,7 @@ using Avalonia.Input;
 using PixiEditor.Models.Preferences;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Extensions.CommonApi.UserPreferences.Settings.PixiEditor;
+using PixiEditor.Models.Config;
 using PixiEditor.Models.Events;
 using PixiEditor.Numerics;
 using PixiEditor.ViewModels.Tools;
@@ -14,11 +15,12 @@ internal interface IToolsHandler : IHandler
     public void SetTool(object parameter);
     public void RestorePreviousTool();
     public IToolHandler ActiveTool { get; }
-    public ICollection<IToolHandler> ToolSet { get; }
+    public IToolSetHandler ActiveToolSet { get; } 
+    public ICollection<IToolSetHandler> AllToolSets { get; }
     public RightClickMode RightClickMode { get; set; }
     public bool EnableSharedToolbar { get; set; }
     public event EventHandler<SelectedToolEventArgs> SelectedToolChanged;
-    public void SetupTools(IServiceProvider services);
+    public void SetupTools(IServiceProvider services, ToolSetsConfig toolSetConfig);
     public void SetupToolsTooltipShortcuts(IServiceProvider services);
     public void SetActiveTool<T>(bool transient) where T : IToolHandler;
     public void SetActiveTool(Type toolType, bool transient);

+ 1 - 37
src/PixiEditor/PixiEditor.csproj

@@ -79,6 +79,7 @@
     <AvaloniaResource Include="Data\Languages\**"/>
     <AvaloniaResource Include="Data\ShortcutActionMaps\**"/>
     <AvaloniaResource Include="Data\BetaExampleFiles\**"/>
+    <AvaloniaResource Include="Data\Configs\**"/>
   </ItemGroup>
 
   <ItemGroup>
@@ -133,41 +134,4 @@
     </None>
   </ItemGroup>
 
-  <ItemGroup>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Clipboard\Copy.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Clipboard\Cut.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Clipboard\Paste.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Clipboard\PasteAsNewLayer.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Clipboard\PasteReferenceLayer.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\CenterContent.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\ResizeCanvas.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\ResizeDocument.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\Rotate180Deg.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\Rotate180DegLayers.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\Rotate270Deg.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\Rotate270DegLayers.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\Rotate90Deg.png"/>
-    <UpToDateCheckInput Remove="Images\Commands\PixiEditor\Document\Rotate90DegLayers.png"/>
-    <UpToDateCheckInput Remove="Images\News\Article.png"/>
-    <UpToDateCheckInput Remove="Images\News\Misc.png"/>
-    <UpToDateCheckInput Remove="Images\News\NewVersion.png"/>
-    <UpToDateCheckInput Remove="Images\News\OfficialAnnouncement.png"/>
-    <UpToDateCheckInput Remove="Images\News\YouTube.png"/>
-    <UpToDateCheckInput Remove="Styles\Templates\NodeProperties\ImageNodePropertyView.axaml"/>
-  </ItemGroup>
-
-  <ItemGroup>
-    <Compile Update="Views\Dock\TimelineDockView.axaml.cs">
-      <DependentUpon>TimelineDockView.axaml</DependentUpon>
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Update="Views\Nodes\Properties\NodeSocket.cs">
-      <DependentUpon>NodeSocket.axaml</DependentUpon>
-      <SubType>Code</SubType>
-    </Compile>
-    <Compile Update="Views\Nodes\ConnectionView.cs">
-      <SubType>Code</SubType>
-    </Compile>
-  </ItemGroup>
-
 </Project>

+ 13 - 2
src/PixiEditor/ViewModels/SubViewModels/ToolSetViewModel.cs

@@ -1,11 +1,22 @@
 using System.Collections.ObjectModel;
 using PixiEditor.Extensions.Common.Localization;
 using PixiEditor.Models.Handlers;
+using PixiEditor.ViewModels.Tools;
 
 namespace PixiEditor.ViewModels.SubViewModels;
 
-internal class ToolSetViewModel : PixiObservableObject
+internal class ToolSetViewModel : PixiObservableObject, IToolSetHandler
 {
-    public LocalizedString SetName { get; } 
+    public LocalizedString ToolSetName { get; }
+    ICollection<IToolHandler> IToolSetHandler.Tools => Tools;
     public ObservableCollection<IToolHandler> Tools { get; } = new();
+    
+    public ToolSetViewModel(string setName, List<IToolHandler> tools)
+    {
+        ToolSetName = setName;
+        foreach (var tool in tools)
+        {
+            Tools.Add(tool);
+        }    
+    }
 }

+ 23 - 8
src/PixiEditor/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -10,6 +10,7 @@ using PixiEditor.Models.AnalyticsAPI;
 using PixiEditor.Models.Commands.Attributes.Commands;
 using PixiEditor.Models.Commands.Attributes.Evaluators;
 using PixiEditor.Models.Commands.CommandContext;
+using PixiEditor.Models.Config;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Events;
 using PixiEditor.Models.Handlers;
@@ -79,8 +80,11 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
         }
     }
 
-    ICollection<IToolHandler> IToolsHandler.ToolSet => ToolSet;
-    public ToolSetViewModel ToolSet { get; private set; }
+    public IToolSetHandler ActiveToolSet { get; private set; }
+
+    ICollection<IToolSetHandler> IToolsHandler.AllToolSets => AllToolSets;
+    
+    public ObservableCollection<IToolSetHandler> AllToolSets { get; } = new();
 
     public event EventHandler<SelectedToolEventArgs>? SelectedToolChanged;
 
@@ -89,21 +93,32 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
     private bool altIsDown;
 
     private ToolViewModel _preTransientTool;
-
+    
+    private List<IToolHandler> allTools = new();
 
     public ToolsViewModel(ViewModelMain owner)
         : base(owner)
     {
     }
 
-    public void SetupTools(IServiceProvider services)
+    public void SetupTools(IServiceProvider services, ToolSetsConfig toolSetConfig)
     {
-        ToolSet = new ObservableCollection<IToolHandler>(services.GetServices<IToolHandler>());
+        allTools = services.GetServices<IToolHandler>().ToList();
+        
+        ToolSetConfig activeToolSetConfig = toolSetConfig.FirstOrDefault();
+        
+        if (activeToolSetConfig is null)
+        {
+            throw new InvalidOperationException("No tool set configuration found.");
+        }
+        
+        List<IToolHandler> tools = activeToolSetConfig.Tools.Select(toolName => allTools.FirstOrDefault(tool => tool.ToolName == toolName)).Where(x => x != null).ToList();
+        ActiveToolSet = new ToolSetViewModel(activeToolSetConfig.Name, tools); 
     }
 
     public void SetupToolsTooltipShortcuts(IServiceProvider services)
     {
-        foreach (ToolViewModel tool in ToolSet!)
+        foreach (ToolViewModel tool in ActiveToolSet.Tools!)
         {
             tool.Shortcut = Owner.ShortcutController.GetToolShortcut(tool.GetType());
         }
@@ -112,7 +127,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
     public T? GetTool<T>()
         where T : IToolHandler
     {
-        return (T?)ToolSet?.Where(static tool => tool is T).FirstOrDefault();
+        return (T?)ActiveToolSet?.Tools.Where(static tool => tool is T).FirstOrDefault();
     }
 
     public void SetActiveTool<T>(bool transient)
@@ -235,7 +250,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
     {
         if (!typeof(ToolViewModel).IsAssignableFrom(toolType))
             throw new ArgumentException($"'{toolType}' does not inherit from {typeof(ToolViewModel)}");
-        IToolHandler foundTool = ToolSet!.First(x => x.GetType().IsAssignableFrom(toolType));
+        IToolHandler foundTool = ActiveToolSet!.Tools.First(x => x.GetType().IsAssignableFrom(toolType));
         SetActiveTool(foundTool, transient, sourceInfo);
     }
     

+ 1 - 1
src/PixiEditor/ViewModels/ToolVM.cs

@@ -11,6 +11,6 @@ internal class ToolVM : MarkupExtension
 
     public override object ProvideValue(IServiceProvider serviceProvider)
     {
-        return ViewModelMain.Current?.ToolsSubViewModel.ToolSet?.Where(tool => tool.GetType().Name == TypeName).FirstOrDefault();
+        return (ViewModelMain.Current?.ToolsSubViewModel.ActiveToolSet?.Tools).FirstOrDefault(tool => tool.GetType().Name == TypeName);
     }
 }

+ 7 - 25
src/PixiEditor/ViewModels/ViewModelMain.cs

@@ -10,6 +10,7 @@ using PixiEditor.Helpers;
 using PixiEditor.Helpers.Collections;
 using PixiEditor.Models.AnalyticsAPI;
 using PixiEditor.Models.Commands;
+using PixiEditor.Models.Config;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.DocumentModels;
@@ -32,59 +33,37 @@ internal partial class ViewModelMain : ViewModelBase, ICommandsHandler
     public Action CloseAction { get; set; }
     public event EventHandler OnStartupEvent;
     public FileViewModel FileSubViewModel { get; set; }
-
     public UpdateViewModel UpdateSubViewModel { get; set; }
-
     public IToolsHandler ToolsSubViewModel { get; set; }
-
     public IoViewModel IoSubViewModel { get; set; }
-
     public LayersViewModel LayersSubViewModel { get; set; }
-
     public ClipboardViewModel ClipboardSubViewModel { get; set; }
-
     public UndoViewModel UndoSubViewModel { get; set; }
-
     public SelectionViewModel SelectionSubViewModel { get; set; }
-
     public ViewOptionsViewModel ViewportSubViewModel { get; set; }
-
     public ColorsViewModel ColorsSubViewModel { get; set; }
-
     public MiscViewModel MiscSubViewModel { get; set; }
-
     public DiscordViewModel DiscordViewModel { get; set; }
-
     public DebugViewModel DebugSubViewModel { get; set; }
-
     public DocumentManagerViewModel DocumentManagerSubViewModel { get; set; }
-
     public CommandController CommandController { get; set; }
-
     public ShortcutController ShortcutController { get; set; }
-
     public StylusViewModel StylusSubViewModel { get; set; }
-
     public WindowViewModel WindowSubViewModel { get; set; }
-
     public SearchViewModel SearchSubViewModel { get; set; }
-
     public RegistryViewModel RegistrySubViewModel { get; set; }
-
     public AdditionalContentViewModel AdditionalContentSubViewModel { get; set; }
-
     public ExtensionsViewModel ExtensionsSubViewModel { get; set; }
-
     public LayoutViewModel LayoutSubViewModel { get; set; }
-
     public MenuBarViewModel MenuBarViewModel { get; set; }
     public AnimationsViewModel AnimationsSubViewModel { get; set; }
-    
     public NodeGraphManagerViewModel NodeGraphManager { get; set; }
 
     public IPreferences Preferences { get; set; }
     public ILocalizationProvider LocalizationProvider { get; set; }
 
+    public ConfigManager Config { get; set; }    
+    
     public LocalizedString ActiveActionDisplay
     {
         get
@@ -117,6 +96,8 @@ internal partial class ViewModelMain : ViewModelBase, ICommandsHandler
     {
         Services = services;
 
+        Config = new ConfigManager(); 
+
         Preferences = services.GetRequiredService<IPreferences>();
         Preferences.Init();
         
@@ -146,7 +127,8 @@ internal partial class ViewModelMain : ViewModelBase, ICommandsHandler
         ColorsSubViewModel = services.GetService<ColorsViewModel>();
         ColorsSubViewModel?.SetupPaletteProviders(services);
 
-        ToolsSubViewModel?.SetupTools(services);
+        ToolSetsConfig toolSetConfig = Config.GetConfig<ToolSetsConfig>("ToolSetsConfig");
+        ToolsSubViewModel?.SetupTools(services, toolSetConfig);
 
         DiscordViewModel = services.GetService<DiscordViewModel>();
         UpdateSubViewModel = services.GetService<UpdateViewModel>();

+ 1 - 1
src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml

@@ -117,7 +117,7 @@
                            Margin="10 55 0 0"
                            HorizontalAlignment="Left"
                            VerticalAlignment="Top"
-                           Tools="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ToolSet}" />
+                           Tools="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ActiveToolSet.Tools}" />
         <rendering:Scene
             Focusable="False" Name="scene"
             ZIndex="1"