diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj
index df21cdfd2..ee57c4987 100644
--- a/src/Artemis.Core/Artemis.Core.csproj
+++ b/src/Artemis.Core/Artemis.Core.csproj
@@ -42,9 +42,9 @@
-
-
-
+
+
+
diff --git a/src/Artemis.Core/DryIoc/ContainerExtensions.cs b/src/Artemis.Core/DryIoc/ContainerExtensions.cs
new file mode 100644
index 000000000..927f606a9
--- /dev/null
+++ b/src/Artemis.Core/DryIoc/ContainerExtensions.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Artemis.Core.DryIoc.Factories;
+using Artemis.Core.Services;
+using Artemis.Storage;
+using Artemis.Storage.Migrations.Interfaces;
+using Artemis.Storage.Repositories.Interfaces;
+using DryIoc;
+
+namespace Artemis.Core.DryIoc;
+
+///
+/// Provides an extension method to register services onto a DryIoc .
+///
+public static class ContainerExtensions
+{
+ ///
+ /// Registers core services into the container.
+ ///
+ /// The builder building the current container
+ public static void RegisterCore(this IContainer container)
+ {
+ Assembly[] coreAssembly = {typeof(IArtemisService).Assembly};
+ Assembly[] storageAssembly = {typeof(IRepository).Assembly};
+
+ // Bind all services as singletons
+ container.RegisterMany(coreAssembly, type => type.IsAssignableTo(), Reuse.Singleton);
+ container.RegisterMany(coreAssembly, type => type.IsAssignableTo(), Reuse.Singleton, setup: Setup.With(condition: HasAccessToProtectedService));
+
+ // Bind storage
+ container.RegisterDelegate(() => StorageManager.CreateRepository(Constants.DataFolder), Reuse.Singleton);
+ container.Register(Reuse.Singleton);
+ container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton);
+
+ // Bind migrations
+ container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true);
+
+ container.Register(Reuse.Singleton);
+ container.Register(made: Made.Of(_ => ServiceInfo.Of(), f => f.CreatePluginSettings(Arg.Index(0)), r => r.Parent.ImplementationType));
+ container.Register(Reuse.Singleton);
+ container.Register(made: Made.Of(_ => ServiceInfo.Of(), f => f.CreateLogger(Arg.Index(0)), r => r.Parent.ImplementationType));
+ }
+
+ ///
+ /// Registers plugin services into the container, this is typically a child container.
+ ///
+ /// The builder building the current container
+ /// The plugin to register
+ public static void RegisterPlugin(this IContainer container, Plugin plugin)
+ {
+ container.RegisterInstance(plugin, setup: Setup.With(preventDisposal: true));
+
+ // Bind plugin service interfaces, DryIoc expects at least one match when calling RegisterMany so ensure there is something to register first
+ if (plugin.Assembly != null && plugin.Assembly.GetTypes().Any(t => t.IsAssignableTo()))
+ container.RegisterMany(new[] {plugin.Assembly}, type => type.IsAssignableTo(), Reuse.Singleton, ifAlreadyRegistered: IfAlreadyRegistered.Keep);
+ }
+
+ private static bool HasAccessToProtectedService(Request request)
+ {
+ // Plugin assembly locations may not be set for some reason, that case it's also not allowed >:(
+ return request.Parent.ImplementationType != null &&
+ !string.IsNullOrWhiteSpace(request.Parent.ImplementationType.Assembly.Location) &&
+ !request.Parent.ImplementationType.Assembly.Location.StartsWith(Constants.PluginsFolder);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.Core/DryIoc/CoreModule.cs b/src/Artemis.Core/DryIoc/CoreModule.cs
deleted file mode 100644
index 0c41cb524..000000000
--- a/src/Artemis.Core/DryIoc/CoreModule.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-using System;
-using System.Reflection;
-using Artemis.Core.DryIoc.Factories;
-using Artemis.Core.Services;
-using Artemis.Storage;
-using Artemis.Storage.Migrations.Interfaces;
-using Artemis.Storage.Repositories.Interfaces;
-using DryIoc;
-
-namespace Artemis.Core.DryIoc;
-
-///
-/// The main of the Artemis Core that binds all services
-///
-public class CoreModule : IModule
-{
- ///
- public void Load(IRegistrator builder)
- {
- Assembly coreAssembly = typeof(IArtemisService).Assembly;
- Assembly storageAssembly = typeof(IRepository).Assembly;
-
- // Bind all services as singletons
- builder.RegisterMany(new[] {coreAssembly}, type => type.IsAssignableTo(), Reuse.Singleton);
- builder.RegisterMany(new[] {coreAssembly}, type => type.IsAssignableTo(), Reuse.Singleton, setup: Setup.With(condition: HasAccessToProtectedService));
-
- // Bind storage
- builder.RegisterDelegate(() => StorageManager.CreateRepository(Constants.DataFolder), Reuse.Singleton);
- builder.Register(Reuse.Singleton);
- builder.RegisterMany(new[] {storageAssembly}, type => type.IsAssignableTo(), Reuse.Singleton);
-
- // Bind migrations
- builder.RegisterMany(new[] { storageAssembly }, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true);
-
- builder.Register(Reuse.Singleton);
- builder.Register(made: Made.Of(_ => ServiceInfo.Of(), factory => factory.CreatePluginSettings(Arg.Index(0)), r => r.Parent.ImplementationType));
- builder.Register(Reuse.Singleton);
- builder.Register(made: Made.Of(_ => ServiceInfo.Of(), f => f.CreateLogger(Arg.Index(0)), r => r.Parent.ImplementationType));
- }
-
- private bool HasAccessToProtectedService(Request request)
- {
- // Plugin assembly locations may not be set for some reason, that case it's also not allowed >:(
- return request.Parent.ImplementationType != null &&
- !string.IsNullOrWhiteSpace(request.Parent.ImplementationType.Assembly.Location) &&
- !request.Parent.ImplementationType.Assembly.Location.StartsWith(Constants.PluginsFolder);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.Core/DryIoc/IModule.cs b/src/Artemis.Core/DryIoc/IModule.cs
deleted file mode 100644
index 08b3247a9..000000000
--- a/src/Artemis.Core/DryIoc/IModule.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using DryIoc;
-
-namespace Artemis.Core.DryIoc;
-
-/**
- * Represents a service module.
- */
-public interface IModule
-{
- ///
- /// Registers the services provided by the module.
- ///
- /// The builder to register the services with.
- void Load(IRegistrator builder);
-}
\ No newline at end of file
diff --git a/src/Artemis.Core/DryIoc/PluginModule.cs b/src/Artemis.Core/DryIoc/PluginModule.cs
deleted file mode 100644
index d6ae8dd07..000000000
--- a/src/Artemis.Core/DryIoc/PluginModule.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-using System;
-using System.Linq;
-using Artemis.Core.Services;
-using DryIoc;
-
-namespace Artemis.Core.DryIoc;
-
-internal class PluginModule : IModule
-{
- public PluginModule(Plugin plugin)
- {
- Plugin = plugin ?? throw new ArgumentNullException(nameof(plugin));
- }
-
- public Plugin Plugin { get; }
-
- ///
- public void Load(IRegistrator builder)
- {
- builder.RegisterInstance(Plugin, setup: Setup.With(preventDisposal: true));
-
- // Bind plugin service interfaces, DryIoc expects at least one match when calling RegisterMany so ensure there is something to register first
- if (Plugin.Assembly != null && Plugin.Assembly.GetTypes().Any(t => t.IsAssignableTo()))
- builder.RegisterMany(new[] {Plugin.Assembly}, type => type.IsAssignableTo(), Reuse.Singleton, ifAlreadyRegistered: IfAlreadyRegistered.Keep);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.Core/Services/PluginManagementService.cs b/src/Artemis.Core/Services/PluginManagementService.cs
index 9565f6320..6de473234 100644
--- a/src/Artemis.Core/Services/PluginManagementService.cs
+++ b/src/Artemis.Core/Services/PluginManagementService.cs
@@ -435,7 +435,7 @@ internal class PluginManagementService : IPluginManagementService
plugin.Container = _container.CreateChild(newRules: _container.Rules.WithConcreteTypeDynamicRegistrations());
try
{
- new PluginModule(plugin).Load(plugin.Container);
+ plugin.Container.RegisterPlugin(plugin);
}
catch (Exception e)
{
diff --git a/src/Artemis.UI.Linux/App.axaml.cs b/src/Artemis.UI.Linux/App.axaml.cs
index f3fdb04cf..7040f8183 100644
--- a/src/Artemis.UI.Linux/App.axaml.cs
+++ b/src/Artemis.UI.Linux/App.axaml.cs
@@ -1,4 +1,5 @@
using Artemis.Core.Services;
+using Artemis.UI.Linux.DryIoc;
using Artemis.UI.Linux.Providers.Input;
using Avalonia;
using Avalonia.Controls;
@@ -17,7 +18,7 @@ public class App : Application
public override void Initialize()
{
- _container = ArtemisBootstrapper.Bootstrap(this);
+ _container = ArtemisBootstrapper.Bootstrap(this, c => c.RegisterProviders());
Program.CreateLogger(_container);
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
AvaloniaXamlLoader.Load(this);
diff --git a/src/Artemis.UI.Linux/DryIoc/ContainerExtensions.cs b/src/Artemis.UI.Linux/DryIoc/ContainerExtensions.cs
new file mode 100644
index 000000000..8647beea5
--- /dev/null
+++ b/src/Artemis.UI.Linux/DryIoc/ContainerExtensions.cs
@@ -0,0 +1,20 @@
+using Artemis.Core.Services;
+using Artemis.UI.Linux.Providers.Input;
+using DryIoc;
+
+namespace Artemis.UI.Linux.DryIoc;
+
+///
+/// Provides an extension method to register services onto a DryIoc .
+///
+public static class UIContainerExtensions
+{
+ ///
+ /// Registers providers into the container.
+ ///
+ /// The builder building the current container
+ public static void RegisterProviders(this IContainer container)
+ {
+ container.Register(serviceKey: LinuxInputProvider.Id);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Linux/DryIoc/LinuxModule.cs b/src/Artemis.UI.Linux/DryIoc/LinuxModule.cs
deleted file mode 100644
index 142e8b667..000000000
--- a/src/Artemis.UI.Linux/DryIoc/LinuxModule.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Artemis.Core.DryIoc;
-using Artemis.Core.Services;
-using Artemis.UI.Linux.Providers.Input;
-using DryIoc;
-
-namespace Artemis.UI.Linux.DryIoc;
-
-public class LinuxModule : IModule
-{
-
- ///
- public void Load(IRegistrator builder)
- {
- builder.Register(serviceKey: LinuxInputProvider.Id);
- }
-
-}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
index 09c2d5479..c8f440c29 100644
--- a/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
+++ b/src/Artemis.UI.Shared/Artemis.UI.Shared.csproj
@@ -20,7 +20,7 @@
-
+
diff --git a/src/Artemis.UI.Shared/DryIoc/ContainerExtensions.cs b/src/Artemis.UI.Shared/DryIoc/ContainerExtensions.cs
new file mode 100644
index 000000000..4c4711b02
--- /dev/null
+++ b/src/Artemis.UI.Shared/DryIoc/ContainerExtensions.cs
@@ -0,0 +1,21 @@
+using System.Reflection;
+using Artemis.UI.Shared.Services;
+using DryIoc;
+
+namespace Artemis.UI.Shared.DryIoc;
+
+///
+/// Provides an extension method to register services onto a DryIoc .
+///
+public static class ContainerExtensions
+{
+ ///
+ /// Registers shared UI services into the container.
+ ///
+ /// The builder building the current container
+ public static void RegisterSharedUI(this IContainer container)
+ {
+ Assembly artemisShared = typeof(IArtemisSharedUIService).GetAssembly();
+ container.RegisterMany(new[] { artemisShared }, type => type.IsAssignableTo(), Reuse.Singleton);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/DryIoc/SharedUIModule.cs b/src/Artemis.UI.Shared/DryIoc/SharedUIModule.cs
deleted file mode 100644
index be6fcced3..000000000
--- a/src/Artemis.UI.Shared/DryIoc/SharedUIModule.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Reflection;
-using Artemis.Core.DryIoc;
-using Artemis.UI.Shared.Services;
-using DryIoc;
-
-namespace Artemis.UI.Shared.DryIoc;
-
-///
-/// The main of the Artemis Shared UI toolkit that binds all services
-///
-public class SharedUIModule : IModule
-{
- ///
- public void Load(IRegistrator builder)
- {
- Assembly artemisShared = typeof(IArtemisSharedUIService).GetAssembly();
- builder.RegisterMany(new[] { artemisShared }, type => type.IsAssignableTo(), Reuse.Singleton);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs
index 8c60677b6..62340d3a6 100644
--- a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs
+++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs
@@ -56,7 +56,7 @@ public class DuplicateNode : INodeEditorCommand, IDisposable
if (targetCollection == null)
continue;
while (targetCollection.Count() < sourceCollection.Count())
- targetCollection.CreatePin();
+ targetCollection.Add(targetCollection.CreatePin());
}
// Copy the storage
diff --git a/src/Artemis.UI.Windows/App.axaml.cs b/src/Artemis.UI.Windows/App.axaml.cs
index 38f0389a7..b2a8db3df 100644
--- a/src/Artemis.UI.Windows/App.axaml.cs
+++ b/src/Artemis.UI.Windows/App.axaml.cs
@@ -33,7 +33,7 @@ public class App : Application
Environment.Exit(1);
}
- _container = ArtemisBootstrapper.Bootstrap(this, new WindowsModule());
+ _container = ArtemisBootstrapper.Bootstrap(this, c => c.RegisterProviders());
Program.CreateLogger(_container);
RxApp.MainThreadScheduler = AvaloniaScheduler.Instance;
AvaloniaXamlLoader.Load(this);
diff --git a/src/Artemis.UI.Windows/DryIoc/ContainerExtensions.cs b/src/Artemis.UI.Windows/DryIoc/ContainerExtensions.cs
new file mode 100644
index 000000000..000931d92
--- /dev/null
+++ b/src/Artemis.UI.Windows/DryIoc/ContainerExtensions.cs
@@ -0,0 +1,27 @@
+using Artemis.Core.Providers;
+using Artemis.Core.Services;
+using Artemis.UI.Shared.Providers;
+using Artemis.UI.Windows.Providers;
+using Artemis.UI.Windows.Providers.Input;
+using DryIoc;
+
+namespace Artemis.UI.Windows.DryIoc;
+
+///
+/// Provides an extension method to register services onto a DryIoc .
+///
+public static class UIContainerExtensions
+{
+ ///
+ /// Registers providers into the container.
+ ///
+ /// The builder building the current container
+ public static void RegisterProviders(this IContainer container)
+ {
+ container.Register(Reuse.Singleton);
+ container.Register(Reuse.Singleton);
+ container.Register(Reuse.Singleton);
+ container.Register();
+ container.Register(serviceKey: WindowsInputProvider.Id);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI.Windows/DryIoc/WindowsModule.cs b/src/Artemis.UI.Windows/DryIoc/WindowsModule.cs
deleted file mode 100644
index 96b8b7ec7..000000000
--- a/src/Artemis.UI.Windows/DryIoc/WindowsModule.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Artemis.Core.DryIoc;
-using Artemis.Core.Providers;
-using Artemis.Core.Services;
-using Artemis.UI.Shared.Providers;
-using Artemis.UI.Windows.Providers;
-using Artemis.UI.Windows.Providers.Input;
-using DryIoc;
-
-namespace Artemis.UI.Windows.DryIoc;
-
-public class WindowsModule : IModule
-{
- ///
- public void Load(IRegistrator builder)
- {
- builder.Register(Reuse.Singleton);
- builder.Register(Reuse.Singleton);
- builder.Register(Reuse.Singleton);
- builder.Register();
- builder.Register(serviceKey: WindowsInputProvider.Id);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj
index bf4ce5d0c..a9446ed2c 100644
--- a/src/Artemis.UI/Artemis.UI.csproj
+++ b/src/Artemis.UI/Artemis.UI.csproj
@@ -31,8 +31,8 @@
-
-
+
+
diff --git a/src/Artemis.UI/ArtemisBootstrapper.cs b/src/Artemis.UI/ArtemisBootstrapper.cs
index 2e4a57937..1b47e8748 100644
--- a/src/Artemis.UI/ArtemisBootstrapper.cs
+++ b/src/Artemis.UI/ArtemisBootstrapper.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reactive;
+using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.DryIoc;
using Artemis.UI.DryIoc;
@@ -25,7 +26,7 @@ public static class ArtemisBootstrapper
private static Container? _container;
private static Application? _application;
- public static IContainer Bootstrap(Application application, params IModule[] modules)
+ public static IContainer Bootstrap(Application application, Action? configureServices = null)
{
if (_application != null || _container != null)
throw new ArtemisUIException("UI already bootstrapped");
@@ -33,18 +34,18 @@ public static class ArtemisBootstrapper
Utilities.PrepareFirstLaunch();
_application = application;
- _container = new Container(rules => rules.WithConcreteTypeDynamicRegistrations()
- .WithoutThrowOnRegisteringDisposableTransient());
+ _container = new Container(rules => rules
+ .WithMicrosoftDependencyInjectionRules()
+ .WithConcreteTypeDynamicRegistrations()
+ .WithoutThrowOnRegisteringDisposableTransient());
- new CoreModule().Load(_container);
- new UIModule().Load(_container);
- new SharedUIModule().Load(_container);
- new NoStringDryIocModule().Load(_container);
- foreach (IModule module in modules)
- module.Load(_container);
+ _container.RegisterCore();
+ _container.RegisterUI();
+ _container.RegisterSharedUI();
+ _container.RegisterNoStringEvaluating();
+ configureServices?.Invoke(_container);
_container.UseDryIocDependencyResolver();
-
return _container;
}
diff --git a/src/Artemis.UI/DryIoc/ContainerExtensions.cs b/src/Artemis.UI/DryIoc/ContainerExtensions.cs
new file mode 100644
index 000000000..3e4caf226
--- /dev/null
+++ b/src/Artemis.UI/DryIoc/ContainerExtensions.cs
@@ -0,0 +1,42 @@
+using System.Reflection;
+using Artemis.UI.DryIoc.Factories;
+using Artemis.UI.DryIoc.InstanceProviders;
+using Artemis.UI.Screens;
+using Artemis.UI.Screens.VisualScripting;
+using Artemis.UI.Services.Interfaces;
+using Artemis.UI.Shared;
+using Artemis.UI.Shared.Services.NodeEditor;
+using Artemis.UI.Shared.Services.ProfileEditor;
+using Avalonia.Platform;
+using Avalonia.Shared.PlatformSupport;
+using DryIoc;
+
+namespace Artemis.UI.DryIoc;
+
+///
+/// Provides an extension method to register services onto a DryIoc .
+///
+public static class ContainerExtensions
+{
+ ///
+ /// Registers UI services into the container.
+ ///
+ /// The builder building the current container
+ public static void RegisterUI(this IContainer container)
+ {
+ Assembly[] thisAssembly = {typeof(ContainerExtensions).Assembly};
+
+ container.RegisterInstance(new AssetLoader(), IfAlreadyRegistered.Throw);
+ container.Register(Reuse.Singleton);
+
+ container.RegisterMany(thisAssembly, type => type.IsAssignableTo());
+ container.RegisterMany(thisAssembly, type => type.IsAssignableTo(), ifAlreadyRegistered: IfAlreadyRegistered.Replace);
+ container.RegisterMany(thisAssembly, type => type.IsAssignableTo() && type.IsInterface);
+ container.RegisterMany(thisAssembly, type => type.IsAssignableTo() && type != typeof(PropertyVmFactory));
+
+ container.Register(Reuse.Singleton);
+ container.Register(Reuse.Singleton);
+
+ container.RegisterMany(thisAssembly, type => type.IsAssignableTo(), Reuse.Singleton);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.UI/DryIoc/UiModule.cs b/src/Artemis.UI/DryIoc/UiModule.cs
deleted file mode 100644
index 652f730d1..000000000
--- a/src/Artemis.UI/DryIoc/UiModule.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Reflection;
-using Artemis.Core.DryIoc;
-using Artemis.UI.DryIoc.Factories;
-using Artemis.UI.DryIoc.InstanceProviders;
-using Artemis.UI.Screens;
-using Artemis.UI.Screens.VisualScripting;
-using Artemis.UI.Services.Interfaces;
-using Artemis.UI.Shared;
-using Artemis.UI.Shared.Services.NodeEditor;
-using Artemis.UI.Shared.Services.ProfileEditor;
-using Avalonia.Platform;
-using Avalonia.Shared.PlatformSupport;
-using DryIoc;
-
-namespace Artemis.UI.DryIoc;
-
-public class UIModule : IModule
-{
- public void Load(IRegistrator builder)
- {
- Assembly thisAssembly = typeof(UIModule).Assembly;
-
- builder.RegisterInstance(new AssetLoader(), IfAlreadyRegistered.Throw);
- builder.Register(Reuse.Singleton);
-
- builder.RegisterMany(new[] { thisAssembly }, type => type.IsAssignableTo());
- builder.RegisterMany(new[] { thisAssembly }, type => type.IsAssignableTo(), ifAlreadyRegistered: IfAlreadyRegistered.Replace);
- builder.RegisterMany(new[] { thisAssembly }, type => type.IsAssignableTo() && type.IsInterface);
- builder.RegisterMany(new[] { thisAssembly }, type => type.IsAssignableTo() && type != typeof(PropertyVmFactory));
-
- builder.Register(Reuse.Singleton);
- builder.Register(Reuse.Singleton);
-
- builder.RegisterMany(new[] { thisAssembly }, type => type.IsAssignableTo(), Reuse.Singleton);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.VisualScripting/DryIoc/ContainerExtensions.cs b/src/Artemis.VisualScripting/DryIoc/ContainerExtensions.cs
new file mode 100644
index 000000000..0377f56ec
--- /dev/null
+++ b/src/Artemis.VisualScripting/DryIoc/ContainerExtensions.cs
@@ -0,0 +1,40 @@
+using DryIoc;
+using Microsoft.Extensions.ObjectPool;
+using NoStringEvaluating;
+using NoStringEvaluating.Contract;
+using NoStringEvaluating.Models.Values;
+using NoStringEvaluating.Services.Cache;
+using NoStringEvaluating.Services.Checking;
+using NoStringEvaluating.Services.Parsing;
+using NoStringEvaluating.Services.Parsing.NodeReaders;
+
+namespace Artemis.VisualScripting.DryIoc;
+
+///
+/// Provides an extension method to register services onto a DryIoc .
+///
+public static class ContainerExtensions
+{
+ ///
+ /// Registers NoStringEvaluating services into the container.
+ ///
+ /// The builder building the current container
+ public static void RegisterNoStringEvaluating(this IContainer container)
+ {
+ // Pooling
+ container.RegisterInstance(ObjectPool.Create>());
+ container.RegisterInstance(ObjectPool.Create>());
+ container.RegisterInstance(ObjectPool.Create());
+
+ // Parser
+ container.Register(Reuse.Singleton);
+ container.Register(Reuse.Singleton);
+ container.Register(Reuse.Singleton);
+
+ // Checker
+ container.Register(Reuse.Singleton);
+
+ // Evaluator
+ container.Register(Reuse.Singleton);
+ }
+}
\ No newline at end of file
diff --git a/src/Artemis.VisualScripting/DryIoc/NoStringNinjectModule.cs b/src/Artemis.VisualScripting/DryIoc/NoStringNinjectModule.cs
deleted file mode 100644
index 8d3563615..000000000
--- a/src/Artemis.VisualScripting/DryIoc/NoStringNinjectModule.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Artemis.Core.DryIoc;
-using DryIoc;
-using Microsoft.Extensions.ObjectPool;
-using NoStringEvaluating;
-using NoStringEvaluating.Contract;
-using NoStringEvaluating.Models.Values;
-using NoStringEvaluating.Services.Cache;
-using NoStringEvaluating.Services.Checking;
-using NoStringEvaluating.Services.Parsing;
-using NoStringEvaluating.Services.Parsing.NodeReaders;
-
-namespace Artemis.VisualScripting.DryIoc;
-
-public class NoStringDryIocModule : IModule
-{
- ///
- public void Load(IRegistrator builder)
- {
- // Pooling
- builder.RegisterInstance(ObjectPool.Create>());
- builder.RegisterInstance(ObjectPool.Create>());
- builder.RegisterInstance(ObjectPool.Create());
-
- // Parser
- builder.Register(Reuse.Singleton);
- builder.Register(Reuse.Singleton);
- builder.Register(Reuse.Singleton);
-
- // Checker
- builder.Register(Reuse.Singleton);
-
- // Evaluator
- builder.Register(Reuse.Singleton);
- }
-}
\ No newline at end of file
diff --git a/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs
index cba686c38..15ce66d84 100644
--- a/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs
+++ b/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs
@@ -3,7 +3,7 @@ using SkiaSharp;
namespace Artemis.VisualScripting.Nodes.Color;
-[Node("HSL Color", "Creates a color from hue, saturation and lightness values", "Color", InputType = typeof(Numeric), OutputType = typeof(SKColor))]
+[Node("HSL Color", "Creates a color from hue, saturation and lightness numbers", "Color", InputType = typeof(Numeric), OutputType = typeof(SKColor))]
public class HslSKColorNode : Node
{
public HslSKColorNode()
diff --git a/src/Artemis.VisualScripting/Nodes/Color/HsvSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/HsvSKColorNode.cs
new file mode 100644
index 000000000..2544ccec2
--- /dev/null
+++ b/src/Artemis.VisualScripting/Nodes/Color/HsvSKColorNode.cs
@@ -0,0 +1,31 @@
+using Artemis.Core;
+using SkiaSharp;
+
+namespace Artemis.VisualScripting.Nodes.Color;
+
+[Node("HSV Color", "Creates a color from hue, saturation and value numbers", "Color", InputType = typeof(Numeric), OutputType = typeof(SKColor))]
+public class HsvSKColorNode : Node
+{
+ public HsvSKColorNode()
+ {
+ H = CreateInputPin("H");
+ S = CreateInputPin("S");
+ V = CreateInputPin("V");
+ Output = CreateOutputPin();
+ }
+
+ public InputPin H { get; set; }
+ public InputPin S { get; set; }
+ public InputPin V { get; set; }
+ public OutputPin Output { get; }
+
+ #region Overrides of Node
+
+ ///
+ public override void Evaluate()
+ {
+ Output.Value = SKColor.FromHsv(H.Value, S.Value, V.Value);
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/src/Artemis.VisualScripting/Nodes/Color/SkColorHsl.cs b/src/Artemis.VisualScripting/Nodes/Color/SkColorHsl.cs
new file mode 100644
index 000000000..aaa1c6e26
--- /dev/null
+++ b/src/Artemis.VisualScripting/Nodes/Color/SkColorHsl.cs
@@ -0,0 +1,36 @@
+using Artemis.Core;
+using SkiaSharp;
+
+namespace Artemis.VisualScripting.Nodes.Color;
+
+[Node("Color to HSL", "Outputs H, S and L values from a color", "Color", InputType = typeof(SKColor), OutputType = typeof(Numeric))]
+public class SkColorHsl : Node
+{
+
+ public SkColorHsl()
+ {
+ Input = CreateInputPin();
+ H = CreateOutputPin("H");
+ S = CreateOutputPin("S");
+ L = CreateOutputPin("L");
+ }
+
+ public InputPin Input { get; }
+ public OutputPin H { get; }
+ public OutputPin S { get; }
+ public OutputPin L { get; }
+
+ #region Overrides of Node
+
+ ///
+ public override void Evaluate()
+ {
+ Input.Value.ToHsl(out float h, out float s, out float l);
+
+ H.Value = h;
+ S.Value = s;
+ L.Value = l;
+ }
+
+ #endregion
+}
\ No newline at end of file
diff --git a/src/Artemis.VisualScripting/Nodes/Color/SkColorHsv.cs b/src/Artemis.VisualScripting/Nodes/Color/SkColorHsv.cs
new file mode 100644
index 000000000..a0e448cf4
--- /dev/null
+++ b/src/Artemis.VisualScripting/Nodes/Color/SkColorHsv.cs
@@ -0,0 +1,36 @@
+using Artemis.Core;
+using SkiaSharp;
+
+namespace Artemis.VisualScripting.Nodes.Color;
+
+[Node("Color to HSV", "Outputs H, S and L values from a color", "Color", InputType = typeof(SKColor), OutputType = typeof(Numeric))]
+public class SkColorHsv : Node
+{
+
+ public SkColorHsv()
+ {
+ Input = CreateInputPin();
+ H = CreateOutputPin("H");
+ S = CreateOutputPin("S");
+ V = CreateOutputPin("V");
+ }
+
+ public InputPin Input { get; }
+ public OutputPin H { get; }
+ public OutputPin S { get; }
+ public OutputPin V { get; }
+
+ #region Overrides of Node
+
+ ///
+ public override void Evaluate()
+ {
+ Input.Value.ToHsv(out float h, out float s, out float v);
+
+ H.Value = h;
+ S.Value = s;
+ V.Value = v;
+ }
+
+ #endregion
+}
\ No newline at end of file