mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Nodes - Changed storage to be based on generics
Nodes - Added XML docs to most types
This commit is contained in:
parent
8413b8d6db
commit
c1dab91c16
@ -76,7 +76,8 @@ namespace Artemis.Core.Services
|
|||||||
node.Y = entity.Y;
|
node.Y = entity.Y;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
node.Storage = CoreJson.DeserializeObject(entity.Storage, true);
|
if (node is Node nodeImplementation)
|
||||||
|
nodeImplementation.DeserializeStorage(entity.Storage);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,6 +12,7 @@ namespace Artemis.Core
|
|||||||
public override PinDirection Direction => PinDirection.Input;
|
public override PinDirection Direction => PinDirection.Input;
|
||||||
|
|
||||||
private T _value;
|
private T _value;
|
||||||
|
|
||||||
public T Value
|
public T Value
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -37,7 +38,8 @@ namespace Artemis.Core
|
|||||||
[JsonConstructor]
|
[JsonConstructor]
|
||||||
internal InputPin(INode node, string name)
|
internal InputPin(INode node, string name)
|
||||||
: base(node, name)
|
: base(node, name)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -62,6 +64,7 @@ namespace Artemis.Core
|
|||||||
public override PinDirection Direction => PinDirection.Input;
|
public override PinDirection Direction => PinDirection.Input;
|
||||||
|
|
||||||
private object _value;
|
private object _value;
|
||||||
|
|
||||||
public object Value
|
public object Value
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@ -98,9 +101,19 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private void Evaluate()
|
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
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,29 +1,73 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using Artemis.Storage.Entities.Profile.Nodes;
|
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a kind of node inside a <see cref="INodeScript" />
|
||||||
|
/// </summary>
|
||||||
public interface INode : INotifyPropertyChanged
|
public interface INode : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the node
|
||||||
|
/// </summary>
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the description of the node
|
||||||
|
/// </summary>
|
||||||
string Description { get; }
|
string Description { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether the node is the exit node of the script
|
||||||
|
/// </summary>
|
||||||
bool IsExitNode { get; }
|
bool IsExitNode { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether the node is a default node that connot be removed
|
||||||
|
/// </summary>
|
||||||
bool IsDefaultNode { get; }
|
bool IsDefaultNode { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the X-position of the node
|
||||||
|
/// </summary>
|
||||||
public double X { get; set; }
|
public double X { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Y-position of the node
|
||||||
|
/// </summary>
|
||||||
public double Y { get; set; }
|
public double Y { get; set; }
|
||||||
public object? Storage { get; set; }
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a read-only collection of the pins on this node
|
||||||
|
/// </summary>
|
||||||
public IReadOnlyCollection<IPin> Pins { get; }
|
public IReadOnlyCollection<IPin> Pins { get; }
|
||||||
public IReadOnlyCollection<IPinCollection> PinCollections { get; }
|
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a read-only collection of the pin collections on this node
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyCollection<IPinCollection> PinCollections { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the node resets
|
||||||
|
/// </summary>
|
||||||
event EventHandler Resetting;
|
event EventHandler Resetting;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when the node was loaded from storage or newly created
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="script">The script the node is contained in</param>
|
||||||
void Initialize(INodeScript script);
|
void Initialize(INodeScript script);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Evaluates the value of the output pins of this node
|
||||||
|
/// </summary>
|
||||||
void Evaluate();
|
void Evaluate();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets the node causing all pins to re-evaluate the next time <see cref="Evaluate"/> is called
|
||||||
|
/// </summary>
|
||||||
void Reset();
|
void Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -5,27 +5,74 @@ using Artemis.Core.Events;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a node script
|
||||||
|
/// </summary>
|
||||||
public interface INodeScript : INotifyPropertyChanged, IDisposable
|
public interface INodeScript : INotifyPropertyChanged, IDisposable
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the node script.
|
||||||
|
/// </summary>
|
||||||
string Name { get; }
|
string Name { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the description of the node script.
|
||||||
|
/// </summary>
|
||||||
string Description { get; }
|
string Description { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an enumerable of all the nodes on this script.
|
||||||
|
/// </summary>
|
||||||
IEnumerable<INode> Nodes { get; }
|
IEnumerable<INode> Nodes { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the return type of the node script.
|
||||||
|
/// </summary>
|
||||||
Type ResultType { get; }
|
Type ResultType { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the context of the node script, usually a <see cref="Profile" /> or
|
||||||
|
/// <see cref="ProfileConfiguration" />.
|
||||||
|
/// </summary>
|
||||||
object? Context { get; set; }
|
object? Context { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs whenever a node was added to the script
|
||||||
|
/// </summary>
|
||||||
event EventHandler<SingleValueEventArgs<INode>>? NodeAdded;
|
event EventHandler<SingleValueEventArgs<INode>>? NodeAdded;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Occurs whenever a node was removed from the script
|
||||||
|
/// </summary>
|
||||||
event EventHandler<SingleValueEventArgs<INode>>? NodeRemoved;
|
event EventHandler<SingleValueEventArgs<INode>>? NodeRemoved;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Runs the script, evaluating nodes where needed
|
||||||
|
/// </summary>
|
||||||
void Run();
|
void Run();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a node to the script
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node">The node to add</param>
|
||||||
void AddNode(INode node);
|
void AddNode(INode node);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a node from the script
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="node">The node to remove</param>
|
||||||
void RemoveNode(INode node);
|
void RemoveNode(INode node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a node script with a result value of type <paramref name="T" />
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of result value</typeparam>
|
||||||
public interface INodeScript<out T> : INodeScript
|
public interface INodeScript<out T> : INodeScript
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the result of the script
|
||||||
|
/// </summary>
|
||||||
T Result { get; }
|
T Result { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,16 +1,24 @@
|
|||||||
using Ninject;
|
using System;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using Ninject;
|
||||||
using Ninject.Parameters;
|
using Ninject.Parameters;
|
||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a kind of node inside a <see cref="NodeScript" />
|
||||||
|
/// </summary>
|
||||||
public abstract class Node : CorePropertyChanged, INode
|
public abstract class Node : CorePropertyChanged, INode
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public event EventHandler? Resetting;
|
||||||
|
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
private string _name;
|
private string _name;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name
|
public string Name
|
||||||
{
|
{
|
||||||
get => _name;
|
get => _name;
|
||||||
@ -18,6 +26,8 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
private string _description;
|
private string _description;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Description
|
public string Description
|
||||||
{
|
{
|
||||||
get => _description;
|
get => _description;
|
||||||
@ -26,6 +36,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
private double _x;
|
private double _x;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public double X
|
public double X
|
||||||
{
|
{
|
||||||
get => _x;
|
get => _x;
|
||||||
@ -33,51 +44,62 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
private double _y;
|
private double _y;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public double Y
|
public double Y
|
||||||
{
|
{
|
||||||
get => _y;
|
get => _y;
|
||||||
set => SetAndNotify(ref _y, value);
|
set => SetAndNotify(ref _y, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private object? _storage;
|
/// <inheritdoc />
|
||||||
public object? Storage
|
|
||||||
{
|
|
||||||
get => _storage;
|
|
||||||
set => SetAndNotify(ref _storage, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool IsExitNode => false;
|
public virtual bool IsExitNode => false;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public virtual bool IsDefaultNode => false;
|
public virtual bool IsDefaultNode => false;
|
||||||
|
|
||||||
private readonly List<IPin> _pins = new();
|
private readonly List<IPin> _pins = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public IReadOnlyCollection<IPin> Pins => new ReadOnlyCollection<IPin>(_pins);
|
public IReadOnlyCollection<IPin> Pins => new ReadOnlyCollection<IPin>(_pins);
|
||||||
|
|
||||||
private readonly List<IPinCollection> _pinCollections = new();
|
private readonly List<IPinCollection> _pinCollections = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public IReadOnlyCollection<IPinCollection> PinCollections => new ReadOnlyCollection<IPinCollection>(_pinCollections);
|
public IReadOnlyCollection<IPinCollection> PinCollections => new ReadOnlyCollection<IPinCollection>(_pinCollections);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Events
|
|
||||||
|
|
||||||
public event EventHandler Resetting;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Construtors
|
#region Construtors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="Node" /> class with an empty name and description
|
||||||
|
/// </summary>
|
||||||
protected Node()
|
protected Node()
|
||||||
{ }
|
{
|
||||||
|
_name = string.Empty;
|
||||||
|
_description = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new instance of the <see cref="Node" /> class with the provided name and description
|
||||||
|
/// </summary>
|
||||||
protected Node(string name, string description)
|
protected Node(string name, string description)
|
||||||
{
|
{
|
||||||
Name = name;
|
_name = name;
|
||||||
Description = description;
|
_description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new input pin and adds it to the <see cref="Pins" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the pin</param>
|
||||||
|
/// <typeparam name="T">The type of value the pin will hold</typeparam>
|
||||||
|
/// <returns>The newly created pin</returns>
|
||||||
protected InputPin<T> CreateInputPin<T>(string name = "")
|
protected InputPin<T> CreateInputPin<T>(string name = "")
|
||||||
{
|
{
|
||||||
InputPin<T> pin = new(this, name);
|
InputPin<T> pin = new(this, name);
|
||||||
@ -86,6 +108,12 @@ namespace Artemis.Core
|
|||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new input pin and adds it to the <see cref="Pins" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type of value the pin will hold</param>
|
||||||
|
/// <param name="name">The name of the pin</param>
|
||||||
|
/// <returns>The newly created pin</returns>
|
||||||
protected InputPin CreateInputPin(Type type, string name = "")
|
protected InputPin CreateInputPin(Type type, string name = "")
|
||||||
{
|
{
|
||||||
InputPin pin = new(this, type, name);
|
InputPin pin = new(this, type, name);
|
||||||
@ -94,6 +122,12 @@ namespace Artemis.Core
|
|||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new output pin and adds it to the <see cref="Pins" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the pin</param>
|
||||||
|
/// <typeparam name="T">The type of value the pin will hold</typeparam>
|
||||||
|
/// <returns>The newly created pin</returns>
|
||||||
protected OutputPin<T> CreateOutputPin<T>(string name = "")
|
protected OutputPin<T> CreateOutputPin<T>(string name = "")
|
||||||
{
|
{
|
||||||
OutputPin<T> pin = new(this, name);
|
OutputPin<T> pin = new(this, name);
|
||||||
@ -102,6 +136,12 @@ namespace Artemis.Core
|
|||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new output pin and adds it to the <see cref="Pins" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type of value the pin will hold</param>
|
||||||
|
/// <param name="name">The name of the pin</param>
|
||||||
|
/// <returns>The newly created pin</returns>
|
||||||
protected OutputPin CreateOutputPin(Type type, string name = "")
|
protected OutputPin CreateOutputPin(Type type, string name = "")
|
||||||
{
|
{
|
||||||
OutputPin pin = new(this, type, name);
|
OutputPin pin = new(this, type, name);
|
||||||
@ -109,7 +149,12 @@ namespace Artemis.Core
|
|||||||
OnPropertyChanged(nameof(Pins));
|
OnPropertyChanged(nameof(Pins));
|
||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the provided <paramref name="pin" /> from the node and it's <see cref="Pins" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pin">The pin to remove</param>
|
||||||
|
/// <returns><see langword="true" /> if the pin was removed; otherwise <see langword="false" />.</returns>
|
||||||
protected bool RemovePin(Pin pin)
|
protected bool RemovePin(Pin pin)
|
||||||
{
|
{
|
||||||
bool isRemoved = _pins.Remove(pin);
|
bool isRemoved = _pins.Remove(pin);
|
||||||
@ -122,6 +167,13 @@ namespace Artemis.Core
|
|||||||
return isRemoved;
|
return isRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new input pin collection and adds it to the <see cref="PinCollections" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of value the pins of this collection will hold</typeparam>
|
||||||
|
/// <param name="name">The name of the pin collection</param>
|
||||||
|
/// <param name="initialCount">The amount of pins to initially add to the collection</param>
|
||||||
|
/// <returns>The resulting input pin collection</returns>
|
||||||
protected InputPinCollection<T> CreateInputPinCollection<T>(string name = "", int initialCount = 1)
|
protected InputPinCollection<T> CreateInputPinCollection<T>(string name = "", int initialCount = 1)
|
||||||
{
|
{
|
||||||
InputPinCollection<T> pin = new(this, name, initialCount);
|
InputPinCollection<T> pin = new(this, name, initialCount);
|
||||||
@ -130,6 +182,13 @@ namespace Artemis.Core
|
|||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new input pin collection and adds it to the <see cref="PinCollections" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">The type of value the pins of this collection will hold</param>
|
||||||
|
/// <param name="name">The name of the pin collection</param>
|
||||||
|
/// <param name="initialCount">The amount of pins to initially add to the collection</param>
|
||||||
|
/// <returns>The resulting input pin collection</returns>
|
||||||
protected InputPinCollection CreateInputPinCollection(Type type, string name = "", int initialCount = 1)
|
protected InputPinCollection CreateInputPinCollection(Type type, string name = "", int initialCount = 1)
|
||||||
{
|
{
|
||||||
InputPinCollection pin = new(this, type, name, initialCount);
|
InputPinCollection pin = new(this, type, name, initialCount);
|
||||||
@ -138,6 +197,13 @@ namespace Artemis.Core
|
|||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new output pin collection and adds it to the <see cref="PinCollections" /> collection
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of value the pins of this collection will hold</typeparam>
|
||||||
|
/// <param name="name">The name of the pin collection</param>
|
||||||
|
/// <param name="initialCount">The amount of pins to initially add to the collection</param>
|
||||||
|
/// <returns>The resulting output pin collection</returns>
|
||||||
protected OutputPinCollection<T> CreateOutputPinCollection<T>(string name = "", int initialCount = 1)
|
protected OutputPinCollection<T> CreateOutputPinCollection<T>(string name = "", int initialCount = 1)
|
||||||
{
|
{
|
||||||
OutputPinCollection<T> pin = new(this, name, initialCount);
|
OutputPinCollection<T> pin = new(this, name, initialCount);
|
||||||
@ -146,12 +212,18 @@ namespace Artemis.Core
|
|||||||
return pin;
|
return pin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes the provided <paramref name="pinCollection" /> from the node and it's <see cref="PinCollections" />
|
||||||
|
/// collection
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pinCollection">The pin collection to remove</param>
|
||||||
|
/// <returns><see langword="true" /> if the pin collection was removed; otherwise <see langword="false" />.</returns>
|
||||||
protected bool RemovePinCollection(PinCollection pinCollection)
|
protected bool RemovePinCollection(PinCollection pinCollection)
|
||||||
{
|
{
|
||||||
bool isRemoved = _pinCollections.Remove(pinCollection);
|
bool isRemoved = _pinCollections.Remove(pinCollection);
|
||||||
if (isRemoved)
|
if (isRemoved)
|
||||||
{
|
{
|
||||||
foreach (IPin pin in pinCollection)
|
foreach (IPin pin in pinCollection)
|
||||||
pin.DisconnectAll();
|
pin.DisconnectAll();
|
||||||
OnPropertyChanged(nameof(PinCollections));
|
OnPropertyChanged(nameof(PinCollections));
|
||||||
}
|
}
|
||||||
@ -159,51 +231,122 @@ namespace Artemis.Core
|
|||||||
return isRemoved;
|
return isRemoved;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public virtual void Initialize(INodeScript script)
|
public virtual void Initialize(INodeScript script)
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract void Evaluate();
|
public abstract void Evaluate();
|
||||||
|
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public virtual void Reset()
|
public virtual void Reset()
|
||||||
{
|
{
|
||||||
Resetting?.Invoke(this, new EventArgs());
|
Resetting?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called whenever the node must show it's custom view model, if <see langword="null" />, no custom view model is used
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The custom view model, if <see langword="null" />, no custom view model is used</returns>
|
||||||
|
public virtual ICustomNodeViewModel? GetCustomViewModel()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serializes the <see cref="Storage" /> object into a string
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The serialized object</returns>
|
||||||
|
internal virtual string SerializeStorage()
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes the <see cref="Storage" /> object and sets it
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="serialized">The serialized object</param>
|
||||||
|
internal virtual void DeserializeStorage(string serialized)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class Node<T> : CustomViewModelNode where T : ICustomNodeViewModel
|
/// <summary>
|
||||||
|
/// Represents a kind of node inside a <see cref="NodeScript" /> containing storage value of type
|
||||||
|
/// <typeparamref name="TStorage" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TStorage">The type of value the node stores</typeparam>
|
||||||
|
public abstract class Node<TStorage> : Node
|
||||||
{
|
{
|
||||||
|
private TStorage? _storage;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected Node()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected Node(string name, string description) : base(name, description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the storage object of this node, this is saved across sessions
|
||||||
|
/// </summary>
|
||||||
|
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<TStorage>(serialized) ?? default(TStorage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a kind of node inside a <see cref="NodeScript" /> containing storage value of type
|
||||||
|
/// <typeparamref name="TStorage" /> and a view model of type <typeparamref name="TViewModel" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TStorage">The type of value the node stores</typeparam>
|
||||||
|
/// <typeparam name="TViewModel">The type of view model the node uses</typeparam>
|
||||||
|
public abstract class Node<TStorage, TViewModel> : Node<TStorage> where TViewModel : ICustomNodeViewModel
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected Node()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected Node(string name, string description) : base(name, description)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[Inject]
|
[Inject]
|
||||||
internal IKernel Kernel { get; set; } = null!;
|
internal IKernel Kernel { get; set; } = null!;
|
||||||
|
|
||||||
protected Node()
|
/// <summary>
|
||||||
{ }
|
/// Called when a view model is required
|
||||||
|
/// </summary>
|
||||||
protected Node(string name, string description) : base(name, description)
|
public virtual TViewModel GetViewModel()
|
||||||
{ }
|
|
||||||
|
|
||||||
public virtual T GetViewModel()
|
|
||||||
{
|
{
|
||||||
return Kernel.Get<T>(new ConstructorArgument("node", this));
|
return Kernel.Get<TViewModel>(new ConstructorArgument("node", this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override ICustomNodeViewModel GetCustomViewModel()
|
public override ICustomNodeViewModel GetCustomViewModel()
|
||||||
{
|
{
|
||||||
return GetViewModel();
|
return GetViewModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract class CustomViewModelNode : Node
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected CustomViewModelNode()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
protected CustomViewModelNode(string name, string description) : base(name, description)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
public abstract ICustomNodeViewModel GetCustomViewModel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -9,6 +9,9 @@ using Artemis.Storage.Entities.Profile.Nodes;
|
|||||||
|
|
||||||
namespace Artemis.Core
|
namespace Artemis.Core
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a node script
|
||||||
|
/// </summary>
|
||||||
public abstract class NodeScript : CorePropertyChanged, INodeScript, IStorageModel
|
public abstract class NodeScript : CorePropertyChanged, INodeScript, IStorageModel
|
||||||
{
|
{
|
||||||
private void NodeTypeStoreOnNodeTypeChanged(object? sender, NodeTypeStoreEvent e)
|
private void NodeTypeStoreOnNodeTypeChanged(object? sender, NodeTypeStoreEvent e)
|
||||||
@ -16,23 +19,41 @@ namespace Artemis.Core
|
|||||||
Load();
|
Load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public event EventHandler<SingleValueEventArgs<INode>>? NodeAdded;
|
public event EventHandler<SingleValueEventArgs<INode>>? NodeAdded;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public event EventHandler<SingleValueEventArgs<INode>>? NodeRemoved;
|
public event EventHandler<SingleValueEventArgs<INode>>? NodeRemoved;
|
||||||
|
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
internal NodeScriptEntity Entity { get; }
|
internal NodeScriptEntity Entity { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public string Description { get; }
|
public string Description { get; }
|
||||||
|
|
||||||
private readonly List<INode> _nodes = new();
|
private readonly List<INode> _nodes = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public IEnumerable<INode> Nodes => new ReadOnlyCollection<INode>(_nodes);
|
public IEnumerable<INode> Nodes => new ReadOnlyCollection<INode>(_nodes);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the exit node of the script
|
||||||
|
/// </summary>
|
||||||
protected INode ExitNode { get; set; }
|
protected INode ExitNode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a boolean indicating whether the exit node is connected to any other nodes
|
||||||
|
/// </summary>
|
||||||
public abstract bool ExitNodeConnected { get; }
|
public abstract bool ExitNodeConnected { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public abstract Type ResultType { get; }
|
public abstract Type ResultType { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public object? Context { get; set; }
|
public object? Context { get; set; }
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -65,6 +86,7 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
foreach (INode node in Nodes)
|
foreach (INode node in Nodes)
|
||||||
@ -73,6 +95,7 @@ namespace Artemis.Core
|
|||||||
ExitNode.Evaluate();
|
ExitNode.Evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public void AddNode(INode node)
|
public void AddNode(INode node)
|
||||||
{
|
{
|
||||||
_nodes.Add(node);
|
_nodes.Add(node);
|
||||||
@ -80,6 +103,7 @@ namespace Artemis.Core
|
|||||||
NodeAdded?.Invoke(this, new SingleValueEventArgs<INode>(node));
|
NodeAdded?.Invoke(this, new SingleValueEventArgs<INode>(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public void RemoveNode(INode node)
|
public void RemoveNode(INode node)
|
||||||
{
|
{
|
||||||
_nodes.Remove(node);
|
_nodes.Remove(node);
|
||||||
@ -90,6 +114,7 @@ namespace Artemis.Core
|
|||||||
NodeRemoved?.Invoke(this, new SingleValueEventArgs<INode>(node));
|
NodeRemoved?.Invoke(this, new SingleValueEventArgs<INode>(node));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
NodeTypeStore.NodeTypeAdded -= NodeTypeStoreOnNodeTypeChanged;
|
NodeTypeStore.NodeTypeAdded -= NodeTypeStoreOnNodeTypeChanged;
|
||||||
@ -147,9 +172,7 @@ namespace Artemis.Core
|
|||||||
// Restore pin collections
|
// Restore pin collections
|
||||||
foreach (NodePinCollectionEntity entityNodePinCollection in nodeEntity.PinCollections)
|
foreach (NodePinCollectionEntity entityNodePinCollection in nodeEntity.PinCollections)
|
||||||
{
|
{
|
||||||
IPinCollection? collection = node.PinCollections.FirstOrDefault(c => c.Name == entityNodePinCollection.Name &&
|
IPinCollection? collection = node.PinCollections.ElementAtOrDefault(entityNodePinCollection.Id);
|
||||||
c.Type.Name == entityNodePinCollection.Type &&
|
|
||||||
(int) c.Direction == entityNodePinCollection.Direction);
|
|
||||||
if (collection == null)
|
if (collection == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -161,12 +184,12 @@ namespace Artemis.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Loads missing connections between the nodes of this node script from the <see cref="Entity"/>
|
/// Loads missing connections between the nodes of this node script from the <see cref="Entity" />
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void LoadConnections()
|
public void LoadConnections()
|
||||||
{
|
{
|
||||||
List<INode> nodes = Nodes.ToList();
|
List<INode> 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);
|
INode? source = nodes.ElementAtOrDefault(nodeConnectionEntity.SourceNode);
|
||||||
if (source == null)
|
if (source == null)
|
||||||
@ -191,15 +214,12 @@ namespace Artemis.Core
|
|||||||
|
|
||||||
// Clear existing connections on input pins, we don't want none of that now
|
// Clear existing connections on input pins, we don't want none of that now
|
||||||
if (targetPin.Direction == PinDirection.Input)
|
if (targetPin.Direction == PinDirection.Input)
|
||||||
{
|
|
||||||
while (targetPin.ConnectedTo.Any())
|
while (targetPin.ConnectedTo.Any())
|
||||||
targetPin.DisconnectFrom(targetPin.ConnectedTo[0]);
|
targetPin.DisconnectFrom(targetPin.ConnectedTo[0]);
|
||||||
}
|
|
||||||
if (sourcePin.Direction == PinDirection.Input)
|
if (sourcePin.Direction == PinDirection.Input)
|
||||||
{
|
while (sourcePin.ConnectedTo.Any())
|
||||||
while (sourcePin.ConnectedTo.Any())
|
|
||||||
sourcePin.DisconnectFrom(sourcePin.ConnectedTo[0]);
|
sourcePin.DisconnectFrom(sourcePin.ConnectedTo[0]);
|
||||||
}
|
|
||||||
|
|
||||||
// Only connect the nodes if they aren't already connected (LoadConnections may be called twice or more)
|
// Only connect the nodes if they aren't already connected (LoadConnections may be called twice or more)
|
||||||
if (!targetPin.ConnectedTo.Contains(sourcePin))
|
if (!targetPin.ConnectedTo.Contains(sourcePin))
|
||||||
@ -231,21 +251,24 @@ namespace Artemis.Core
|
|||||||
Type = node.GetType().Name,
|
Type = node.GetType().Name,
|
||||||
X = node.X,
|
X = node.X,
|
||||||
Y = node.Y,
|
Y = node.Y,
|
||||||
Storage = CoreJson.SerializeObject(node.Storage, true),
|
|
||||||
Name = node.Name,
|
Name = node.Name,
|
||||||
Description = node.Description,
|
Description = node.Description,
|
||||||
IsExitNode = node.IsExitNode
|
IsExitNode = node.IsExitNode
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (node is Node nodeImplementation)
|
||||||
|
nodeEntity.Storage = nodeImplementation.SerializeStorage();
|
||||||
|
|
||||||
|
int collectionId = 0;
|
||||||
foreach (IPinCollection nodePinCollection in node.PinCollections)
|
foreach (IPinCollection nodePinCollection in node.PinCollections)
|
||||||
{
|
{
|
||||||
nodeEntity.PinCollections.Add(new NodePinCollectionEntity
|
nodeEntity.PinCollections.Add(new NodePinCollectionEntity
|
||||||
{
|
{
|
||||||
Name = nodePinCollection.Name,
|
Id = collectionId,
|
||||||
Type = nodePinCollection.Type.Name,
|
|
||||||
Direction = (int) nodePinCollection.Direction,
|
Direction = (int) nodePinCollection.Direction,
|
||||||
Amount = nodePinCollection.Count()
|
Amount = nodePinCollection.Count()
|
||||||
});
|
});
|
||||||
|
collectionId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity.Nodes.Add(nodeEntity);
|
Entity.Nodes.Add(nodeEntity);
|
||||||
@ -309,13 +332,21 @@ namespace Artemis.Core
|
|||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a node script with a result value of type <paramref name="T" />
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type of result value</typeparam>
|
||||||
public class NodeScript<T> : NodeScript, INodeScript<T>
|
public class NodeScript<T> : NodeScript, INodeScript<T>
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public T Result => ((ExitNode<T>) ExitNode).Value;
|
public T Result => ((ExitNode<T>) ExitNode).Value;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override bool ExitNodeConnected => ((ExitNode<T>) ExitNode).Input.ConnectedTo.Any();
|
public override bool ExitNodeConnected => ((ExitNode<T>) ExitNode).Input.ConnectedTo.Any();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public override Type ResultType => typeof(T);
|
public override Type ResultType => typeof(T);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -2,8 +2,7 @@
|
|||||||
{
|
{
|
||||||
public class NodePinCollectionEntity
|
public class NodePinCollectionEntity
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public int Id { get; set; }
|
||||||
public string Type { get; set; }
|
|
||||||
public int Direction { set; get; }
|
public int Direction { set; get; }
|
||||||
public int Amount { get; set; }
|
public int Amount { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -155,10 +155,10 @@ namespace Artemis.VisualScripting.Editor.Controls
|
|||||||
{
|
{
|
||||||
CustomViewModel?.OnDeactivate();
|
CustomViewModel?.OnDeactivate();
|
||||||
|
|
||||||
if (Node?.Node is CustomViewModelNode customViewModelNode)
|
if (Node?.Node is Node customViewModelNode)
|
||||||
{
|
{
|
||||||
CustomViewModel = customViewModelNode.GetCustomViewModel();
|
CustomViewModel = customViewModelNode.GetCustomViewModel();
|
||||||
CustomViewModel.OnActivate();
|
CustomViewModel?.OnActivate();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CustomViewModel = null;
|
CustomViewModel = null;
|
||||||
|
|||||||
@ -1,38 +1,11 @@
|
|||||||
using System.ComponentModel;
|
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
|
||||||
using SkiaSharp;
|
|
||||||
|
|
||||||
namespace Artemis.VisualScripting.Nodes.Color.CustomViewModels
|
namespace Artemis.VisualScripting.Nodes.Color.CustomViewModels
|
||||||
{
|
{
|
||||||
public class StaticSKColorValueNodeCustomViewModel : CustomNodeViewModel
|
public class StaticSKColorValueNodeCustomViewModel : CustomNodeViewModel
|
||||||
{
|
{
|
||||||
private readonly StaticSKColorValueNode _node;
|
|
||||||
|
|
||||||
public StaticSKColorValueNodeCustomViewModel(StaticSKColorValueNode node) : base(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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,5 +12,5 @@
|
|||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<shared:ColorPicker VerticalAlignment="Center"
|
<shared:ColorPicker VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Color="{Binding Input, Converter={StaticResource SKColorToColorConverter}}" />
|
Color="{Binding Node.Storage, Converter={StaticResource SKColorToColorConverter}}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -5,7 +5,7 @@ using SkiaSharp;
|
|||||||
namespace Artemis.VisualScripting.Nodes.Color
|
namespace Artemis.VisualScripting.Nodes.Color
|
||||||
{
|
{
|
||||||
[Node("Color-Value", "Outputs a configurable color value.", "Static", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
[Node("Color-Value", "Outputs a configurable color value.", "Static", InputType = typeof(SKColor), OutputType = typeof(SKColor))]
|
||||||
public class StaticSKColorValueNode : Node<StaticSKColorValueNodeCustomViewModel>
|
public class StaticSKColorValueNode : Node<SKColor, StaticSKColorValueNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
@ -27,17 +27,9 @@ namespace Artemis.VisualScripting.Nodes.Color
|
|||||||
|
|
||||||
public override void Evaluate()
|
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
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,6 +1,4 @@
|
|||||||
using System;
|
using Artemis.Core;
|
||||||
using System.ComponentModel;
|
|
||||||
using Artemis.Core;
|
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
using Artemis.UI.Shared;
|
using Artemis.UI.Shared;
|
||||||
using Stylet;
|
using Stylet;
|
||||||
@ -16,19 +14,12 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
|||||||
_node = node;
|
_node = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Enum Input
|
|
||||||
{
|
|
||||||
get => _node.Storage as Enum;
|
|
||||||
set => _node.Storage = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BindableCollection<ValueDescription> EnumValues { get; } = new();
|
public BindableCollection<ValueDescription> EnumValues { get; } = new();
|
||||||
|
|
||||||
public override void OnActivate()
|
public override void OnActivate()
|
||||||
{
|
{
|
||||||
_node.InputPin.PinConnected += InputPinOnPinConnected;
|
_node.InputPin.PinConnected += InputPinOnPinConnected;
|
||||||
_node.InputPin.PinDisconnected += InputPinOnPinDisconnected;
|
_node.InputPin.PinDisconnected += InputPinOnPinDisconnected;
|
||||||
_node.PropertyChanged += NodeOnPropertyChanged;
|
|
||||||
|
|
||||||
if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
||||||
EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
||||||
@ -39,7 +30,6 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
|||||||
{
|
{
|
||||||
_node.InputPin.PinConnected -= InputPinOnPinConnected;
|
_node.InputPin.PinConnected -= InputPinOnPinConnected;
|
||||||
_node.InputPin.PinDisconnected -= InputPinOnPinDisconnected;
|
_node.InputPin.PinDisconnected -= InputPinOnPinDisconnected;
|
||||||
_node.PropertyChanged -= NodeOnPropertyChanged;
|
|
||||||
|
|
||||||
base.OnDeactivate();
|
base.OnDeactivate();
|
||||||
}
|
}
|
||||||
@ -55,11 +45,5 @@ namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
|||||||
if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
if (_node.InputPin.Value != null && _node.InputPin.Value.GetType().IsEnum)
|
||||||
EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
EnumValues.AddRange(EnumUtilities.GetAllValuesAndDescriptions(_node.InputPin.Value.GetType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NodeOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.PropertyName == nameof(Node.Storage))
|
|
||||||
OnPropertyChanged(nameof(Input));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,132 +1,32 @@
|
|||||||
using System.ComponentModel;
|
using Artemis.Core;
|
||||||
|
|
||||||
namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
namespace Artemis.VisualScripting.Nodes.CustomViewModels
|
||||||
{
|
{
|
||||||
public class StaticDoubleValueNodeCustomViewModel : CustomNodeViewModel
|
public class StaticDoubleValueNodeCustomViewModel : CustomNodeViewModel
|
||||||
{
|
{
|
||||||
private readonly StaticDoubleValueNode _node;
|
public StaticDoubleValueNodeCustomViewModel(INode node) : base(node)
|
||||||
|
|
||||||
public StaticDoubleValueNodeCustomViewModel(StaticDoubleValueNode 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
|
public class StaticFloatValueNodeCustomViewModel : CustomNodeViewModel
|
||||||
{
|
{
|
||||||
private readonly StaticFloatValueNode _node;
|
public StaticFloatValueNodeCustomViewModel(INode node) : base(node)
|
||||||
|
|
||||||
public StaticFloatValueNodeCustomViewModel(StaticFloatValueNode 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
|
public class StaticIntegerValueNodeCustomViewModel : CustomNodeViewModel
|
||||||
{
|
{
|
||||||
private readonly StaticIntegerValueNode _node;
|
public StaticIntegerValueNodeCustomViewModel(INode node) : base(node)
|
||||||
|
|
||||||
public StaticIntegerValueNodeCustomViewModel(StaticIntegerValueNode 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
|
public class StaticStringValueNodeCustomViewModel : CustomNodeViewModel
|
||||||
{
|
{
|
||||||
private readonly StaticStringValueNode _node;
|
public StaticStringValueNodeCustomViewModel(INode node) : base(node)
|
||||||
|
|
||||||
public StaticStringValueNodeCustomViewModel(StaticStringValueNode 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -12,7 +12,7 @@
|
|||||||
materialDesign:ComboBoxAssist.ClassicMode="True"
|
materialDesign:ComboBoxAssist.ClassicMode="True"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
SelectedValue="{Binding Input}"
|
SelectedValue="{Binding Node.Storage}"
|
||||||
ItemsSource="{Binding EnumValues}"
|
ItemsSource="{Binding EnumValues}"
|
||||||
SelectedValuePath="Value"
|
SelectedValuePath="Value"
|
||||||
DisplayMemberPath="Description">
|
DisplayMemberPath="Description">
|
||||||
|
|||||||
@ -8,5 +8,5 @@
|
|||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<TextBox VerticalAlignment="Center"
|
<TextBox VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Text="{Binding Input}" />
|
Text="{Binding Node.Storage}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -8,5 +8,5 @@
|
|||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<TextBox VerticalAlignment="Center"
|
<TextBox VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Text="{Binding Input}" />
|
Text="{Binding Node.Storage}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -8,5 +8,5 @@
|
|||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<TextBox VerticalAlignment="Center"
|
<TextBox VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Text="{Binding Input}" />
|
Text="{Binding Node.Storage}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -8,5 +8,5 @@
|
|||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<TextBox VerticalAlignment="Center"
|
<TextBox VerticalAlignment="Center"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Text="{Binding Input}" />
|
Text="{Binding Node.Storage}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Events;
|
using Artemis.Core.Events;
|
||||||
@ -8,19 +9,69 @@ using Artemis.VisualScripting.Nodes.DataModel.CustomViewModels;
|
|||||||
namespace Artemis.VisualScripting.Nodes.DataModel
|
namespace Artemis.VisualScripting.Nodes.DataModel
|
||||||
{
|
{
|
||||||
[Node("Data Model-Event", "Responds to a data model event trigger", "External", OutputType = typeof(bool))]
|
[Node("Data Model-Event", "Responds to a data model event trigger", "External", OutputType = typeof(bool))]
|
||||||
public class DataModelEventNode : Node<DataModelEventNodeCustomViewModel>, IDisposable
|
public class DataModelEventNode : Node<DataModelPathEntity, DataModelEventNodeCustomViewModel>, IDisposable
|
||||||
{
|
{
|
||||||
private DataModelPath _dataModelPath;
|
private DataModelPath _dataModelPath;
|
||||||
private DateTime _lastTrigger;
|
private DateTime _lastTrigger;
|
||||||
private int _currentIndex;
|
private int _currentIndex;
|
||||||
|
private Type _currentType;
|
||||||
|
private bool _updating;
|
||||||
|
|
||||||
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
public DataModelEventNode() : base("Data Model-Event", "Responds to a data model event trigger")
|
||||||
{
|
{
|
||||||
Input = CreateInputPin<object>();
|
_currentType = typeof(object);
|
||||||
Input.PinConnected += InputOnPinConnected;
|
CreateCycleValues(typeof(object), 1);
|
||||||
|
Output = CreateOutputPin(typeof(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputPin<object> 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<IPin> e)
|
||||||
|
{
|
||||||
|
e.Value.PinConnected += OnPinConnected;
|
||||||
|
e.Value.PinDisconnected += OnPinDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CycleValuesOnPinRemoved(object sender, SingleValueEventArgs<IPin> e)
|
||||||
|
{
|
||||||
|
e.Value.PinConnected -= OnPinConnected;
|
||||||
|
e.Value.PinDisconnected -= OnPinDisconnected;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPinDisconnected(object sender, SingleValueEventArgs<IPin> e)
|
||||||
|
{
|
||||||
|
ProcessPinDisconnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPinConnected(object sender, SingleValueEventArgs<IPin> e)
|
||||||
|
{
|
||||||
|
IPin source = e.Value;
|
||||||
|
IPin target = (IPin) sender;
|
||||||
|
ProcessPinConnected(source, target);
|
||||||
|
}
|
||||||
|
|
||||||
public InputPinCollection CycleValues { get; set; }
|
public InputPinCollection CycleValues { get; set; }
|
||||||
public OutputPin Output { get; set; }
|
public OutputPin Output { get; set; }
|
||||||
@ -35,70 +86,101 @@ namespace Artemis.VisualScripting.Nodes.DataModel
|
|||||||
public override void Initialize(INodeScript script)
|
public override void Initialize(INodeScript script)
|
||||||
{
|
{
|
||||||
Script = script;
|
Script = script;
|
||||||
CreateCycleValues();
|
|
||||||
CreateOutput();
|
|
||||||
|
|
||||||
if (Storage is not DataModelPathEntity pathEntity)
|
if (Storage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DataModelPath = new DataModelPath(pathEntity);
|
DataModelPath = new DataModelPath(Storage);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
object outputValue = null;
|
object outputValue = null;
|
||||||
if (DataModelPath?.GetValue() is DataModelEvent dataModelEvent)
|
if (DataModelPath?.GetValue() is IDataModelEvent dataModelEvent)
|
||||||
{
|
{
|
||||||
if (dataModelEvent.LastTrigger > _lastTrigger)
|
if (dataModelEvent.LastTrigger > _lastTrigger)
|
||||||
{
|
{
|
||||||
_lastTrigger = dataModelEvent.LastTrigger;
|
_lastTrigger = dataModelEvent.LastTrigger;
|
||||||
_currentIndex++;
|
_currentIndex++;
|
||||||
|
|
||||||
if (_currentIndex > CycleValues.Count())
|
if (_currentIndex >= CycleValues.Count())
|
||||||
_currentIndex = 0;
|
_currentIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
outputValue = _currentIndex == 0
|
outputValue = CycleValues.ElementAt(_currentIndex).PinValue;
|
||||||
? Input.Value
|
|
||||||
: CycleValues.ElementAt(_currentIndex - 1).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<IPin> e)
|
private void ProcessPinConnected(IPin source, IPin target)
|
||||||
{
|
{
|
||||||
CreateCycleValues();
|
if (_updating)
|
||||||
CreateOutput();
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateCycleValues()
|
try
|
||||||
{
|
|
||||||
int pinCount = CycleValues?.Count() ?? 1;
|
|
||||||
Type inputType = Input.ConnectedTo.FirstOrDefault()?.Type ?? typeof(object);
|
|
||||||
|
|
||||||
if (CycleValues != null)
|
|
||||||
{
|
{
|
||||||
if (inputType == CycleValues.Type)
|
_updating = true;
|
||||||
return;
|
|
||||||
RemovePinCollection(CycleValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
CreateCycleValues(type, CycleValues.Count());
|
||||||
|
|
||||||
if (Output != null)
|
List<IPin> 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)
|
oldOutputConnection.DisconnectAll();
|
||||||
return;
|
oldOutputConnection.ConnectTo(Output);
|
||||||
RemovePin(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)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@ -7,7 +7,7 @@ using Stylet;
|
|||||||
namespace Artemis.VisualScripting.Nodes.DataModel
|
namespace Artemis.VisualScripting.Nodes.DataModel
|
||||||
{
|
{
|
||||||
[Node("Data Model-Value", "Outputs a selectable data model value.", "External")]
|
[Node("Data Model-Value", "Outputs a selectable data model value.", "External")]
|
||||||
public class DataModelNode : Node<DataModelNodeCustomViewModel>, IDisposable
|
public class DataModelNode : Node<DataModelPathEntity, DataModelNodeCustomViewModel>, IDisposable
|
||||||
{
|
{
|
||||||
private DataModelPath _dataModelPath;
|
private DataModelPath _dataModelPath;
|
||||||
|
|
||||||
@ -28,10 +28,10 @@ namespace Artemis.VisualScripting.Nodes.DataModel
|
|||||||
{
|
{
|
||||||
Script = script;
|
Script = script;
|
||||||
|
|
||||||
if (Storage is not DataModelPathEntity pathEntity)
|
if (Storage == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DataModelPath = new DataModelPath(pathEntity);
|
DataModelPath = new DataModelPath(Storage);
|
||||||
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
DataModelPath.PathValidated += DataModelPathOnPathValidated;
|
||||||
|
|
||||||
UpdateOutputPin(false);
|
UpdateOutputPin(false);
|
||||||
|
|||||||
@ -15,9 +15,7 @@ namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels
|
|||||||
public EasingTypeNodeCustomViewModel(EasingTypeNode node) : base(node)
|
public EasingTypeNodeCustomViewModel(EasingTypeNode node) : base(node)
|
||||||
{
|
{
|
||||||
_node = node;
|
_node = node;
|
||||||
EasingViewModels = new BindableCollection<NodeEasingViewModel>(Enum.GetValues(typeof(Easings.Functions))
|
EasingViewModels = new BindableCollection<NodeEasingViewModel>(Enum.GetValues(typeof(Easings.Functions)).Cast<Easings.Functions>().Select(e => new NodeEasingViewModel(e)));
|
||||||
.Cast<Easings.Functions>()
|
|
||||||
.Select(e => new NodeEasingViewModel(e)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BindableCollection<NodeEasingViewModel> EasingViewModels { get; }
|
public BindableCollection<NodeEasingViewModel> EasingViewModels { get; }
|
||||||
@ -35,7 +33,7 @@ namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels
|
|||||||
public override void OnActivate()
|
public override void OnActivate()
|
||||||
{
|
{
|
||||||
_node.PropertyChanged += NodeOnPropertyChanged;
|
_node.PropertyChanged += NodeOnPropertyChanged;
|
||||||
SelectedEasingViewModel = EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.EasingFunction);
|
SelectedEasingViewModel = GetNodeEasingViewModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnDeactivate()
|
public override void OnDeactivate()
|
||||||
@ -45,11 +43,16 @@ namespace Artemis.VisualScripting.Nodes.Easing.CustomViewModels
|
|||||||
|
|
||||||
private void NodeOnPropertyChanged(object sender, PropertyChangedEventArgs e)
|
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));
|
NotifyOfPropertyChange(nameof(SelectedEasingViewModel));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private NodeEasingViewModel GetNodeEasingViewModel()
|
||||||
|
{
|
||||||
|
return EasingViewModels.FirstOrDefault(vm => vm.EasingFunction == _node.Storage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,7 +4,7 @@ using Artemis.VisualScripting.Nodes.Easing.CustomViewModels;
|
|||||||
namespace Artemis.VisualScripting.Nodes.Easing
|
namespace Artemis.VisualScripting.Nodes.Easing
|
||||||
{
|
{
|
||||||
[Node("Easing Type", "Outputs a selectable easing type.", "Easing", OutputType = typeof(Easings.Functions))]
|
[Node("Easing Type", "Outputs a selectable easing type.", "Easing", OutputType = typeof(Easings.Functions))]
|
||||||
public class EasingTypeNode : Node<EasingTypeNodeCustomViewModel>
|
public class EasingTypeNode : Node<Easings.Functions, EasingTypeNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.")
|
public EasingTypeNode() : base("Easing Type", "Outputs a selectable easing type.")
|
||||||
{
|
{
|
||||||
@ -12,11 +12,10 @@ namespace Artemis.VisualScripting.Nodes.Easing
|
|||||||
}
|
}
|
||||||
|
|
||||||
public OutputPin<Easings.Functions> Output { get; }
|
public OutputPin<Easings.Functions> Output { get; }
|
||||||
public Easings.Functions EasingFunction => Storage as Easings.Functions? ?? Easings.Functions.Linear;
|
|
||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
Output.Value = EasingFunction;
|
Output.Value = Storage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,12 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
using Artemis.Core;
|
using Artemis.Core;
|
||||||
using Artemis.Core.Events;
|
|
||||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||||
|
|
||||||
namespace Artemis.VisualScripting.Nodes
|
namespace Artemis.VisualScripting.Nodes
|
||||||
{
|
{
|
||||||
[Node("Enum Equals", "Determines the equality between an input and a selected enum value", InputType = typeof(Enum), OutputType = typeof(bool))]
|
[Node("Enum Equals", "Determines the equality between an input and a selected enum value", InputType = typeof(Enum), OutputType = typeof(bool))]
|
||||||
public class EnumEqualsNode : Node<EnumEqualsNodeCustomViewModel>
|
public class EnumEqualsNode : Node<Enum, EnumEqualsNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
public EnumEqualsNode() : base("Enum Equals", "Determines the equality between an input and a selected enum value")
|
public EnumEqualsNode() : base("Enum Equals", "Determines the equality between an input and a selected enum value")
|
||||||
{
|
{
|
||||||
|
|||||||
@ -7,7 +7,7 @@ using Artemis.VisualScripting.Nodes.CustomViewModels;
|
|||||||
namespace Artemis.VisualScripting.Nodes
|
namespace Artemis.VisualScripting.Nodes
|
||||||
{
|
{
|
||||||
[Node("Layer/Folder Property", "Outputs the property of a selected layer or folder", "External")]
|
[Node("Layer/Folder Property", "Outputs the property of a selected layer or folder", "External")]
|
||||||
public class LayerPropertyNode : Node<LayerPropertyNodeCustomViewModel>
|
public class LayerPropertyNode : Node<LayerPropertyNodeEntity, LayerPropertyNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
private readonly object _layerPropertyLock = new();
|
private readonly object _layerPropertyLock = new();
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
{
|
{
|
||||||
Script = script;
|
Script = script;
|
||||||
|
|
||||||
if (script.Context is Profile profile)
|
if (script.Context is Profile profile)
|
||||||
profile.ChildRemoved += ProfileOnChildRemoved;
|
profile.ChildRemoved += ProfileOnChildRemoved;
|
||||||
|
|
||||||
LoadLayerProperty();
|
LoadLayerProperty();
|
||||||
@ -54,15 +54,13 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
{
|
{
|
||||||
lock (_layerPropertyLock)
|
lock (_layerPropertyLock)
|
||||||
{
|
{
|
||||||
if (Script.Context is not Profile profile)
|
if (Script.Context is not Profile profile || Storage == null)
|
||||||
return;
|
return;
|
||||||
if (Storage is not LayerPropertyNodeEntity entity)
|
|
||||||
return;
|
RenderProfileElement element = profile.GetAllRenderElements().FirstOrDefault(l => l.EntityId == Storage.ElementId);
|
||||||
|
|
||||||
RenderProfileElement element = profile.GetAllRenderElements().FirstOrDefault(l => l.EntityId == entity.ElementId);
|
|
||||||
|
|
||||||
ProfileElement = element;
|
ProfileElement = element;
|
||||||
LayerProperty = element?.GetAllLayerProperties().FirstOrDefault(p => p.Path == entity.PropertyPath);
|
LayerProperty = element?.GetAllLayerProperties().FirstOrDefault(p => p.Path == Storage.PropertyPath);
|
||||||
CreatePins();
|
CreatePins();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,37 +1,12 @@
|
|||||||
using System.ComponentModel;
|
using Artemis.Core;
|
||||||
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
using Artemis.VisualScripting.Nodes.CustomViewModels;
|
||||||
|
|
||||||
namespace Artemis.VisualScripting.Nodes.Maths.CustomViewModels
|
namespace Artemis.VisualScripting.Nodes.Maths.CustomViewModels
|
||||||
{
|
{
|
||||||
public class MathExpressionNodeCustomViewModel : CustomNodeViewModel
|
public class MathExpressionNodeCustomViewModel : CustomNodeViewModel
|
||||||
{
|
{
|
||||||
private readonly MathExpressionNode _node;
|
public MathExpressionNodeCustomViewModel(INode node) : base(node)
|
||||||
|
|
||||||
public MathExpressionNodeCustomViewModel(MathExpressionNode 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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -8,5 +8,5 @@
|
|||||||
d:DesignHeight="450" d:DesignWidth="800">
|
d:DesignHeight="450" d:DesignWidth="800">
|
||||||
<TextBox VerticalAlignment="Bottom"
|
<TextBox VerticalAlignment="Bottom"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
Text="{Binding Input}" />
|
Text="{Binding Node.Storage}" />
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -9,12 +9,13 @@ using NoStringEvaluating.Models.Values;
|
|||||||
namespace Artemis.VisualScripting.Nodes.Maths
|
namespace Artemis.VisualScripting.Nodes.Maths
|
||||||
{
|
{
|
||||||
[Node("Math Expression", "Outputs the result of a math expression.", "Math", OutputType = typeof(int))]
|
[Node("Math Expression", "Outputs the result of a math expression.", "Math", OutputType = typeof(int))]
|
||||||
public class MathExpressionNode : Node<MathExpressionNodeCustomViewModel>
|
public class MathExpressionNode : Node<string, MathExpressionNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
private readonly INoStringEvaluator _evaluator;
|
private readonly INoStringEvaluator _evaluator;
|
||||||
private readonly PinsVariablesContainer _variables;
|
private readonly PinsVariablesContainer _variables;
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|
||||||
public MathExpressionNode(INoStringEvaluator evaluator)
|
public MathExpressionNode(INoStringEvaluator evaluator)
|
||||||
: base("Math Expression", "Outputs the result of a math expression.")
|
: base("Math Expression", "Outputs the result of a math expression.")
|
||||||
{
|
{
|
||||||
@ -24,7 +25,7 @@ namespace Artemis.VisualScripting.Nodes.Maths
|
|||||||
Values.PinAdded += (_, _) => SetPinNames();
|
Values.PinAdded += (_, _) => SetPinNames();
|
||||||
Values.PinRemoved += (_, _) => SetPinNames();
|
Values.PinRemoved += (_, _) => SetPinNames();
|
||||||
_variables = new PinsVariablesContainer(Values);
|
_variables = new PinsVariablesContainer(Values);
|
||||||
|
|
||||||
SetPinNames();
|
SetPinNames();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,8 +42,8 @@ namespace Artemis.VisualScripting.Nodes.Maths
|
|||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
if (Storage is string formula)
|
if (Storage != null)
|
||||||
Output.Value = (float) _evaluator.CalcNumber(formula, _variables);
|
Output.Value = (float) _evaluator.CalcNumber(Storage, _variables);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetPinNames()
|
private void SetPinNames()
|
||||||
|
|||||||
@ -4,7 +4,7 @@ using Artemis.VisualScripting.Nodes.CustomViewModels;
|
|||||||
namespace Artemis.VisualScripting.Nodes
|
namespace Artemis.VisualScripting.Nodes
|
||||||
{
|
{
|
||||||
[Node("Integer-Value", "Outputs an configurable integer value.", "Static", OutputType = typeof(int))]
|
[Node("Integer-Value", "Outputs an configurable integer value.", "Static", OutputType = typeof(int))]
|
||||||
public class StaticIntegerValueNode : Node<StaticIntegerValueNodeCustomViewModel>
|
public class StaticIntegerValueNode : Node<int, StaticIntegerValueNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
@ -26,16 +26,14 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
Output.Value = Storage as int? ?? 0;
|
Output.Value = Storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize(INodeScript script) => Storage ??= 0;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
[Node("Double-Value", "Outputs a configurable double value.", "Static", OutputType = typeof(double))]
|
[Node("Double-Value", "Outputs a configurable double value.", "Static", OutputType = typeof(double))]
|
||||||
public class StaticDoubleValueNode : Node<StaticDoubleValueNodeCustomViewModel>
|
public class StaticDoubleValueNode : Node<double, StaticDoubleValueNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
@ -60,13 +58,11 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
Output.Value = Storage as double? ?? 0.0;
|
Output.Value = Storage as double? ?? 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize(INodeScript script) => Storage ??= 0.0;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
[Node("Float-Value", "Outputs a configurable float value.", "Static", OutputType = typeof(float))]
|
[Node("Float-Value", "Outputs a configurable float value.", "Static", OutputType = typeof(float))]
|
||||||
public class StaticFloatValueNode : Node<StaticFloatValueNodeCustomViewModel>
|
public class StaticFloatValueNode : Node<float, StaticFloatValueNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
@ -88,19 +84,14 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
if (Storage is double doubleValue)
|
Output.Value = Storage;
|
||||||
Storage = (float) doubleValue;
|
|
||||||
|
|
||||||
Output.Value = Storage as float? ?? 0.0f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Initialize(INodeScript script) => Storage ??= 0.0f;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
[Node("String-Value", "Outputs a configurable string value.", "Static", OutputType = typeof(string))]
|
[Node("String-Value", "Outputs a configurable string value.", "Static", OutputType = typeof(string))]
|
||||||
public class StaticStringValueNode : Node<StaticStringValueNodeCustomViewModel>
|
public class StaticStringValueNode : Node<string, StaticStringValueNodeCustomViewModel>
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
@ -122,7 +113,7 @@ namespace Artemis.VisualScripting.Nodes
|
|||||||
|
|
||||||
public override void Evaluate()
|
public override void Evaluate()
|
||||||
{
|
{
|
||||||
Output.Value = Storage as string;
|
Output.Value = Storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user