diff --git a/src/Artemis.Core/DryIoc/ContainerExtensions.cs b/src/Artemis.Core/DryIoc/ContainerExtensions.cs index 44d377e8a..8aa35b65f 100644 --- a/src/Artemis.Core/DryIoc/ContainerExtensions.cs +++ b/src/Artemis.Core/DryIoc/ContainerExtensions.cs @@ -5,7 +5,7 @@ using Artemis.Core.DryIoc.Factories; using Artemis.Core.Providers; using Artemis.Core.Services; using Artemis.Storage; -using Artemis.Storage.Migrations.Interfaces; +using Artemis.Storage.Migrations; using Artemis.Storage.Repositories.Interfaces; using DryIoc; @@ -36,6 +36,7 @@ public static class ContainerExtensions // Bind migrations container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true); + container.RegisterMany(storageAssembly, type => type.IsAssignableTo(), Reuse.Singleton, nonPublicServiceTypes: true); container.RegisterMany(coreAssembly, type => type.IsAssignableTo(), Reuse.Singleton); container.Register(Reuse.Singleton); diff --git a/src/Artemis.Core/Plugins/Nodes/NodeProvider.cs b/src/Artemis.Core/Plugins/Nodes/NodeProvider.cs new file mode 100644 index 000000000..24506297e --- /dev/null +++ b/src/Artemis.Core/Plugins/Nodes/NodeProvider.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Reflection; +using SkiaSharp; + +namespace Artemis.Core.Nodes; + +/// +/// Allows you to register one or more s usable by node scripts. +/// +public abstract class NodeProvider : PluginFeature +{ + private readonly List _nodeDescriptors; + + /// + /// Creates a new instance of the class. + /// + public NodeProvider() + { + _nodeDescriptors = new List(); + NodeDescriptors = new ReadOnlyCollection(_nodeDescriptors); + Disabled += OnDisabled; + } + + /// + /// A read-only collection of all nodes added with + /// + public ReadOnlyCollection NodeDescriptors { get; set; } + + /// + /// Adds a node descriptor for a given node, so that it appears in the UI. + /// Note: You do not need to manually remove these on disable + /// + /// The type of the node you wish to register + protected void RegisterNodeType() where T : INode + { + RegisterNodeType(typeof(T)); + } + + /// + /// Adds a node descriptor for a given node, so that it appears in the UI. + /// Note: You do not need to manually remove these on disable + /// + /// The type of the node you wish to register + protected void RegisterNodeType(Type nodeType) + { + if (!IsEnabled) + throw new ArtemisPluginFeatureException(this, "Can only add a node descriptor when the plugin is enabled"); + if (nodeType == null) + throw new ArgumentNullException(nameof(nodeType)); + if (!nodeType.IsAssignableTo(typeof(INode))) + throw new ArgumentException("Node has to be a base type of the Node-Type.", nameof(nodeType)); + + NodeAttribute? nodeAttribute = nodeType.GetCustomAttribute(); + string name = nodeAttribute?.Name ?? nodeType.Name; + string description = nodeAttribute?.Description ?? string.Empty; + string category = nodeAttribute?.Category ?? string.Empty; + string helpUrl = nodeAttribute?.HelpUrl ?? string.Empty; + + NodeData nodeData = new(this, nodeType, name, description, category, helpUrl, nodeAttribute?.InputType, nodeAttribute?.OutputType); + _nodeDescriptors.Add(nodeData); + NodeTypeStore.Add(nodeData); + } + + /// + /// Adds a color for lines of the provided type. + /// + /// The color to add. + /// The type to use the color for. + protected TypeColorRegistration RegisterTypeColor(SKColor color) + { + return NodeTypeStore.AddColor(typeof(T), color, this); + } + + private void OnDisabled(object? sender, EventArgs e) + { + // The store will clean up the registrations by itself, the plugin feature just needs to clear its own list + _nodeDescriptors.Clear(); + } +} \ No newline at end of file diff --git a/src/Artemis.Core/Services/NodeService.cs b/src/Artemis.Core/Services/NodeService.cs index 7cae6709b..96a0b617b 100644 --- a/src/Artemis.Core/Services/NodeService.cs +++ b/src/Artemis.Core/Services/NodeService.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; using System.Security.Cryptography; using System.Text; using Artemis.Storage.Entities.Profile.Nodes; -using DryIoc; using Newtonsoft.Json; using SkiaSharp; @@ -13,31 +11,8 @@ namespace Artemis.Core.Services; internal class NodeService : INodeService { - #region Constants - - private static readonly Type TypeNode = typeof(INode); - - #endregion - - private readonly IContainer _container; - - #region Constructors - - public NodeService(IContainer container) - { - _container = container; - } - - #endregion - - #region Properties & Fields - public IEnumerable AvailableNodes => NodeTypeStore.GetAll(); - #endregion - - #region Methods - /// public List GetRegisteredTypes() { @@ -53,7 +28,7 @@ internal class NodeService : INodeService // Objects represent an input that can take any type, these are hardcoded white if (type == typeof(object)) - return new TypeColorRegistration(type, new SKColor(255, 255, 255, 255), Constants.CorePlugin); + return new TypeColorRegistration(type, new SKColor(255, 255, 255, 255), Constants.CorePluginFeature); // Come up with a random color based on the type name that should be the same each time MD5 md5Hasher = MD5.Create(); @@ -61,32 +36,7 @@ internal class NodeService : INodeService int hash = BitConverter.ToInt32(hashed, 0); SKColor baseColor = SKColor.FromHsl(hash % 255, 50 + hash % 50, 50); - return new TypeColorRegistration(type, baseColor, Constants.CorePlugin); - } - - public NodeTypeRegistration RegisterNodeType(Plugin plugin, Type nodeType) - { - if (plugin == null) throw new ArgumentNullException(nameof(plugin)); - if (nodeType == null) throw new ArgumentNullException(nameof(nodeType)); - - if (!TypeNode.IsAssignableFrom(nodeType)) throw new ArgumentException("Node has to be a base type of the Node-Type.", nameof(nodeType)); - - NodeAttribute? nodeAttribute = nodeType.GetCustomAttribute(); - string name = nodeAttribute?.Name ?? nodeType.Name; - string description = nodeAttribute?.Description ?? string.Empty; - string category = nodeAttribute?.Category ?? string.Empty; - string helpUrl = nodeAttribute?.HelpUrl ?? string.Empty; - - NodeData nodeData = new(plugin, nodeType, name, description, category, helpUrl, nodeAttribute?.InputType, nodeAttribute?.OutputType, (s, e) => CreateNode(s, e, nodeType)); - return NodeTypeStore.Add(nodeData); - } - - public TypeColorRegistration RegisterTypeColor(Plugin plugin, Type type, SKColor color) - { - if (plugin == null) throw new ArgumentNullException(nameof(plugin)); - if (type == null) throw new ArgumentNullException(nameof(type)); - - return NodeTypeStore.AddColor(type, color, plugin); + return new TypeColorRegistration(type, baseColor, Constants.CorePluginFeature); } public string ExportScript(NodeScript nodeScript) @@ -103,33 +53,6 @@ internal class NodeService : INodeService target.LoadFromEntity(entity); } - - private INode CreateNode(INodeScript script, NodeEntity? entity, Type nodeType) - { - INode node = _container.Resolve(nodeType) as INode ?? throw new InvalidOperationException($"Node {nodeType} is not an INode"); - if (node is Node concreteNode) - concreteNode.Container = _container; - - if (entity != null) - { - node.X = entity.X; - node.Y = entity.Y; - try - { - if (node is Node nodeImplementation) - nodeImplementation.DeserializeStorage(entity.Storage); - } - catch - { - // ignored - } - } - - node.TryInitialize(script); - return node; - } - - #endregion } /// @@ -153,21 +76,6 @@ public interface INodeService : IArtemisService /// TypeColorRegistration GetTypeColorRegistration(Type type); - /// - /// Registers a node of the provided - /// - /// The plugin the node belongs to - /// The type of node to initialize - NodeTypeRegistration RegisterNodeType(Plugin plugin, Type nodeType); - - /// - /// Registers a type with a provided color for use in the node editor - /// - /// The plugin making the registration - /// The type to associate the color with - /// The color to display - TypeColorRegistration RegisterTypeColor(Plugin plugin, Type type, SKColor color); - /// /// Exports the provided node script to JSON. /// diff --git a/src/Artemis.Core/Services/Storage/ProfileService.cs b/src/Artemis.Core/Services/Storage/ProfileService.cs index f2dd26de6..90b25ea5f 100644 --- a/src/Artemis.Core/Services/Storage/ProfileService.cs +++ b/src/Artemis.Core/Services/Storage/ProfileService.cs @@ -8,8 +8,10 @@ using System.Text; using System.Threading.Tasks; using Artemis.Core.Modules; using Artemis.Storage.Entities.Profile; +using Artemis.Storage.Migrations; using Artemis.Storage.Repositories.Interfaces; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using Serilog; using SkiaSharp; @@ -24,9 +26,10 @@ internal class ProfileService : IProfileService private readonly List _pendingKeyboardEvents = new(); private readonly List _profileCategories; private readonly IProfileRepository _profileRepository; + private readonly List _profileMigrators; private readonly List _renderExceptions = new(); private readonly List _updateExceptions = new(); - + private DateTime _lastRenderExceptionLog; private DateTime _lastUpdateExceptionLog; @@ -35,13 +38,15 @@ internal class ProfileService : IProfileService IPluginManagementService pluginManagementService, IInputService inputService, IDeviceService deviceService, - IProfileRepository profileRepository) + IProfileRepository profileRepository, + List profileMigrators) { _logger = logger; _profileCategoryRepository = profileCategoryRepository; _pluginManagementService = pluginManagementService; _deviceService = deviceService; _profileRepository = profileRepository; + _profileMigrators = profileMigrators; _profileCategories = new List(_profileCategoryRepository.GetAll().Select(c => new ProfileCategory(c)).OrderBy(c => c.Order)); _deviceService.LedsChanged += DeviceServiceOnLedsChanged; @@ -58,7 +63,7 @@ internal class ProfileService : IProfileService public ProfileConfiguration? FocusProfile { get; set; } public ProfileElement? FocusProfileElement { get; set; } public bool UpdateFocusProfile { get; set; } - + public bool ProfileRenderingDisabled { get; set; } /// @@ -461,7 +466,12 @@ internal class ProfileService : IProfileService await using Stream profileStream = profileEntry.Open(); using StreamReader profileReader = new(profileStream); - ProfileEntity? profileEntity = JsonConvert.DeserializeObject(await profileReader.ReadToEndAsync(), IProfileService.ExportSettings); + JObject? profileJson = JsonConvert.DeserializeObject(await profileReader.ReadToEndAsync(), IProfileService.ExportSettings); + + // Before deserializing, apply any pending migrations + MigrateProfile(configurationEntity, profileJson); + + ProfileEntity? profileEntity = profileJson?.ToObject(JsonSerializer.Create(IProfileService.ExportSettings)); if (profileEntity == null) throw new ArtemisCoreException("Could not import profile, failed to deserialize profile.json"); @@ -514,10 +524,10 @@ internal class ProfileService : IProfileService public async Task OverwriteProfile(MemoryStream archiveStream, ProfileConfiguration profileConfiguration) { ProfileConfiguration imported = await ImportProfile(archiveStream, profileConfiguration.Category, true, true, null, profileConfiguration.Order + 1); - + DeleteProfile(profileConfiguration); SaveProfileCategory(imported.Category); - + return imported; } @@ -545,6 +555,21 @@ internal class ProfileService : IProfileService } } + private void MigrateProfile(ProfileConfigurationEntity configurationEntity, JObject? profileJson) + { + if (profileJson == null) + return; + + foreach (IProfileMigration profileMigrator in _profileMigrators.OrderBy(m => m.Version)) + { + if (profileMigrator.Version <= configurationEntity.Version) + continue; + + profileMigrator.Migrate(profileJson); + configurationEntity.Version = profileMigrator.Version; + } + } + /// /// Populates all missing LEDs on all currently active profiles /// diff --git a/src/Artemis.Core/Stores/NodeTypeStore.cs b/src/Artemis.Core/Stores/NodeTypeStore.cs index 052cac84c..05c31519b 100644 --- a/src/Artemis.Core/Stores/NodeTypeStore.cs +++ b/src/Artemis.Core/Stores/NodeTypeStore.cs @@ -13,16 +13,13 @@ internal class NodeTypeStore public static NodeTypeRegistration Add(NodeData nodeData) { - if (nodeData.Plugin == null) - throw new ArtemisCoreException("Cannot add a data binding modifier type that is not associated with a plugin"); - NodeTypeRegistration typeRegistration; lock (Registrations) { if (Registrations.Any(r => r.NodeData == nodeData)) throw new ArtemisCoreException($"Data binding modifier type store already contains modifier '{nodeData.Name}'"); - typeRegistration = new NodeTypeRegistration(nodeData, nodeData.Plugin) {IsInStore = true}; + typeRegistration = new NodeTypeRegistration(nodeData, nodeData.Provider) {IsInStore = true}; Registrations.Add(typeRegistration); } @@ -60,24 +57,12 @@ internal class NodeTypeStore } } - public static Plugin? GetPlugin(INode node) - { - Type nodeType = node.GetType(); - lock (Registrations) - { - return Registrations.FirstOrDefault(r => r.NodeData.Type == nodeType)?.Plugin; - } - } - - public static TypeColorRegistration AddColor(Type type, SKColor color, Plugin plugin) + public static TypeColorRegistration AddColor(Type type, SKColor color, PluginFeature pluginFeature) { TypeColorRegistration typeColorRegistration; lock (ColorRegistrations) { - if (ColorRegistrations.Any(r => r.Type == type)) - throw new ArtemisCoreException($"Node color store already contains a color for '{type.Name}'"); - - typeColorRegistration = new TypeColorRegistration(type, color, plugin) {IsInStore = true}; + typeColorRegistration = new TypeColorRegistration(type, color, pluginFeature) {IsInStore = true}; ColorRegistrations.Add(typeColorRegistration); } diff --git a/src/Artemis.Core/Stores/Registrations/NodeTypeRegistration.cs b/src/Artemis.Core/Stores/Registrations/NodeTypeRegistration.cs index 659eb3503..bc5064c63 100644 --- a/src/Artemis.Core/Stores/Registrations/NodeTypeRegistration.cs +++ b/src/Artemis.Core/Stores/Registrations/NodeTypeRegistration.cs @@ -9,12 +9,12 @@ namespace Artemis.Core; /// public class NodeTypeRegistration { - internal NodeTypeRegistration(NodeData nodeData, Plugin plugin) + internal NodeTypeRegistration(NodeData nodeData, PluginFeature pluginFeature) { NodeData = nodeData; - Plugin = plugin; + PluginFeature = pluginFeature; - Plugin.Disabled += OnDisabled; + PluginFeature.Disabled += OnDisabled; } /// @@ -23,9 +23,9 @@ public class NodeTypeRegistration public NodeData NodeData { get; } /// - /// Gets the plugin the node is associated with + /// Gets the plugin feature the node is associated with /// - public Plugin Plugin { get; } + public PluginFeature PluginFeature { get; } /// /// Gets a boolean indicating whether the registration is in the internal Core store @@ -39,12 +39,12 @@ public class NodeTypeRegistration /// if the entity matches this registration; otherwise . public bool MatchesEntity(NodeEntity entity) { - return Plugin.Guid == entity.PluginId && NodeData.Type.Name == entity.Type; + return PluginFeature.Id == entity.ProviderId && NodeData.Type.Name == entity.Type; } private void OnDisabled(object? sender, EventArgs e) { - Plugin.Disabled -= OnDisabled; + PluginFeature.Disabled -= OnDisabled; if (IsInStore) NodeTypeStore.Remove(this); } @@ -55,13 +55,13 @@ public class NodeTypeRegistration /// public class TypeColorRegistration { - internal TypeColorRegistration(Type type, SKColor color, Plugin plugin) + internal TypeColorRegistration(Type type, SKColor color, PluginFeature pluginFeature) { Type = type; Color = color; - Plugin = plugin; + PluginFeature = pluginFeature; - Plugin.Disabled += OnDisabled; + PluginFeature.Disabled += OnDisabled; } /// @@ -80,9 +80,9 @@ public class TypeColorRegistration public SKColor DarkenedColor => Color.Darken(0.35f); /// - /// Gets the plugin type color is associated with + /// Gets the plugin feature this type color is associated with /// - public Plugin Plugin { get; } + public PluginFeature PluginFeature { get; } /// /// Gets a boolean indicating whether the registration is in the internal Core store @@ -91,7 +91,7 @@ public class TypeColorRegistration private void OnDisabled(object? sender, EventArgs e) { - Plugin.Disabled -= OnDisabled; + PluginFeature.Disabled -= OnDisabled; if (IsInStore) NodeTypeStore.RemoveColor(this); } diff --git a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs index 3bc2521fb..4ce40a0ab 100644 --- a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs +++ b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs @@ -14,6 +14,11 @@ public interface INode : INotifyPropertyChanged, IBreakableModel /// Gets or sets the ID of the node. /// Guid Id { get; set; } + + /// + /// Gets or sets the node data with information about this node + /// + NodeData? NodeData { get; set; } /// /// Gets the name of the node diff --git a/src/Artemis.Core/VisualScripting/NodeData.cs b/src/Artemis.Core/VisualScripting/NodeData.cs index 5b0c678e2..dff2a5a2d 100644 --- a/src/Artemis.Core/VisualScripting/NodeData.cs +++ b/src/Artemis.Core/VisualScripting/NodeData.cs @@ -1,4 +1,5 @@ using System; +using Artemis.Core.Nodes; using Artemis.Storage.Entities.Profile.Nodes; namespace Artemis.Core; @@ -10,9 +11,9 @@ public class NodeData { #region Constructors - internal NodeData(Plugin plugin, Type type, string name, string description, string category, string helpUrl, Type? inputType, Type? outputType, Func create) + internal NodeData(NodeProvider provider, Type type, string name, string description, string category, string helpUrl, Type? inputType, Type? outputType) { - Plugin = plugin; + Provider = provider; Type = type; Name = name; Description = description; @@ -20,7 +21,6 @@ public class NodeData HelpUrl = helpUrl; InputType = inputType; OutputType = outputType; - _create = create; } #endregion @@ -35,14 +35,31 @@ public class NodeData /// The returning node of type public INode CreateNode(INodeScript script, NodeEntity? entity) { - INode node = _create(script, entity); + INode node = (INode) Provider.Plugin.Resolve(Type); + node.NodeData = this; if (string.IsNullOrWhiteSpace(node.Name)) node.Name = Name; if (string.IsNullOrWhiteSpace(node.Description)) node.Description = Description; if (string.IsNullOrWhiteSpace(node.HelpUrl)) node.HelpUrl = HelpUrl; + + if (entity != null) + { + node.X = entity.X; + node.Y = entity.Y; + try + { + if (node is Node nodeImplementation) + nodeImplementation.DeserializeStorage(entity.Storage); + } + catch + { + // ignored + } + } + node.TryInitialize(script); return node; } @@ -91,11 +108,11 @@ public class NodeData } #region Properties & Fields - + /// - /// Gets the plugin that provided this node data + /// Gets the node provider that provided this node data /// - public Plugin Plugin { get; } + public NodeProvider Provider { get; } /// /// Gets the type of this data represents @@ -132,7 +149,5 @@ public class NodeData /// public Type? OutputType { get; } - private readonly Func _create; - #endregion } \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/NodeScript.cs b/src/Artemis.Core/VisualScripting/NodeScript.cs index 7672f3504..e8ccddd4a 100644 --- a/src/Artemis.Core/VisualScripting/NodeScript.cs +++ b/src/Artemis.Core/VisualScripting/NodeScript.cs @@ -161,6 +161,7 @@ public abstract class NodeScript : CorePropertyChanged, INodeScript { foreach (INode node in _nodes) { + // ReSharper disable once SuspiciousTypeConversion.Global - Provided by plugins if (node is IDisposable disposable) disposable.Dispose(); } @@ -181,6 +182,7 @@ public abstract class NodeScript : CorePropertyChanged, INodeScript foreach (INode removeNode in removeNodes) { RemoveNode(removeNode); + // ReSharper disable once SuspiciousTypeConversion.Global - Provided by plugins if (removeNode is IDisposable disposable) disposable.Dispose(); } @@ -312,7 +314,7 @@ public abstract class NodeScript : CorePropertyChanged, INodeScript NodeEntity nodeEntity = new() { Id = node.Id, - PluginId = NodeTypeStore.GetPlugin(node)?.Guid ?? Constants.CorePlugin.Guid, + ProviderId = node.NodeData?.Provider.Id ?? Constants.CorePluginFeature.Id, Type = node.GetType().Name, X = node.X, Y = node.Y, diff --git a/src/Artemis.Core/VisualScripting/Nodes/Node.cs b/src/Artemis.Core/VisualScripting/Nodes/Node.cs index 5ff7dd254..8d4a40d3d 100644 --- a/src/Artemis.Core/VisualScripting/Nodes/Node.cs +++ b/src/Artemis.Core/VisualScripting/Nodes/Node.cs @@ -41,6 +41,9 @@ public abstract class Node : BreakableModel, INode set => SetAndNotify(ref _id, value); } + /// + public NodeData? NodeData { get; set; } + private string _name; /// @@ -104,8 +107,6 @@ public abstract class Node : BreakableModel, INode /// public override string BrokenDisplayName => Name; - internal IContainer Container { get; set; } = null!; - #endregion #region Construtors diff --git a/src/Artemis.Core/VisualScripting/Nodes/NodeTStorageTViewModel.cs b/src/Artemis.Core/VisualScripting/Nodes/NodeTStorageTViewModel.cs index 98965c154..79e858644 100644 --- a/src/Artemis.Core/VisualScripting/Nodes/NodeTStorageTViewModel.cs +++ b/src/Artemis.Core/VisualScripting/Nodes/NodeTStorageTViewModel.cs @@ -25,7 +25,9 @@ public abstract class Node : Node, ICustomViewMo /// public virtual TViewModel GetViewModel(NodeScript nodeScript) { - return Container.Resolve(args: new object[] {this, nodeScript}); + if (NodeData == null) + throw new ArtemisCoreException("Nodes without node data (default nodes or exit nodes) cannot have custom view models"); + return NodeData.Provider.Plugin.Container.Resolve(args: new object[] {this, nodeScript}); } /// diff --git a/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs b/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs index 234d3c7a7..cec7d2601 100644 --- a/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/Nodes/NodeEntity.cs @@ -15,7 +15,7 @@ public class NodeEntity { Id = nodeEntity.Id; Type = nodeEntity.Type; - PluginId = nodeEntity.PluginId; + ProviderId = nodeEntity.ProviderId; Name = nodeEntity.Name; Description = nodeEntity.Description; @@ -29,7 +29,7 @@ public class NodeEntity public Guid Id { get; set; } public string Type { get; set; } = string.Empty; - public Guid PluginId { get; set; } + public string ProviderId { get; set; } = string.Empty; public string Name { get; set; } = string.Empty; public string Description { get; set; } = string.Empty; diff --git a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs index 17f94580b..a3eeef113 100644 --- a/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/ProfileConfigurationEntity.cs @@ -26,4 +26,5 @@ public class ProfileConfigurationEntity public Guid ProfileId { get; set; } public bool FadeInAndOut { get; set; } + public int Version { get; set; } } \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/IProfileMigration.cs b/src/Artemis.Storage/Migrations/IProfileMigration.cs index d48cab32b..1bb41c022 100644 --- a/src/Artemis.Storage/Migrations/IProfileMigration.cs +++ b/src/Artemis.Storage/Migrations/IProfileMigration.cs @@ -1,11 +1,9 @@ -using LiteDB; using Newtonsoft.Json.Linq; namespace Artemis.Storage.Migrations; -internal interface IProfileMigration +public interface IProfileMigration { int Version { get; } void Migrate(JObject profileJson); - void Migrate(BsonDocument profileBson); } \ No newline at end of file diff --git a/src/Artemis.Storage/Migrations/IStorageMigration.cs b/src/Artemis.Storage/Migrations/IStorageMigration.cs index dbee4bcba..4382a837d 100644 --- a/src/Artemis.Storage/Migrations/IStorageMigration.cs +++ b/src/Artemis.Storage/Migrations/IStorageMigration.cs @@ -1,6 +1,6 @@ using LiteDB; -namespace Artemis.Storage.Migrations.Interfaces; +namespace Artemis.Storage.Migrations; public interface IStorageMigration { diff --git a/src/Artemis.Storage/Migrations/Profile/M0001NodeProviders.cs b/src/Artemis.Storage/Migrations/Profile/M0001NodeProviders.cs index 9e8f62f1f..0dfab33a2 100644 --- a/src/Artemis.Storage/Migrations/Profile/M0001NodeProviders.cs +++ b/src/Artemis.Storage/Migrations/Profile/M0001NodeProviders.cs @@ -1,4 +1,3 @@ -using LiteDB; using Newtonsoft.Json.Linq; namespace Artemis.Storage.Migrations.Profile; @@ -21,9 +20,7 @@ internal class M0001NodeProviders : IProfileMigration if (folders != null) { foreach (JToken folder in folders) - { MigrateProfileElement(folder); - } } if (layers != null) @@ -38,12 +35,6 @@ internal class M0001NodeProviders : IProfileMigration } } - /// - public void Migrate(BsonDocument profileBson) - { - throw new System.NotImplementedException(); - } - private void MigrateProfileElement(JToken profileElement) { JArray? layerEffects = (JArray?) profileElement["LayerEffects"]?["$values"]; diff --git a/src/Artemis.Storage/Migrations/Storage/M0020AvaloniaReset.cs b/src/Artemis.Storage/Migrations/Storage/M0020AvaloniaReset.cs index 741ba35b0..293fc1ff7 100644 --- a/src/Artemis.Storage/Migrations/Storage/M0020AvaloniaReset.cs +++ b/src/Artemis.Storage/Migrations/Storage/M0020AvaloniaReset.cs @@ -1,9 +1,8 @@ using System.Collections.Generic; using System.Linq; -using Artemis.Storage.Migrations.Interfaces; using LiteDB; -namespace Artemis.Storage.Migrations; +namespace Artemis.Storage.Migrations.Storage; public class M0020AvaloniaReset : IStorageMigration { diff --git a/src/Artemis.Storage/Migrations/Storage/M0021GradientNodes.cs b/src/Artemis.Storage/Migrations/Storage/M0021GradientNodes.cs index a6ebcac3e..2bb90a45c 100644 --- a/src/Artemis.Storage/Migrations/Storage/M0021GradientNodes.cs +++ b/src/Artemis.Storage/Migrations/Storage/M0021GradientNodes.cs @@ -3,10 +3,9 @@ using System.Collections.Generic; using System.Linq; using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile.Nodes; -using Artemis.Storage.Migrations.Interfaces; using LiteDB; -namespace Artemis.Storage.Migrations; +namespace Artemis.Storage.Migrations.Storage; public class M0021GradientNodes : IStorageMigration { @@ -22,7 +21,7 @@ public class M0021GradientNodes : IStorageMigration { Id = Guid.NewGuid(), Type = "ColorGradientNode", - PluginId = Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff"), + ProviderId = "Artemis.Plugins.Nodes.General.GeneralNodesProvider-d9e1ee78", Name = "Color Gradient", Description = "Outputs a color gradient with the given colors", X = exitNode.X, diff --git a/src/Artemis.Storage/Migrations/Storage/M0022TransitionNodes.cs b/src/Artemis.Storage/Migrations/Storage/M0022TransitionNodes.cs index 6256c097d..791b95ea9 100644 --- a/src/Artemis.Storage/Migrations/Storage/M0022TransitionNodes.cs +++ b/src/Artemis.Storage/Migrations/Storage/M0022TransitionNodes.cs @@ -3,10 +3,9 @@ using Artemis.Storage.Entities.Profile; using Artemis.Storage.Entities.Profile.Abstract; using Artemis.Storage.Entities.Profile.Conditions; using Artemis.Storage.Entities.Profile.Nodes; -using Artemis.Storage.Migrations.Interfaces; using LiteDB; -namespace Artemis.Storage.Migrations; +namespace Artemis.Storage.Migrations.Storage; public class M0022TransitionNodes : IStorageMigration { diff --git a/src/Artemis.Storage/Migrations/Storage/M0023LayoutProviders.cs b/src/Artemis.Storage/Migrations/Storage/M0023LayoutProviders.cs index 5914b01c2..5296d5842 100644 --- a/src/Artemis.Storage/Migrations/Storage/M0023LayoutProviders.cs +++ b/src/Artemis.Storage/Migrations/Storage/M0023LayoutProviders.cs @@ -1,8 +1,7 @@ using System.Collections.Generic; -using Artemis.Storage.Migrations.Interfaces; using LiteDB; -namespace Artemis.Storage.Migrations; +namespace Artemis.Storage.Migrations.Storage; public class M0023LayoutProviders : IStorageMigration { diff --git a/src/Artemis.Storage/Migrations/Storage/M0024NodeProviders.cs b/src/Artemis.Storage/Migrations/Storage/M0024NodeProviders.cs new file mode 100644 index 000000000..4d0a4211e --- /dev/null +++ b/src/Artemis.Storage/Migrations/Storage/M0024NodeProviders.cs @@ -0,0 +1,100 @@ +using System.Collections.Generic; +using Artemis.Storage.Entities.Profile; +using LiteDB; + +namespace Artemis.Storage.Migrations.Storage; + +public class M0024NodeProviders : IStorageMigration +{ + public int UserVersion => 24; + + public void Apply(LiteRepository repository) + { + List profileCategories = repository.Query().ToList(); + foreach (ProfileCategoryEntity profileCategory in profileCategories) + { + foreach (ProfileConfigurationEntity profileConfigurationEntity in profileCategory.ProfileConfigurations) + { + profileConfigurationEntity.Version = 1; + } + repository.Update(profileCategory); + } + + ILiteCollection collection = repository.Database.GetCollection("ProfileEntity"); + foreach (BsonDocument profileBson in collection.FindAll()) + { + BsonArray? folders = profileBson["Folders"]?.AsArray; + BsonArray? layers = profileBson["Layers"]?.AsArray; + + if (folders != null) + { + foreach (BsonValue folder in folders) + MigrateProfileElement(folder.AsDocument); + } + + if (layers != null) + { + foreach (BsonValue layer in layers) + { + MigrateProfileElement(layer.AsDocument); + MigratePropertyGroup(layer.AsDocument["GeneralPropertyGroup"].AsDocument); + MigratePropertyGroup(layer.AsDocument["TransformPropertyGroup"].AsDocument); + MigratePropertyGroup(layer.AsDocument["LayerBrush"]?["PropertyGroup"].AsDocument); + } + } + + collection.Update(profileBson); + } + } + + private void MigrateProfileElement(BsonDocument profileElement) + { + BsonArray? layerEffects = profileElement["LayerEffects"]?.AsArray; + if (layerEffects != null) + { + foreach (BsonValue layerEffect in layerEffects) + MigratePropertyGroup(layerEffect.AsDocument["PropertyGroup"].AsDocument); + } + + BsonValue? displayCondition = profileElement["DisplayCondition"]; + if (displayCondition != null) + MigrateNodeScript(displayCondition.AsDocument["Script"].AsDocument); + } + + private void MigratePropertyGroup(BsonDocument? propertyGroup) + { + if (propertyGroup == null || propertyGroup.Keys.Count == 0) + return; + + BsonArray? properties = propertyGroup["Properties"]?.AsArray; + BsonArray? propertyGroups = propertyGroup["PropertyGroups"]?.AsArray; + + if (properties != null) + { + foreach (BsonValue property in properties) + MigrateNodeScript(property.AsDocument["DataBinding"]?["NodeScript"]?.AsDocument); + } + + if (propertyGroups != null) + { + foreach (BsonValue childPropertyGroup in propertyGroups) + MigratePropertyGroup(childPropertyGroup.AsDocument); + } + } + + private void MigrateNodeScript(BsonDocument? nodeScript) + { + if (nodeScript == null || nodeScript.Keys.Count == 0) + return; + + BsonArray? nodes = nodeScript["Nodes"]?.AsArray; + if (nodes == null) + return; + + foreach (BsonValue node in nodes) + { + node.AsDocument["Type"] = node.AsDocument["Type"]?.AsString?.Replace("Artemis.VisualScripting.Nodes", "Artemis.Plugins.Nodes.General.Nodes"); + node.AsDocument["ProviderId"] = "Artemis.Plugins.Nodes.General.GeneralNodesProvider-d9e1ee78"; + } + } +} \ No newline at end of file diff --git a/src/Artemis.Storage/Repositories/PluginRepository.cs b/src/Artemis.Storage/Repositories/PluginRepository.cs index 9c278b607..02a8985c0 100644 --- a/src/Artemis.Storage/Repositories/PluginRepository.cs +++ b/src/Artemis.Storage/Repositories/PluginRepository.cs @@ -29,7 +29,6 @@ internal class PluginRepository : IPluginRepository public void SavePlugin(PluginEntity pluginEntity) { _repository.Upsert(pluginEntity); - _repository.Database.Checkpoint(); } public void AddSetting(PluginSettingEntity pluginSettingEntity) diff --git a/src/Artemis.Storage/StorageMigrationService.cs b/src/Artemis.Storage/StorageMigrationService.cs index 169144e5c..cf728023b 100644 --- a/src/Artemis.Storage/StorageMigrationService.cs +++ b/src/Artemis.Storage/StorageMigrationService.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Artemis.Storage.Migrations.Interfaces; +using Artemis.Storage.Migrations; using LiteDB; using Serilog; diff --git a/src/Artemis.UI.Shared/Services/DataModelUIService.cs b/src/Artemis.UI.Shared/Services/DataModelUIService.cs index f7fe353f6..fc8569711 100644 --- a/src/Artemis.UI.Shared/Services/DataModelUIService.cs +++ b/src/Artemis.UI.Shared/Services/DataModelUIService.cs @@ -18,16 +18,20 @@ internal class DataModelUIService : IDataModelUIService private readonly IContainer _container; private readonly List _registeredDataModelDisplays; private readonly List _registeredDataModelEditors; + private readonly PluginSetting _showFullPaths; + private readonly PluginSetting _showDataModelValues; - public DataModelUIService(IDataModelService dataModelService, IContainer container) + public DataModelUIService(IDataModelService dataModelService, IContainer container, ISettingsService settingsService) { _dataModelService = dataModelService; _container = container; _registeredDataModelEditors = new List(); _registeredDataModelDisplays = new List(); - + RegisteredDataModelEditors = new ReadOnlyCollection(_registeredDataModelEditors); RegisteredDataModelDisplays = new ReadOnlyCollection(_registeredDataModelDisplays); + ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true); + ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false); } private DataModelInputViewModel InstantiateDataModelInputViewModel(DataModelVisualizationRegistration registration, DataModelPropertyAttribute? description, object? initialValue) @@ -43,7 +47,9 @@ internal class DataModelUIService : IDataModelUIService public IReadOnlyCollection RegisteredDataModelEditors { get; } public IReadOnlyCollection RegisteredDataModelDisplays { get; } - + public PluginSetting ShowFullPaths { get; } + public PluginSetting ShowDataModelValues { get; } + public DataModelPropertiesViewModel GetMainDataModelVisualization() { DataModelPropertiesViewModel viewModel = new(null, null, null); diff --git a/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs b/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs index a91766a44..b70c5e8af 100644 --- a/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs +++ b/src/Artemis.UI.Shared/Services/Interfaces/IDataModelUIService.cs @@ -104,4 +104,14 @@ public interface IDataModelUIService : IArtemisSharedUIService /// A function to call whenever the input was updated (submitted or not) /// The most appropriate input view model for the provided DataModelInputViewModel? GetDataModelInputViewModel(Type propertyType, DataModelPropertyAttribute? description, object? initialValue, Action updateCallback); + + /// + /// Gets a boolean indicating whether or not to show full paths when displaying data model paths. + /// + PluginSetting ShowFullPaths { get; } + + /// + /// Gets a boolean indicating whether or not to show values when displaying data model paths. + /// + PluginSetting ShowDataModelValues { get; } } \ No newline at end of file diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs index 3d6033784..c3bff92f1 100644 --- a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs +++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/AddNode.cs @@ -27,6 +27,7 @@ public class AddNode : INodeEditorCommand, IDisposable /// public void Dispose() { + // ReSharper disable once SuspiciousTypeConversion.Global - Provided by plugins if (_isRemoved && _node is IDisposable disposableNode) disposableNode.Dispose(); } diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs index 944c81e81..d40664d58 100644 --- a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs +++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DeleteNode.cs @@ -29,6 +29,7 @@ public class DeleteNode : INodeEditorCommand, IDisposable /// public void Dispose() { + // ReSharper disable once SuspiciousTypeConversion.Global - Provided by plugins if (_isRemoved && _node is IDisposable disposableNode) disposableNode.Dispose(); } diff --git a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs index 62340d3a6..b872e069e 100644 --- a/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs +++ b/src/Artemis.UI.Shared/Services/NodeEditor/Commands/DuplicateNode.cs @@ -87,6 +87,7 @@ public class DuplicateNode : INodeEditorCommand, IDisposable /// public void Dispose() { + // ReSharper disable once SuspiciousTypeConversion.Global - Provided by plugins if (!_executed && _copy is IDisposable disposableNode) disposableNode.Dispose(); } diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 88b39600b..582b75799 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -10,7 +10,6 @@ - diff --git a/src/Artemis.UI/ArtemisBootstrapper.cs b/src/Artemis.UI/ArtemisBootstrapper.cs index f869bb8e3..1da2a10ec 100644 --- a/src/Artemis.UI/ArtemisBootstrapper.cs +++ b/src/Artemis.UI/ArtemisBootstrapper.cs @@ -10,10 +10,8 @@ using Artemis.UI.Screens.Root; using Artemis.UI.Shared.DataModelPicker; using Artemis.UI.Shared.DryIoc; using Artemis.UI.Shared.Services; -using Artemis.VisualScripting.DryIoc; using Artemis.WebClient.Updating.DryIoc; using Artemis.WebClient.Workshop.DryIoc; -using Artemis.WebClient.Workshop.Services; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; @@ -49,7 +47,6 @@ public static class ArtemisBootstrapper _container.RegisterSharedUI(); _container.RegisterUpdatingClient(); _container.RegisterWorkshopClient(); - _container.RegisterNoStringEvaluating(); configureServices?.Invoke(_container); _container.UseDryIocDependencyResolver(); diff --git a/src/Artemis.UI/Screens/VisualScripting/NodeViewModel.cs b/src/Artemis.UI/Screens/VisualScripting/NodeViewModel.cs index 722bfbf26..f1ff6dbb3 100644 --- a/src/Artemis.UI/Screens/VisualScripting/NodeViewModel.cs +++ b/src/Artemis.UI/Screens/VisualScripting/NodeViewModel.cs @@ -18,11 +18,13 @@ using DynamicData; using DynamicData.Binding; using PropertyChanged.SourceGenerator; using ReactiveUI; +using Serilog; namespace Artemis.UI.Screens.VisualScripting; public partial class NodeViewModel : ActivatableViewModelBase { + private readonly ILogger _logger; private readonly INodeEditorService _nodeEditorService; private readonly IWindowService _windowService; private ObservableAsPropertyHelper? _hasInputPins; @@ -39,8 +41,9 @@ public partial class NodeViewModel : ActivatableViewModelBase [Notify] private bool _displayCustomViewModelBelow; [Notify] private VerticalAlignment _customViewModelVerticalAlignment; - public NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService, IWindowService windowService) + public NodeViewModel(NodeScriptViewModel nodeScriptViewModel, INode node, ILogger logger, INodeVmFactory nodeVmFactory, INodeEditorService nodeEditorService, IWindowService windowService) { + _logger = logger; _nodeEditorService = nodeEditorService; _windowService = windowService; NodeScriptViewModel = nodeScriptViewModel; @@ -137,25 +140,7 @@ public partial class NodeViewModel : ActivatableViewModelBase }); // Set up the custom node VM if needed - if (Node is ICustomViewModelNode customViewModelNode) - { - CustomNodeViewModel = customViewModelNode.GetCustomViewModel(nodeScriptViewModel.NodeScript); - if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.AbovePins) - DisplayCustomViewModelAbove = true; - else if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.BelowPins) - DisplayCustomViewModelBelow = true; - else - { - DisplayCustomViewModelBetween = true; - - if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.BetweenPinsTop) - CustomViewModelVerticalAlignment = VerticalAlignment.Top; - else if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.BetweenPinsTop) - CustomViewModelVerticalAlignment = VerticalAlignment.Center; - else - CustomViewModelVerticalAlignment = VerticalAlignment.Bottom; - } - } + SetupCustomNodeViewModel(); }); } @@ -209,4 +194,35 @@ public partial class NodeViewModel : ActivatableViewModelBase if (Node.BrokenState != null && Node.BrokenStateException != null) _windowService.ShowExceptionDialog(Node.BrokenState, Node.BrokenStateException); } + + private void SetupCustomNodeViewModel() + { + if (Node is not ICustomViewModelNode customViewModelNode) + return; + + try + { + CustomNodeViewModel = customViewModelNode.GetCustomViewModel(NodeScriptViewModel.NodeScript); + } + catch (Exception e) + { + _logger.Error(e, "Failed to instantiate custom node view model"); + } + + if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.AbovePins) + DisplayCustomViewModelAbove = true; + else if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.BelowPins) + DisplayCustomViewModelBelow = true; + else + { + DisplayCustomViewModelBetween = true; + + if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.BetweenPinsTop) + CustomViewModelVerticalAlignment = VerticalAlignment.Top; + else if (customViewModelNode.ViewModelPosition == CustomNodeViewModelPosition.BetweenPinsTop) + CustomViewModelVerticalAlignment = VerticalAlignment.Center; + else + CustomViewModelVerticalAlignment = VerticalAlignment.Bottom; + } + } } \ No newline at end of file diff --git a/src/Artemis.UI/Services/Interfaces/IRegistrationService.cs b/src/Artemis.UI/Services/Interfaces/IRegistrationService.cs index d77128fc3..08da9c640 100644 --- a/src/Artemis.UI/Services/Interfaces/IRegistrationService.cs +++ b/src/Artemis.UI/Services/Interfaces/IRegistrationService.cs @@ -6,5 +6,4 @@ public interface IRegistrationService : IArtemisUIService void RegisterBuiltInDataModelInputs(); void RegisterBuiltInPropertyEditors(); void RegisterControllers(); - void RegisterBuiltInNodeTypes(); } \ No newline at end of file diff --git a/src/Artemis.UI/Services/RegistrationService.cs b/src/Artemis.UI/Services/RegistrationService.cs index 32288e8c3..0a4447cda 100644 --- a/src/Artemis.UI/Services/RegistrationService.cs +++ b/src/Artemis.UI/Services/RegistrationService.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections; -using System.Linq; -using System.Reflection; +using System.Linq; using Artemis.Core; using Artemis.Core.Services; using Artemis.UI.Controllers; @@ -13,10 +10,8 @@ using Artemis.UI.Shared.Routing; using Artemis.UI.Shared.Services; using Artemis.UI.Shared.Services.ProfileEditor; using Artemis.UI.Shared.Services.PropertyInput; -using Artemis.VisualScripting.Nodes.Mathematics; using Avalonia; using DryIoc; -using SkiaSharp; namespace Artemis.UI.Services; @@ -26,7 +21,6 @@ public class RegistrationService : IRegistrationService private readonly IInputService _inputService; private readonly IContainer _container; private readonly IRouter _router; - private readonly INodeService _nodeService; private readonly IPropertyInputService _propertyInputService; private readonly IWebServerService _webServerService; private bool _registeredBuiltInPropertyEditors; @@ -36,7 +30,6 @@ public class RegistrationService : IRegistrationService IInputService inputService, IPropertyInputService propertyInputService, IProfileEditorService profileEditorService, - INodeService nodeService, IDataModelUIService dataModelUIService, IWebServerService webServerService, IDeviceLayoutService deviceLayoutService // here to make sure it is instantiated @@ -46,13 +39,11 @@ public class RegistrationService : IRegistrationService _router = router; _inputService = inputService; _propertyInputService = propertyInputService; - _nodeService = nodeService; _dataModelUIService = dataModelUIService; _webServerService = webServerService; CreateCursorResources(); RegisterRoutes(); - RegisterBuiltInNodeTypes(); RegisterControllers(); } @@ -105,22 +96,4 @@ public class RegistrationService : IRegistrationService { _webServerService.AddController(Constants.CorePlugin.Features.First().Instance!); } - - public void RegisterBuiltInNodeTypes() - { - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(bool), new SKColor(0xFFCD3232)); - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(string), new SKColor(0xFFFFD700)); - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(Numeric), new SKColor(0xFF32CD32)); - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(float), new SKColor(0xFFFF7C00)); - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(SKColor), new SKColor(0xFFAD3EED)); - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(IList), new SKColor(0xFFED3E61)); - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(Enum), new SKColor(0xFF1E90FF)); - _nodeService.RegisterTypeColor(Constants.CorePlugin, typeof(ColorGradient), new SKColor(0xFF00B2A9)); - - foreach (Type nodeType in typeof(SumNumericsNode).Assembly.GetTypes().Where(t => typeof(INode).IsAssignableFrom(t) && t.IsPublic && !t.IsAbstract && !t.IsInterface)) - { - if (nodeType.GetCustomAttribute(typeof(NodeAttribute)) != null) - _nodeService.RegisterNodeType(Constants.CorePlugin, nodeType); - } - } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Artemis.VisualScripting.csproj b/src/Artemis.VisualScripting/Artemis.VisualScripting.csproj deleted file mode 100644 index 90b14e4fa..000000000 --- a/src/Artemis.VisualScripting/Artemis.VisualScripting.csproj +++ /dev/null @@ -1,17 +0,0 @@ - - - net8.0 - enable - enable - x64 - - - - - - - - - - - diff --git a/src/Artemis.VisualScripting/Converters/JsonConverter.cs b/src/Artemis.VisualScripting/Converters/JsonConverter.cs deleted file mode 100644 index c23e257a6..000000000 --- a/src/Artemis.VisualScripting/Converters/JsonConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System.Globalization; -using Artemis.Core; -using Avalonia.Data.Converters; -using Newtonsoft.Json; - -namespace Artemis.VisualScripting.Converters; - -/// -/// Converts input into . -/// -public class JsonConverter : IValueConverter -{ - /// - public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - return JsonConvert.SerializeObject(value, Formatting.Indented); - } - - /// - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - string? json = value?.ToString(); - return json == null ? null : JsonConvert.DeserializeObject(json, targetType); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Converters/NumericConverter.cs b/src/Artemis.VisualScripting/Converters/NumericConverter.cs deleted file mode 100644 index 397b0564c..000000000 --- a/src/Artemis.VisualScripting/Converters/NumericConverter.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Globalization; -using Artemis.Core; -using Avalonia.Data.Converters; - -namespace Artemis.VisualScripting.Converters; - -/// -/// Converts input into . -/// -public class NumericConverter : IValueConverter -{ - /// - public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) - { - if (value is not Numeric numeric) - return value; - - object result = Numeric.IsTypeCompatible(targetType) ? numeric.ToType(targetType, NumberFormatInfo.InvariantInfo) : value; - return result; - } - - /// - public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) - { - return new Numeric(value); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/DryIoc/ContainerExtensions.cs b/src/Artemis.VisualScripting/DryIoc/ContainerExtensions.cs deleted file mode 100644 index ca4c9845c..000000000 --- a/src/Artemis.VisualScripting/DryIoc/ContainerExtensions.cs +++ /dev/null @@ -1,41 +0,0 @@ -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); - container.Register(Reuse.Singleton); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Branching/BooleanBranchNode.cs b/src/Artemis.VisualScripting/Nodes/Branching/BooleanBranchNode.cs deleted file mode 100644 index b07aea8cf..000000000 --- a/src/Artemis.VisualScripting/Nodes/Branching/BooleanBranchNode.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Events; - -namespace Artemis.VisualScripting.Nodes.Branching; - -[Node("Branch", "Forwards one of two values depending on an input boolean", "Branching", InputType = typeof(object), OutputType = typeof(object))] -public class BooleanBranchNode : Node -{ - public BooleanBranchNode() - { - BooleanInput = CreateInputPin(); - TrueInput = CreateInputPin(typeof(object), "True"); - FalseInput = CreateInputPin(typeof(object), "False"); - - Output = CreateOutputPin(typeof(object)); - - TrueInput.PinConnected += InputPinConnected; - FalseInput.PinConnected += InputPinConnected; - TrueInput.PinDisconnected += InputPinDisconnected; - FalseInput.PinDisconnected += InputPinDisconnected; - } - - public InputPin BooleanInput { get; set; } - public InputPin TrueInput { get; set; } - public InputPin FalseInput { get; set; } - - public OutputPin Output { get; set; } - - #region Overrides of Node - - /// - public override void Evaluate() - { - Output.Value = BooleanInput.Value ? TrueInput.Value : FalseInput.Value; - } - - #endregion - - private void InputPinConnected(object? sender, SingleValueEventArgs e) - { - if (TrueInput.ConnectedTo.Any()) - ChangeType(TrueInput.ConnectedTo.First().Type); - else if (FalseInput.ConnectedTo.Any()) - ChangeType(FalseInput.ConnectedTo.First().Type); - } - - private void InputPinDisconnected(object? sender, SingleValueEventArgs e) - { - if (!TrueInput.ConnectedTo.Any() && !FalseInput.ConnectedTo.Any()) - ChangeType(typeof(object)); - } - - private void ChangeType(Type type) - { - TrueInput.ChangeType(type); - FalseInput.ChangeType(type); - Output.ChangeType(type); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs b/src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs deleted file mode 100644 index eb3803290..000000000 --- a/src/Artemis.VisualScripting/Nodes/Branching/EnumSwitchNode.cs +++ /dev/null @@ -1,100 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Events; -using Humanizer; - -namespace Artemis.VisualScripting.Nodes.Branching; - -[Node("Switch (Enum)", "Outputs the input that corresponds to the switch value", "Operators", InputType = typeof(Enum), OutputType = typeof(object))] -public class EnumSwitchNode : Node -{ - private readonly Dictionary _inputPins; - - public EnumSwitchNode() - { - _inputPins = new Dictionary(); - - Output = CreateOutputPin(typeof(object), "Result"); - SwitchValue = CreateInputPin("Switch"); - - SwitchValue.PinConnected += OnSwitchPinConnected; - SwitchValue.PinDisconnected += OnSwitchPinDisconnected; - } - - public OutputPin Output { get; } - public InputPin SwitchValue { get; } - - public override void Evaluate() - { - if (SwitchValue.Value is null) - { - Output.Value = null; - return; - } - - if (!_inputPins.TryGetValue(SwitchValue.Value, out InputPin? pin)) - { - Output.Value = null; - return; - } - - if (pin.ConnectedTo.Count == 0) - { - Output.Value = null; - return; - } - - Output.Value = pin.Value; - } - - private void OnInputPinDisconnected(object? sender, SingleValueEventArgs e) - { - // if this is the last pin to disconnect, reset the type. - if (_inputPins.Values.All(i => i.ConnectedTo.Count == 0)) - ChangeType(typeof(object)); - } - - private void OnInputPinConnected(object? sender, SingleValueEventArgs e) - { - // change the type of our inputs and output - // depending on the first node the user connects to - ChangeType(e.Value.Type); - } - - private void OnSwitchPinConnected(object? sender, SingleValueEventArgs e) - { - if (SwitchValue.ConnectedTo.Count == 0) - return; - - Type enumType = SwitchValue.ConnectedTo[0].Type; - if (!enumType.IsEnum) - return; - - foreach (Enum enumValue in Enum.GetValues(enumType).Cast()) - { - InputPin pin = CreateOrAddInputPin(typeof(object), enumValue.Humanize(LetterCasing.Sentence)); - pin.PinConnected += OnInputPinConnected; - pin.PinDisconnected += OnInputPinDisconnected; - _inputPins[enumValue] = pin; - } - } - - private void OnSwitchPinDisconnected(object? sender, SingleValueEventArgs e) - { - foreach (InputPin input in _inputPins.Values) - { - input.PinConnected -= OnInputPinConnected; - input.PinDisconnected -= OnInputPinDisconnected; - RemovePin(input); - } - - _inputPins.Clear(); - ChangeType(typeof(object)); - } - - private void ChangeType(Type type) - { - foreach (InputPin input in _inputPins.Values) - input.ChangeType(type); - Output.ChangeType(type); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs deleted file mode 100644 index e5adaad4e..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/BrightenSKColorNode.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Brighten Color", "Brightens a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class BrightenSKColorNode : Node -{ - public BrightenSKColorNode() - { - Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); - Output = CreateOutputPin(); - } - - public InputPin Input { get; } - public InputPin Percentage { get; } - public OutputPin Output { get; set; } - - public override void Evaluate() - { - Input.Value.ToHsl(out float h, out float s, out float l); - l += l * (Percentage.Value / 100f); - Output.Value = SKColor.FromHsl(h, s, l); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientFromPinsNode.cs b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientFromPinsNode.cs deleted file mode 100644 index 5467aecb7..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientFromPinsNode.cs +++ /dev/null @@ -1,102 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Events; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Color Gradient (Advanced)", "Outputs a Color Gradient from colors and positions", "Color", OutputType = typeof(ColorGradient))] -public class ColorGradientFromPinsNode : Node -{ - public OutputPin Gradient { get; set; } - public InputPinCollection Colors { get; set; } - public InputPinCollection Positions { get; set; } - - public ColorGradientFromPinsNode() - { - Colors = CreateInputPinCollection("Colors", 0); - Positions = CreateInputPinCollection("Positions", 0); - Gradient = CreateOutputPin("Gradient"); - - Colors.PinAdded += OnPinAdded; - Colors.PinRemoved += OnPinRemoved; - Positions.PinAdded += OnPinAdded; - Positions.PinRemoved += OnPinRemoved; - } - - private void OnPinRemoved(object? sender, SingleValueEventArgs e) - { - int colorsCount = Colors.Count(); - int positionsCount = Positions.Count(); - if (colorsCount == positionsCount) - return; - - while (colorsCount > positionsCount) - { - IPin pinToRemove = Colors.Last(); - Colors.Remove(pinToRemove); - - --colorsCount; - } - - while (positionsCount > colorsCount) - { - IPin pinToRemove = Positions.Last(); - Positions.Remove(pinToRemove); - --positionsCount; - } - - RenamePins(); - } - - private void OnPinAdded(object? sender, SingleValueEventArgs e) - { - int colorsCount = Colors.Count(); - int positionsCount = Positions.Count(); - if (colorsCount == positionsCount) - return; - - while (colorsCount < positionsCount) - { - Colors.Add(Colors.CreatePin()); - - ++colorsCount; - } - - while (positionsCount < colorsCount) - { - Positions.Add(Positions.CreatePin()); - - ++positionsCount; - } - - RenamePins(); - } - - private void RenamePins() - { - int colors = 0; - foreach (IPin item in Colors) - { - item.Name = $"Color #{++colors}"; - } - - int positions = 0; - foreach (IPin item in Positions) - { - item.Name = $"Position #{++positions}"; - } - } - - public override void Evaluate() - { - List stops = new List(); - InputPin[] colors = Colors.Pins.ToArray(); - InputPin[] positions = Positions.Pins.ToArray(); - for (int i = 0; i < colors.Length; i++) - { - stops.Add(new ColorGradientStop(colors[i].Value, positions[i].Value)); - } - - Gradient.Value = new ColorGradient(stops); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs b/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs deleted file mode 100644 index 18dc15f54..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/ColorGradientNode.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System.Collections.Specialized; -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Color.Screens; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Color Gradient (Simple)", "Outputs a color gradient with the given colors", "Color", OutputType = typeof(ColorGradient))] -public class ColorGradientNode : Node -{ - private readonly List _inputPins; - - public ColorGradientNode() - { - _inputPins = new List(); - - Gradient = ColorGradient.GetUnicornBarf(); - Output = CreateOutputPin(); - ViewModelPosition = CustomNodeViewModelPosition.AbovePins; - } - - public ColorGradient Gradient { get; private set; } - public OutputPin Output { get; } - - public override void Initialize(INodeScript script) - { - UpdateGradient(); - ComputeInputPins(); - - // Not expecting storage to get modified, but lets just make sure - StorageModified += OnStorageModified; - } - - public override void Evaluate() - { - ColorGradientStop[] stops = Gradient.ToArray(); - - if (_inputPins.Count != stops.Length) - return; - - for (int i = 0; i < _inputPins.Count; i++) - { - // if nothing is connected, leave the stop alone. - if (_inputPins[i].ConnectedTo.Count == 0) - continue; - - // if the pin has a connection, update the stop. - if (_inputPins[i].PinValue is SKColor color) - stops[i].Color = color; - } - - Output.Value = Gradient; - } - - private void DisconnectAllInputPins() - { - foreach (InputPin item in _inputPins) - item.DisconnectAll(); - } - - private void UpdateGradient() - { - Gradient.CollectionChanged -= OnGradientCollectionChanged; - if (Storage != null) - Gradient = Storage; - else - Storage = Gradient; - Gradient.CollectionChanged += OnGradientCollectionChanged; - } - - private void ComputeInputPins() - { - int newAmount = Gradient.Count; - if (newAmount == _inputPins.Count) - return; - - while (newAmount > _inputPins.Count) - _inputPins.Add(CreateOrAddInputPin(typeof(SKColor), string.Empty)); - - while (newAmount < _inputPins.Count) - { - InputPin pin = _inputPins.Last(); - RemovePin(pin); - _inputPins.Remove(pin); - } - - int index = 0; - foreach (InputPin item in _inputPins) - item.Name = $"Color #{++index}"; - } - - private void OnStorageModified(object? sender, EventArgs e) - { - UpdateGradient(); - ComputeInputPins(); - } - - private void OnGradientCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) - { - // if the user reorders the gradient, let it slide and do nothing. - // of course, the user might want to change the input pins since they will no longer line up. - if (e.Action == NotifyCollectionChangedAction.Move) - return; - - // DisconnectAllInputPins(); - ComputeInputPins(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs deleted file mode 100644 index 5b4983e40..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/DarkenSKColorNode.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Darken Color", "Darkens a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class DarkenSKColorNode : Node -{ - public DarkenSKColorNode() - { - Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); - Output = CreateOutputPin(); - } - - public InputPin Input { get; } - public InputPin Percentage { get; } - public OutputPin Output { get; set; } - - public override void Evaluate() - { - Input.Value.ToHsl(out float h, out float s, out float l); - l -= l * (Percentage.Value / 100f); - Output.Value = SKColor.FromHsl(h, s, l); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs deleted file mode 100644 index f02e9b6f6..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/DesaturateSKColorNode.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Desaturate Color", "Desaturates a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class DesaturateSKColorNode : Node -{ - public DesaturateSKColorNode() - { - Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); - Output = CreateOutputPin(); - } - - public InputPin Input { get; } - public InputPin Percentage { get; } - public OutputPin Output { get; set; } - - public override void Evaluate() - { - Input.Value.ToHsl(out float h, out float s, out float l); - s -= s * (Percentage.Value / 100f); - Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/GradientBuilderNode.cs b/src/Artemis.VisualScripting/Nodes/Color/GradientBuilderNode.cs deleted file mode 100644 index 26ff8067f..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/GradientBuilderNode.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color -{ - [Node("Gradient Builder", "Generates a gradient based on some values", "Color", OutputType = typeof(ColorGradient), HelpUrl = "https://krazydad.com/tutorials/makecolors.php")] - public class GradientBuilderNode : Node - { - public OutputPin Output { get; } - - public InputPin Frequency1 { get; } - public InputPin Frequency2 { get; } - public InputPin Frequency3 { get; } - public InputPin Phase1 { get; } - public InputPin Phase2 { get; } - public InputPin Phase3 { get; } - public InputPin Center { get; } - public InputPin Width { get; } - public InputPin Length { get; } - - public GradientBuilderNode() - { - Output = CreateOutputPin(); - Frequency1 = CreateInputPin("Frequency 1"); - Frequency2 = CreateInputPin("Frequency 2"); - Frequency3 = CreateInputPin("Frequency 3"); - Phase1 = CreateInputPin("Phase 1"); - Phase2 = CreateInputPin("Phase 2"); - Phase3 = CreateInputPin("Phase 3"); - Center = CreateInputPin("Center"); - Width = CreateInputPin("Width"); - Length = CreateInputPin("Length"); - } - - public override void Evaluate() - { - ColorGradient gradient = new ColorGradient(); - - for (int i = 0; i < Length.Value; i++) - { - Numeric r = Math.Sin(Frequency1.Value * i + Phase1.Value) * Width.Value + Center.Value; - Numeric g = Math.Sin(Frequency2.Value * i + Phase2.Value) * Width.Value + Center.Value; - Numeric b = Math.Sin(Frequency3.Value * i + Phase3.Value) * Width.Value + Center.Value; - gradient.Add(new ColorGradientStop(new SKColor((byte)r, (byte)g, (byte)b), i / Length.Value)); - } - - Output.Value = gradient; - } - } -} diff --git a/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs deleted file mode 100644 index 15ce66d84..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/HslSKColorNode.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[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() - { - H = CreateInputPin("H"); - S = CreateInputPin("S"); - L = CreateInputPin("L"); - Output = CreateOutputPin(); - } - - public InputPin H { get; set; } - public InputPin S { get; set; } - public InputPin L { get; set; } - public OutputPin Output { get; } - - #region Overrides of Node - - /// - public override void Evaluate() - { - Output.Value = SKColor.FromHsl(H.Value, S.Value, L.Value); - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/HsvSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/HsvSKColorNode.cs deleted file mode 100644 index 2544ccec2..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/HsvSKColorNode.cs +++ /dev/null @@ -1,31 +0,0 @@ -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/InvertSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/InvertSKColorNode.cs deleted file mode 100644 index b194b8a01..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/InvertSKColorNode.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Invert Color", "Inverts a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class InvertSKColorNode : Node -{ - public InvertSKColorNode() - { - Input = CreateInputPin(); - Output = CreateOutputPin(); - } - - public InputPin Input { get; } - public OutputPin Output { get; set; } - - public override void Evaluate() - { - Output.Value = new SKColor( - (byte) (255 - Input.Value.Red), - (byte) (255 - Input.Value.Green), - (byte) (255 - Input.Value.Blue), - Input.Value.Alpha - ); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs deleted file mode 100644 index 7bf45e08d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/LerpSKColorNode.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Artemis.Core; -using RGB.NET.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Lerp (Color)", "Interpolates linear between the two colors A and B", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class LerpSKColorNode : Node -{ - #region Properties & Fields - - public InputPin A { get; } - public InputPin B { get; } - public InputPin T { get; } - - public OutputPin Result { get; } - - #endregion - - #region Constructors - - public LerpSKColorNode() - { - Name = "Lerp"; - A = CreateInputPin("A"); - B = CreateInputPin("B"); - T = CreateInputPin("T"); - - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() - { - SKColor a = A.Value; - SKColor b = B.Value; - float t = ((float)T.Value).Clamp(0f, 1f); - - float aAlpha = a.Alpha.GetPercentageFromByteValue(); - float aRed = a.Red.GetPercentageFromByteValue(); - float aGreen = a.Green.GetPercentageFromByteValue(); - float aBlue = a.Blue.GetPercentageFromByteValue(); - - float alpha = ((b.Alpha.GetPercentageFromByteValue() - aAlpha) * t) + aAlpha; - float red = ((b.Red.GetPercentageFromByteValue() - aRed) * t) + aRed; - float green = ((b.Green.GetPercentageFromByteValue() - aGreen) * t) + aGreen; - float blue = ((b.Blue.GetPercentageFromByteValue() - aBlue) * t) + aBlue; - - Result.Value = new SKColor(red.GetByteValueFromPercentage(), green.GetByteValueFromPercentage(), blue.GetByteValueFromPercentage(), alpha.GetByteValueFromPercentage()); - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs deleted file mode 100644 index c70e1489d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/RampSKColorNode.cs +++ /dev/null @@ -1,42 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Color.Screens; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Color Ramp", "Maps values to colors with the use of a gradient.", "Color", InputType = typeof(Numeric), OutputType = typeof(SKColor))] -public class RampSKColorNode : Node -{ - #region Constructors - - public RampSKColorNode() - { - Input = CreateInputPin(); - Output = CreateOutputPin(); - Storage = ColorGradient.GetUnicornBarf(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - // Wrap the input between 0 and 1 - // 1 % 1 = 0, 2 % 1 = 0 etc. but we want that to be 1 but 0 should stay 0, call me stupid but this works and makes sense - float value = Input.Value % 1; - if (value == 0 && Input.Value != 0) - value = 1; - - Output.Value = Storage?.GetColor(value) ?? SKColor.Empty; - } - - #endregion - - #region Properties & Fields - - public InputPin Input { get; } - public OutputPin Output { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs deleted file mode 100644 index 7d3bd63b7..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/RgbSKColorNode.cs +++ /dev/null @@ -1,37 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("RGB Color", "Creates a color from red, green and blue values", "Color", InputType = typeof(Numeric), OutputType = typeof(SKColor))] -public class RgbSKColorNode : Node -{ - #region Properties & Fields - - public InputPin R { get; set; } - public InputPin G { get; set; } - public InputPin B { get; set; } - public OutputPin Output { get; } - - #endregion - - #region Constructors - - public RgbSKColorNode() - { - R = CreateInputPin("R"); - G = CreateInputPin("G"); - B = CreateInputPin("B"); - - Output = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() => Output.Value = new SKColor(R.Value, G.Value, B.Value); - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs deleted file mode 100644 index 4325724b0..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/RotateHueSkColorNode.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Rotate Color Hue", "Rotates the hue of a color by a specified amount in degrees", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class RotateHueSKColorNode : Node -{ - public RotateHueSKColorNode() - { - Input = CreateInputPin("Color"); - Amount = CreateInputPin("Amount"); - Output = CreateOutputPin(); - } - - public InputPin Input { get; } - public InputPin Amount { get; } - public OutputPin Output { get; set; } - - public override void Evaluate() - { - Input.Value.ToHsl(out float h, out float s, out float l); - h += Amount.Value; - Output.Value = SKColor.FromHsl(h % 360, s, l); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs b/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs deleted file mode 100644 index 1c8922262..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/SaturateSkColorNode.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Saturate Color", "Saturates a color by a specified amount in percent", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class SaturateSKColorNode : Node -{ - public SaturateSKColorNode() - { - Input = CreateInputPin("Color"); - Percentage = CreateInputPin("%"); - Output = CreateOutputPin(); - } - - public InputPin Input { get; } - public InputPin Percentage { get; } - public OutputPin Output { get; set; } - - public override void Evaluate() - { - Input.Value.ToHsl(out float h, out float s, out float l); - s += s * (Percentage.Value / 100f); - Output.Value = SKColor.FromHsl(h, Math.Clamp(s, 0f, 100f), l); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomView.axaml deleted file mode 100644 index 404c13af2..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomView.axaml +++ /dev/null @@ -1,15 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomView.axaml.cs deleted file mode 100644 index ec578cde5..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomView.axaml.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Artemis.UI.Shared.Controls.GradientPicker; -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Color.Screens; - -public partial class ColorGradientNodeCustomView : ReactiveUserControl -{ - public ColorGradientNodeCustomView() - { - InitializeComponent(); - } - - - private void GradientPickerButton_OnFlyoutOpened(GradientPickerButton sender, EventArgs args) - { - } - - private void GradientPickerButton_OnFlyoutClosed(GradientPickerButton sender, EventArgs args) - { - ViewModel?.StoreGradient(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomViewModel.cs deleted file mode 100644 index 1b586f24a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/Screens/ColorGradientNodeCustomViewModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; - -namespace Artemis.VisualScripting.Nodes.Color.Screens; - -public class ColorGradientNodeCustomViewModel : CustomNodeViewModel -{ - private readonly ColorGradientNode _node; - private readonly INodeEditorService _nodeEditorService; - - /// - public ColorGradientNodeCustomViewModel(ColorGradientNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - Gradient = _node.Gradient; - } - - public ColorGradient Gradient { get; } - - public void StoreGradient() - { - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, Gradient)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomView.axaml deleted file mode 100644 index 4d05928ed..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomView.axaml +++ /dev/null @@ -1,16 +0,0 @@ - - - diff --git a/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomView.axaml.cs deleted file mode 100644 index d70520a1d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomView.axaml.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Artemis.UI.Shared.Controls.GradientPicker; -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Color.Screens; - -public partial class RampSKColorNodeCustomView : ReactiveUserControl -{ - public RampSKColorNodeCustomView() - { - InitializeComponent(); - } - - - private void GradientPickerButton_OnFlyoutOpened(GradientPickerButton sender, EventArgs args) - { - } - - private void GradientPickerButton_OnFlyoutClosed(GradientPickerButton sender, EventArgs args) - { - ViewModel?.StoreGradient(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomViewModel.cs deleted file mode 100644 index cbd1a9539..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/Screens/RampSKColorNodeCustomViewModel.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; - -namespace Artemis.VisualScripting.Nodes.Color.Screens; - -public class RampSKColorNodeCustomViewModel : CustomNodeViewModel -{ - private readonly RampSKColorNode _node; - private readonly INodeEditorService _nodeEditorService; - - /// - public RampSKColorNodeCustomViewModel(RampSKColorNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - Gradient = _node.Storage ?? new ColorGradient(); - } - - public ColorGradient Gradient { get; } - - public void StoreGradient() - { - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, Gradient)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/SkColorHsl.cs b/src/Artemis.VisualScripting/Nodes/Color/SkColorHsl.cs deleted file mode 100644 index aaa1c6e26..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/SkColorHsl.cs +++ /dev/null @@ -1,36 +0,0 @@ -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 deleted file mode 100644 index a0e448cf4..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/SkColorHsv.cs +++ /dev/null @@ -1,36 +0,0 @@ -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 diff --git a/src/Artemis.VisualScripting/Nodes/Color/SortedGradient.cs b/src/Artemis.VisualScripting/Nodes/Color/SortedGradient.cs deleted file mode 100644 index 00cdd61d0..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/SortedGradient.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Artemis.Core; -using Artemis.Core.ColorScience; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color -{ - [Node("Sorted Gradient", "Generates a sorted gradient from the given colors", "Color", InputType = typeof(SKColor), OutputType = typeof(ColorGradient))] - public class SortedGradientNode : Node - { - private int lastComputedColorGroup; - public InputPinCollection Inputs { get; } - public OutputPin Output { get; } - - public SortedGradientNode() - { - Inputs = CreateInputPinCollection(); - Output = CreateOutputPin(); - lastComputedColorGroup = 0; - } - - public override void Evaluate() - { - int newHash = GetInputColorHash(); - if (newHash == lastComputedColorGroup) - return; - - SKColor[] colors = Inputs.Values.ToArray(); - - if (colors.Length == 0) - { - Output.Value = null; - return; - } - - ColorSorter.Sort(colors, SKColors.Black); - - ColorGradient gradient = new(); - for (int i = 0; i < colors.Length; i++) - { - gradient.Add(new ColorGradientStop(colors[i], (float)i / (colors.Length - 1))); - } - - Output.Value = gradient; - lastComputedColorGroup = newHash; - } - - private int GetInputColorHash() - { - int hash = 0; - - foreach (SKColor color in Inputs.Values) - hash = HashCode.Combine(hash, color.GetHashCode()); - - return hash; - } - } -} diff --git a/src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs b/src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs deleted file mode 100644 index 49b86ed14..000000000 --- a/src/Artemis.VisualScripting/Nodes/Color/SumSKColorsNode.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Color; - -[Node("Sum (Color)", "Sums the connected color values.", "Color", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class SumSKColorsNode : Node -{ - #region Constructors - - public SumSKColorsNode() - { - Name = "Sum"; - Values = CreateInputPinCollection("Values", 2); - Sum = CreateOutputPin("Sum"); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - SKColor result = SKColor.Empty; - - bool first = true; - foreach (SKColor current in Values.Values) - { - result = first ? current : result.Sum(current); - first = false; - } - - Sum.Value = result; - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Values { get; } - - public OutputPin Sum { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToNumericNode.cs b/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToNumericNode.cs deleted file mode 100644 index 0dcfb6e1b..000000000 --- a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToNumericNode.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Conversion; - -[Node("To Numeric", "Converts the input to a numeric.", "Conversion", InputType = typeof(object), OutputType = typeof(Numeric))] -public class ConvertToNumericNode : Node -{ - #region Constructors - - public ConvertToNumericNode() - { - Input = CreateInputPin(); - Output = CreateOutputPin(); - } - - #endregion - - #region Properties & Fields - - public InputPin Input { get; } - - public OutputPin Output { get; } - - #endregion - - #region Methods - - public override void Evaluate() - { - Output.Value = Input.Value switch - { - int input => new Numeric(input), - double input => new Numeric(input), - float input => new Numeric(input), - byte input => new Numeric(input), - bool input => new Numeric(input ? 1 : 0), - _ => TryParse(Input.Value) - }; - } - - private Numeric TryParse(object? input) - { - Numeric.TryParse(input?.ToString(), out Numeric value); - return value; - } - - #endregion -} diff --git a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs b/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs deleted file mode 100644 index d54d5ab7a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Conversion/ConvertToStringNode.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Conversion; - -[Node("To Text", "Converts the input to text.", "Conversion", InputType = typeof(object), OutputType = typeof(string))] -public class ConvertToStringNode : Node -{ - #region Constructors - - public ConvertToStringNode() - { - Input = CreateInputPin(); - String = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - String.Value = Input.Value?.ToString(); - } - - #endregion - - #region Properties & Fields - - public InputPin Input { get; } - - public OutputPin String { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventCycleNode.cs b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventCycleNode.cs deleted file mode 100644 index 6ab264a77..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventCycleNode.cs +++ /dev/null @@ -1,171 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Events; -using Artemis.Storage.Entities.Profile; -using Artemis.VisualScripting.Nodes.DataModel.Screens; - -namespace Artemis.VisualScripting.Nodes.DataModel; - -[Node("Data Model-Event Value Cycle", "Cycles through provided values each time the select event fires.", "Data Model", OutputType = typeof(object))] -public class DataModelEventCycleNode : Node, IDisposable -{ - private int _currentIndex; - private Type _currentType; - private DataModelPath? _dataModelPath; - private IDataModelEvent? _subscribedEvent; - private object? _lastPathValue; - private bool _updating; - - public DataModelEventCycleNode() - { - _currentType = typeof(object); - - CycleValues = CreateInputPinCollection(typeof(object), "", 0); - Output = CreateOutputPin(typeof(object)); - - CycleValues.PinAdded += OnCycleValuesOnPinAdded; - CycleValues.PinRemoved += OnCycleValuesOnPinRemoved; - CycleValues.Add(CycleValues.CreatePin()); - - // Monitor storage for changes - StorageModified += (_, _) => UpdateDataModelPath(); - } - - public INodeScript? Script { get; set; } - - public InputPinCollection CycleValues { get; } - public OutputPin Output { get; } - - public override void Initialize(INodeScript script) - { - Script = script; - - if (Storage != null) - UpdateDataModelPath(); - } - - public override void Evaluate() - { - object? pathValue = _dataModelPath?.GetValue(); - if (pathValue is not IDataModelEvent && EvaluateValue(pathValue)) - Cycle(); - - object? outputValue = CycleValues.ElementAt(_currentIndex).PinValue; - if (Output.Type.IsInstanceOfType(outputValue)) - Output.Value = outputValue; - else if (Output.Type.IsValueType) - Output.Value = Output.Type.GetDefault()!; - } - - private bool EvaluateValue(object? pathValue) - { - if (Equals(pathValue, _lastPathValue)) - return false; - - _lastPathValue = pathValue; - return true; - } - - private void Cycle() - { - _currentIndex++; - - if (_currentIndex >= CycleValues.Count()) - _currentIndex = 0; - } - - private void UpdateDataModelPath() - { - DataModelPath? old = _dataModelPath; - - if (_subscribedEvent != null) - { - _subscribedEvent.EventTriggered -= OnEventTriggered; - _subscribedEvent = null; - } - - _dataModelPath = Storage != null ? new DataModelPath(Storage) : null; - - if (_dataModelPath?.GetValue() is IDataModelEvent newEvent) - { - _subscribedEvent = newEvent; - _subscribedEvent.EventTriggered += OnEventTriggered; - } - - old?.Dispose(); - } - - private void ChangeCurrentType(Type type) - { - CycleValues.ChangeType(type); - Output.ChangeType(type); - - _currentType = type; - } - - private void OnEventTriggered(object? sender, EventArgs e) - { - Cycle(); - } - - private void OnCycleValuesOnPinAdded(object? sender, SingleValueEventArgs e) - { - e.Value.PinConnected += OnPinConnected; - e.Value.PinDisconnected += OnPinDisconnected; - } - - private void OnCycleValuesOnPinRemoved(object? sender, SingleValueEventArgs e) - { - e.Value.PinConnected -= OnPinConnected; - e.Value.PinDisconnected -= OnPinDisconnected; - } - - private void OnPinDisconnected(object? sender, SingleValueEventArgs e) - { - if (_updating) - return; - - try - { - // If there's still a connected pin, stick to the current type - if (CycleValues.Any(v => v.ConnectedTo.Any())) - return; - - ChangeCurrentType(typeof(object)); - } - finally - { - _updating = false; - } - } - - private void OnPinConnected(object? sender, SingleValueEventArgs e) - { - if (_updating) - return; - - try - { - _updating = true; - - // No need to change anything if the types haven't changed - if (_currentType != e.Value.Type) - ChangeCurrentType(e.Value.Type); - } - finally - { - _updating = false; - } - } - - /// - public void Dispose() - { - if (_subscribedEvent != null) - { - _subscribedEvent.EventTriggered -= OnEventTriggered; - _subscribedEvent = null; - } - - _dataModelPath?.Dispose(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventNode.cs b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventNode.cs deleted file mode 100644 index 1893e5cc5..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventNode.cs +++ /dev/null @@ -1,164 +0,0 @@ -using Artemis.Core; -using Artemis.Storage.Entities.Profile; -using Artemis.VisualScripting.Nodes.DataModel.Screens; - -namespace Artemis.VisualScripting.Nodes.DataModel; - -[Node("Data Model-Event", "Outputs the latest values of a data model event.", "Data Model", OutputType = typeof(object))] -public class DataModelEventNode : Node, IDisposable -{ - private readonly ObjectOutputPins _objectOutputPins; - private IDataModelEvent? _dataModelEvent; - private DataModelPath? _dataModelPath; - private DateTime _lastTrigger; - private object? _lastValue; - private OutputPin? _newValuePin; - private OutputPin? _oldValuePin; - private int _valueChangeCount; - - public DataModelEventNode() - { - _objectOutputPins = new ObjectOutputPins(this); - - TimeSinceLastTrigger = CreateOutputPin("Time since trigger"); - TriggerCount = CreateOutputPin("Trigger count"); - - // Monitor storage for changes - StorageModified += (_, _) => UpdateDataModelPath(); - } - - public INodeScript? Script { get; set; } - public OutputPin TimeSinceLastTrigger { get; } - public OutputPin TriggerCount { get; } - - public override void Initialize(INodeScript script) - { - Script = script; - - if (Storage == null) - return; - - UpdateDataModelPath(); - } - - public override void Evaluate() - { - object? pathValue = _dataModelPath?.GetValue(); - - // If the path is a data model event, evaluate the event - if (pathValue is IDataModelEvent dataModelEvent) - { - TimeSinceLastTrigger.Value = dataModelEvent.TimeSinceLastTrigger.TotalMilliseconds; - TriggerCount.Value = dataModelEvent.TriggerCount; - - _objectOutputPins.SetCurrentValue(dataModelEvent.LastEventArgumentsUntyped); - } - // If the path is a regular value, evaluate the current value - else if (_oldValuePin != null && _newValuePin != null) - { - if (_newValuePin.IsNumeric) - pathValue = new Numeric(pathValue); - - if (Equals(_lastValue, pathValue)) - { - TimeSinceLastTrigger.Value = (DateTime.Now - _lastTrigger).TotalMilliseconds; - return; - } - - _valueChangeCount++; - _lastTrigger = DateTime.Now; - - _oldValuePin.Value = _lastValue; - _newValuePin.Value = pathValue; - - _lastValue = pathValue; - - TimeSinceLastTrigger.Value = 0; - TriggerCount.Value = _valueChangeCount; - } - } - - private void UpdateDataModelPath() - { - DataModelPath? old = _dataModelPath; - _dataModelPath = Storage != null ? new DataModelPath(Storage) : null; - if (_dataModelPath != null) - _dataModelPath.PathValidated += DataModelPathOnPathValidated; - - if (old != null) - { - old.PathValidated -= DataModelPathOnPathValidated; - old.Dispose(); - } - - UpdateOutputPins(); - } - - private void UpdateOutputPins() - { - object? pathValue = _dataModelPath?.GetValue(); - - if (pathValue is IDataModelEvent dataModelEvent) - CreateEventPins(dataModelEvent); - else - CreateValuePins(); - } - - private void CreateEventPins(IDataModelEvent dataModelEvent) - { - if (_dataModelEvent == dataModelEvent) - return; - - ClearPins(); - _dataModelEvent = dataModelEvent; - _objectOutputPins.ChangeType(dataModelEvent.ArgumentsType); - } - - private void CreateValuePins() - { - ClearPins(); - - Type? propertyType = _dataModelPath?.GetPropertyType(); - if (propertyType == null) - return; - - if (Numeric.IsTypeCompatible(propertyType)) - propertyType = typeof(Numeric); - - _oldValuePin = CreateOrAddOutputPin(propertyType, "Old value"); - _newValuePin = CreateOrAddOutputPin(propertyType, "New value"); - _lastValue = null; - _valueChangeCount = 0; - } - - private void ClearPins() - { - // Clear the output pins by changing the type to null - _objectOutputPins.ChangeType(null); - - if (_oldValuePin != null) - { - RemovePin(_oldValuePin); - _oldValuePin = null; - } - - if (_newValuePin != null) - { - RemovePin(_newValuePin); - _newValuePin = null; - } - } - - private void DataModelPathOnPathValidated(object? sender, EventArgs e) - { - // Update the output pin now that the type is known and attempt to restore the connection that was likely missing - UpdateOutputPins(); - Script?.LoadConnections(); - } - - /// - public void Dispose() - { - _dataModelPath?.Dispose(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs deleted file mode 100644 index 1488796e9..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs +++ /dev/null @@ -1,88 +0,0 @@ -using Artemis.Core; -using Artemis.Storage.Entities.Profile; -using Artemis.VisualScripting.Nodes.DataModel.Screens; - -namespace Artemis.VisualScripting.Nodes.DataModel; - -[Node("Data Model-Value", "Outputs a selectable data model value.", "Data Model", OutputType = typeof(object))] -public class DataModelNode : Node, IDisposable -{ - private DataModelPath? _dataModelPath; - - public DataModelNode() - { - Output = CreateOutputPin(typeof(object)); - StorageModified += (_, _) => UpdateDataModelPath(); - } - - public INodeScript? Script { get; private set; } - public OutputPin Output { get; } - - public override void Initialize(INodeScript script) - { - Script = script; - - if (Storage == null) - return; - - UpdateDataModelPath(); - } - - public override void Evaluate() - { - if (_dataModelPath == null || !_dataModelPath.IsValid) - return; - - object? pathValue = _dataModelPath.GetValue(); - if (pathValue == null) - { - if (!Output.Type.IsValueType) - Output.Value = null; - } - else - { - Output.Value = Output.IsNumeric ? new Numeric(pathValue) : pathValue; - } - } - - public void UpdateOutputPin() - { - Type? type = _dataModelPath?.GetPropertyType(); - if (type == null) - type = typeof(object); - else if (Numeric.IsTypeCompatible(type)) - type = typeof(Numeric); - - if (Output.Type != type) - Output.ChangeType(type); - } - - private void UpdateDataModelPath() - { - DataModelPath? old = _dataModelPath; - _dataModelPath = Storage != null ? new DataModelPath(Storage) : null; - if (_dataModelPath != null) - _dataModelPath.PathValidated += DataModelPathOnPathValidated; - - if (old != null) - { - old.PathValidated -= DataModelPathOnPathValidated; - old.Dispose(); - } - - UpdateOutputPin(); - } - - private void DataModelPathOnPathValidated(object? sender, EventArgs e) - { - // Update the output pin now that the type is known and attempt to restore the connection that was likely missing - UpdateOutputPin(); - Script?.LoadConnections(); - } - - /// - public void Dispose() - { - _dataModelPath?.Dispose(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomView.axaml deleted file mode 100644 index f98ebc0d9..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomView.axaml +++ /dev/null @@ -1,18 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomView.axaml.cs deleted file mode 100644 index 39c27cb08..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.DataModel.Screens; - -public partial class DataModelEventCycleNodeCustomView : ReactiveUserControl -{ - public DataModelEventCycleNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomViewModel.cs deleted file mode 100644 index 20247322b..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventCycleNodeCustomViewModel.cs +++ /dev/null @@ -1,104 +0,0 @@ -using System.Collections.ObjectModel; -using System.Reactive.Disposables; -using Artemis.Core; -using Artemis.Core.Modules; -using Artemis.Core.Services; -using Artemis.Storage.Entities.Profile; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.DataModel.Screens; - -public class DataModelEventCycleNodeCustomViewModel : CustomNodeViewModel -{ - private readonly DataModelEventCycleNode _cycleNode; - private readonly INodeEditorService _nodeEditorService; - private DataModelPath? _dataModelPath; - private ObservableCollection? _modules; - private bool _updating; - - public DataModelEventCycleNodeCustomViewModel(DataModelEventCycleNode cycleNode, INodeScript script, ISettingsService settingsService, INodeEditorService nodeEditorService) : base(cycleNode, script) - { - _cycleNode = cycleNode; - _nodeEditorService = nodeEditorService; - - ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true); - ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false); - Modules = new ObservableCollection(); - - this.WhenActivated(d => - { - // Set up extra modules - if (_cycleNode.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null) - Modules = new ObservableCollection {scriptProfile.Configuration.Module}; - else if (_cycleNode.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null) - Modules = new ObservableCollection {profileConfiguration.Module}; - - // Subscribe to node changes - _cycleNode.WhenAnyValue(n => n.Storage).Subscribe(UpdateDataModelPath).DisposeWith(d); - this.WhenAnyValue(vm => vm.DataModelPath).WhereNotNull().Subscribe(ApplyDataModelPath).DisposeWith(d); - - Disposable.Create(() => - { - _dataModelPath?.Dispose(); - _dataModelPath = null; - }).DisposeWith(d); - }); - } - - public PluginSetting ShowFullPaths { get; } - public PluginSetting ShowDataModelValues { get; } - - public ObservableCollection? Modules - { - get => _modules; - set => this.RaiseAndSetIfChanged(ref _modules, value); - } - - public DataModelPath? DataModelPath - { - get => _dataModelPath; - set => this.RaiseAndSetIfChanged(ref _dataModelPath, value); - } - - private void UpdateDataModelPath(DataModelPathEntity? entity) - { - try - { - if (_updating) - return; - - _updating = true; - - DataModelPath? old = DataModelPath; - DataModelPath = entity != null ? new DataModelPath(entity) : null; - old?.Dispose(); - } - finally - { - _updating = false; - } - } - - private void ApplyDataModelPath(DataModelPath path) - { - try - { - if (_updating) - return; - if (path.Path == _cycleNode.Storage?.Path) - return; - - _updating = true; - - path.Save(); - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_cycleNode, path?.Entity, "event")); - } - finally - { - _updating = false; - } - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomView.axaml deleted file mode 100644 index a73713e3c..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomView.axaml +++ /dev/null @@ -1,19 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomView.axaml.cs deleted file mode 100644 index 62653fdb8..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.DataModel.Screens; - -public partial class DataModelEventNodeCustomView : ReactiveUserControl -{ - public DataModelEventNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomViewModel.cs deleted file mode 100644 index 3238ba287..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelEventNodeCustomViewModel.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System.Collections.ObjectModel; -using System.Reactive.Disposables; -using Artemis.Core; -using Artemis.Core.Modules; -using Artemis.Core.Services; -using Artemis.Storage.Entities.Profile; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.DataModel.Screens; - -public class DataModelEventNodeCustomViewModel : CustomNodeViewModel -{ - private readonly DataModelEventNode _node; - private readonly INodeEditorService _nodeEditorService; - private DataModelPath? _dataModelPath; - private ObservableCollection? _modules; - private bool _updating; - - public DataModelEventNodeCustomViewModel(DataModelEventNode node, INodeScript script, ISettingsService settingsService, INodeEditorService nodeEditorService, INodeService nodeService) - : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true); - ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false); - Modules = new ObservableCollection(); - - List nodePinTypes = nodeService.GetRegisteredTypes(); - nodePinTypes.AddRange(Constants.NumberTypes); - nodePinTypes.Add(typeof(IDataModelEvent)); - NodePinTypes = new ObservableCollection(nodePinTypes); - - this.WhenActivated(d => - { - // Set up extra modules - if (_node.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null) - Modules = new ObservableCollection {scriptProfile.Configuration.Module}; - else if (_node.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null) - Modules = new ObservableCollection {profileConfiguration.Module}; - - // Subscribe to node changes - _node.WhenAnyValue(n => n.Storage).Subscribe(UpdateDataModelPath).DisposeWith(d); - this.WhenAnyValue(vm => vm.DataModelPath).WhereNotNull().Subscribe(ApplyDataModelPath).DisposeWith(d); - - Disposable.Create(() => - { - _dataModelPath?.Dispose(); - _dataModelPath = null; - }).DisposeWith(d); - }); - } - - public PluginSetting ShowFullPaths { get; } - public PluginSetting ShowDataModelValues { get; } - public ObservableCollection NodePinTypes { get; } - - public ObservableCollection? Modules - { - get => _modules; - set => this.RaiseAndSetIfChanged(ref _modules, value); - } - - public DataModelPath? DataModelPath - { - get => _dataModelPath; - set => this.RaiseAndSetIfChanged(ref _dataModelPath, value); - } - - private void UpdateDataModelPath(DataModelPathEntity? entity) - { - try - { - if (_updating) - return; - - _updating = true; - - DataModelPath? old = DataModelPath; - DataModelPath = entity != null ? new DataModelPath(entity) : null; - old?.Dispose(); - } - finally - { - _updating = false; - } - } - - private void ApplyDataModelPath(DataModelPath path) - { - try - { - if (_updating) - return; - if (path.Path == _node.Storage?.Path) - return; - - _updating = true; - - path.Save(); - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, path?.Entity, "event")); - } - finally - { - _updating = false; - } - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomView.axaml deleted file mode 100644 index cef80d0ae..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomView.axaml +++ /dev/null @@ -1,17 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomView.axaml.cs deleted file mode 100644 index c40e8768d..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.DataModel.Screens; - -public partial class DataModelNodeCustomView : ReactiveUserControl -{ - public DataModelNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomViewModel.cs deleted file mode 100644 index 91d502e98..000000000 --- a/src/Artemis.VisualScripting/Nodes/DataModel/Screens/DataModelNodeCustomViewModel.cs +++ /dev/null @@ -1,108 +0,0 @@ -using System.Collections.ObjectModel; -using System.Reactive.Disposables; -using Artemis.Core; -using Artemis.Core.Modules; -using Artemis.Core.Services; -using Artemis.Storage.Entities.Profile; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.DataModel.Screens; - -public class DataModelNodeCustomViewModel : CustomNodeViewModel -{ - private readonly DataModelNode _node; - private readonly INodeEditorService _nodeEditorService; - private DataModelPath? _dataModelPath; - private ObservableCollection? _modules; - private bool _updating; - - public DataModelNodeCustomViewModel(DataModelNode node, INodeScript script, ISettingsService settingsService, INodeEditorService nodeEditorService, INodeService nodeService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - ShowFullPaths = settingsService.GetSetting("ProfileEditor.ShowFullPaths", true); - ShowDataModelValues = settingsService.GetSetting("ProfileEditor.ShowDataModelValues", false); - - List nodePinTypes = nodeService.GetRegisteredTypes(); - nodePinTypes.AddRange(Constants.NumberTypes); - NodePinTypes = new ObservableCollection(nodePinTypes); - - this.WhenActivated(d => - { - // Set up extra modules - if (_node.Script?.Context is Profile scriptProfile && scriptProfile.Configuration.Module != null) - Modules = new ObservableCollection {scriptProfile.Configuration.Module}; - else if (_node.Script?.Context is ProfileConfiguration profileConfiguration && profileConfiguration.Module != null) - Modules = new ObservableCollection {profileConfiguration.Module}; - - // Subscribe to node changes - _node.WhenAnyValue(n => n.Storage).Subscribe(UpdateDataModelPath).DisposeWith(d); - this.WhenAnyValue(vm => vm.DataModelPath).WhereNotNull().Subscribe(ApplyDataModelPath).DisposeWith(d); - - Disposable.Create(() => - { - _dataModelPath?.Dispose(); - _dataModelPath = null; - }).DisposeWith(d); - }); - } - - public PluginSetting ShowFullPaths { get; } - public PluginSetting ShowDataModelValues { get; } - public ObservableCollection NodePinTypes { get; } - - public ObservableCollection? Modules - { - get => _modules; - set => this.RaiseAndSetIfChanged(ref _modules, value); - } - - public DataModelPath? DataModelPath - { - get => _dataModelPath; - set => this.RaiseAndSetIfChanged(ref _dataModelPath, value); - } - - private void UpdateDataModelPath(DataModelPathEntity? entity) - { - try - { - if (_updating) - return; - - _updating = true; - - DataModelPath? old = DataModelPath; - DataModelPath = entity != null ? new DataModelPath(entity) : null; - old?.Dispose(); - } - finally - { - _updating = false; - } - } - - private void ApplyDataModelPath(DataModelPath path) - { - try - { - if (_updating) - return; - if (path.Path == _node.Storage?.Path) - return; - - _updating = true; - - path.Save(); - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, path?.Entity, "path")); - } - finally - { - _updating = false; - } - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedLayerProperty.cs b/src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedLayerProperty.cs deleted file mode 100644 index ae6c62f28..000000000 --- a/src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedLayerProperty.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; - -namespace Artemis.VisualScripting.Nodes.External.Commands; - -public class UpdateLayerPropertyNodeSelectedLayerProperty : INodeEditorCommand -{ - private readonly NodeConnectionStore _connections; - private readonly LayerPropertyNode _node; - private readonly ILayerProperty? _oldValue; - private readonly ILayerProperty? _value; - - public UpdateLayerPropertyNodeSelectedLayerProperty(LayerPropertyNode node, ILayerProperty? value) - { - _node = node; - _connections = new NodeConnectionStore(_node); - - _value = value; - _oldValue = _node.LayerProperty; - } - - - /// - public string DisplayName => "Update node layer property"; - - /// - public void Execute() - { - // Store connections as they currently are - _connections.Store(); - - // Update the selected profile element - _node.ChangeLayerProperty(_value); - } - - /// - public void Undo() - { - // Restore the previous layer property - _node.ChangeLayerProperty(_oldValue); - - // Restore connections - _connections.Restore(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedProfileElement.cs b/src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedProfileElement.cs deleted file mode 100644 index fa7793b81..000000000 --- a/src/Artemis.VisualScripting/Nodes/External/Commands/UpdateLayerPropertyNodeSelectedProfileElement.cs +++ /dev/null @@ -1,54 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; - -namespace Artemis.VisualScripting.Nodes.External.Commands; - -public class UpdateLayerPropertyNodeSelectedProfileElement : INodeEditorCommand -{ - private readonly NodeConnectionStore _connections; - private readonly LayerPropertyNode _node; - private readonly ILayerProperty? _oldLayerProperty; - private readonly RenderProfileElement? _oldValue; - - private readonly RenderProfileElement? _value; - - public UpdateLayerPropertyNodeSelectedProfileElement(LayerPropertyNode node, RenderProfileElement? value) - { - _node = node; - _connections = new NodeConnectionStore(_node); - - _value = value; - _oldValue = node.ProfileElement; - _oldLayerProperty = node.LayerProperty; - } - - /// - public string DisplayName => "Update node profile element"; - - /// - public void Execute() - { - // Store connections as they currently are - _connections.Store(); - - // Update the selected profile element - _node.ChangeProfileElement(_value); - } - - /// - public void Undo() - { - // Can't undo it if that profile element is now gone :\ - if (_oldValue != null && _oldValue.Disposed) - return; - - // Restore the previous profile element - _node.ChangeProfileElement(_oldValue); - - // Restore the previous layer property - _node.ChangeLayerProperty(_oldLayerProperty); - - // Restore connections - _connections.Restore(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/External/LayerPropertyNode.cs b/src/Artemis.VisualScripting/Nodes/External/LayerPropertyNode.cs deleted file mode 100644 index 5a2199c05..000000000 --- a/src/Artemis.VisualScripting/Nodes/External/LayerPropertyNode.cs +++ /dev/null @@ -1,154 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.External.Screens; - -namespace Artemis.VisualScripting.Nodes.External; - -// [Node("Layer/Folder Property", "Outputs the property of a selected layer or folder", "External")] -public class LayerPropertyNode : Node -{ - private readonly object _layerPropertyLock = new(); - private readonly List _pinBucket = new(); - - public LayerPropertyNode() : base("Layer/Folder Property", "Outputs the property of a selected layer or folder") - { - } - - public INodeScript? Script { get; private set; } - public RenderProfileElement? ProfileElement { get; private set; } - public ILayerProperty? LayerProperty { get; private set; } - - public override void Evaluate() - { - lock (_layerPropertyLock) - { - // In this case remove the pins so no further evaluations occur - if (LayerProperty == null) - { - CreatePins(); - return; - } - - List list = LayerProperty.BaseDataBinding.Properties.ToList(); - int index = 0; - foreach (IPin pin in Pins) - { - OutputPin outputPin = (OutputPin) pin; - IDataBindingProperty dataBindingProperty = list[index]; - index++; - - // TODO: Is this really non-nullable? - outputPin.Value = dataBindingProperty.GetValue(); - } - } - } - - public override void Initialize(INodeScript script) - { - Script = script; - - if (script.Context is Profile profile) - profile.ChildRemoved += ProfileOnChildRemoved; - - LoadLayerProperty(); - } - - public void LoadLayerProperty() - { - lock (_layerPropertyLock) - { - if (Script?.Context is not Profile profile || Storage == null) - return; - - RenderProfileElement? element = profile.GetAllRenderElements().FirstOrDefault(l => l.EntityId == Storage.ElementId); - - ProfileElement = element; - LayerProperty = element?.GetAllLayerProperties().FirstOrDefault(p => p.Path == Storage.PropertyPath); - CreatePins(); - } - } - - public void ChangeProfileElement(RenderProfileElement? profileElement) - { - lock (_layerPropertyLock) - { - ProfileElement = profileElement; - LayerProperty = profileElement?.GetAllLayerProperties().FirstOrDefault(); - - Storage = new LayerPropertyNodeEntity - { - ElementId = ProfileElement?.EntityId ?? Guid.Empty, - PropertyPath = null - }; - - CreatePins(); - } - } - - public void ChangeLayerProperty(ILayerProperty? layerProperty) - { - lock (_layerPropertyLock) - { - LayerProperty = layerProperty; - - Storage = new LayerPropertyNodeEntity - { - ElementId = ProfileElement?.EntityId ?? Guid.Empty, - PropertyPath = LayerProperty?.Path - }; - - CreatePins(); - } - } - - private void CreatePins() - { - while (Pins.Any()) - RemovePin((Pin) Pins.First()); - - if (LayerProperty == null) - return; - - foreach (IDataBindingProperty dataBindingRegistration in LayerProperty.BaseDataBinding.Properties) - CreateOrAddOutputPin(dataBindingRegistration.ValueType, dataBindingRegistration.DisplayName); - } - - /// - /// Creates or adds an input pin to the node using a bucket. - /// The bucket might grow a bit over time as the user edits the node but pins won't get lost, enabling undo/redo in the - /// editor. - /// - private new void CreateOrAddOutputPin(Type valueType, string displayName) - { - // Grab the first pin from the bucket that isn't on the node yet - OutputPin? pin = _pinBucket.FirstOrDefault(p => !Pins.Contains(p)); - - // If there is none, create a new one and add it to the bucket - if (pin == null) - { - pin = CreateOutputPin(valueType, displayName); - _pinBucket.Add(pin); - } - // If there was a pin in the bucket, update it's type and display name and reuse it - else - { - pin.ChangeType(valueType); - pin.Name = displayName; - AddPin(pin); - } - } - - private void ProfileOnChildRemoved(object? sender, EventArgs e) - { - if (Script?.Context is not Profile profile) - return; - - if (ProfileElement == null || !profile.GetAllRenderElements().Contains(ProfileElement)) - ChangeProfileElement(null); - } -} - -public class LayerPropertyNodeEntity -{ - public Guid ElementId { get; set; } - public string? PropertyPath { get; set; } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml deleted file mode 100644 index 4a323a590..000000000 --- a/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - Node not available - - - This node cannot be used outside profile scripts. - - - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml.cs deleted file mode 100644 index 4348da66e..000000000 --- a/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.External.Screens; - -public partial class LayerPropertyNodeCustomView : ReactiveUserControl -{ - public LayerPropertyNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomViewModel.cs deleted file mode 100644 index bca028ff6..000000000 --- a/src/Artemis.VisualScripting/Nodes/External/Screens/LayerPropertyNodeCustomViewModel.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System.Collections.ObjectModel; -using System.Reactive.Disposables; -using System.Reactive.Linq; -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.VisualScripting; -using Artemis.VisualScripting.Nodes.External.Commands; -using DynamicData; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.External.Screens; - -public class LayerPropertyNodeCustomViewModel : CustomNodeViewModel -{ - private readonly LayerPropertyNode _node; - private readonly INodeEditorService _nodeEditorService; - private bool _outsideProfileContext; - - public LayerPropertyNodeCustomViewModel(LayerPropertyNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - this.WhenActivated(d => - { - if (_node.Script?.Context is not Profile profile) - { - OutsideProfileContext = true; - return; - } - - OutsideProfileContext = false; - Observable.FromEventPattern(x => profile.DescendentAdded += x, x => profile.DescendentAdded -= x).Subscribe(_ => GetProfileElements()).DisposeWith(d); - Observable.FromEventPattern(x => profile.DescendentRemoved += x, x => profile.DescendentRemoved -= x).Subscribe(_ => GetProfileElements()).DisposeWith(d); - GetProfileElements(); - GetLayerProperties(); - }); - - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(SelectedProfileElement)); - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(SelectedLayerProperty)); - this.WhenAnyValue(vm => vm.SelectedProfileElement).Subscribe(_ => GetLayerProperties()); - } - - public ObservableCollection ProfileElements { get; } = new(); - public ObservableCollection LayerProperties { get; } = new(); - - public bool OutsideProfileContext - { - get => _outsideProfileContext; - set => this.RaiseAndSetIfChanged(ref _outsideProfileContext, value); - } - - public RenderProfileElement? SelectedProfileElement - { - get => _node.ProfileElement; - set - { - if (value != null && !Equals(_node.ProfileElement, value)) - _nodeEditorService.ExecuteCommand(Script, new UpdateLayerPropertyNodeSelectedProfileElement(_node, value)); - } - } - - public ILayerProperty? SelectedLayerProperty - { - get => _node.LayerProperty; - set - { - if (value != null && !Equals(_node.LayerProperty, value)) - _nodeEditorService.ExecuteCommand(Script, new UpdateLayerPropertyNodeSelectedLayerProperty(_node, value)); - } - } - - private void GetProfileElements() - { - ProfileElements.Clear(); - if (_node.Script?.Context is not Profile profile) - return; - - List elements = new(profile.GetAllRenderElements()); - - ProfileElements.AddRange(elements.OrderBy(e => e.Order)); - SelectedProfileElement = _node.ProfileElement; - } - - private void GetLayerProperties() - { - LayerProperties.Clear(); - if (_node.ProfileElement == null) - return; - - LayerProperties.AddRange(_node.ProfileElement.GetAllLayerProperties().Where(l => !l.IsHidden && l.DataBindingsSupported)); - SelectedLayerProperty = _node.LayerProperty; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/HotkeyEnableDisableNode.cs b/src/Artemis.VisualScripting/Nodes/Input/HotkeyEnableDisableNode.cs deleted file mode 100644 index 12946deb8..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/HotkeyEnableDisableNode.cs +++ /dev/null @@ -1,74 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Services; -using Artemis.VisualScripting.Nodes.Input.Screens; - -namespace Artemis.VisualScripting.Nodes.Input; - -[Node("Hotkey enable/disable", "Outputs a boolean value enabled and disabled by a set of hotkeys", "Input", OutputType = typeof(bool))] -public class HotkeyEnableDisableNode : Node, IDisposable -{ - private readonly IInputService _inputService; - private Hotkey? _disableHotkey; - private Hotkey? _enableHotkey; - private bool _value; - private bool _retrievedInitialValue; - - public HotkeyEnableDisableNode(IInputService inputService) - { - _inputService = inputService; - _inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp; - - InitialValue = CreateInputPin(); - Output = CreateOutputPin(); - StorageModified += OnStorageModified; - } - - public InputPin InitialValue { get; } - public OutputPin Output { get; } - - public override void Initialize(INodeScript script) - { - LoadHotkeys(); - } - - public override void Evaluate() - { - if (!_retrievedInitialValue) - { - _value = InitialValue.Value; - _retrievedInitialValue = true; - } - - Output.Value = _value; - } - - private void OnStorageModified(object? sender, EventArgs e) - { - LoadHotkeys(); - } - - private void LoadHotkeys() - { - if (Storage == null) - return; - - _enableHotkey = Storage.EnableHotkey != null ? new Hotkey(Storage.EnableHotkey) : null; - _disableHotkey = Storage.DisableHotkey != null ? new Hotkey(Storage.DisableHotkey) : null; - } - - private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e) - { - if (Storage == null) - return; - - if (_disableHotkey != null && _disableHotkey.MatchesEventArgs(e)) - _value = false; - else if (_enableHotkey != null && _enableHotkey.MatchesEventArgs(e)) - _value = true; - } - - public void Dispose() - { - _inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/HotkeyEnableDisableNodeEntity.cs b/src/Artemis.VisualScripting/Nodes/Input/HotkeyEnableDisableNodeEntity.cs deleted file mode 100644 index 98f84b2b0..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/HotkeyEnableDisableNodeEntity.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Artemis.Core; -using Artemis.Storage.Entities.Profile; - -namespace Artemis.VisualScripting.Nodes.Input; - -public class HotkeyEnableDisableNodeEntity -{ - public HotkeyEnableDisableNodeEntity(Hotkey? enableHotkey, Hotkey? disableHotkey) - { - enableHotkey?.Save(); - EnableHotkey = enableHotkey?.Entity; - disableHotkey?.Save(); - DisableHotkey = disableHotkey?.Entity; - } - - public ProfileConfigurationHotkeyEntity? EnableHotkey { get; set; } - public ProfileConfigurationHotkeyEntity? DisableHotkey { get; set; } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/HotkeyPressNode.cs b/src/Artemis.VisualScripting/Nodes/Input/HotkeyPressNode.cs deleted file mode 100644 index 593eaf8bf..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/HotkeyPressNode.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Services; -using Artemis.VisualScripting.Nodes.Input.Screens; - -namespace Artemis.VisualScripting.Nodes.Input; - -[Node("Hotkey press", "Outputs a boolean value for as long as a hotkey is pressed", "Input", OutputType = typeof(bool))] -public class HotkeyPressNode : Node, IDisposable -{ - private readonly IInputService _inputService; - private Hotkey? _toggleHotkey; - private bool _value; - - public HotkeyPressNode(IInputService inputService) - { - _inputService = inputService; - _inputService.KeyboardKeyDown += InputServiceOnKeyboardKeyDown; - _inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp; - - Output = CreateOutputPin(); - StorageModified += OnStorageModified; - } - - public OutputPin Output { get; } - - public override void Initialize(INodeScript script) - { - LoadHotkeys(); - } - - public override void Evaluate() - { - Output.Value = _value; - } - - private void OnStorageModified(object? sender, EventArgs e) - { - LoadHotkeys(); - } - - private void LoadHotkeys() - { - if (Storage == null) - return; - - _toggleHotkey = Storage.EnableHotkey != null ? new Hotkey(Storage.EnableHotkey) : null; - } - - private void InputServiceOnKeyboardKeyDown(object? sender, ArtemisKeyboardKeyEventArgs e) - { - if (Storage == null) - return; - if (_toggleHotkey != null && _toggleHotkey.MatchesEventArgs(e)) - _value = true; - } - - private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e) - { - if (Storage == null) - return; - if (_toggleHotkey != null && _toggleHotkey.MatchesEventArgs(e)) - _value = false; - } - - public void Dispose() - { - _inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/HotkeyToggleNode.cs b/src/Artemis.VisualScripting/Nodes/Input/HotkeyToggleNode.cs deleted file mode 100644 index a31d5d253..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/HotkeyToggleNode.cs +++ /dev/null @@ -1,69 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Services; -using Artemis.VisualScripting.Nodes.Input.Screens; - -namespace Artemis.VisualScripting.Nodes.Input; - -[Node("Hotkey toggle", "Outputs a boolean value toggled by a hotkey", "Input", OutputType = typeof(bool))] -public class HotkeyToggleNode : Node, IDisposable -{ - private readonly IInputService _inputService; - private Hotkey? _toggleHotkey; - private bool _value; - private bool _retrievedInitialValue; - - public HotkeyToggleNode(IInputService inputService) - { - _inputService = inputService; - _inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp; - - InitialValue = CreateInputPin(); - Output = CreateOutputPin(); - StorageModified += OnStorageModified; - } - - public InputPin InitialValue { get; } - public OutputPin Output { get; } - - public override void Initialize(INodeScript script) - { - LoadHotkeys(); - } - - public override void Evaluate() - { - if (!_retrievedInitialValue) - { - _value = InitialValue.Value; - _retrievedInitialValue = true; - } - - Output.Value = _value; - } - - private void OnStorageModified(object? sender, EventArgs e) - { - LoadHotkeys(); - } - - private void LoadHotkeys() - { - if (Storage == null) - return; - - _toggleHotkey = Storage.EnableHotkey != null ? new Hotkey(Storage.EnableHotkey) : null; - } - - private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e) - { - if (Storage == null) - return; - if (_toggleHotkey != null && _toggleHotkey.MatchesEventArgs(e)) - _value = !_value; - } - - public void Dispose() - { - _inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/PressedKeyPositionNode.cs b/src/Artemis.VisualScripting/Nodes/Input/PressedKeyPositionNode.cs deleted file mode 100644 index e08b05fab..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/PressedKeyPositionNode.cs +++ /dev/null @@ -1,73 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Services; -using Artemis.VisualScripting.Nodes.Input.Screens; -using SkiaSharp; -using static Artemis.VisualScripting.Nodes.Input.PressedKeyPositionNodeEntity; - -namespace Artemis.VisualScripting.Nodes.Input; - -[Node("Pressed Key Position", "Outputs the position of a pressed key relative to a layer", "Input", OutputType = typeof(Numeric))] -public class PressedKeyPositionNode : Node, IDisposable -{ - private readonly IInputService _inputService; - private Layer? _layer; - private SKPoint _ledPosition; - private Profile? _profile; - - public PressedKeyPositionNode(IInputService inputService) - { - _inputService = inputService; - XPosition = CreateOutputPin("X"); - YPosition = CreateOutputPin("Y"); - - StorageModified += OnStorageModified; - _inputService.KeyboardKeyDown += InputServiceOnKeyboardKeyDown; - _inputService.KeyboardKeyUp += InputServiceOnKeyboardKeyUp; - } - - public OutputPin XPosition { get; } - public OutputPin YPosition { get; } - - public override void Initialize(INodeScript script) - { - Storage ??= new PressedKeyPositionNodeEntity(); - - _profile = script.Context as Profile; - _layer = _profile?.GetAllLayers().FirstOrDefault(l => l.EntityId == Storage.LayerId); - } - - public override void Evaluate() - { - XPosition.Value = _ledPosition.X; - YPosition.Value = _ledPosition.Y; - } - - private void InputServiceOnKeyboardKeyDown(object? sender, ArtemisKeyboardKeyEventArgs e) - { - if (Storage?.RespondTo is KeyPressType.Down or KeyPressType.UpDown) - SetLedPosition(e.Led); - } - - private void InputServiceOnKeyboardKeyUp(object? sender, ArtemisKeyboardKeyEventArgs e) - { - if (Storage?.RespondTo is KeyPressType.Up or KeyPressType.UpDown) - SetLedPosition(e.Led); - } - - private void SetLedPosition(ArtemisLed? led) - { - if (_layer != null && led != null) - _ledPosition = new SKPoint((led.AbsoluteRectangle.MidX - _layer.Bounds.Left) / _layer.Bounds.Width, (led.AbsoluteRectangle.MidY - _layer.Bounds.Top) / _layer.Bounds.Height); - } - - private void OnStorageModified(object? sender, EventArgs e) - { - _layer = _profile?.GetAllLayers().FirstOrDefault(l => l.EntityId == Storage?.LayerId); - } - - public void Dispose() - { - _inputService.KeyboardKeyDown -= InputServiceOnKeyboardKeyDown; - _inputService.KeyboardKeyUp -= InputServiceOnKeyboardKeyUp; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/PressedKeyPositionNodeEntity.cs b/src/Artemis.VisualScripting/Nodes/Input/PressedKeyPositionNodeEntity.cs deleted file mode 100644 index 1c74a9899..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/PressedKeyPositionNodeEntity.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.ComponentModel; - -namespace Artemis.VisualScripting.Nodes.Input; - -public class PressedKeyPositionNodeEntity -{ - public PressedKeyPositionNodeEntity() - { - } - - public PressedKeyPositionNodeEntity(Guid layerId, KeyPressType respondTo) - { - LayerId = layerId; - RespondTo = respondTo; - } - - public Guid LayerId { get; set; } - public KeyPressType RespondTo { get; set; } - - public enum KeyPressType - { - [Description("Up")] - Up, - [Description("Down")] - Down, - [Description("Up/down")] - UpDown - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomView.axaml deleted file mode 100644 index 7285adced..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomView.axaml +++ /dev/null @@ -1,16 +0,0 @@ - - - Enable - - Disable - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomView.axaml.cs deleted file mode 100644 index 7bc6bf76d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomView.axaml.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Artemis.UI.Shared; -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public partial class HotkeyEnableDisableNodeCustomView : ReactiveUserControl -{ - public HotkeyEnableDisableNodeCustomView() - { - InitializeComponent(); - } - - - private void HotkeyBox_OnHotkeyChanged(HotkeyBox sender, EventArgs args) - { - ViewModel?.Save(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomViewModel.cs deleted file mode 100644 index abf8bcbb8..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyEnableDisableNodeCustomViewModel.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Reactive.Disposables; -using System.Reactive.Linq; -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public class HotkeyEnableDisableNodeCustomViewModel : CustomNodeViewModel -{ - private readonly HotkeyEnableDisableNode _enableDisableNode; - private readonly INodeEditorService _nodeEditorService; - private Hotkey? _enableHotkey; - private Hotkey? _disableHotkey; - private bool _updating; - - /// - public HotkeyEnableDisableNodeCustomViewModel(HotkeyEnableDisableNode enableDisableNode, INodeScript script, INodeEditorService nodeEditorService) : base(enableDisableNode, script) - { - _enableDisableNode = enableDisableNode; - _nodeEditorService = nodeEditorService; - - this.WhenActivated(d => - { - Observable.FromEventPattern(x => _enableDisableNode.StorageModified += x, x => _enableDisableNode.StorageModified -= x).Subscribe(_ => Update()).DisposeWith(d); - Update(); - }); - - } - - private void Update() - { - _updating = true; - - EnableHotkey = _enableDisableNode.Storage?.EnableHotkey != null ? new Hotkey(_enableDisableNode.Storage.EnableHotkey) : null; - DisableHotkey = _enableDisableNode.Storage?.DisableHotkey != null ? new Hotkey(_enableDisableNode.Storage.DisableHotkey) : null; - - _updating = false; - } - - public Hotkey? EnableHotkey - { - get => _enableHotkey; - set => this.RaiseAndSetIfChanged(ref _enableHotkey, value); - } - - public Hotkey? DisableHotkey - { - get => _disableHotkey; - set => this.RaiseAndSetIfChanged(ref _disableHotkey, value); - } - - public void Save() - { - if (_updating) - return; - - _nodeEditorService.ExecuteCommand( - Script, - new UpdateStorage(_enableDisableNode, new HotkeyEnableDisableNodeEntity(EnableHotkey, DisableHotkey), "hotkey") - ); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomView.axaml deleted file mode 100644 index 19097f664..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomView.axaml +++ /dev/null @@ -1,11 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomView.axaml.cs deleted file mode 100644 index 1ac0f3569..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomView.axaml.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Artemis.UI.Shared; -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public partial class HotkeyPressNodeCustomView : ReactiveUserControl -{ - public HotkeyPressNodeCustomView() - { - InitializeComponent(); - } - - - private void HotkeyBox_OnHotkeyChanged(HotkeyBox sender, EventArgs args) - { - ViewModel?.Save(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomViewModel.cs deleted file mode 100644 index a161de70b..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyPressNodeCustomViewModel.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Reactive.Disposables; -using System.Reactive.Linq; -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public class HotkeyPressNodeCustomViewModel : CustomNodeViewModel -{ - private readonly HotkeyPressNode _pressNode; - private readonly INodeEditorService _nodeEditorService; - private Hotkey? _toggleHotkey; - private bool _updating; - - /// - public HotkeyPressNodeCustomViewModel(HotkeyPressNode pressNode, INodeScript script, INodeEditorService nodeEditorService) : base(pressNode, script) - { - _pressNode = pressNode; - _nodeEditorService = nodeEditorService; - - this.WhenActivated(d => - { - Observable.FromEventPattern(x => _pressNode.StorageModified += x, x => _pressNode.StorageModified -= x).Subscribe(_ => Update()).DisposeWith(d); - Update(); - }); - - } - - private void Update() - { - _updating = true; - ToggleHotkey = _pressNode.Storage?.EnableHotkey != null ? new Hotkey(_pressNode.Storage.EnableHotkey) : null; - _updating = false; - } - - public Hotkey? ToggleHotkey - { - get => _toggleHotkey; - set => this.RaiseAndSetIfChanged(ref _toggleHotkey, value); - } - - public void Save() - { - if (_updating) - return; - - _nodeEditorService.ExecuteCommand( - Script, - new UpdateStorage(_pressNode, new HotkeyEnableDisableNodeEntity(ToggleHotkey, null), "hotkey") - ); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomView.axaml deleted file mode 100644 index b147737f3..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomView.axaml +++ /dev/null @@ -1,11 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomView.axaml.cs deleted file mode 100644 index 53a4a7adc..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomView.axaml.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Artemis.UI.Shared; -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public partial class HotkeyToggleNodeCustomView : ReactiveUserControl -{ - public HotkeyToggleNodeCustomView() - { - InitializeComponent(); - } - - - private void HotkeyBox_OnHotkeyChanged(HotkeyBox sender, EventArgs args) - { - ViewModel?.Save(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomViewModel.cs deleted file mode 100644 index c7dc683ea..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/HotkeyToggleNodeCustomViewModel.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System.Reactive.Disposables; -using System.Reactive.Linq; -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public class HotkeyToggleNodeCustomViewModel : CustomNodeViewModel -{ - private readonly HotkeyToggleNode _toggleNode; - private readonly INodeEditorService _nodeEditorService; - private Hotkey? _toggleHotkey; - private bool _updating; - - /// - public HotkeyToggleNodeCustomViewModel(HotkeyToggleNode toggleNode, INodeScript script, INodeEditorService nodeEditorService) : base(toggleNode, script) - { - _toggleNode = toggleNode; - _nodeEditorService = nodeEditorService; - - this.WhenActivated(d => - { - Observable.FromEventPattern(x => _toggleNode.StorageModified += x, x => _toggleNode.StorageModified -= x).Subscribe(_ => Update()).DisposeWith(d); - Update(); - }); - - } - - private void Update() - { - _updating = true; - ToggleHotkey = _toggleNode.Storage?.EnableHotkey != null ? new Hotkey(_toggleNode.Storage.EnableHotkey) : null; - _updating = false; - } - - public Hotkey? ToggleHotkey - { - get => _toggleHotkey; - set => this.RaiseAndSetIfChanged(ref _toggleHotkey, value); - } - - public void Save() - { - if (_updating) - return; - - _nodeEditorService.ExecuteCommand( - Script, - new UpdateStorage(_toggleNode, new HotkeyEnableDisableNodeEntity(ToggleHotkey, null), "hotkey") - ); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomView.axaml deleted file mode 100644 index bcb70f3f2..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomView.axaml +++ /dev/null @@ -1,29 +0,0 @@ - - - Layer - - - - - - - - - - - - Respond to - - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomView.axaml.cs deleted file mode 100644 index 0b24f4d51..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public partial class PressedKeyPositionNodeCustomView : ReactiveUserControl -{ - public PressedKeyPositionNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomViewModel.cs deleted file mode 100644 index 2cc2660e1..000000000 --- a/src/Artemis.VisualScripting/Nodes/Input/Screens/PressedKeyPositionNodeCustomViewModel.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System.Collections.ObjectModel; -using System.Reactive.Disposables; -using System.Reactive.Linq; -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; -using static Artemis.VisualScripting.Nodes.Input.PressedKeyPositionNodeEntity; - -namespace Artemis.VisualScripting.Nodes.Input.Screens; - -public class PressedKeyPositionNodeCustomViewModel : CustomNodeViewModel -{ - private readonly INodeEditorService _nodeEditorService; - private readonly Profile? _profile; - private readonly PressedKeyPositionNode _node; - private Layer? _selectedLayer; - private KeyPressType _respondTo; - - public PressedKeyPositionNodeCustomViewModel(PressedKeyPositionNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _nodeEditorService = nodeEditorService; - _profile = script.Context as Profile; - _node = node; - - Layers = new ObservableCollection(); - - this.WhenActivated(d => - { - if (_profile == null) - return; - - Observable.FromEventPattern(x => _profile.DescendentAdded += x, x => _profile.DescendentAdded -= x).Subscribe(_ => GetLayers()).DisposeWith(d); - Observable.FromEventPattern(x => _profile.DescendentRemoved += x, x => _profile.DescendentRemoved -= x).Subscribe(_ => GetLayers()).DisposeWith(d); - Observable.FromEventPattern(x => _node.StorageModified += x, x => _node.StorageModified -= x).Subscribe(_ => Update()).DisposeWith(d); - - GetLayers(); - }); - - this.WhenAnyValue(vm => vm.SelectedLayer).Subscribe(UpdateSelectedLayer); - this.WhenAnyValue(vm => vm.RespondTo).Subscribe(UpdateSelectedRespondTo); - } - - public ObservableCollection Layers { get; } - - public Layer? SelectedLayer - { - get => _selectedLayer; - set => this.RaiseAndSetIfChanged(ref _selectedLayer, value); - } - - public KeyPressType RespondTo - { - get => _respondTo; - set => this.RaiseAndSetIfChanged(ref _respondTo, value); - } - - private void GetLayers() - { - Layers.Clear(); - if (_profile == null) - return; - foreach (Layer layer in _profile.GetAllLayers()) - Layers.Add(layer); - - Update(); - } - - private void Update() - { - SelectedLayer = Layers.FirstOrDefault(l => l.EntityId == _node.Storage?.LayerId); - RespondTo = _node.Storage?.RespondTo ?? KeyPressType.Up; - } - - private void UpdateSelectedLayer(Layer? layer) - { - if (layer == null || _node.Storage?.LayerId == layer.EntityId) - return; - - _nodeEditorService.ExecuteCommand( - Script, - new UpdateStorage(_node, new PressedKeyPositionNodeEntity(layer.EntityId, _node.Storage?.RespondTo ?? KeyPressType.Up), "layer") - ); - } - - private void UpdateSelectedRespondTo(KeyPressType respondTo) - { - if (_node.Storage?.RespondTo == respondTo) - return; - - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, new PressedKeyPositionNodeEntity(_node.Storage?.LayerId ?? Guid.Empty, respondTo), "layer")); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorEntity.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorEntity.cs deleted file mode 100644 index 515f8be2e..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorEntity.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Artemis.Storage.Entities.Profile.Nodes; - -namespace Artemis.VisualScripting.Nodes.List; - -public class ListOperatorEntity -{ - public NodeScriptEntity? Script { get; set; } - public ListOperator Operator { get; set; } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs deleted file mode 100644 index 5a2cadd5b..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorNode.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections; -using Artemis.Core; -using Artemis.VisualScripting.Nodes.List.Screens; - -namespace Artemis.VisualScripting.Nodes.List; - -[Node("List Operator (Simple)", "Checks if any/all/no values in the input list match the input value", "List", InputType = typeof(IEnumerable), OutputType = typeof(bool))] -public class ListOperatorNode : Node -{ - public ListOperatorNode() - { - InputList = CreateInputPin(); - InputValue = CreateInputPin(); - - Output = CreateOutputPin(); - } - - public InputPin InputList { get; } - public InputPin InputValue { get; } - public OutputPin Output { get; } - - /// - public override void Evaluate() - { - if (InputList.Value == null) - { - Output.Value = Storage == ListOperator.None; - return; - } - - object? input = InputValue.Value; - if (Storage == ListOperator.Any) - Output.Value = InputList.Value.Cast().Any(v => v.Equals(input)); - else if (Storage == ListOperator.All) - Output.Value = InputList.Value.Cast().All(v => v.Equals(input)); - else if (Storage == ListOperator.None) - Output.Value = InputList.Value.Cast().All(v => !v.Equals(input)); - } -} - -public enum ListOperator -{ - Any, - All, - None -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs deleted file mode 100644 index 3631e5934..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs +++ /dev/null @@ -1,106 +0,0 @@ -using System.Collections; -using Artemis.Core; -using Artemis.Core.Events; -using Artemis.VisualScripting.Nodes.List.Screens; - -namespace Artemis.VisualScripting.Nodes.List; - -[Node("List Operator (Advanced)", "Checks if any/all/no values in the input list match a condition", "List", InputType = typeof(IEnumerable), OutputType = typeof(bool))] -public class ListOperatorPredicateNode : Node, IDisposable -{ - private readonly object _scriptLock = new(); - private readonly ListOperatorPredicateStartNode _startNode; - - public ListOperatorPredicateNode() - { - _startNode = new ListOperatorPredicateStartNode {X = -200}; - - InputList = CreateInputPin(); - Output = CreateOutputPin(); - - InputList.PinConnected += InputListOnPinConnected; - } - - public InputPin InputList { get; } - public OutputPin Output { get; } - public NodeScript? Script { get; private set; } - - public override void Initialize(INodeScript script) - { - Storage ??= new ListOperatorEntity(); - - lock (_scriptLock) - { - Script = Storage?.Script != null - ? new NodeScript("Is match", "Determines whether the current list item is a match", Storage.Script, script.Context, new List {_startNode}) - : new NodeScript("Is match", "Determines whether the current list item is a match", script.Context, new List {_startNode}); - } - } - - /// - public override void Evaluate() - { - if (Storage == null) - return; - - if (InputList.Value == null) - { - Output.Value = Storage.Operator == ListOperator.None; - return; - } - - lock (_scriptLock) - { - if (Script == null) - return; - - if (Storage.Operator == ListOperator.Any) - Output.Value = InputList.Value.Cast().Any(EvaluateItem); - else if (Storage.Operator == ListOperator.All) - Output.Value = InputList.Value.Cast().All(EvaluateItem); - else if (Storage.Operator == ListOperator.None) - Output.Value = InputList.Value.Cast().All(v => !EvaluateItem(v)); - } - } - - private bool EvaluateItem(object item) - { - if (Script == null) - return false; - - _startNode.Item = item; - Script.Run(); - return Script.Result; - } - - private void UpdateStartNode() - { - Type? type = InputList.ConnectedTo.FirstOrDefault()?.Type; - // List must be generic or there's no way to tell what objects it contains in advance, that's not supported for now - if (type is not {IsGenericType: true}) - return; - - Type listType = type.GetGenericArguments().Single(); - _startNode?.ChangeType(listType); - } - - private void InputListOnPinConnected(object? sender, SingleValueEventArgs e) - { - lock (_scriptLock) - { - UpdateStartNode(); - Script?.LoadConnections(); - } - } - - #region IDisposable - - /// - public void Dispose() - { - Script?.Dispose(); - Script = null; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateStartNode.cs b/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateStartNode.cs deleted file mode 100644 index ca37fb237..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateStartNode.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.List; - -public class ListOperatorPredicateStartNode : DefaultNode -{ - internal static readonly Guid NodeId = new("9A714CF3-8D02-4CC3-A1AC-73833F82D7C6"); - private readonly ObjectOutputPins _objectOutputPins; - - public ListOperatorPredicateStartNode() : base(NodeId, "List item", "Contains the current list item") - { - _objectOutputPins = new ObjectOutputPins(this); - } - - public object? Item { get; set; } - - public override void Evaluate() - { - if (Item != null) - _objectOutputPins.SetCurrentValue(Item); - } - - public void ChangeType(Type? type) - { - _objectOutputPins.ChangeType(type); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml deleted file mode 100644 index faa4e5543..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml.cs deleted file mode 100644 index e83b57bb7..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.List.Screens; - -public partial class ListOperatorNodeCustomView : ReactiveUserControl -{ - public ListOperatorNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomViewModel.cs deleted file mode 100644 index 134e6e1f1..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorNodeCustomViewModel.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.List.Screens; - -public class ListOperatorNodeCustomViewModel : CustomNodeViewModel -{ - private readonly ListOperatorNode _node; - private readonly INodeEditorService _nodeEditorService; - - public ListOperatorNodeCustomViewModel(ListOperatorNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue)); - } - - public ListOperator CurrentValue - { - get => _node.Storage; - set => _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomView.axaml deleted file mode 100644 index dbc6728a7..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomView.axaml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomView.axaml.cs deleted file mode 100644 index 1e34cf875..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.List.Screens; - -public partial class ListOperatorPredicateNodeCustomView : ReactiveUserControl -{ - public ListOperatorPredicateNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomViewModel.cs deleted file mode 100644 index b1a922752..000000000 --- a/src/Artemis.VisualScripting/Nodes/List/Screens/ListOperatorPredicateNodeCustomViewModel.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Reactive; -using System.Reactive.Disposables; -using Artemis.Core; -using Artemis.Core.Events; -using Artemis.UI.Shared.Services; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.List.Screens; - -public class ListOperatorPredicateNodeCustomViewModel : CustomNodeViewModel -{ - private readonly ListOperatorPredicateNode _node; - private readonly IWindowService _windowService; - private ListOperator _operator; - private bool _canOpenEditor; - - public ListOperatorPredicateNodeCustomViewModel(ListOperatorPredicateNode node, INodeScript script, IWindowService windowService) : base(node, script) - { - _node = node; - _windowService = windowService; - - OpenEditor = ReactiveCommand.CreateFromTask(ExecuteOpenEditor, this.WhenAnyValue(vm => vm.CanOpenEditor)); - CanOpenEditor = node.InputList.ConnectedTo.Any(); - - this.WhenActivated(d => - { - node.InputList.PinConnected += InputListOnPinConnected; - node.InputList.PinDisconnected += InputListOnPinDisconnected; - - Disposable.Create(() => - { - node.InputList.PinConnected -= InputListOnPinConnected; - node.InputList.PinDisconnected -= InputListOnPinDisconnected; - }).DisposeWith(d); - }); - } - - public ReactiveCommand OpenEditor { get; } - - private bool CanOpenEditor - { - get => _canOpenEditor; - set => this.RaiseAndSetIfChanged(ref _canOpenEditor, value); - } - - public ListOperator Operator - { - get => _operator; - set => this.RaiseAndSetIfChanged(ref _operator, value); - } - - private async Task ExecuteOpenEditor() - { - if (_node.Script == null) - return; - - await _windowService.ShowDialogAsync(_node.Script); - _node.Script.Save(); - - _node.Storage ??= new ListOperatorEntity(); - _node.Storage.Script = _node.Script.Entity; - } - - private void InputListOnPinDisconnected(object? sender, SingleValueEventArgs e) - { - CanOpenEditor = false; - } - - private void InputListOnPinConnected(object? sender, SingleValueEventArgs e) - { - CanOpenEditor = true; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs deleted file mode 100644 index 4cd839ecb..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/Clamp.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Artemis.Core; -using RGB.NET.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Clamp", "Clamps the value to be in between min and max", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class ClampNode : Node -{ - #region Properties & Fields - - public InputPin Value { get; } - public InputPin Min { get; } - public InputPin Max { get; } - - public OutputPin Result { get; } - - #endregion - - #region Constructors - - public ClampNode() - { - Value = CreateInputPin("Value"); - Min = CreateInputPin("Min"); - Max = CreateInputPin("Max"); - - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() => Result.Value = ((float)Value.Value).Clamp(Min.Value, Max.Value); - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs deleted file mode 100644 index b8e08d641..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/CounterNode.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Counter", "Counts from 0.0 to 1.0 at a configurable rate.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class CounterNode : Node -{ - private DateTime _lastEvaluate = DateTime.MinValue; - private float _progress; - - public CounterNode() - { - Time = CreateInputPin("Time (ms)"); - Output = CreateOutputPin(); - } - - public InputPin Time { get; set; } - public OutputPin Output { get; set; } - - public override void Evaluate() - { - DateTime now = DateTime.Now; - TimeSpan delta = now - _lastEvaluate; - - if (Time.Value != 0) - _progress = (float) (_progress + delta.TotalMilliseconds / Time.Value) % 1.0f; - - Output.Value = new Numeric(MathF.Round(_progress, 4, MidpointRounding.AwayFromZero)); - _lastEvaluate = now; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs deleted file mode 100644 index 5ae96af1c..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/LerpNode.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Artemis.Core; -using RGB.NET.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Lerp", "Interpolates linear between the two values A and B", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class LerpNode : Node -{ - #region Properties & Fields - - public InputPin A { get; } - public InputPin B { get; } - public InputPin T { get; } - - public OutputPin Result { get; } - - #endregion - - #region Constructors - - public LerpNode() - { - A = CreateInputPin("A"); - B = CreateInputPin("B"); - T = CreateInputPin("T"); - - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() - { - float a = A.Value; - float b = B.Value; - float t = ((float)T.Value).Clamp(0f, 1f); - Result.Value = ((b - a) * t) + a; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/MathExpressionNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/MathExpressionNode.cs deleted file mode 100644 index f274c8e03..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/MathExpressionNode.cs +++ /dev/null @@ -1,119 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Mathematics.Screens; -using NoStringEvaluating.Contract; -using NoStringEvaluating.Models.FormulaChecker; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Math Expression", "Outputs the result of a math expression.", "Mathematics", "https://wiki.artemis-rgb.com/en/guides/user/profiles/nodes/mathematics/math-expression?mtm_campaign=artemis&mtm_kwd=node-help", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class MathExpressionNode : Node -{ - private readonly IFormulaChecker _checker; - private readonly INoStringEvaluator _evaluator; - private readonly PinsVariablesContainer _variables; - - #region Constructors - - public MathExpressionNode(INoStringEvaluator evaluator, IFormulaChecker checker) - { - _evaluator = evaluator; - _checker = checker; - Output = CreateOutputPin(); - Values = CreateInputPinCollection("Values", 2); - Values.PinAdded += (_, _) => SetPinNames(); - Values.PinRemoved += (_, _) => SetPinNames(); - _variables = new PinsVariablesContainer(Values); - - SetPinNames(); - } - - #endregion - - public bool IsSyntaxValid(string? s) - { - if (s == null) - return true; - - if (!_checker.CheckSyntax(s).Ok) - return false; - - try - { - _evaluator.CalcNumber(s, _variables); - return true; - } - catch - { - return false; - } - } - - public string GetSyntaxErrors(string? s) - { - if (s == null) - return ""; - - CheckFormulaResult? syntaxCheck = _checker.CheckSyntax(s); - if (!syntaxCheck.Ok) - return string.Join(",", syntaxCheck.Mistakes); - - try - { - _evaluator.CalcNumber(s, _variables); - return ""; - } - catch (Exception e) - { - return e.Message; - } - } - - #region Properties & Fields - - public OutputPin Output { get; } - public InputPinCollection Values { get; } - - #endregion - - #region Methods - - public override void Evaluate() - { - try - { - if (Storage != null) - Output.Value = new Numeric(Math.Round(_evaluator.CalcNumber(Storage, _variables), 4, MidpointRounding.AwayFromZero)); - } - catch - { - Output.Value = new Numeric(0); - } - } - - private void SetPinNames() - { - int index = 1; - foreach (IPin value in Values) - { - value.Name = ExcelColumnFromNumber(index).ToLower(); - index++; - } - } - - public static string ExcelColumnFromNumber(int column) - { - string columnString = ""; - decimal columnNumber = column; - while (columnNumber > 0) - { - decimal currentLetterNumber = (columnNumber - 1) % 26; - char currentLetter = (char) (currentLetterNumber + 65); - columnString = currentLetter + columnString; - columnNumber = (columnNumber - (currentLetterNumber + 1)) / 26; - } - - return columnString; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/MaxNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/MaxNode.cs deleted file mode 100644 index 388774e81..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/MaxNode.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Max", "Outputs the largest of the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class MaxNumericsNode : Node -{ - #region Constructors - - public MaxNumericsNode() - { - Values = CreateInputPinCollection("Values", 2); - Max = CreateOutputPin("Max"); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Max.Value = Values.Values.Max(); - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Values { get; } - - public OutputPin Max { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs deleted file mode 100644 index 84a5dee37..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/MinNode.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Min", "Outputs the smallest of the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class MinNumericsNode : Node -{ - #region Constructors - - public MinNumericsNode() - { - Values = CreateInputPinCollection("Values", 2); - Min = CreateOutputPin("Min"); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Min.Value = Values.Values.Min(); - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Values { get; } - - public OutputPin Min { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/NormalizeNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/NormalizeNode.cs deleted file mode 100644 index 59a6f1f31..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/NormalizeNode.cs +++ /dev/null @@ -1,30 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Normalize", "Normalizes the number into range between 0-1", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class NormalizeNode : Node -{ - public InputPin Input { get; } - public InputPin Start { get; } - public InputPin End { get; } - - public OutputPin Result { get; } - - public NormalizeNode() - { - Input = CreateInputPin("Input"); - Start = CreateInputPin("Start"); - End = CreateInputPin("End"); - - Result = CreateOutputPin(); - } - - public override void Evaluate() - { - double inputValue = Input.Value; - double startValue = Start.Value; - double endValue = End.Value; - Result.Value = (Math.Clamp(inputValue, startValue, endValue) - startValue) / (endValue - startValue); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/NumericEasingNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/NumericEasingNode.cs deleted file mode 100644 index c2305adaa..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/NumericEasingNode.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Numeric Easing", "Interpolates a value from 0-1 to 0-1 with the given function", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class NumericEasingNode : Node -{ - public InputPin Input { get; } - - public InputPin EasingFunction { get; } - - public OutputPin Result { get; } - - public NumericEasingNode() - { - Input = CreateInputPin("Input"); - EasingFunction = CreateInputPin("Function"); - - Result = CreateOutputPin(); - } - - public override void Evaluate() - { - double inputValue = Input.Value; - double progress = Math.Clamp(inputValue, 0, 1); - - Result.Value = Easings.Interpolate(progress, EasingFunction.Value); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/PinsVariablesContainer.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/PinsVariablesContainer.cs deleted file mode 100644 index 6faf28044..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/PinsVariablesContainer.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Artemis.Core; -using NoStringEvaluating.Contract.Variables; -using NoStringEvaluating.Models.Values; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -public class PinsVariablesContainer : IVariablesContainer -{ - private readonly InputPinCollection _values; - - public PinsVariablesContainer(InputPinCollection values) - { - _values = values; - } - - #region Implementation of IVariablesContainer - - /// - public IVariable AddOrUpdate(string name, double value) - { - throw new NotImplementedException(); - } - - /// - public EvaluatorValue GetValue(string name) - { - IPin? pin = _values.FirstOrDefault(v => v.Name == name); - if (pin?.PinValue is Numeric numeric) - return new EvaluatorValue(numeric); - return new EvaluatorValue(0); - } - - /// - public bool TryGetValue(string name, out EvaluatorValue value) - { - IPin? pin = _values.FirstOrDefault(v => v.Name == name); - if (pin?.PinValue is Numeric numeric) - { - value = new EvaluatorValue(numeric); - return true; - } - - value = new EvaluatorValue(0); - return false; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs deleted file mode 100644 index 2f8dbef51..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/RangeNode.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Artemis.Core; -using RGB.NET.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Range", "Selects the best integer value in the given range by the given percentage", "Static", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class RangeNode : Node -{ - #region Properties & Fields - - public InputPin Min { get; } - public InputPin Max { get; } - public InputPin Percentage { get; } - - public OutputPin Result { get; } - - #endregion - - #region Constructors - - public RangeNode() - { - Min = CreateInputPin("Min"); - Max = CreateInputPin("Max"); - Percentage = CreateInputPin("Percentage"); - - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() - { - int min = Min.Value; - int max = Max.Value; - float percentage = ((float)Percentage.Value).Clamp(0f, 1f); - - int range = max - min; - - Result.Value = percentage >= 1.0f ? max : ((int)(percentage * (range + 1)) + min); - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs deleted file mode 100644 index c445f5316..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/RoundNode.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Round", "Outputs a rounded numeric value.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class RoundNode : Node -{ - public RoundNode() - { - Input = CreateInputPin(); - Output = CreateOutputPin(); - } - - public OutputPin Output { get; set; } - public InputPin Input { get; set; } - - #region Overrides of Node - - /// - public override void Evaluate() - { - Output.Value = new Numeric(MathF.Round(Input.Value, MidpointRounding.AwayFromZero)); - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs deleted file mode 100644 index 3cd22c958..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/Saturate.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Artemis.Core; -using RGB.NET.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Saturate", "Clamps the value to be in between 0 and 1", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class SaturateNode : Node -{ - #region Properties & Fields - - public InputPin Value { get; } - - public OutputPin Result { get; } - - #endregion - - #region Constructors - - public SaturateNode() - { - Value = CreateInputPin(); - - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() => Result.Value = ((float)Value.Value).Clamp(0f, 1f); - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomView.axaml deleted file mode 100644 index 0000a401a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomView.axaml +++ /dev/null @@ -1,14 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomView.axaml.cs deleted file mode 100644 index c4250d95a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomView.axaml.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Mathematics.Screens; - -public partial class MathExpressionNodeCustomView : ReactiveUserControl -{ - public MathExpressionNodeCustomView() - { - InitializeComponent(); - } - - - private void InputElement_OnLostFocus(object? sender, RoutedEventArgs e) - { - ViewModel?.UpdateInputValue(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomViewModel.cs deleted file mode 100644 index 4cd475a8d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/Screens/MathExpressionNodeCustomViewModel.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System.Reactive.Disposables; -using System.Reactive.Linq; -using Artemis.Core; -using Artemis.Core.Events; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; -using ReactiveUI.Validation.Extensions; - -namespace Artemis.VisualScripting.Nodes.Mathematics.Screens; - -public class MathExpressionNodeCustomViewModel : CustomNodeViewModel -{ - private readonly MathExpressionNode _node; - private readonly INodeEditorService _nodeEditorService; - private string? _inputValue; - - public MathExpressionNodeCustomViewModel(MathExpressionNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - this.ValidationRule(vm => vm.InputValue, value => _node.IsSyntaxValid(value), value => _node.GetSyntaxErrors(value)); - - this.WhenActivated(d => - { - Observable.FromEventPattern>(x => _node.Values.PinAdded += x, x => _node.Values.PinAdded -= x) - .Subscribe(_ => - { - string? old = InputValue; - InputValue = null; - InputValue = old; - }) - .DisposeWith(d); - Observable.FromEventPattern>(x => _node.Values.PinRemoved += x, x => _node.Values.PinRemoved -= x) - .Subscribe(_ => - { - string? old = InputValue; - InputValue = null; - InputValue = old; - }) - .DisposeWith(d); - }); - - NodeModified += (_, _) => InputValue = _node.Storage; - InputValue = _node.Storage; - } - - public string? InputValue - { - get => _inputValue; - set => this.RaiseAndSetIfChanged(ref _inputValue, value); - } - - public void UpdateInputValue() - { - // The value could be invalid but that's ok, we still want to save it - if (_node.Storage != InputValue) - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, InputValue)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/SubtractNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/SubtractNode.cs deleted file mode 100644 index baaf4147a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/SubtractNode.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Subtract", "Subtracts the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class SubtractNumericsNode : Node -{ - #region Constructors - - public SubtractNumericsNode() - { - Values = CreateInputPinCollection("Values", 2); - Remainder = CreateOutputPin("Remainder"); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Remainder.Value = Values.Values.Subtract(); - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Values { get; } - - public OutputPin Remainder { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs b/src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs deleted file mode 100644 index 8fc6913c2..000000000 --- a/src/Artemis.VisualScripting/Nodes/Mathematics/SumNode.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Mathematics; - -[Node("Sum", "Sums the connected numeric values.", "Mathematics", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class SumNumericsNode : Node -{ - #region Constructors - - public SumNumericsNode() - { - Values = CreateInputPinCollection("Values", 2); - Sum = CreateOutputPin("Sum"); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Sum.Value = Values.Values.Sum(); - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Values { get; } - - public OutputPin Sum { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs deleted file mode 100644 index efbecdfc1..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/AndNode.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("And", "Checks if all inputs are true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))] -public class AndNode : Node -{ - #region Constructors - - public AndNode() - { - Input = CreateInputPinCollection(); - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Result.Value = Input.Values.All(v => v); - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Input { get; set; } - public OutputPin Result { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs deleted file mode 100644 index e4e2bdf2f..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/EnumEqualsNode.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Operators.Screens; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("Enum Equals", "Determines the equality between an input and a selected enum value", "Operators", InputType = typeof(Enum), OutputType = typeof(bool))] -public class EnumEqualsNode : Node -{ - public EnumEqualsNode() - { - InputPin = CreateInputPin(); - OutputPin = CreateOutputPin(); - } - - public InputPin InputPin { get; } - public OutputPin OutputPin { get; } - - /// - public override void Evaluate() - { - if (InputPin.Value == null) - OutputPin.Value = false; - else - OutputPin.Value = Convert.ToInt64(InputPin.Value) == Storage; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs deleted file mode 100644 index 7c022f1d7..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/EqualsNode.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("Equals", "Checks if the two inputs are equals.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))] -public class EqualsNode : Node -{ - #region Constructors - - public EqualsNode() - { - Input1 = CreateInputPin(); - Input2 = CreateInputPin(); - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - try - { - Result.Value = Equals(Input1.Value, Input2.Value); - } - catch - { - Result.Value = false; - } - } - - #endregion - - #region Properties & Fields - - public InputPin Input1 { get; } - public InputPin Input2 { get; } - - public OutputPin Result { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs deleted file mode 100644 index adae0971a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/GreaterThanNode.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections; -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("Greater than", "Checks if the first input is greater than the second.", "Operators", InputType = typeof(object), OutputType = typeof(bool))] -public class GreaterThanNode : Node -{ - #region Constructors - - public GreaterThanNode() - { - Input1 = CreateInputPin(); - Input2 = CreateInputPin(); - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - if (Input1.Value is Numeric numeric1 && Input2.Value is Numeric numeric2) - { - Result.Value = numeric1 > numeric2; - return; - } - - if (Input2.Value != null && Input1.Value != null && Input1.Value.IsNumber() && Input2.Value.IsNumber()) - { - Result.Value = Convert.ToSingle(Input1.Value) > Convert.ToSingle(Input2.Value); - return; - } - - try - { - Result.Value = Comparer.DefaultInvariant.Compare(Input1.Value, Input2.Value) == 1; - } - catch - { - Result.Value = false; - } - } - - #endregion - - #region Properties & Fields - - public InputPin Input1 { get; } - public InputPin Input2 { get; } - - public OutputPin Result { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs deleted file mode 100644 index 4eb100a7f..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/LessThanNode.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections; -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("Less than", "Checks if the first input is less than the second.", "Operators", InputType = typeof(object), OutputType = typeof(bool))] -public class LessThanNode : Node -{ - #region Constructors - - public LessThanNode() - { - Input1 = CreateInputPin(); - Input2 = CreateInputPin(); - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - if (Input1.Value is Numeric numeric1 && Input2.Value is Numeric numeric2) - { - Result.Value = numeric1 < numeric2; - return; - } - - if (Input2.Value != null && Input1.Value != null && Input1.Value.IsNumber() && Input2.Value.IsNumber()) - { - Result.Value = Convert.ToSingle(Input1.Value) < Convert.ToSingle(Input2.Value); - return; - } - - try - { - Result.Value = Comparer.DefaultInvariant.Compare(Input1.Value, Input2.Value) == -1; - } - catch - { - Result.Value = false; - } - } - - #endregion - - #region Properties & Fields - - public InputPin Input1 { get; } - public InputPin Input2 { get; } - - public OutputPin Result { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs deleted file mode 100644 index a911c2e81..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/NegateNode.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("Negate", "Negates the boolean.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))] -public class NegateNode : Node -{ - #region Constructors - - public NegateNode() - { - Input = CreateInputPin(); - Output = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Output.Value = !Input.Value; - } - - #endregion - - #region Properties & Fields - - public InputPin Input { get; } - public OutputPin Output { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs deleted file mode 100644 index b78d24d3d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/OrNode.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("Or", "Checks if any inputs are true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))] -public class OrNode : Node -{ - #region Constructors - - public OrNode() - { - Input = CreateInputPinCollection(); - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Result.Value = Input.Values.Any(v => v); - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Input { get; set; } - public OutputPin Result { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml deleted file mode 100644 index 3d6357933..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml.cs deleted file mode 100644 index 88795dc01..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Operators.Screens; - -public partial class EnumEqualsNodeCustomView : ReactiveUserControl -{ - public EnumEqualsNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomViewModel.cs deleted file mode 100644 index cb571936d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/Screens/EnumEqualsNodeCustomViewModel.cs +++ /dev/null @@ -1,95 +0,0 @@ -using System.Collections.ObjectModel; -using System.Reactive.Disposables; -using System.Reactive.Linq; -using Artemis.Core; -using Artemis.Core.Events; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using Avalonia.Threading; -using DynamicData; -using Humanizer; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Operators.Screens; - -public class EnumEqualsNodeCustomViewModel : CustomNodeViewModel -{ - private readonly EnumEqualsNode _node; - private readonly INodeEditorService _nodeEditorService; - - public EnumEqualsNodeCustomViewModel(EnumEqualsNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue)); - this.WhenActivated(d => - { - if (_node.InputPin.ConnectedTo.Any()) - { - EnumValues.Clear(); - if (_node.InputPin.ConnectedTo.First().Type.IsEnum) - AddEnumValues(_node.InputPin.ConnectedTo.First().Type); - } - - Observable.FromEventPattern>(x => _node.InputPin.PinConnected += x, x => _node.InputPin.PinConnected -= x) - .Subscribe(p => AddEnumValues(p.EventArgs.Value.Type)) - .DisposeWith(d); - Observable.FromEventPattern>(x => _node.InputPin.PinDisconnected += x, x => _node.InputPin.PinDisconnected -= x) - .Subscribe(_ => EnumValues.Clear()) - .DisposeWith(d); - }); - } - - public ObservableCollection EnumValues { get; } = new(); - - public EnumValueItem? CurrentValue - { - get => EnumValues.FirstOrDefault(v => v.Value == _node.Storage); - set - { - if (!Equals(_node.Storage, value.Value)) - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value.Value)); - } - } - - private void AddEnumValues(Type type) - { - Dispatcher.UIThread.Post(() => - { - List values = Enum.GetValues(type).Cast().Select(e => new EnumValueItem(value: Convert.ToInt64(e), name: e.Humanize())).ToList(); - if (values.Count > 20) - EnumValues.AddRange(values.OrderBy(v => v.Name)); - else - EnumValues.AddRange(values); - - this.RaisePropertyChanged(nameof(CurrentValue)); - }, DispatcherPriority.Background); - } -} - -/// -/// Represents a single enum value -/// -public class EnumValueItem -{ - /// - /// Creates a new instance of the class. - /// - public EnumValueItem(long value, string name) - { - Value = value; - Name = name; - } - - /// - /// The underlying value of the enum - /// - public long Value { get; set; } - - /// - /// The name of the enum value - /// - public string Name { get; set; } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs b/src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs deleted file mode 100644 index 42197ed25..000000000 --- a/src/Artemis.VisualScripting/Nodes/Operators/XorNode.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Operators; - -[Node("Exclusive Or", "Checks if one of the inputs is true.", "Operators", InputType = typeof(bool), OutputType = typeof(bool))] -public class XorNode : Node -{ - #region Constructors - - public XorNode() - { - Input = CreateInputPinCollection(); - Result = CreateOutputPin(); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - Result.Value = Input.Values.Count(v => v) == 1; - } - - #endregion - - #region Properties & Fields - - public InputPinCollection Input { get; set; } - public OutputPin Result { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs deleted file mode 100644 index d4206cbec..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/DisplayValueNode.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Static.Screens; - -namespace Artemis.VisualScripting.Nodes.Static; - -[Node("Display Value", "Displays an input value for testing purposes.", "Static", InputType = typeof(object))] -public class DisplayValueNode : Node -{ - public DisplayValueNode() - { - Input = CreateInputPin(); - } - - public InputPin Input { get; } - - public override void Evaluate() - { - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/RandomNumericValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/RandomNumericValueNode.cs deleted file mode 100644 index b00d2f419..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/RandomNumericValueNode.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Static; - -[Node("Random", "Generates a random value between 0 and 1", "Static", OutputType = typeof(Numeric))] -public class RandomNumericValueNode : Node -{ - #region Properties & Fields - - private static readonly Random RANDOM = new(); - - public OutputPin Output { get; } - - #endregion - - #region Constructors - - public RandomNumericValueNode() - { - Output = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() => Output.Value = RANDOM.NextSingle(); - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml deleted file mode 100644 index 8831dd1e9..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml.cs deleted file mode 100644 index 769c49881..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public partial class DisplayValueNodeCustomView : ReactiveUserControl -{ - public DisplayValueNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomViewModel.cs deleted file mode 100644 index 590a397fb..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/DisplayValueNodeCustomViewModel.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.Reactive.Disposables; -using Artemis.Core; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public class DisplayValueNodeCustomViewModel : CustomNodeViewModel -{ - private readonly DisplayValueNode _node; - private object? _currentValue; - - public DisplayValueNodeCustomViewModel(DisplayValueNode node, INodeScript script) : base(node, script) - { - _node = node; - - // Because the DisplayValueNode has no output it never evaluates, manually do so here - this.WhenActivated(d => - { - System.Timers.Timer updateTimer = new(TimeSpan.FromMilliseconds(25.0 / 1000)); - updateTimer.Elapsed += (_, _) => Update(); - updateTimer.Start(); - updateTimer.DisposeWith(d); - }); - } - - public object? CurrentValue - { - get => _currentValue; - private set => this.RaiseAndSetIfChanged(ref _currentValue, value); - } - - private void Update() - { - try - { - CurrentValue = _node.Input.Value; - } - catch (Exception ex) - { - // Don't crash the timer on exceptions and display the messages as a bit of a nice to have - CurrentValue = ex.Message; - } - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomView.axaml deleted file mode 100644 index 4207380d2..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomView.axaml +++ /dev/null @@ -1,13 +0,0 @@ - - - False - True - - diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomView.axaml.cs deleted file mode 100644 index c7a81e188..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public partial class StaticBooleanValueNodeCustomView : ReactiveUserControl -{ - public StaticBooleanValueNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomViewModel.cs deleted file mode 100644 index 6dde68817..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticBooleanValueNodeCustomViewModel.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public class StaticBooleanValueNodeCustomViewModel : CustomNodeViewModel -{ - private readonly StaticBooleanValueNode _node; - private readonly INodeEditorService _nodeEditorService; - - public StaticBooleanValueNodeCustomViewModel(StaticBooleanValueNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue)); - } - - public int? CurrentValue - { - get => _node.Storage ? 1 : 0; - set => _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value == 1)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomView.axaml deleted file mode 100644 index e420ebbc4..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomView.axaml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomView.axaml.cs deleted file mode 100644 index 869514564..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public partial class StaticNumericValueNodeCustomView : ReactiveUserControl -{ - public StaticNumericValueNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomViewModel.cs deleted file mode 100644 index e9b0ee94c..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticNumericValueNodeCustomViewModel.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public class StaticNumericValueNodeCustomViewModel : CustomNodeViewModel -{ - private readonly StaticNumericValueNode _node; - private readonly INodeEditorService _nodeEditorService; - - public StaticNumericValueNodeCustomViewModel(StaticNumericValueNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue)); - } - - public Numeric? CurrentValue - { - get => _node.Storage; - set => _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value ?? new Numeric())); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomView.axaml deleted file mode 100644 index fb109aff3..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomView.axaml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomView.axaml.cs deleted file mode 100644 index 51f401ac5..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomView.axaml.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; -using FluentAvalonia.UI.Controls; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public partial class StaticSKColorValueNodeCustomView : ReactiveUserControl -{ - public StaticSKColorValueNodeCustomView() - { - InitializeComponent(); - } - - - private void ColorPickerButton_OnFlyoutOpened(ColorPickerButton sender, EventArgs args) - { - ViewModel?.PauseUpdating(); - } - - private void ColorPickerButton_OnFlyoutClosed(ColorPickerButton sender, EventArgs args) - { - ViewModel?.ResumeUpdating(); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomViewModel.cs deleted file mode 100644 index a968d14ac..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticSKColorValueNodeCustomViewModel.cs +++ /dev/null @@ -1,51 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public class StaticSKColorValueNodeCustomViewModel : CustomNodeViewModel -{ - private readonly StaticSKColorValueNode _node; - private readonly INodeEditorService _nodeEditorService; - private bool _applyChanges; - private SKColor? _currentValue; - - public StaticSKColorValueNodeCustomViewModel(StaticSKColorValueNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - _applyChanges = true; - - NodeModified += (_, _) => CurrentValue = _node.Storage; - CurrentValue = _node.Storage; - } - - public SKColor? CurrentValue - { - get => _currentValue; - set - { - if (_applyChanges && value != _node.Storage) - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value ?? SKColor.Empty)); - this.RaiseAndSetIfChanged(ref _currentValue, value); - } - } - - public void PauseUpdating() - { - _applyChanges = false; - } - - public void ResumeUpdating() - { - _applyChanges = true; - - SKColor updatedValue = CurrentValue ?? SKColor.Empty; - if (updatedValue != _node.Storage) - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, updatedValue)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticStringValueNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticStringValueNodeCustomView.axaml deleted file mode 100644 index 03ce44340..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticStringValueNodeCustomView.axaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticStringValueNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticStringValueNodeCustomView.axaml.cs deleted file mode 100644 index 95644633d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticStringValueNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public partial class StaticStringValueNodeCustomView : ReactiveUserControl -{ - public StaticStringValueNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticValueNodeViewModels.cs b/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticValueNodeViewModels.cs deleted file mode 100644 index e22c4f2e5..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/Screens/StaticValueNodeViewModels.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Static.Screens; - -public class StaticStringValueNodeCustomViewModel : CustomNodeViewModel -{ - private readonly StaticStringValueNode _node; - private readonly INodeEditorService _nodeEditorService; - - public StaticStringValueNodeCustomViewModel(StaticStringValueNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(CurrentValue)); - } - - public string? CurrentValue - { - get => _node.Storage; - set => _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticBooleanValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticBooleanValueNode.cs deleted file mode 100644 index 9db639db9..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticBooleanValueNode.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Static.Screens; - -namespace Artemis.VisualScripting.Nodes.Static; - -[Node("Boolean-Value", "Outputs a configurable static boolean value.", "Static", OutputType = typeof(bool))] -public class StaticBooleanValueNode : Node -{ - #region Constructors - - public StaticBooleanValueNode() - { - Name = "Boolean"; - Output = CreateOutputPin(); - } - - #endregion - - #region Properties & Fields - - public OutputPin Output { get; } - - #endregion - - #region Methods - - public override void Evaluate() - { - Output.Value = Storage; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs deleted file mode 100644 index 8b11709cb..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticNumericValueNode.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Static.Screens; - -namespace Artemis.VisualScripting.Nodes.Static; - -[Node("Numeric-Value", "Outputs a configurable static numeric value.", "Static", OutputType = typeof(Numeric))] -public class StaticNumericValueNode : Node -{ - #region Constructors - - public StaticNumericValueNode() - { - Name = "Numeric"; - Output = CreateOutputPin(); - } - - #endregion - - #region Properties & Fields - - public OutputPin Output { get; } - - #endregion - - #region Methods - - public override void Evaluate() - { - Output.Value = Storage; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticSKColorValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticSKColorValueNode.cs deleted file mode 100644 index 84879d3a3..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticSKColorValueNode.cs +++ /dev/null @@ -1,35 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Static.Screens; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Static; - -[Node("Color-Value", "Outputs a configurable color value.", "Static", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class StaticSKColorValueNode : Node -{ - #region Constructors - - public StaticSKColorValueNode() - { - Name = "Color"; - Output = CreateOutputPin(); - Storage = new SKColor(255, 0, 0); - } - - #endregion - - #region Properties & Fields - - public OutputPin Output { get; } - - #endregion - - #region Methods - - public override void Evaluate() - { - Output.Value = Storage; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs b/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs deleted file mode 100644 index 2c1c7079a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Static/StaticStringValueNode.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Static.Screens; - -namespace Artemis.VisualScripting.Nodes.Static; - -[Node("Text-Value", "Outputs a configurable static text value.", "Static", OutputType = typeof(string))] -public class StaticStringValueNode : Node -{ - #region Constructors - - public StaticStringValueNode() - { - Name = "Text"; - Output = CreateOutputPin(); - } - - #endregion - - #region Properties & Fields - - public OutputPin Output { get; } - - #endregion - - #region Methods - - public override void Evaluate() - { - Output.Value = Storage; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs deleted file mode 100644 index 547a85fbe..000000000 --- a/src/Artemis.VisualScripting/Nodes/Text/StringContainsNode.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Text; - -[Node("Contains", "Checks whether the first input is contained in the second input.", "Text", InputType = typeof(string), OutputType = typeof(bool))] -public class StringContainsNode : Node -{ - public StringContainsNode() - { - Input1 = CreateInputPin(); - Input2 = CreateInputPin(); - Result = CreateOutputPin(); - } - - public InputPin Input1 { get; } - public InputPin Input2 { get; } - - public OutputPin Result { get; } - - public override void Evaluate() - { - if (Input1.Value == null && Input2.Value == null) - Result.Value = false; - else if (Input1.Value == null && Input2.Value != null) - Result.Value = false; - else if (Input1.Value != null && Input2.Value == null) - Result.Value = true; - else if (Input1.Value != null && Input2.Value != null) - Result.Value = Input1.Value.Contains(Input2.Value, StringComparison.InvariantCultureIgnoreCase); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs deleted file mode 100644 index 4985555c1..000000000 --- a/src/Artemis.VisualScripting/Nodes/Text/StringFormatNode.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Text; - -[Node("Format", "Formats the input text.", "Text", InputType = typeof(object), OutputType = typeof(string))] -public class StringFormatNode : Node -{ - #region Constructors - - public StringFormatNode() - { - Format = CreateInputPin("Format"); - Values = CreateInputPinCollection("Values"); - Output = CreateOutputPin("Result"); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - // Convert numerics to floats beforehand to allow string.Format to format them - object[] values = Values.Values.Select(v => v is Numeric n ? (float) n : v).ToArray(); - Output.Value = string.Format(Format.Value ?? string.Empty, values); - } - - #endregion - - #region Properties & Fields - - public InputPin Format { get; } - public InputPinCollection Values { get; } - - public OutputPin Output { get; } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs deleted file mode 100644 index 006f84c5f..000000000 --- a/src/Artemis.VisualScripting/Nodes/Text/StringLengthNode.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Text; - -[Node("Text Length", "Outputs the length of the input text.", - "Text", InputType = typeof(string), OutputType = typeof(Numeric))] -public class StringLengthNode : Node -{ - public StringLengthNode() - { - Input1 = CreateInputPin(); - Result = CreateOutputPin(); - } - - public InputPin Input1 { get; } - - public OutputPin Result { get; } - - public override void Evaluate() - { - Result.Value = Input1.Value == null ? new Numeric(0) : new Numeric(Input1.Value.Length); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringNullOrEmptyNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringNullOrEmptyNode.cs deleted file mode 100644 index 50e703c96..000000000 --- a/src/Artemis.VisualScripting/Nodes/Text/StringNullOrEmptyNode.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Text; - -[Node("Text is empty", "Outputs true if the input text is empty, false if it contains any text.", - "Text", InputType = typeof(string), OutputType = typeof(bool))] -public class StringNullOrEmptyNode : Node -{ - public StringNullOrEmptyNode() - { - Input1 = CreateInputPin(); - Output1 = CreateOutputPin(); - } - - public InputPin Input1 { get; } - - public OutputPin Output1 { get; } - - public override void Evaluate() - { - bool isNullOrWhiteSpace = string.IsNullOrWhiteSpace(Input1.Value); - Output1.Value = isNullOrWhiteSpace; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs b/src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs deleted file mode 100644 index b33a0aaa3..000000000 --- a/src/Artemis.VisualScripting/Nodes/Text/StringRegexMatchNode.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Text.RegularExpressions; -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Text; - -[Node("Regex Match", "Checks provided regex pattern matches the input.", "Text", InputType = typeof(string), OutputType = typeof(bool))] -public class StringRegexMatchNode : Node -{ - private string? _lastPattern; - private Regex? _regex; - private Exception? _exception; - - public StringRegexMatchNode() - { - Pattern = CreateInputPin("Pattern"); - Input = CreateInputPin("Input"); - Result = CreateOutputPin(); - } - - public InputPin Pattern { get; } - public InputPin Input { get; } - public OutputPin Result { get; } - - public override void Evaluate() - { - if (Input.Value == null || Pattern.Value == null) - return; - - // If the regex was invalid output false and rethrow the exception - if (_lastPattern == Pattern.Value && _exception != null) - { - Result.Value = false; - throw _exception; - } - - // If there is no regex yet or the regex changed, recompile - if (_regex == null || _lastPattern != Pattern.Value) - { - try - { - _regex = new Regex(Pattern.Value, RegexOptions.Compiled); - _exception = null; - } - catch (Exception e) - { - // If there is an exception, save it to keep rethrowing until the regex is fixed - _exception = e; - throw; - } - finally - { - _lastPattern = Pattern.Value; - } - } - - Result.Value = _regex.IsMatch(Input.Value); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs deleted file mode 100644 index d1a1f59b7..000000000 --- a/src/Artemis.VisualScripting/Nodes/Timing/DelayNode.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System.Diagnostics; -using Artemis.Core; -using Artemis.Core.Events; -using RGB.NET.Core; - -namespace Artemis.VisualScripting.Nodes.Timing; - -[Node("Delay", "Delays the resolution of the input pin(s) for the given time after each update", "Timing", InputType = typeof(object), OutputType = typeof(object))] -public class DelayNode : Node -{ - #region Properties & Fields - - private long _lastUpdateTimestamp = 0; - - public InputPin Delay { get; } - public InputPinCollection Input { get; } - - public OutputPin IsUpdated { get; } - public OutputPin NextUpdateTime { get; } - - private Dictionary _pinPairs = new(); - - #endregion - - #region Constructors - - public DelayNode() - { - Delay = CreateInputPin("Delay"); - Input = CreateInputPinCollection(typeof(object), initialCount: 0); - - IsUpdated = CreateOutputPin("Updated"); - NextUpdateTime = CreateOutputPin("Next Update"); - - Input.PinAdded += OnInputPinAdded; - Input.PinRemoved += OnInputPinRemoved; - - Input.Add(Input.CreatePin()); - } - - #endregion - - #region Methods - - private void OnInputPinAdded(object? sender, SingleValueEventArgs args) - { - IPin inputPin = args.Value; - _pinPairs.Add(inputPin, CreateOutputPin(typeof(object))); - - inputPin.PinConnected += OnInputPinConnected; - inputPin.PinDisconnected += OnInputPinDisconnected; - - UpdatePinNames(); - } - - private void OnInputPinRemoved(object? sender, SingleValueEventArgs args) - { - IPin inputPin = args.Value; - RemovePin(_pinPairs[inputPin]); - _pinPairs.Remove(inputPin); - - inputPin.PinConnected -= OnInputPinConnected; - inputPin.PinDisconnected -= OnInputPinDisconnected; - - UpdatePinNames(); - } - - private void OnInputPinConnected(object? sender, SingleValueEventArgs args) - { - if (sender is not IPin inputPin || !_pinPairs.ContainsKey(inputPin)) return; - - OutputPin outputPin = _pinPairs[inputPin]; - outputPin.ChangeType(args.Value.Type); - } - - private void OnInputPinDisconnected(object? sender, SingleValueEventArgs args) - { - if (sender is not IPin inputPin || !_pinPairs.ContainsKey(inputPin)) return; - - OutputPin outputPin = _pinPairs[inputPin]; - outputPin.ChangeType(typeof(object)); - } - - private void UpdatePinNames() - { - int counter = 1; - foreach (IPin inputPin in Input.Pins) - { - string name = counter.ToString(); - inputPin.Name = name; - _pinPairs[inputPin].Name = name; - - counter++; - } - } - - /// - public override void Evaluate() - { - double nextUpdateIn = Delay.Value - TimerHelper.GetElapsedTime(_lastUpdateTimestamp); - NextUpdateTime.Value = nextUpdateIn; - - if (nextUpdateIn <= 0) - { - IsUpdated.Value = true; - foreach ((IPin input, OutputPin output) in _pinPairs) - output.Value = input.PinValue; - - _lastUpdateTimestamp = Stopwatch.GetTimestamp(); - } - else - IsUpdated.Value = false; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs deleted file mode 100644 index 10f341668..000000000 --- a/src/Artemis.VisualScripting/Nodes/Timing/EdgeNode.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Timing; - -[Node("Edge", "Outputs true on each edge when the input changes", "Timing", InputType = typeof(bool), OutputType = typeof(bool))] -public class EdgeNode : Node -{ - #region Properties & Fields - - private bool _lastInput; - - public InputPin Input { get; } - public OutputPin Output { get; } - - #endregion - - #region Constructors - - public EdgeNode() - { - Input = CreateInputPin(); - Output = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() - { - bool input = Input.Value; - - Output.Value = input != _lastInput; - - _lastInput = input; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs deleted file mode 100644 index a3807e93d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Timing/FlipFlopNode.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Timing; - -[Node("FlipFlop", "Inverts the output when the input changes from false to true", "Timing", InputType = typeof(bool), OutputType = typeof(bool))] -public class FlipFlopNode : Node -{ - #region Properties & Fields - - private bool _lastInput; - private bool _currentValue; - - public InputPin Input { get; } - public OutputPin Output { get; } - - #endregion - - #region Constructors - - public FlipFlopNode() - { - Input = CreateInputPin(); - Output = CreateOutputPin(); - } - - #endregion - - #region Methods - - /// - public override void Evaluate() - { - bool input = Input.Value; - if (input && !_lastInput) - { - _currentValue = !_currentValue; - Output.Value = _currentValue; - } - - _lastInput = input; - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs deleted file mode 100644 index 53c2e71c5..000000000 --- a/src/Artemis.VisualScripting/Nodes/Timing/LatchNode.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System.Diagnostics; -using Artemis.Core; -using Artemis.Core.Events; -using RGB.NET.Core; - -namespace Artemis.VisualScripting.Nodes.Timing; - -[Node("Latch", "Only passes the input to the output as long as the control-pin is true. If the control pin is false the last passed value is provided.", "Timing", InputType = typeof(object), OutputType = typeof(object))] -public class LatchNode : Node -{ - #region Properties & Fields - - private long _lastUpdateTimestamp = 0; - - public InputPin Control { get; } - public InputPinCollection Input { get; } - - //TODO DarthAffe 21.08.2022: Find something to output to aling in- and outputs - public OutputPin LastUpdateTime { get; } - - private Dictionary _pinPairs = new(); - - #endregion - - #region Constructors - - public LatchNode() - { - Control = CreateInputPin("Control"); - Input = CreateInputPinCollection(typeof(object), initialCount: 0); - - LastUpdateTime = CreateOutputPin("Last Update"); - - Input.PinAdded += OnInputPinAdded; - Input.PinRemoved += OnInputPinRemoved; - - Input.Add(Input.CreatePin()); - } - - #endregion - - #region Methods - - private void OnInputPinAdded(object? sender, SingleValueEventArgs args) - { - IPin inputPin = args.Value; - _pinPairs.Add(inputPin, CreateOutputPin(typeof(object))); - - inputPin.PinConnected += OnInputPinConnected; - inputPin.PinDisconnected += OnInputPinDisconnected; - - UpdatePinNames(); - } - - private void OnInputPinRemoved(object? sender, SingleValueEventArgs args) - { - IPin inputPin = args.Value; - RemovePin(_pinPairs[inputPin]); - _pinPairs.Remove(inputPin); - - inputPin.PinConnected -= OnInputPinConnected; - inputPin.PinDisconnected -= OnInputPinDisconnected; - - UpdatePinNames(); - } - - private void OnInputPinConnected(object? sender, SingleValueEventArgs args) - { - if (sender is not IPin inputPin || !_pinPairs.ContainsKey(inputPin)) return; - - OutputPin outputPin = _pinPairs[inputPin]; - outputPin.ChangeType(args.Value.Type); - } - - private void OnInputPinDisconnected(object? sender, SingleValueEventArgs args) - { - if (sender is not IPin inputPin || !_pinPairs.ContainsKey(inputPin)) return; - - OutputPin outputPin = _pinPairs[inputPin]; - outputPin.ChangeType(typeof(object)); - } - - private void UpdatePinNames() - { - int counter = 1; - foreach (IPin inputPin in Input.Pins) - { - string name = counter.ToString(); - inputPin.Name = name; - _pinPairs[inputPin].Name = name; - - counter++; - } - } - - /// - public override void Evaluate() - { - if (Control.Value) - { - foreach ((IPin input, OutputPin output) in _pinPairs) - output.Value = input.PinValue; - - LastUpdateTime.Value = 0; - _lastUpdateTimestamp = Stopwatch.GetTimestamp(); - } - else - LastUpdateTime.Value = TimerHelper.GetElapsedTime(_lastUpdateTimestamp); - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs b/src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs deleted file mode 100644 index e72c8d5e1..000000000 --- a/src/Artemis.VisualScripting/Nodes/Timing/SequencerNode.cs +++ /dev/null @@ -1,135 +0,0 @@ -using Artemis.Core; -using Artemis.Core.Events; - -namespace Artemis.VisualScripting.Nodes.Timing; - -[Node("Sequencer", "Advances on input every time the control has a rising edge (change to true)", "Timing", OutputType = typeof(object))] -public class SequencerNode : Node -{ - #region Properties & Fields - - private int _currentIndex; - private Type _currentType; - private bool _updating; - private IPin? _currentCyclePin; - - private bool _lastInput; - - public InputPin Input { get; } - public InputPinCollection CycleValues { get; } - - public OutputPin Output { get; } - - #endregion - - #region Constructors - - public SequencerNode() - { - _currentType = typeof(object); - - Input = CreateInputPin("Control"); - CycleValues = CreateInputPinCollection(typeof(object), "", 0); - Output = CreateOutputPin(typeof(object)); - - CycleValues.PinAdded += CycleValuesOnPinAdded; - CycleValues.PinRemoved += CycleValuesOnPinRemoved; - CycleValues.Add(CycleValues.CreatePin()); - } - - #endregion - - #region Methods - - public override void Evaluate() - { - bool input = Input.Value; - - if (input != _lastInput) - { - _currentIndex++; - - if (_currentIndex >= CycleValues.Count()) - _currentIndex = 0; - - _currentCyclePin = null; - } - - _currentCyclePin ??= CycleValues.ElementAt(_currentIndex); - - object? outputValue = _currentCyclePin.PinValue; - if (Output.Type.IsInstanceOfType(outputValue)) - Output.Value = outputValue; - else if (Output.Type.IsValueType) - Output.Value = Output.Type.GetDefault()!; - - _lastInput = input; - } - - private void CycleValuesOnPinAdded(object? sender, SingleValueEventArgs e) - { - e.Value.PinConnected += OnPinConnected; - e.Value.PinDisconnected += OnPinDisconnected; - - _currentCyclePin = null; - } - - private void CycleValuesOnPinRemoved(object? sender, SingleValueEventArgs e) - { - e.Value.PinConnected -= OnPinConnected; - e.Value.PinDisconnected -= OnPinDisconnected; - - _currentCyclePin = null; - } - - private void OnPinDisconnected(object? sender, SingleValueEventArgs e) => ProcessPinDisconnected(); - - private void OnPinConnected(object? sender, SingleValueEventArgs e) => ProcessPinConnected(e.Value); - - private void ProcessPinConnected(IPin source) - { - if (_updating) - return; - - try - { - _updating = true; - - // No need to change anything if the types haven't changed - if (_currentType != source.Type) - ChangeCurrentType(source.Type); - } - finally - { - _updating = false; - } - } - - private void ChangeCurrentType(Type type) - { - CycleValues.ChangeType(type); - Output.ChangeType(type); - - _currentType = type; - } - - private void ProcessPinDisconnected() - { - if (_updating) - return; - try - { - // If there's still a connected pin, stick to the current type - if (CycleValues.Any(v => v.ConnectedTo.Any())) - return; - - ChangeCurrentType(typeof(object)); - } - finally - { - _updating = false; - } - } - - #endregion -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/ColorGradientTransitionNode.cs b/src/Artemis.VisualScripting/Nodes/Transition/ColorGradientTransitionNode.cs deleted file mode 100644 index 69430d4ea..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/ColorGradientTransitionNode.cs +++ /dev/null @@ -1,71 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Transition; - -[Node("Color Gradient Transition", "Outputs smoothly transitioned changes to the input color gradient", "Transition", InputType = typeof(ColorGradient), OutputType = typeof(ColorGradient))] -public class ColorGradientTransitionNode : Node -{ - private DateTime _lastEvaluate = DateTime.MinValue; - private float _progress; - private ColorGradient? _currentValue; - private ColorGradient? _sourceValue; - private ColorGradient? _targetValue; - - public ColorGradientTransitionNode() - { - Input = CreateInputPin(); - EasingTime = CreateInputPin("Delay"); - EasingFunction = CreateInputPin("Function"); - - Output = CreateOutputPin(); - } - - public InputPin Input { get; set; } - public InputPin EasingTime { get; set; } - public InputPin EasingFunction { get; set; } - - public OutputPin Output { get; set; } - - public override void Evaluate() - { - DateTime now = DateTime.Now; - - if (Input.Value == null) - return; - - // If the value changed reset progress - if (!Equals(_targetValue, Input.Value)) - { - _sourceValue = _currentValue ?? new ColorGradient(Input.Value); - _targetValue = new ColorGradient(Input.Value); - _progress = 0f; - } - - // Update until finished - if (_progress < 1f) - { - Update(); - Output.Value = _currentValue; - } - // Stop updating past 1 and use the target value - else - { - Output.Value = _targetValue; - } - - _lastEvaluate = now; - } - - private void Update() - { - if (_sourceValue == null || _targetValue == null) - return; - - float easingTime = EasingTime.Value != 0f ? EasingTime.Value : 1f; - TimeSpan delta = DateTime.Now - _lastEvaluate; - - // In case of odd delta's, keep progress between 0f and 1f - _progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / easingTime, 0f, 1f); - _currentValue = _sourceValue.Interpolate(_targetValue, (float) Easings.Interpolate(_progress, EasingFunction.Value)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/EasingFunctionNode.cs b/src/Artemis.VisualScripting/Nodes/Transition/EasingFunctionNode.cs deleted file mode 100644 index a0086bf27..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/EasingFunctionNode.cs +++ /dev/null @@ -1,20 +0,0 @@ -using Artemis.Core; -using Artemis.VisualScripting.Nodes.Transition.Screens; - -namespace Artemis.VisualScripting.Nodes.Transition; - -[Node("Easing Function", "Outputs a selectable easing function", "Transition", OutputType = typeof(Easings.Functions))] -public class EasingFunctionNode : Node -{ - public EasingFunctionNode() - { - Output = CreateOutputPin(); - } - - public OutputPin Output { get; } - - public override void Evaluate() - { - Output.Value = Storage; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/NumericTransitionNode.cs b/src/Artemis.VisualScripting/Nodes/Transition/NumericTransitionNode.cs deleted file mode 100644 index 658ceedf3..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/NumericTransitionNode.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Artemis.Core; - -namespace Artemis.VisualScripting.Nodes.Transition; - -[Node("Numeric Transition", "Outputs smoothly transitioned changes to the input numeric value", "Transition", InputType = typeof(Numeric), OutputType = typeof(Numeric))] -public class NumericTransitionNode : Node -{ - private float _currentValue; - private DateTime _lastEvaluate = DateTime.MinValue; - private float _progress; - private float _sourceValue; - private float _targetValue; - - public NumericTransitionNode() - { - Input = CreateInputPin(); - EasingTime = CreateInputPin("Delay"); - EasingFunction = CreateInputPin("Function"); - - Output = CreateOutputPin(); - } - - public InputPin Input { get; set; } - public InputPin EasingTime { get; set; } - public InputPin EasingFunction { get; set; } - - public OutputPin Output { get; set; } - - public override void Evaluate() - { - DateTime now = DateTime.Now; - float inputValue = Input.Value; - - // If the value changed reset progress - if (Math.Abs(_targetValue - inputValue) > 0.001f) - { - _sourceValue = _currentValue; - _targetValue = Input.Value; - _progress = 0f; - } - - // Update until finished - if (_progress < 1f) - { - Update(); - Output.Value = new Numeric(_currentValue); - } - // Stop updating past 1 and use the target value - else - { - Output.Value = new Numeric(_targetValue); - } - - _lastEvaluate = now; - } - - private void Update() - { - float easingTime = EasingTime.Value != 0f ? EasingTime.Value : 1f; - TimeSpan delta = DateTime.Now - _lastEvaluate; - - // In case of odd delta's, keep progress between 0f and 1f - _progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / easingTime, 0f, 1f); - - double eased = _sourceValue + (_targetValue - _sourceValue) * Easings.Interpolate(_progress, EasingFunction.Value); - _currentValue = (float) eased; - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/SKColorTransitionNode.cs b/src/Artemis.VisualScripting/Nodes/Transition/SKColorTransitionNode.cs deleted file mode 100644 index 7ffd037b8..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/SKColorTransitionNode.cs +++ /dev/null @@ -1,66 +0,0 @@ -using Artemis.Core; -using SkiaSharp; - -namespace Artemis.VisualScripting.Nodes.Transition; - -[Node("Color Transition", "Outputs smoothly transitioned changes to the input color", "Transition", InputType = typeof(SKColor), OutputType = typeof(SKColor))] -public class SKColorTransitionNode : Node -{ - private SKColor _currentValue; - private DateTime _lastEvaluate = DateTime.MinValue; - private float _progress; - private SKColor _sourceValue; - private SKColor _targetValue; - - public SKColorTransitionNode() - { - Input = CreateInputPin(); - EasingTime = CreateInputPin("Delay"); - EasingFunction = CreateInputPin("Function"); - - Output = CreateOutputPin(); - } - - public InputPin Input { get; set; } - public InputPin EasingTime { get; set; } - public InputPin EasingFunction { get; set; } - - public OutputPin Output { get; set; } - - public override void Evaluate() - { - DateTime now = DateTime.Now; - - // If the value changed reset progress - if (_targetValue != Input.Value) - { - _sourceValue = _currentValue; - _targetValue = Input.Value; - _progress = 0f; - } - - // Update until finished - if (_progress < 1f) - { - Update(); - Output.Value = _currentValue; - } - // Stop updating past 1 and use the target value - else - { - Output.Value = _targetValue; - } - - _lastEvaluate = now; - } - - private void Update() - { - float easingTime = EasingTime.Value != 0f ? EasingTime.Value : 1f; - TimeSpan delta = DateTime.Now - _lastEvaluate; - - // In case of odd delta's, keep progress between 0f and 1f - _progress = Math.Clamp(_progress + (float) delta.TotalMilliseconds / easingTime, 0f, 1f); - _currentValue = _sourceValue.Interpolate(_targetValue, (float) Easings.Interpolate(_progress, EasingFunction.Value)); - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomView.axaml b/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomView.axaml deleted file mode 100644 index 457cb2994..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomView.axaml +++ /dev/null @@ -1,10 +0,0 @@ - - - \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomView.axaml.cs deleted file mode 100644 index e989a374a..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Markup.Xaml; -using Avalonia.ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Transition.Screens; - -public partial class EasingFunctionNodeCustomView : ReactiveUserControl -{ - public EasingFunctionNodeCustomView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomViewModel.cs deleted file mode 100644 index 01540d7e6..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionNodeCustomViewModel.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Collections.ObjectModel; -using Artemis.Core; -using Artemis.UI.Shared.Services.NodeEditor; -using Artemis.UI.Shared.Services.NodeEditor.Commands; -using Artemis.UI.Shared.VisualScripting; -using ReactiveUI; - -namespace Artemis.VisualScripting.Nodes.Transition.Screens; - -public class EasingFunctionNodeCustomViewModel : CustomNodeViewModel -{ - private readonly EasingFunctionNode _node; - private readonly INodeEditorService _nodeEditorService; - - public EasingFunctionNodeCustomViewModel(EasingFunctionNode node, INodeScript script, INodeEditorService nodeEditorService) : base(node, script) - { - _node = node; - _nodeEditorService = nodeEditorService; - - NodeModified += (_, _) => this.RaisePropertyChanged(nameof(SelectedEasingViewModel)); - EasingViewModels = - new ObservableCollection(Enum.GetValues(typeof(Easings.Functions)).Cast().Select(e => new EasingFunctionViewModel(e))); - } - - public ObservableCollection EasingViewModels { get; } - - public EasingFunctionViewModel? SelectedEasingViewModel - { - get => EasingViewModels.FirstOrDefault(e => e.EasingFunction == _node.Storage); - set - { - if (value != null && _node.Storage != value.EasingFunction) - _nodeEditorService.ExecuteCommand(Script, new UpdateStorage(_node, value.EasingFunction)); - } - } -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionView.axaml b/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionView.axaml deleted file mode 100644 index 93f9b1de0..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionView.axaml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - diff --git a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionView.axaml.cs b/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionView.axaml.cs deleted file mode 100644 index c55200ad6..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionView.axaml.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Avalonia.Controls; -using Avalonia.Markup.Xaml; - -namespace Artemis.VisualScripting.Nodes.Transition.Screens; - -public partial class EasingFunctionView : UserControl -{ - public EasingFunctionView() - { - InitializeComponent(); - } - -} \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionViewModel.cs b/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionViewModel.cs deleted file mode 100644 index 29f3ad39d..000000000 --- a/src/Artemis.VisualScripting/Nodes/Transition/Screens/EasingFunctionViewModel.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Artemis.Core; -using Artemis.UI.Shared; -using Avalonia; -using Humanizer; - -namespace Artemis.VisualScripting.Nodes.Transition.Screens; - -public class EasingFunctionViewModel : ViewModelBase -{ - public EasingFunctionViewModel(Easings.Functions easingFunction) - { - EasingFunction = easingFunction; - Description = easingFunction.Humanize(); - - EasingPoints = new List(); - for (int i = 1; i <= 10; i++) - { - double y = Easings.Interpolate(i / 10.0, EasingFunction) * 10; - EasingPoints.Add(new Point(i, y)); - } - } - - public Easings.Functions EasingFunction { get; } - public List EasingPoints { get; } - public string Description { get; } -} \ No newline at end of file diff --git a/src/Artemis.sln b/src/Artemis.sln index cd0039bd1..03067b279 100644 --- a/src/Artemis.sln +++ b/src/Artemis.sln @@ -17,8 +17,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.Linux", "Artemis EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.UI.MacOS", "Artemis.UI.MacOS\Artemis.UI.MacOS.csproj", "{2F5F16DC-FACF-4559-9882-37C2949814C7}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Artemis.VisualScripting", "Artemis.VisualScripting\Artemis.VisualScripting.csproj", "{412B921A-26F5-4AE6-8B32-0C19BE54F421}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.WebClient.Updating", "Artemis.WebClient.Updating\Artemis.WebClient.Updating.csproj", "{7C8C6F50-0CC8-45B3-B608-A7218C005E4B}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Artemis.WebClient.Workshop", "Artemis.WebClient.Workshop\Artemis.WebClient.Workshop.csproj", "{2B982C2E-3CBC-4DAB-9167-CCCA4C78E92B}" @@ -63,10 +61,6 @@ Global {2F5F16DC-FACF-4559-9882-37C2949814C7}.Debug|x64.Build.0 = Debug|x64 {2F5F16DC-FACF-4559-9882-37C2949814C7}.Release|x64.ActiveCfg = Release|x64 {2F5F16DC-FACF-4559-9882-37C2949814C7}.Release|x64.Build.0 = Release|x64 - {412B921A-26F5-4AE6-8B32-0C19BE54F421}.Debug|x64.ActiveCfg = Debug|x64 - {412B921A-26F5-4AE6-8B32-0C19BE54F421}.Debug|x64.Build.0 = Debug|x64 - {412B921A-26F5-4AE6-8B32-0C19BE54F421}.Release|x64.ActiveCfg = Release|x64 - {412B921A-26F5-4AE6-8B32-0C19BE54F421}.Release|x64.Build.0 = Release|x64 {7C8C6F50-0CC8-45B3-B608-A7218C005E4B}.Debug|x64.ActiveCfg = Debug|x64 {7C8C6F50-0CC8-45B3-B608-A7218C005E4B}.Debug|x64.Build.0 = Debug|x64 {7C8C6F50-0CC8-45B3-B608-A7218C005E4B}.Release|x64.ActiveCfg = Release|x64