diff --git a/src/Artemis.Core/Services/NodeService.cs b/src/Artemis.Core/Services/NodeService.cs index 59e4ccb65..0de01d907 100644 --- a/src/Artemis.Core/Services/NodeService.cs +++ b/src/Artemis.Core/Services/NodeService.cs @@ -76,7 +76,8 @@ namespace Artemis.Core.Services node.Y = entity.Y; try { - node.Storage = CoreJson.DeserializeObject(entity.Storage, true); + if (node is Node nodeImplementation) + nodeImplementation.DeserializeStorage(entity.Storage); } catch { diff --git a/src/Artemis.Core/VisualScripting/InputPin.cs b/src/Artemis.Core/VisualScripting/InputPin.cs index 1179a1885..908173bf8 100644 --- a/src/Artemis.Core/VisualScripting/InputPin.cs +++ b/src/Artemis.Core/VisualScripting/InputPin.cs @@ -12,6 +12,7 @@ namespace Artemis.Core public override PinDirection Direction => PinDirection.Input; private T _value; + public T Value { get @@ -37,7 +38,8 @@ namespace Artemis.Core [JsonConstructor] internal InputPin(INode node, string name) : base(node, name) - { } + { + } #endregion @@ -62,6 +64,7 @@ namespace Artemis.Core public override PinDirection Direction => PinDirection.Input; private object _value; + public object Value { get @@ -98,9 +101,19 @@ namespace Artemis.Core private void Evaluate() { - Value = ConnectedTo.Count > 0 ? ConnectedTo[0].PinValue : Type.GetDefault(); + if (Type.IsValueType) + { + if (ConnectedTo.Count > 0 && ConnectedTo[0].PinValue != null) + Value = ConnectedTo[0].PinValue; + else + Value = Type.GetDefault()!; + } + else + { + Value = ConnectedTo[0].PinValue; + } } #endregion } -} +} \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs index a5d734f3d..56bd18103 100644 --- a/src/Artemis.Core/VisualScripting/Interfaces/INode.cs +++ b/src/Artemis.Core/VisualScripting/Interfaces/INode.cs @@ -1,29 +1,73 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using Artemis.Storage.Entities.Profile.Nodes; namespace Artemis.Core { + /// + /// Represents a kind of node inside a + /// public interface INode : INotifyPropertyChanged { + /// + /// Gets the name of the node + /// string Name { get; } + + /// + /// Gets the description of the node + /// string Description { get; } + + /// + /// Gets a boolean indicating whether the node is the exit node of the script + /// bool IsExitNode { get; } + + /// + /// Gets a boolean indicating whether the node is a default node that connot be removed + /// bool IsDefaultNode { get; } + /// + /// Gets or sets the X-position of the node + /// public double X { get; set; } + + /// + /// Gets or sets the Y-position of the node + /// public double Y { get; set; } - public object? Storage { get; set; } + /// + /// Gets a read-only collection of the pins on this node + /// public IReadOnlyCollection Pins { get; } - public IReadOnlyCollection PinCollections { get; } - + /// + /// Gets a read-only collection of the pin collections on this node + /// + public IReadOnlyCollection PinCollections { get; } + + /// + /// Called when the node resets + /// event EventHandler Resetting; + /// + /// Called when the node was loaded from storage or newly created + /// + /// The script the node is contained in void Initialize(INodeScript script); + + /// + /// Evaluates the value of the output pins of this node + /// void Evaluate(); + + /// + /// Resets the node causing all pins to re-evaluate the next time is called + /// void Reset(); } } \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs b/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs index 2a299743c..0cc546f21 100644 --- a/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs +++ b/src/Artemis.Core/VisualScripting/Interfaces/INodeScript.cs @@ -5,27 +5,74 @@ using Artemis.Core.Events; namespace Artemis.Core { + /// + /// Represents a node script + /// public interface INodeScript : INotifyPropertyChanged, IDisposable { + /// + /// Gets the name of the node script. + /// string Name { get; } + + /// + /// Gets the description of the node script. + /// string Description { get; } - + + /// + /// Gets an enumerable of all the nodes on this script. + /// IEnumerable Nodes { get; } + /// + /// Gets the return type of the node script. + /// Type ResultType { get; } + /// + /// Gets or sets the context of the node script, usually a or + /// . + /// object? Context { get; set; } - + + /// + /// Occurs whenever a node was added to the script + /// event EventHandler>? NodeAdded; + + /// + /// Occurs whenever a node was removed from the script + /// event EventHandler>? NodeRemoved; - + + /// + /// Runs the script, evaluating nodes where needed + /// void Run(); + + /// + /// Adds a node to the script + /// + /// The node to add void AddNode(INode node); + + /// + /// Removes a node from the script + /// + /// The node to remove void RemoveNode(INode node); } + /// + /// Represents a node script with a result value of type + /// + /// The type of result value public interface INodeScript : INodeScript { + /// + /// Gets the result of the script + /// T Result { get; } } -} +} \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/Node.cs b/src/Artemis.Core/VisualScripting/Node.cs index dfb232fc8..b41841e63 100644 --- a/src/Artemis.Core/VisualScripting/Node.cs +++ b/src/Artemis.Core/VisualScripting/Node.cs @@ -1,16 +1,24 @@ -using Ninject; -using System; +using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using Ninject; using Ninject.Parameters; namespace Artemis.Core { + /// + /// Represents a kind of node inside a + /// public abstract class Node : CorePropertyChanged, INode { + /// + public event EventHandler? Resetting; + #region Properties & Fields private string _name; + + /// public string Name { get => _name; @@ -18,6 +26,8 @@ namespace Artemis.Core } private string _description; + + /// public string Description { get => _description; @@ -26,6 +36,7 @@ namespace Artemis.Core private double _x; + /// public double X { get => _x; @@ -33,51 +44,62 @@ namespace Artemis.Core } private double _y; + + /// public double Y { get => _y; set => SetAndNotify(ref _y, value); } - private object? _storage; - public object? Storage - { - get => _storage; - set => SetAndNotify(ref _storage, value); - } - + /// public virtual bool IsExitNode => false; + + /// public virtual bool IsDefaultNode => false; private readonly List _pins = new(); + + /// public IReadOnlyCollection Pins => new ReadOnlyCollection(_pins); private readonly List _pinCollections = new(); + + /// public IReadOnlyCollection PinCollections => new ReadOnlyCollection(_pinCollections); #endregion - #region Events - - public event EventHandler Resetting; - - #endregion - #region Construtors + /// + /// Creates a new instance of the class with an empty name and description + /// protected Node() - { } + { + _name = string.Empty; + _description = string.Empty; + } + /// + /// Creates a new instance of the class with the provided name and description + /// protected Node(string name, string description) { - Name = name; - Description = description; + _name = name; + _description = description; } #endregion #region Methods + /// + /// Creates a new input pin and adds it to the collection + /// + /// The name of the pin + /// The type of value the pin will hold + /// The newly created pin protected InputPin CreateInputPin(string name = "") { InputPin pin = new(this, name); @@ -86,6 +108,12 @@ namespace Artemis.Core return pin; } + /// + /// Creates a new input pin and adds it to the collection + /// + /// The type of value the pin will hold + /// The name of the pin + /// The newly created pin protected InputPin CreateInputPin(Type type, string name = "") { InputPin pin = new(this, type, name); @@ -94,6 +122,12 @@ namespace Artemis.Core return pin; } + /// + /// Creates a new output pin and adds it to the collection + /// + /// The name of the pin + /// The type of value the pin will hold + /// The newly created pin protected OutputPin CreateOutputPin(string name = "") { OutputPin pin = new(this, name); @@ -102,6 +136,12 @@ namespace Artemis.Core return pin; } + /// + /// Creates a new output pin and adds it to the collection + /// + /// The type of value the pin will hold + /// The name of the pin + /// The newly created pin protected OutputPin CreateOutputPin(Type type, string name = "") { OutputPin pin = new(this, type, name); @@ -109,7 +149,12 @@ namespace Artemis.Core OnPropertyChanged(nameof(Pins)); return pin; } - + + /// + /// Removes the provided from the node and it's collection + /// + /// The pin to remove + /// if the pin was removed; otherwise . protected bool RemovePin(Pin pin) { bool isRemoved = _pins.Remove(pin); @@ -122,6 +167,13 @@ namespace Artemis.Core return isRemoved; } + /// + /// Creates a new input pin collection and adds it to the collection + /// + /// The type of value the pins of this collection will hold + /// The name of the pin collection + /// The amount of pins to initially add to the collection + /// The resulting input pin collection protected InputPinCollection CreateInputPinCollection(string name = "", int initialCount = 1) { InputPinCollection pin = new(this, name, initialCount); @@ -130,6 +182,13 @@ namespace Artemis.Core return pin; } + /// + /// Creates a new input pin collection and adds it to the collection + /// + /// The type of value the pins of this collection will hold + /// The name of the pin collection + /// The amount of pins to initially add to the collection + /// The resulting input pin collection protected InputPinCollection CreateInputPinCollection(Type type, string name = "", int initialCount = 1) { InputPinCollection pin = new(this, type, name, initialCount); @@ -138,6 +197,13 @@ namespace Artemis.Core return pin; } + /// + /// Creates a new output pin collection and adds it to the collection + /// + /// The type of value the pins of this collection will hold + /// The name of the pin collection + /// The amount of pins to initially add to the collection + /// The resulting output pin collection protected OutputPinCollection CreateOutputPinCollection(string name = "", int initialCount = 1) { OutputPinCollection pin = new(this, name, initialCount); @@ -146,12 +212,18 @@ namespace Artemis.Core return pin; } + /// + /// Removes the provided from the node and it's + /// collection + /// + /// The pin collection to remove + /// if the pin collection was removed; otherwise . protected bool RemovePinCollection(PinCollection pinCollection) { bool isRemoved = _pinCollections.Remove(pinCollection); if (isRemoved) { - foreach (IPin pin in pinCollection) + foreach (IPin pin in pinCollection) pin.DisconnectAll(); OnPropertyChanged(nameof(PinCollections)); } @@ -159,51 +231,122 @@ namespace Artemis.Core return isRemoved; } + /// public virtual void Initialize(INodeScript script) - { } + { + } + /// public abstract void Evaluate(); + + /// public virtual void Reset() { - Resetting?.Invoke(this, new EventArgs()); + Resetting?.Invoke(this, EventArgs.Empty); + } + + /// + /// Called whenever the node must show it's custom view model, if , no custom view model is used + /// + /// The custom view model, if , no custom view model is used + public virtual ICustomNodeViewModel? GetCustomViewModel() + { + return null; + } + + /// + /// Serializes the object into a string + /// + /// The serialized object + internal virtual string SerializeStorage() + { + return string.Empty; + } + + /// + /// Deserializes the object and sets it + /// + /// The serialized object + internal virtual void DeserializeStorage(string serialized) + { } #endregion } - public abstract class Node : CustomViewModelNode where T : ICustomNodeViewModel + /// + /// Represents a kind of node inside a containing storage value of type + /// . + /// + /// The type of value the node stores + public abstract class Node : Node { + private TStorage? _storage; + + /// + protected Node() + { + } + + /// + protected Node(string name, string description) : base(name, description) + { + } + + /// + /// Gets or sets the storage object of this node, this is saved across sessions + /// + public TStorage? Storage + { + get => _storage; + set => SetAndNotify(ref _storage, value); + } + + internal override string SerializeStorage() + { + return CoreJson.SerializeObject(Storage, true); + } + + internal override void DeserializeStorage(string serialized) + { + Storage = CoreJson.DeserializeObject(serialized) ?? default(TStorage); + } + } + + /// + /// Represents a kind of node inside a containing storage value of type + /// and a view model of type . + /// + /// The type of value the node stores + /// The type of view model the node uses + public abstract class Node : Node where TViewModel : ICustomNodeViewModel + { + /// + protected Node() + { + } + + /// + protected Node(string name, string description) : base(name, description) + { + } + [Inject] internal IKernel Kernel { get; set; } = null!; - protected Node() - { } - - protected Node(string name, string description) : base(name, description) - { } - - public virtual T GetViewModel() + /// + /// Called when a view model is required + /// + public virtual TViewModel GetViewModel() { - return Kernel.Get(new ConstructorArgument("node", this)); + return Kernel.Get(new ConstructorArgument("node", this)); } + /// public override ICustomNodeViewModel GetCustomViewModel() { return GetViewModel(); } } - - public abstract class CustomViewModelNode : Node - { - /// - protected CustomViewModelNode() - { } - - /// - protected CustomViewModelNode(string name, string description) : base(name, description) - { } - - public abstract ICustomNodeViewModel GetCustomViewModel(); - } } \ No newline at end of file diff --git a/src/Artemis.Core/VisualScripting/NodeScript.cs b/src/Artemis.Core/VisualScripting/NodeScript.cs index 8458136d0..2d2ff20eb 100644 --- a/src/Artemis.Core/VisualScripting/NodeScript.cs +++ b/src/Artemis.Core/VisualScripting/NodeScript.cs @@ -9,6 +9,9 @@ using Artemis.Storage.Entities.Profile.Nodes; namespace Artemis.Core { + /// + /// Represents a node script + /// public abstract class NodeScript : CorePropertyChanged, INodeScript, IStorageModel { private void NodeTypeStoreOnNodeTypeChanged(object? sender, NodeTypeStoreEvent e) @@ -16,23 +19,41 @@ namespace Artemis.Core Load(); } + /// public event EventHandler>? NodeAdded; + + /// public event EventHandler>? NodeRemoved; #region Properties & Fields internal NodeScriptEntity Entity { get; } + /// public string Name { get; } + + /// public string Description { get; } private readonly List _nodes = new(); + + /// public IEnumerable Nodes => new ReadOnlyCollection(_nodes); + /// + /// Gets or sets the exit node of the script + /// protected INode ExitNode { get; set; } + + /// + /// Gets a boolean indicating whether the exit node is connected to any other nodes + /// public abstract bool ExitNodeConnected { get; } + + /// public abstract Type ResultType { get; } + /// public object? Context { get; set; } #endregion @@ -65,6 +86,7 @@ namespace Artemis.Core #region Methods + /// public void Run() { foreach (INode node in Nodes) @@ -73,6 +95,7 @@ namespace Artemis.Core ExitNode.Evaluate(); } + /// public void AddNode(INode node) { _nodes.Add(node); @@ -80,6 +103,7 @@ namespace Artemis.Core NodeAdded?.Invoke(this, new SingleValueEventArgs(node)); } + /// public void RemoveNode(INode node) { _nodes.Remove(node); @@ -90,6 +114,7 @@ namespace Artemis.Core NodeRemoved?.Invoke(this, new SingleValueEventArgs(node)); } + /// public void Dispose() { NodeTypeStore.NodeTypeAdded -= NodeTypeStoreOnNodeTypeChanged; @@ -147,9 +172,7 @@ namespace Artemis.Core // Restore pin collections foreach (NodePinCollectionEntity entityNodePinCollection in nodeEntity.PinCollections) { - IPinCollection? collection = node.PinCollections.FirstOrDefault(c => c.Name == entityNodePinCollection.Name && - c.Type.Name == entityNodePinCollection.Type && - (int) c.Direction == entityNodePinCollection.Direction); + IPinCollection? collection = node.PinCollections.ElementAtOrDefault(entityNodePinCollection.Id); if (collection == null) continue; @@ -161,12 +184,12 @@ namespace Artemis.Core } /// - /// Loads missing connections between the nodes of this node script from the + /// Loads missing connections between the nodes of this node script from the /// public void LoadConnections() { List nodes = Nodes.ToList(); - foreach (NodeConnectionEntity nodeConnectionEntity in Entity.Connections) + foreach (NodeConnectionEntity nodeConnectionEntity in Entity.Connections.OrderBy(p => p.SourcePinCollectionId)) { INode? source = nodes.ElementAtOrDefault(nodeConnectionEntity.SourceNode); if (source == null) @@ -191,15 +214,12 @@ namespace Artemis.Core // Clear existing connections on input pins, we don't want none of that now if (targetPin.Direction == PinDirection.Input) - { while (targetPin.ConnectedTo.Any()) targetPin.DisconnectFrom(targetPin.ConnectedTo[0]); - } + if (sourcePin.Direction == PinDirection.Input) - { - while (sourcePin.ConnectedTo.Any()) + while (sourcePin.ConnectedTo.Any()) sourcePin.DisconnectFrom(sourcePin.ConnectedTo[0]); - } // Only connect the nodes if they aren't already connected (LoadConnections may be called twice or more) if (!targetPin.ConnectedTo.Contains(sourcePin)) @@ -231,21 +251,24 @@ namespace Artemis.Core Type = node.GetType().Name, X = node.X, Y = node.Y, - Storage = CoreJson.SerializeObject(node.Storage, true), Name = node.Name, Description = node.Description, IsExitNode = node.IsExitNode }; + if (node is Node nodeImplementation) + nodeEntity.Storage = nodeImplementation.SerializeStorage(); + + int collectionId = 0; foreach (IPinCollection nodePinCollection in node.PinCollections) { nodeEntity.PinCollections.Add(new NodePinCollectionEntity { - Name = nodePinCollection.Name, - Type = nodePinCollection.Type.Name, + Id = collectionId, Direction = (int) nodePinCollection.Direction, Amount = nodePinCollection.Count() }); + collectionId++; } Entity.Nodes.Add(nodeEntity); @@ -309,13 +332,21 @@ namespace Artemis.Core #endregion } + /// + /// Represents a node script with a result value of type + /// + /// The type of result value public class NodeScript : NodeScript, INodeScript { #region Properties & Fields + /// public T Result => ((ExitNode) ExitNode).Value; + /// public override bool ExitNodeConnected => ((ExitNode) ExitNode).Input.ConnectedTo.Any(); + + /// public override Type ResultType => typeof(T); #endregion diff --git a/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs b/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs index 61e65eac4..ff6f2ac1c 100644 --- a/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs +++ b/src/Artemis.Storage/Entities/Profile/Nodes/NodePinCollectionEntity.cs @@ -2,8 +2,7 @@ { public class NodePinCollectionEntity { - public string Name { get; set; } - public string Type { get; set; } + public int Id { get; set; } public int Direction { set; get; } public int Amount { get; set; } } diff --git a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs index 4532b9d8b..17caa6d21 100644 --- a/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs +++ b/src/Artemis.VisualScripting/Editor/Controls/VisualScriptNodePresenter.cs @@ -155,10 +155,10 @@ namespace Artemis.VisualScripting.Editor.Controls { CustomViewModel?.OnDeactivate(); - if (Node?.Node is CustomViewModelNode customViewModelNode) + if (Node?.Node is Node customViewModelNode) { CustomViewModel = customViewModelNode.GetCustomViewModel(); - CustomViewModel.OnActivate(); + CustomViewModel?.OnActivate(); } else CustomViewModel = null; diff --git a/src/Artemis.VisualScripting/Nodes/Color/CustomViewModels/StaticSKColorValueNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Color/CustomViewModels/StaticSKColorValueNodeCustomViewModel.cs index 67a6c87a8..9cc486726 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/CustomViewModels/StaticSKColorValueNodeCustomViewModel.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/CustomViewModels/StaticSKColorValueNodeCustomViewModel.cs @@ -1,38 +1,11 @@ -using System.ComponentModel; -using Artemis.VisualScripting.Nodes.CustomViewModels; -using SkiaSharp; +using Artemis.VisualScripting.Nodes.CustomViewModels; namespace Artemis.VisualScripting.Nodes.Color.CustomViewModels { public class StaticSKColorValueNodeCustomViewModel : CustomNodeViewModel { - private readonly StaticSKColorValueNode _node; - public StaticSKColorValueNodeCustomViewModel(StaticSKColorValueNode node) : base(node) { - _node = node; - } - - public SKColor Input - { - get => (SKColor) (_node.Storage ?? SKColor.Empty); - set => _node.Storage = value; - } - - public override void OnActivate() - { - _node.PropertyChanged += NodeOnPropertyChanged; - } - - public override void OnDeactivate() - { - _node.PropertyChanged -= NodeOnPropertyChanged; - } - - private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Node.Storage)) - OnPropertyChanged(nameof(Input)); } } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Color/CustomViews/StaticSKColorValueNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/Color/CustomViews/StaticSKColorValueNodeCustomView.xaml index 6b34b4a5c..ff1137f3f 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/CustomViews/StaticSKColorValueNodeCustomView.xaml +++ b/src/Artemis.VisualScripting/Nodes/Color/CustomViews/StaticSKColorValueNodeCustomView.xaml @@ -12,5 +12,5 @@ + Color="{Binding Node.Storage, Converter={StaticResource SKColorToColorConverter}}" /> diff --git a/src/Artemis.VisualScripting/Nodes/Color/StaticSKColorValueNode.cs b/src/Artemis.VisualScripting/Nodes/Color/StaticSKColorValueNode.cs index 0c9a46162..cfdcd3edb 100644 --- a/src/Artemis.VisualScripting/Nodes/Color/StaticSKColorValueNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Color/StaticSKColorValueNode.cs @@ -5,7 +5,7 @@ using SkiaSharp; namespace Artemis.VisualScripting.Nodes.Color { [Node("Color-Value", "Outputs a configurable color value.", "Static", InputType = typeof(SKColor), OutputType = typeof(SKColor))] - public class StaticSKColorValueNode : Node + public class StaticSKColorValueNode : Node { #region Constructors @@ -27,17 +27,9 @@ namespace Artemis.VisualScripting.Nodes.Color public override void Evaluate() { - Output.Value = Storage as SKColor? ?? SKColor.Empty; + Output.Value = Storage; } - - public override void Initialize(INodeScript script) - { - if (Storage is string && SKColor.TryParse(Storage.ToString(), out SKColor parsed)) - Storage = parsed; - else - Storage = SKColor.Empty; - } - + #endregion } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/CustomViewModels/EnumEqualsNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/CustomViewModels/EnumEqualsNodeCustomViewModel.cs index d03fa5395..65f0eb05a 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViewModels/EnumEqualsNodeCustomViewModel.cs +++ b/src/Artemis.VisualScripting/Nodes/CustomViewModels/EnumEqualsNodeCustomViewModel.cs @@ -1,6 +1,4 @@ -using System; -using System.ComponentModel; -using Artemis.Core; +using Artemis.Core; using Artemis.Core.Events; using Artemis.UI.Shared; using Stylet; @@ -16,19 +14,12 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels _node = node; } - public Enum Input - { - get => _node.Storage as Enum; - set => _node.Storage = value; - } - public BindableCollection EnumValues { get; } = new(); public override void OnActivate() { _node.InputPin.PinConnected += InputPinOnPinConnected; _node.InputPin.PinDisconnected += InputPinOnPinDisconnected; - _node.PropertyChanged += NodeOnPropertyChanged; if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum) EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType())); @@ -39,7 +30,6 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels { _node.InputPin.PinConnected -= InputPinOnPinConnected; _node.InputPin.PinDisconnected -= InputPinOnPinDisconnected; - _node.PropertyChanged -= NodeOnPropertyChanged; base.OnDeactivate(); } @@ -55,11 +45,5 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum) EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType())); } - - private void NodeOnPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Node.Storage)) - OnPropertyChanged(nameof(Input)); - } } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/CustomViewModels/StaticValueNodeViewModels.cs b/src/Artemis.VisualScripting/Nodes/CustomViewModels/StaticValueNodeViewModels.cs index 82087eb87..e976d5059 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViewModels/StaticValueNodeViewModels.cs +++ b/src/Artemis.VisualScripting/Nodes/CustomViewModels/StaticValueNodeViewModels.cs @@ -1,132 +1,32 @@ -using System.ComponentModel; +using Artemis.Core; namespace Artemis.VisualScripting.Nodes.CustomViewModels { public class StaticDoubleValueNodeCustomViewModel : CustomNodeViewModel { - private readonly StaticDoubleValueNode _node; - - public StaticDoubleValueNodeCustomViewModel(StaticDoubleValueNode node) : base(node) + public StaticDoubleValueNodeCustomViewModel(INode node) : base(node) { - _node = node; - } - - public double Input - { - get => (double) (_node.Storage ?? 0.0); - set => _node.Storage = value; - } - - public override void OnActivate() - { - _node.PropertyChanged += NodeOnPropertyChanged; - } - - public override void OnDeactivate() - { - _node.PropertyChanged -= NodeOnPropertyChanged; - } - - private void NodeOnPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Node.Storage)) - OnPropertyChanged(nameof(Input)); } } public class StaticFloatValueNodeCustomViewModel : CustomNodeViewModel { - private readonly StaticFloatValueNode _node; - - public StaticFloatValueNodeCustomViewModel(StaticFloatValueNode node) : base(node) + public StaticFloatValueNodeCustomViewModel(INode node) : base(node) { - _node = node; - } - - public float Input - { - get => (float) (_node.Storage ?? 0f); - set => _node.Storage = value; - } - - public override void OnActivate() - { - _node.PropertyChanged += NodeOnPropertyChanged; - } - - public override void OnDeactivate() - { - _node.PropertyChanged -= NodeOnPropertyChanged; - } - - private void NodeOnPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Node.Storage)) - OnPropertyChanged(nameof(Input)); } } public class StaticIntegerValueNodeCustomViewModel : CustomNodeViewModel { - private readonly StaticIntegerValueNode _node; - - public StaticIntegerValueNodeCustomViewModel(StaticIntegerValueNode node) : base(node) + public StaticIntegerValueNodeCustomViewModel(INode node) : base(node) { - _node = node; - } - - public int Input - { - get => _node.Storage is long longInput ? (int) longInput : (int) (_node.Storage ?? 0); - set => _node.Storage = value; - } - - public override void OnActivate() - { - _node.PropertyChanged += NodeOnPropertyChanged; - } - - public override void OnDeactivate() - { - _node.PropertyChanged -= NodeOnPropertyChanged; - } - - private void NodeOnPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Node.Storage)) - OnPropertyChanged(nameof(Input)); } } public class StaticStringValueNodeCustomViewModel : CustomNodeViewModel { - private readonly StaticStringValueNode _node; - - public StaticStringValueNodeCustomViewModel(StaticStringValueNode node) : base(node) + public StaticStringValueNodeCustomViewModel(INode node) : base(node) { - _node = node; - } - - public string Input - { - get => (string) _node.Storage; - set => _node.Storage = value; - } - - public override void OnActivate() - { - _node.PropertyChanged += NodeOnPropertyChanged; - } - - public override void OnDeactivate() - { - _node.PropertyChanged -= NodeOnPropertyChanged; - } - - private void NodeOnPropertyChanged(object? sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Node.Storage)) - OnPropertyChanged(nameof(Input)); } } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/CustomViews/EnumEqualsNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/CustomViews/EnumEqualsNodeCustomView.xaml index 01c753dcf..1f2dced37 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViews/EnumEqualsNodeCustomView.xaml +++ b/src/Artemis.VisualScripting/Nodes/CustomViews/EnumEqualsNodeCustomView.xaml @@ -12,7 +12,7 @@ materialDesign:ComboBoxAssist.ClassicMode="True" VerticalAlignment="Center" HorizontalAlignment="Stretch" - SelectedValue="{Binding Input}" + SelectedValue="{Binding Node.Storage}" ItemsSource="{Binding EnumValues}" SelectedValuePath="Value" DisplayMemberPath="Description"> diff --git a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticDoubleValueNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticDoubleValueNodeCustomView.xaml index 3e81bf356..17731036d 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticDoubleValueNodeCustomView.xaml +++ b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticDoubleValueNodeCustomView.xaml @@ -8,5 +8,5 @@ d:DesignHeight="450" d:DesignWidth="800"> + Text="{Binding Node.Storage}" /> diff --git a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticFloatValueNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticFloatValueNodeCustomView.xaml index 7cd2b5ad7..3720a3acd 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticFloatValueNodeCustomView.xaml +++ b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticFloatValueNodeCustomView.xaml @@ -8,5 +8,5 @@ d:DesignHeight="450" d:DesignWidth="800"> + Text="{Binding Node.Storage}" /> diff --git a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticIntegerValueNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticIntegerValueNodeCustomView.xaml index c79b89aa7..66f828f08 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticIntegerValueNodeCustomView.xaml +++ b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticIntegerValueNodeCustomView.xaml @@ -8,5 +8,5 @@ d:DesignHeight="450" d:DesignWidth="800"> + Text="{Binding Node.Storage}" /> diff --git a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticStringValueNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticStringValueNodeCustomView.xaml index 21ad9ad7d..69e410129 100644 --- a/src/Artemis.VisualScripting/Nodes/CustomViews/StaticStringValueNodeCustomView.xaml +++ b/src/Artemis.VisualScripting/Nodes/CustomViews/StaticStringValueNodeCustomView.xaml @@ -8,5 +8,5 @@ d:DesignHeight="450" d:DesignWidth="800"> + Text="{Binding Node.Storage}" /> diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventNode.cs b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventNode.cs index 304607e5a..a98f764e8 100644 --- a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventNode.cs +++ b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelEventNode.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using Artemis.Core; using Artemis.Core.Events; @@ -8,19 +9,69 @@ using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels; namespace Artemis.VisualScripting.Nodes.DataModel { [Node("Data Model-Event", "Responds to a data model event trigger", "External", OutputType = typeof(bool))] - public class DataModelEventNode : Node, IDisposable + public class DataModelEventNode : Node, IDisposable { private DataModelPath _dataModelPath; private DateTime _lastTrigger; private int _currentIndex; + private Type _currentType; + private bool _updating; public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger") { - Input = CreateInputPin(); - Input.PinConnected += InputOnPinConnected; + _currentType = typeof(object); + CreateCycleValues(typeof(object), 1); + Output = CreateOutputPin(typeof(object)); } - public InputPin Input { get; } + private void CreateCycleValues(Type type, int initialCount) + { + if (CycleValues != null) + { + CycleValues.PinAdded -= CycleValuesOnPinAdded; + CycleValues.PinRemoved -= CycleValuesOnPinRemoved; + foreach (IPin pin in CycleValues) + { + pin.PinConnected -= OnPinConnected; + pin.PinDisconnected -= OnPinDisconnected; + } + + RemovePinCollection(CycleValues); + } + + CycleValues = CreateInputPinCollection(type, "", initialCount); + CycleValues.PinAdded += CycleValuesOnPinAdded; + CycleValues.PinRemoved += CycleValuesOnPinRemoved; + foreach (IPin pin in CycleValues) + { + pin.PinConnected += OnPinConnected; + pin.PinDisconnected += OnPinDisconnected; + } + } + + private void CycleValuesOnPinAdded(object sender, SingleValueEventArgs e) + { + e.Value.PinConnected += OnPinConnected; + e.Value.PinDisconnected += OnPinDisconnected; + } + + private void CycleValuesOnPinRemoved(object sender, SingleValueEventArgs e) + { + e.Value.PinConnected -= OnPinConnected; + e.Value.PinDisconnected -= OnPinDisconnected; + } + + private void OnPinDisconnected(object sender, SingleValueEventArgs e) + { + ProcessPinDisconnected(); + } + + private void OnPinConnected(object sender, SingleValueEventArgs e) + { + IPin source = e.Value; + IPin target = (IPin) sender; + ProcessPinConnected(source, target); + } public InputPinCollection CycleValues { get; set; } public OutputPin Output { get; set; } @@ -35,70 +86,101 @@ namespace Artemis.VisualScripting.Nodes.DataModel public override void Initialize(INodeScript script) { Script = script; - CreateCycleValues(); - CreateOutput(); - if (Storage is not DataModelPathEntity pathEntity) + if (Storage == null) return; - DataModelPath = new DataModelPath(pathEntity); + DataModelPath = new DataModelPath(Storage); } public override void Evaluate() { object outputValue = null; - if (DataModelPath?.GetValue() is DataModelEvent dataModelEvent) + if (DataModelPath?.GetValue() is IDataModelEvent dataModelEvent) { if (dataModelEvent.LastTrigger > _lastTrigger) { _lastTrigger = dataModelEvent.LastTrigger; _currentIndex++; - if (_currentIndex > CycleValues.Count()) + if (_currentIndex >= CycleValues.Count()) _currentIndex = 0; } - outputValue = _currentIndex == 0 - ? Input.Value - : CycleValues.ElementAt(_currentIndex - 1).PinValue; + outputValue = CycleValues.ElementAt(_currentIndex).PinValue; } - Output.Value = outputValue ?? Output.Type.GetDefault(); + if (Output.Type.IsInstanceOfType(outputValue)) + Output.Value = outputValue; + else if (Output.Type.IsValueType) + Output.Value = Output.Type.GetDefault()!; } - private void InputOnPinConnected(object sender, SingleValueEventArgs e) + private void ProcessPinConnected(IPin source, IPin target) { - CreateCycleValues(); - CreateOutput(); - } + if (_updating) + return; - private void CreateCycleValues() - { - int pinCount = CycleValues?.Count() ?? 1; - Type inputType = Input.ConnectedTo.FirstOrDefault()?.Type ?? typeof(object); - - if (CycleValues != null) + try { - if (inputType == CycleValues.Type) - return; - RemovePinCollection(CycleValues); - } + _updating = true; - CycleValues = CreateInputPinCollection(inputType, "", pinCount); + // No need to change anything if the types haven't changed + if (_currentType == source.Type) + return; + + int reconnectIndex = CycleValues.ToList().IndexOf(target); + ChangeCurrentType(source.Type); + + if (reconnectIndex != -1) + { + CycleValues.ToList()[reconnectIndex].ConnectTo(source); + source.ConnectTo(CycleValues.ToList()[reconnectIndex]); + } + } + finally + { + _updating = false; + } } - private void CreateOutput() + private void ChangeCurrentType(Type type) { - Type inputType = Input.ConnectedTo.FirstOrDefault()?.Type ?? typeof(object); - - if (Output != null) + CreateCycleValues(type, CycleValues.Count()); + + List oldOutputConnections = Output.ConnectedTo.ToList(); + RemovePin(Output); + Output = CreateOutputPin(type); + foreach (IPin oldOutputConnection in oldOutputConnections.Where(o => o.Type.IsAssignableFrom(Output.Type))) { - if (inputType == Output.Type) - return; - RemovePin(Output); + oldOutputConnection.DisconnectAll(); + oldOutputConnection.ConnectTo(Output); + Output.ConnectTo(oldOutputConnection); } - Output = CreateOutputPin(inputType); + _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; + } + } + + private void UpdatePinsType(IPin source) + { } /// diff --git a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs index 056a6ae92..1639056ea 100644 --- a/src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs +++ b/src/Artemis.VisualScripting/Nodes/DataModel/DataModelNode.cs @@ -7,7 +7,7 @@ using Stylet; namespace Artemis.VisualScripting.Nodes.DataModel { [Node("Data Model-Value", "Outputs a selectable data model value.", "External")] - public class DataModelNode : Node, IDisposable + public class DataModelNode : Node, IDisposable { private DataModelPath _dataModelPath; @@ -28,10 +28,10 @@ namespace Artemis.VisualScripting.Nodes.DataModel { Script = script; - if (Storage is not DataModelPathEntity pathEntity) + if (Storage == null) return; - DataModelPath = new DataModelPath(pathEntity); + DataModelPath = new DataModelPath(Storage); DataModelPath.PathValidated += DataModelPathOnPathValidated; UpdateOutputPin(false); diff --git a/src/Artemis.VisualScripting/Nodes/Easing/CustomViewModels/EasingTypeNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Easing/CustomViewModels/EasingTypeNodeCustomViewModel.cs index 6675c211a..82794c093 100644 --- a/src/Artemis.VisualScripting/Nodes/Easing/CustomViewModels/EasingTypeNodeCustomViewModel.cs +++ b/src/Artemis.VisualScripting/Nodes/Easing/CustomViewModels/EasingTypeNodeCustomViewModel.cs @@ -15,9 +15,7 @@ namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels public EasingTypeNodeCustomViewModel(EasingTypeNode node) : base(node) { _node = node; - EasingViewModels = new BindableCollection(Enum.GetValues(typeof(Easings.Functions)) - .Cast() - .Select(e => new NodeEasingViewModel(e))); + EasingViewModels = new BindableCollection(Enum.GetValues(typeof(Easings.Functions)).Cast().Select(e => new NodeEasingViewModel(e))); } public BindableCollection EasingViewModels { get; } @@ -35,7 +33,7 @@ namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels public override void OnActivate() { _node.PropertyChanged += NodeOnPropertyChanged; - SelectedEasingViewModel = EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.EasingFunction); + SelectedEasingViewModel = GetNodeEasingViewModel(); } public override void OnDeactivate() @@ -45,11 +43,16 @@ namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (e.PropertyName == nameof(Node.Storage)) + if (e.PropertyName == nameof(_node.Storage)) { - _selectedEasingViewModel = EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.EasingFunction); + _selectedEasingViewModel = GetNodeEasingViewModel(); NotifyOfPropertyChange(nameof(SelectedEasingViewModel)); } } + + private NodeEasingViewModel GetNodeEasingViewModel() + { + return EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.Storage); + } } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs b/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs index c35d7f3a6..7a14ff904 100644 --- a/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Easing/EasingTypeNode.cs @@ -4,7 +4,7 @@ using Artemis.VisualScripting.Nodes.Easing.CustomViewModels; namespace Artemis.VisualScripting.Nodes.Easing { [Node("Easing Type", "Outputs a selectable easing type.", "Easing", OutputType = typeof(Easings.Functions))] - public class EasingTypeNode : Node + public class EasingTypeNode : Node { public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.") { @@ -12,11 +12,10 @@ namespace Artemis.VisualScripting.Nodes.Easing } public OutputPin Output { get; } - public Easings.Functions EasingFunction => Storage as Easings.Functions? ?? Easings.Functions.Linear; public override void Evaluate() { - Output.Value = EasingFunction; + Output.Value = Storage; } } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/EnumEqualsNode.cs b/src/Artemis.VisualScripting/Nodes/EnumEqualsNode.cs index 59df2269e..75eb0dbb0 100644 --- a/src/Artemis.VisualScripting/Nodes/EnumEqualsNode.cs +++ b/src/Artemis.VisualScripting/Nodes/EnumEqualsNode.cs @@ -1,12 +1,11 @@ using System; using Artemis.Core; -using Artemis.Core.Events; using Artemis.VisualScripting.Nodes.CustomViewModels; namespace Artemis.VisualScripting.Nodes { [Node("Enum Equals", "Determines the equality between an input and a selected enum value", InputType = typeof(Enum), OutputType = typeof(bool))] - public class EnumEqualsNode : Node + public class EnumEqualsNode : Node { public EnumEqualsNode() : base("Enum Equals", "Determines the equality between an input and a selected enum value") { diff --git a/src/Artemis.VisualScripting/Nodes/LayerPropertyNode.cs b/src/Artemis.VisualScripting/Nodes/LayerPropertyNode.cs index 2ee41e434..b76d9002b 100644 --- a/src/Artemis.VisualScripting/Nodes/LayerPropertyNode.cs +++ b/src/Artemis.VisualScripting/Nodes/LayerPropertyNode.cs @@ -7,7 +7,7 @@ using Artemis.VisualScripting.Nodes.CustomViewModels; namespace Artemis.VisualScripting.Nodes { [Node("Layer/Folder Property", "Outputs the property of a selected layer or folder", "External")] - public class LayerPropertyNode : Node + public class LayerPropertyNode : Node { private readonly object _layerPropertyLock = new(); @@ -44,7 +44,7 @@ namespace Artemis.VisualScripting.Nodes { Script = script; - if (script.Context is Profile profile) + if (script.Context is Profile profile) profile.ChildRemoved += ProfileOnChildRemoved; LoadLayerProperty(); @@ -54,15 +54,13 @@ namespace Artemis.VisualScripting.Nodes { lock (_layerPropertyLock) { - if (Script.Context is not Profile profile) + if (Script.Context is not Profile profile || Storage == null) return; - if (Storage is not LayerPropertyNodeEntity entity) - return; - - RenderProfileElement element = profile.GetAllRenderElements().FirstOrDefault(l => l.EntityId == entity.ElementId); + + RenderProfileElement element = profile.GetAllRenderElements().FirstOrDefault(l => l.EntityId == Storage.ElementId); ProfileElement = element; - LayerProperty = element?.GetAllLayerProperties().FirstOrDefault(p => p.Path == entity.PropertyPath); + LayerProperty = element?.GetAllLayerProperties().FirstOrDefault(p => p.Path == Storage.PropertyPath); CreatePins(); } } diff --git a/src/Artemis.VisualScripting/Nodes/Maths/CustomViewModels/MathExpressionNodeCustomViewModel.cs b/src/Artemis.VisualScripting/Nodes/Maths/CustomViewModels/MathExpressionNodeCustomViewModel.cs index fac0f3d54..f01d77da3 100644 --- a/src/Artemis.VisualScripting/Nodes/Maths/CustomViewModels/MathExpressionNodeCustomViewModel.cs +++ b/src/Artemis.VisualScripting/Nodes/Maths/CustomViewModels/MathExpressionNodeCustomViewModel.cs @@ -1,37 +1,12 @@ -using System.ComponentModel; +using Artemis.Core; using Artemis.VisualScripting.Nodes.CustomViewModels; namespace Artemis.VisualScripting.Nodes.Maths.CustomViewModels { public class MathExpressionNodeCustomViewModel : CustomNodeViewModel { - private readonly MathExpressionNode _node; - - public MathExpressionNodeCustomViewModel(MathExpressionNode node) : base(node) + public MathExpressionNodeCustomViewModel(INode node) : base(node) { - _node = node; - } - - public string Input - { - get => (string)_node.Storage; - set => _node.Storage = value; - } - - public override void OnActivate() - { - _node.PropertyChanged += NodeOnPropertyChanged; - } - - public override void OnDeactivate() - { - _node.PropertyChanged -= NodeOnPropertyChanged; - } - - private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e) - { - if (e.PropertyName == nameof(Node.Storage)) - OnPropertyChanged(nameof(Input)); } } } \ No newline at end of file diff --git a/src/Artemis.VisualScripting/Nodes/Maths/CustomViews/MathExpressionNodeCustomView.xaml b/src/Artemis.VisualScripting/Nodes/Maths/CustomViews/MathExpressionNodeCustomView.xaml index 0e1d3366f..5bd82fab2 100644 --- a/src/Artemis.VisualScripting/Nodes/Maths/CustomViews/MathExpressionNodeCustomView.xaml +++ b/src/Artemis.VisualScripting/Nodes/Maths/CustomViews/MathExpressionNodeCustomView.xaml @@ -8,5 +8,5 @@ d:DesignHeight="450" d:DesignWidth="800"> + Text="{Binding Node.Storage}" /> diff --git a/src/Artemis.VisualScripting/Nodes/Maths/ExpressionNode.cs b/src/Artemis.VisualScripting/Nodes/Maths/ExpressionNode.cs index 591ef526f..a413fc76f 100644 --- a/src/Artemis.VisualScripting/Nodes/Maths/ExpressionNode.cs +++ b/src/Artemis.VisualScripting/Nodes/Maths/ExpressionNode.cs @@ -9,12 +9,13 @@ using NoStringEvaluating.Models.Values; namespace Artemis.VisualScripting.Nodes.Maths { [Node("Math Expression", "Outputs the result of a math expression.", "Math", OutputType = typeof(int))] - public class MathExpressionNode : Node + public class MathExpressionNode : Node { private readonly INoStringEvaluator _evaluator; private readonly PinsVariablesContainer _variables; #region Constructors + public MathExpressionNode(INoStringEvaluator evaluator) : base("Math Expression", "Outputs the result of a math expression.") { @@ -24,7 +25,7 @@ namespace Artemis.VisualScripting.Nodes.Maths Values.PinAdded += (_, _) => SetPinNames(); Values.PinRemoved += (_, _) => SetPinNames(); _variables = new PinsVariablesContainer(Values); - + SetPinNames(); } @@ -41,8 +42,8 @@ namespace Artemis.VisualScripting.Nodes.Maths public override void Evaluate() { - if (Storage is string formula) - Output.Value = (float) _evaluator.CalcNumber(formula, _variables); + if (Storage != null) + Output.Value = (float) _evaluator.CalcNumber(Storage, _variables); } private void SetPinNames() diff --git a/src/Artemis.VisualScripting/Nodes/StaticValueNodes.cs b/src/Artemis.VisualScripting/Nodes/StaticValueNodes.cs index 49db40d9c..cd09f9409 100644 --- a/src/Artemis.VisualScripting/Nodes/StaticValueNodes.cs +++ b/src/Artemis.VisualScripting/Nodes/StaticValueNodes.cs @@ -4,7 +4,7 @@ using Artemis.VisualScripting.Nodes.CustomViewModels; namespace Artemis.VisualScripting.Nodes { [Node("Integer-Value", "Outputs an configurable integer value.", "Static", OutputType = typeof(int))] - public class StaticIntegerValueNode : Node + public class StaticIntegerValueNode : Node { #region Properties & Fields @@ -26,16 +26,14 @@ namespace Artemis.VisualScripting.Nodes public override void Evaluate() { - Output.Value = Storage as int? ?? 0; + Output.Value = Storage; } - public override void Initialize(INodeScript script) => Storage ??= 0; - #endregion } [Node("Double-Value", "Outputs a configurable double value.", "Static", OutputType = typeof(double))] - public class StaticDoubleValueNode : Node + public class StaticDoubleValueNode : Node { #region Properties & Fields @@ -60,13 +58,11 @@ namespace Artemis.VisualScripting.Nodes Output.Value = Storage as double? ?? 0.0; } - public override void Initialize(INodeScript script) => Storage ??= 0.0; - #endregion } [Node("Float-Value", "Outputs a configurable float value.", "Static", OutputType = typeof(float))] - public class StaticFloatValueNode : Node + public class StaticFloatValueNode : Node { #region Properties & Fields @@ -88,19 +84,14 @@ namespace Artemis.VisualScripting.Nodes public override void Evaluate() { - if (Storage is double doubleValue) - Storage = (float) doubleValue; - - Output.Value = Storage as float? ?? 0.0f; + Output.Value = Storage; } - public override void Initialize(INodeScript script) => Storage ??= 0.0f; - #endregion } [Node("String-Value", "Outputs a configurable string value.", "Static", OutputType = typeof(string))] - public class StaticStringValueNode : Node + public class StaticStringValueNode : Node { #region Properties & Fields @@ -122,7 +113,7 @@ namespace Artemis.VisualScripting.Nodes public override void Evaluate() { - Output.Value = Storage as string; + Output.Value = Storage; } #endregion