mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Nodes - Added XML docs for remaining types
Nodes - Fully implemented nullable reference types
This commit is contained in:
parent
c1dab91c16
commit
c21acf87a7
@ -93,6 +93,13 @@ namespace Artemis.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the index of the provided element inside the read only collection
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of element to find</typeparam>
|
||||
/// <param name="self">The collection to search in</param>
|
||||
/// <param name="elementToFind">The element to find</param>
|
||||
/// <returns>If found, the index of the element to find; otherwise -1</returns>
|
||||
public static int IndexOf<T>(this IReadOnlyCollection<T> self, T elementToFind)
|
||||
{
|
||||
int i = 0;
|
||||
@ -102,6 +109,7 @@ namespace Artemis.Core
|
||||
return i;
|
||||
i++;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,6 +6,9 @@ using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a condition that is based on a <see cref="DataModelEvent" />
|
||||
/// </summary>
|
||||
public class EventCondition : CorePropertyChanged, INodeScriptCondition
|
||||
{
|
||||
private readonly string _displayName;
|
||||
@ -78,7 +81,7 @@ namespace Artemis.Core
|
||||
}
|
||||
else
|
||||
{
|
||||
_eventNode = new EventDefaultNode() {X = -300};
|
||||
_eventNode = new EventDefaultNode {X = -300};
|
||||
_eventNode.UpdateDataModelEvent(dataModelEvent);
|
||||
}
|
||||
|
||||
|
||||
@ -3,11 +3,17 @@ using Artemis.Storage.Entities.Profile.Conditions;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a condition that is based on a data model value
|
||||
/// </summary>
|
||||
public class StaticCondition : CorePropertyChanged, INodeScriptCondition
|
||||
{
|
||||
private readonly StaticConditionEntity _entity;
|
||||
private readonly string _displayName;
|
||||
private readonly StaticConditionEntity _entity;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="StaticCondition" /> class
|
||||
/// </summary>
|
||||
public StaticCondition(ProfileElement profileElement)
|
||||
{
|
||||
_entity = new StaticConditionEntity();
|
||||
|
||||
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a data model event that can trigger <see cref="DataModelConditionEvent" />s.
|
||||
/// Represents an event that is part of a data model
|
||||
/// </summary>
|
||||
public interface IDataModelEvent
|
||||
{
|
||||
|
||||
@ -82,7 +82,6 @@ namespace Artemis.Core
|
||||
|
||||
private TimeSpan _position;
|
||||
private TimeSpan _lastDelta;
|
||||
private TimeLineEventOverlapMode _eventOverlapMode;
|
||||
private TimelinePlayMode _playMode;
|
||||
private TimelineStopMode _stopMode;
|
||||
private readonly List<Timeline> _extraTimelines;
|
||||
|
||||
@ -114,17 +114,20 @@ namespace Artemis.Core.Modules
|
||||
private readonly List<(DefaultCategoryName, string)> _defaultProfilePaths = new();
|
||||
private readonly List<(DefaultCategoryName, string)> _pendingDefaultProfilePaths = new();
|
||||
|
||||
protected Module()
|
||||
{
|
||||
DefaultProfilePaths = new ReadOnlyCollection<(DefaultCategoryName, string)>(_defaultProfilePaths);
|
||||
HiddenProperties = new(HiddenPropertiesList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all properties ignored at runtime using <c>IgnoreProperty(x => x.y)</c>
|
||||
/// </summary>
|
||||
protected internal readonly List<PropertyInfo> HiddenPropertiesList = new();
|
||||
|
||||
/// <summary>
|
||||
/// The base constructor of the <see cref="Module" /> class.
|
||||
/// </summary>
|
||||
protected Module()
|
||||
{
|
||||
DefaultProfilePaths = new ReadOnlyCollection<(DefaultCategoryName, string)>(_defaultProfilePaths);
|
||||
HiddenProperties = new ReadOnlyCollection<PropertyInfo>(HiddenPropertiesList);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read only collection of default profile paths
|
||||
/// </summary>
|
||||
@ -237,7 +240,7 @@ namespace Artemis.Core.Modules
|
||||
/// <returns></returns>
|
||||
public virtual DataModelPropertyAttribute GetDataModelDescription()
|
||||
{
|
||||
return new() {Name = Plugin.Info.Name, Description = Plugin.Info.Description};
|
||||
return new DataModelPropertyAttribute {Name = Plugin.Info.Name, Description = Plugin.Info.Description};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -44,9 +44,12 @@ namespace Artemis.Core.ScriptingProviders
|
||||
/// </summary>
|
||||
public abstract class ScriptingProvider : PluginFeature
|
||||
{
|
||||
/// <summary>
|
||||
/// The base constructor of the <see cref="ScriptingProvider" /> class
|
||||
/// </summary>
|
||||
protected ScriptingProvider()
|
||||
{
|
||||
Scripts = new(InternalScripts);
|
||||
Scripts = new ReadOnlyCollection<Script>(InternalScripts);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@ -2,21 +2,28 @@
|
||||
|
||||
namespace Artemis.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an event argument containing a single value of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value the argument contains</typeparam>
|
||||
public class SingleValueEventArgs<T> : EventArgs
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public T Value { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public SingleValueEventArgs(T value)
|
||||
internal SingleValueEventArgs(T value)
|
||||
{
|
||||
this.Value = value;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the argument
|
||||
/// </summary>
|
||||
public T Value { get; }
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,42 +3,18 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an input pin containing a value of type <typeparamref name="T" /> on a <see cref="INode" />
|
||||
/// </summary>
|
||||
public sealed class InputPin<T> : Pin
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public override Type Type { get; } = typeof(T);
|
||||
public override object PinValue => Value;
|
||||
public override PinDirection Direction => PinDirection.Input;
|
||||
|
||||
private T _value;
|
||||
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsEvaluated)
|
||||
Evaluate();
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
private set
|
||||
{
|
||||
_value = value;
|
||||
IsEvaluated = true;
|
||||
OnPropertyChanged(nameof(PinValue));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
[JsonConstructor]
|
||||
internal InputPin(INode node, string name)
|
||||
: base(node, name)
|
||||
{
|
||||
Value = default;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -47,25 +23,29 @@ namespace Artemis.Core
|
||||
|
||||
private void Evaluate()
|
||||
{
|
||||
if (ConnectedTo.Count > 0)
|
||||
if (ConnectedTo[0].PinValue is T value)
|
||||
Value = value;
|
||||
if (ConnectedTo.Count > 0 && ConnectedTo[0].PinValue is T value)
|
||||
Value = value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public sealed class InputPin : Pin
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public override Type Type { get; }
|
||||
public override object PinValue => Value;
|
||||
/// <inheritdoc />
|
||||
public override Type Type { get; } = typeof(T);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? PinValue => Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PinDirection Direction => PinDirection.Input;
|
||||
|
||||
private object _value;
|
||||
private T? _value;
|
||||
|
||||
public object Value
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the input pin
|
||||
/// </summary>
|
||||
public T? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -77,8 +57,6 @@ namespace Artemis.Core
|
||||
|
||||
private set
|
||||
{
|
||||
if (!Type.IsInstanceOfType(value)) throw new ArgumentException($"Value of type '{value?.GetType().Name ?? "null"}' can't be assigned to a pin of type {Type.Name}.");
|
||||
|
||||
_value = value;
|
||||
IsEvaluated = true;
|
||||
OnPropertyChanged(nameof(PinValue));
|
||||
@ -86,13 +64,20 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an input pin on a <see cref="INode" />
|
||||
/// </summary>
|
||||
public sealed class InputPin : Pin
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
internal InputPin(INode node, Type type, string name)
|
||||
: base(node, name)
|
||||
{
|
||||
this.Type = type;
|
||||
Type = type;
|
||||
_value = type.GetDefault();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@ -115,5 +100,54 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type Type { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? PinValue => Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PinDirection Direction => PinDirection.Input;
|
||||
|
||||
private object? _value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the input pin
|
||||
/// </summary>
|
||||
public object? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsEvaluated)
|
||||
Evaluate();
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
private set
|
||||
{
|
||||
if (Type.IsValueType && value == null)
|
||||
{
|
||||
// We can't take null for value types so set it to the default value for that type
|
||||
_value = Type.GetDefault();
|
||||
}
|
||||
else if (value != null)
|
||||
{
|
||||
// If a value was given make sure it matches
|
||||
if (!Type.IsInstanceOfType(value))
|
||||
throw new ArgumentException($"Value of type '{value.GetType().Name}' can't be assigned to a pin of type {Type.Name}.");
|
||||
}
|
||||
|
||||
// Otherwise we're good and we can put a null here if it happens to be that
|
||||
_value = value;
|
||||
IsEvaluated = true;
|
||||
OnPropertyChanged(nameof(PinValue));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -5,53 +5,63 @@ using System.Linq;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of input pins containing values of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value the pins in this collection hold</typeparam>
|
||||
public sealed class InputPinCollection<T> : PinCollection
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public override PinDirection Direction => PinDirection.Input;
|
||||
public override Type Type => typeof(T);
|
||||
|
||||
public new IEnumerable<InputPin<T>> Pins => base.Pins.Cast<InputPin<T>>();
|
||||
|
||||
public IEnumerable<T> Values => Pins.Select(p => p.Value);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal InputPinCollection(INode node, string name, int initialCount)
|
||||
: base(node, name, initialCount)
|
||||
{ }
|
||||
{
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override IPin CreatePin() => new InputPin<T>(Node, string.Empty);
|
||||
/// <inheritdoc />
|
||||
protected override IPin CreatePin()
|
||||
{
|
||||
return new InputPin<T>(Node, string.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PinDirection Direction => PinDirection.Input;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type Type => typeof(T);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerable of the pins in this collection
|
||||
/// </summary>
|
||||
public new IEnumerable<InputPin<T>> Pins => base.Pins.Cast<InputPin<T>>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerable of the values of the pins in this collection
|
||||
/// </summary>
|
||||
public IEnumerable<T> Values => Pins.Where(p => p.Value != null).Select(p => p.Value!);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a collection of input pins
|
||||
/// </summary>
|
||||
public sealed class InputPinCollection : PinCollection
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public override PinDirection Direction => PinDirection.Input;
|
||||
public override Type Type { get; }
|
||||
|
||||
public new IEnumerable<InputPin> Pins => base.Pins.Cast<InputPin>();
|
||||
|
||||
public IEnumerable Values => Pins.Select(p => p.Value);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal InputPinCollection(INode node, Type type, string name, int initialCount)
|
||||
: base(node, name, 0)
|
||||
{
|
||||
this.Type = type;
|
||||
Type = type;
|
||||
|
||||
// Can't do this in the base constructor because the type won't be set yet
|
||||
for (int i = 0; i < initialCount; i++)
|
||||
@ -62,8 +72,32 @@ namespace Artemis.Core
|
||||
|
||||
#region Methods
|
||||
|
||||
protected override IPin CreatePin() => new InputPin(Node, Type, string.Empty);
|
||||
/// <inheritdoc />
|
||||
protected override IPin CreatePin()
|
||||
{
|
||||
return new InputPin(Node, Type, string.Empty);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PinDirection Direction => PinDirection.Input;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerable of the pins in this collection
|
||||
/// </summary>
|
||||
public new IEnumerable<InputPin> Pins => base.Pins.Cast<InputPin>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an enumerable of the values of the pins in this collection
|
||||
/// </summary>
|
||||
public IEnumerable Values => Pins.Where(p => p.Value != null).Select(p => p.Value);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -65,7 +65,7 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a node script with a result value of type <paramref name="T" />
|
||||
/// Represents a node script with a result value of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of result value</typeparam>
|
||||
public interface INodeScript<out T> : INodeScript
|
||||
@ -73,6 +73,6 @@ namespace Artemis.Core
|
||||
/// <summary>
|
||||
/// Gets the result of the script
|
||||
/// </summary>
|
||||
T Result { get; }
|
||||
T? Result { get; }
|
||||
}
|
||||
}
|
||||
@ -4,24 +4,76 @@ using Artemis.Core.Events;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a pin containing a value on a <see cref="INode" />
|
||||
/// </summary>
|
||||
public interface IPin
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the node the pin belongs to
|
||||
/// </summary>
|
||||
INode Node { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the pin
|
||||
/// </summary>
|
||||
string Name { get; set; }
|
||||
PinDirection Direction { get; }
|
||||
Type Type { get; }
|
||||
object PinValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the direction of the pin
|
||||
/// </summary>
|
||||
PinDirection Direction { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of value the pin holds
|
||||
/// </summary>
|
||||
Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value the pin holds
|
||||
/// </summary>
|
||||
object? PinValue { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read only list of pins this pin is connected to
|
||||
/// </summary>
|
||||
IReadOnlyList<IPin> ConnectedTo { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether this pin is evaluated or not
|
||||
/// </summary>
|
||||
bool IsEvaluated { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the pin connects to another pin
|
||||
/// </summary>
|
||||
event EventHandler<SingleValueEventArgs<IPin>> PinConnected;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when the pin disconnects from another pin
|
||||
/// </summary>
|
||||
event EventHandler<SingleValueEventArgs<IPin>> PinDisconnected;
|
||||
|
||||
/// <summary>
|
||||
/// Resets the pin, causing it to re-evaluate the next time its value is requested
|
||||
/// </summary>
|
||||
void Reset();
|
||||
|
||||
/// <summary>
|
||||
/// Connects the pin to the provided <paramref name="pin"></paramref>
|
||||
/// </summary>
|
||||
/// <param name="pin">The pin to connect this pin to</param>
|
||||
void ConnectTo(IPin pin);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects the pin to the provided <paramref name="pin"></paramref>
|
||||
/// </summary>
|
||||
/// <param name="pin">The pin to disconnect this pin to</param>
|
||||
void DisconnectFrom(IPin pin);
|
||||
|
||||
/// <summary>
|
||||
/// Disconnects all pins this pin is connected to
|
||||
/// </summary>
|
||||
void DisconnectAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,16 +4,56 @@ using Artemis.Core.Events;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of <see cref="IPin" />s on a <see cref="INode" />
|
||||
/// </summary>
|
||||
public interface IPinCollection : IEnumerable<IPin>
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the node the pin collection belongs to
|
||||
/// </summary>
|
||||
INode Node { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the pin collection
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the direction of the pin collection and all its pins
|
||||
/// </summary>
|
||||
PinDirection Direction { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of values the pin collection and all its pins holds
|
||||
/// </summary>
|
||||
Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a pin was added to the collection
|
||||
/// </summary>
|
||||
event EventHandler<SingleValueEventArgs<IPin>> PinAdded;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a pin was removed from the collection
|
||||
/// </summary>
|
||||
event EventHandler<SingleValueEventArgs<IPin>> PinRemoved;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new pin and adds it to the collection
|
||||
/// </summary>
|
||||
/// <returns>The newly added pin</returns>
|
||||
IPin AddPin();
|
||||
|
||||
/// <summary>
|
||||
/// Removes the provided <paramref name="pin" /> from the collection
|
||||
/// </summary>
|
||||
/// <param name="pin">The pin to remove</param>
|
||||
bool Remove(IPin pin);
|
||||
|
||||
/// <summary>
|
||||
/// Resets the pin collection, causing its pins to re-evaluate the next time its value is requested
|
||||
/// </summary>
|
||||
void Reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@ namespace Artemis.Core.Internal
|
||||
foreach (var (property, inputPin) in _propertyPins)
|
||||
{
|
||||
if (inputPin.ConnectedTo.Any())
|
||||
_propertyValues[property] = inputPin.Value;
|
||||
_propertyValues[property] = inputPin.Value!;
|
||||
else
|
||||
_propertyValues.Remove(property);
|
||||
}
|
||||
@ -55,7 +55,7 @@ namespace Artemis.Core.Internal
|
||||
foreach (IDataBindingProperty property in DataBinding.Properties)
|
||||
_propertyPins.Add(property, CreateInputPin(property.ValueType, property.DisplayName));
|
||||
}
|
||||
|
||||
|
||||
#region Event handlers
|
||||
|
||||
private void DataBindingOnDataBindingPropertyRegistered(object? sender, DataBindingEventArgs e)
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
public InputPin<T> Input { get; }
|
||||
|
||||
public T Value { get; private set; }
|
||||
public T? Value { get; private set; }
|
||||
|
||||
public override bool IsExitNode => true;
|
||||
|
||||
|
||||
@ -239,10 +239,14 @@ namespace Artemis.Core
|
||||
/// <inheritdoc />
|
||||
public abstract void Evaluate();
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void Reset()
|
||||
{
|
||||
foreach (IPin pin in _pins)
|
||||
pin.Reset();
|
||||
foreach (IPinCollection pinCollection in _pinCollections)
|
||||
pinCollection.Reset();
|
||||
|
||||
Resetting?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
|
||||
@ -2,38 +2,69 @@
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an attribute that can be used to provide metadata on a node
|
||||
/// </summary>
|
||||
public class NodeAttribute : Attribute
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the node
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
public string Description { get; set; }
|
||||
public string Category { get; set; }
|
||||
public Type InputType { get; set; }
|
||||
public Type OutputType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the node
|
||||
/// </summary>
|
||||
public string Description { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the category of the node
|
||||
/// </summary>
|
||||
public string Category { get; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary input type of the node
|
||||
/// </summary>
|
||||
public Type? InputType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary output type of the node
|
||||
/// </summary>
|
||||
public Type? OutputType { get; init; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="NodeAttribute" /> class
|
||||
/// </summary>
|
||||
public NodeAttribute(string name)
|
||||
{
|
||||
this.Name = name;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="NodeAttribute" /> class
|
||||
/// </summary>
|
||||
public NodeAttribute(string name, string description)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Description = description;
|
||||
Name = name;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="NodeAttribute" /> class
|
||||
/// </summary>
|
||||
public NodeAttribute(string name, string description, string category)
|
||||
{
|
||||
this.Name = name;
|
||||
this.Description = description;
|
||||
this.Category = category;
|
||||
Name = name;
|
||||
Description = description;
|
||||
Category = category;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,43 +3,81 @@ using Artemis.Storage.Entities.Profile.Nodes;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents node data describing a certain <see cref="INode" />
|
||||
/// </summary>
|
||||
public class NodeData
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public Plugin Plugin { get; }
|
||||
|
||||
public Type Type { get; }
|
||||
public string Name { get; }
|
||||
public string Description { get; }
|
||||
public string Category { get; }
|
||||
public Type? InputType { get; }
|
||||
public Type? OutputType { get; }
|
||||
|
||||
private Func<INodeScript, NodeEntity?, INode> _create;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal NodeData(Plugin plugin, Type type, string name, string description, string category, Type? inputType, Type? outputType, Func<INodeScript, NodeEntity?, INode>? create)
|
||||
internal NodeData(Plugin plugin, Type type, string name, string description, string category, Type? inputType, Type? outputType, Func<INodeScript, NodeEntity?, INode> create)
|
||||
{
|
||||
this.Plugin = plugin;
|
||||
this.Type = type;
|
||||
this.Name = name;
|
||||
this.Description = description;
|
||||
this.Category = category;
|
||||
this.InputType = inputType;
|
||||
this.OutputType = outputType;
|
||||
this._create = create;
|
||||
Plugin = plugin;
|
||||
Type = type;
|
||||
Name = name;
|
||||
Description = description;
|
||||
Category = category;
|
||||
InputType = inputType;
|
||||
OutputType = outputType;
|
||||
_create = create;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public INode CreateNode(INodeScript script, NodeEntity? entity) => _create(script, entity);
|
||||
/// <summary>
|
||||
/// Creates a new instance of the node this data represents
|
||||
/// </summary>
|
||||
/// <param name="script">The script to create the node for</param>
|
||||
/// <param name="entity">An optional storage entity to apply to the node</param>
|
||||
/// <returns>The returning node of type <see cref="Type" /></returns>
|
||||
public INode CreateNode(INodeScript script, NodeEntity? entity)
|
||||
{
|
||||
return _create(script, entity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin that provided this node data
|
||||
/// </summary>
|
||||
public Plugin Plugin { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of <see cref="INode" /> this data represents
|
||||
/// </summary>
|
||||
public Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the node this data represents
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description of the node this data represents
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the category of the node this data represents
|
||||
/// </summary>
|
||||
public string Category { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary input type of the node this data represents
|
||||
/// </summary>
|
||||
public Type? InputType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the primary output of the node this data represents
|
||||
/// </summary>
|
||||
public Type? OutputType { get; }
|
||||
|
||||
private readonly Func<INodeScript, NodeEntity?, INode> _create;
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -60,12 +60,19 @@ namespace Artemis.Core
|
||||
|
||||
#region Constructors
|
||||
|
||||
public NodeScript(string name, string description, object? context = null)
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="NodeScript"/> class with a name, description and optional context
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the node script</param>
|
||||
/// <param name="description">The description of the node script</param>
|
||||
/// <param name="context">The context of the node script, usually a <see cref="Profile" /> or <see cref="ProfileConfiguration" /></param>
|
||||
protected NodeScript(string name, string description, object? context = null)
|
||||
{
|
||||
Name = name;
|
||||
Description = description;
|
||||
Context = context;
|
||||
Entity = new NodeScriptEntity();
|
||||
ExitNode = null!;
|
||||
|
||||
NodeTypeStore.NodeTypeAdded += NodeTypeStoreOnNodeTypeChanged;
|
||||
NodeTypeStore.NodeTypeRemoved += NodeTypeStoreOnNodeTypeChanged;
|
||||
@ -77,6 +84,7 @@ namespace Artemis.Core
|
||||
Description = description;
|
||||
Entity = entity;
|
||||
Context = context;
|
||||
ExitNode = null!;
|
||||
|
||||
NodeTypeStore.NodeTypeAdded += NodeTypeStoreOnNodeTypeChanged;
|
||||
NodeTypeStore.NodeTypeRemoved += NodeTypeStoreOnNodeTypeChanged;
|
||||
@ -176,6 +184,8 @@ namespace Artemis.Core
|
||||
if (collection == null)
|
||||
continue;
|
||||
|
||||
while (collection.Count() > entityNodePinCollection.Amount)
|
||||
collection.Remove(collection.Last());
|
||||
while (collection.Count() < entityNodePinCollection.Amount)
|
||||
collection.AddPin();
|
||||
}
|
||||
@ -333,7 +343,7 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents a node script with a result value of type <paramref name="T" />
|
||||
/// Represents a node script with a result value of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of result value</typeparam>
|
||||
public class NodeScript<T> : NodeScript, INodeScript<T>
|
||||
@ -341,7 +351,7 @@ namespace Artemis.Core
|
||||
#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();
|
||||
@ -362,6 +372,7 @@ namespace Artemis.Core
|
||||
Load();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public NodeScript(string name, string description, object? context = null)
|
||||
: base(name, description, context)
|
||||
{
|
||||
|
||||
@ -3,55 +3,39 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an output pin containing a value of type <typeparamref name="T" /> on a <see cref="INode" />
|
||||
/// </summary>
|
||||
public sealed class OutputPin<T> : Pin
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public override Type Type { get; } = typeof(T);
|
||||
public override object PinValue => Value;
|
||||
public override PinDirection Direction => PinDirection.Output;
|
||||
|
||||
private T _value;
|
||||
public T Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsEvaluated)
|
||||
Node?.Evaluate();
|
||||
|
||||
return _value;
|
||||
}
|
||||
set
|
||||
{
|
||||
_value = value;
|
||||
IsEvaluated = true;
|
||||
|
||||
OnPropertyChanged(nameof(PinValue));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
[JsonConstructor]
|
||||
internal OutputPin(INode node, string name)
|
||||
: base(node, name)
|
||||
{ }
|
||||
{
|
||||
_value = default;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public sealed class OutputPin : Pin
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public override Type Type { get; }
|
||||
public override object PinValue => Value;
|
||||
/// <inheritdoc />
|
||||
public override Type Type { get; } = typeof(T);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? PinValue => Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PinDirection Direction => PinDirection.Output;
|
||||
|
||||
private object _value;
|
||||
public object Value
|
||||
private T? _value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the output pin
|
||||
/// </summary>
|
||||
public T? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
@ -62,8 +46,72 @@ namespace Artemis.Core
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!Type.IsInstanceOfType(value)) throw new ArgumentException($"Value of type '{value?.GetType().Name ?? "null"}' can't be assigned to a pin of type {Type.Name}.");
|
||||
_value = value;
|
||||
IsEvaluated = true;
|
||||
|
||||
OnPropertyChanged(nameof(PinValue));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an output pin on a <see cref="INode" />
|
||||
/// </summary>
|
||||
public sealed class OutputPin : Pin
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
internal OutputPin(INode node, Type type, string name)
|
||||
: base(node, name)
|
||||
{
|
||||
Type = type;
|
||||
_value = type.GetDefault();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Type Type { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object? PinValue => Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PinDirection Direction => PinDirection.Output;
|
||||
|
||||
private object? _value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value of the output pin
|
||||
/// </summary>
|
||||
public object? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!IsEvaluated)
|
||||
Node?.Evaluate();
|
||||
|
||||
return _value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (Type.IsValueType && value == null)
|
||||
{
|
||||
// We can't take null for value types so set it to the default value for that type
|
||||
_value = Type.GetDefault();
|
||||
}
|
||||
else if (value != null)
|
||||
{
|
||||
// If a value was given make sure it matches
|
||||
if (!Type.IsInstanceOfType(value))
|
||||
throw new ArgumentException($"Value of type '{value.GetType().Name}' can't be assigned to a pin of type {Type.Name}.");
|
||||
}
|
||||
|
||||
// Otherwise we're good and we can put a null here if it happens to be that
|
||||
_value = value;
|
||||
IsEvaluated = true;
|
||||
OnPropertyChanged(nameof(PinValue));
|
||||
@ -71,15 +119,5 @@ namespace Artemis.Core
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal OutputPin(INode node, Type type, string name)
|
||||
: base(node, name)
|
||||
{
|
||||
this.Type = type;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,11 +2,17 @@
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a collection of output pins containing values of type <typeparamref name="T" />
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value the pins in this collection hold</typeparam>
|
||||
public sealed class OutputPinCollection<T> : PinCollection
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public override PinDirection Direction => PinDirection.Output;
|
||||
/// <inheritdoc />
|
||||
public override Type Type => typeof(T);
|
||||
|
||||
#endregion
|
||||
@ -21,6 +27,7 @@ namespace Artemis.Core
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override IPin CreatePin() => new OutputPin<T>(Node, string.Empty);
|
||||
|
||||
#endregion
|
||||
|
||||
@ -5,12 +5,35 @@ using Artemis.Core.Events;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <inheritdoc cref="IPin" />
|
||||
public abstract class Pin : CorePropertyChanged, IPin
|
||||
{
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="Pin" /> class on the provided node with the provided name
|
||||
/// </summary>
|
||||
/// <param name="node">The node the pin belongs to</param>
|
||||
/// <param name="name">The name of the pin</param>
|
||||
protected Pin(INode node, string name = "")
|
||||
{
|
||||
Node = node;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<SingleValueEventArgs<IPin>>? PinConnected;
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<SingleValueEventArgs<IPin>>? PinDisconnected;
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public INode Node { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
@ -19,6 +42,7 @@ namespace Artemis.Core
|
||||
|
||||
private bool _isEvaluated;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsEvaluated
|
||||
{
|
||||
get => _isEvaluated;
|
||||
@ -27,36 +51,30 @@ namespace Artemis.Core
|
||||
|
||||
private readonly List<IPin> _connectedTo = new();
|
||||
private string _name;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IReadOnlyList<IPin> ConnectedTo => new ReadOnlyCollection<IPin>(_connectedTo);
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract PinDirection Direction { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Type Type { get; }
|
||||
public abstract object PinValue { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<SingleValueEventArgs<IPin>> PinConnected;
|
||||
public event EventHandler<SingleValueEventArgs<IPin>> PinDisconnected;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
protected Pin(INode node, string name = "")
|
||||
{
|
||||
this.Node = node;
|
||||
this.Name = name;
|
||||
|
||||
if (Node != null)
|
||||
Node.Resetting += OnNodeResetting;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public abstract object? PinValue { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
{
|
||||
IsEvaluated = false;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ConnectTo(IPin pin)
|
||||
{
|
||||
_connectedTo.Add(pin);
|
||||
@ -65,6 +83,7 @@ namespace Artemis.Core
|
||||
PinConnected?.Invoke(this, new SingleValueEventArgs<IPin>(pin));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DisconnectFrom(IPin pin)
|
||||
{
|
||||
_connectedTo.Remove(pin);
|
||||
@ -73,6 +92,7 @@ namespace Artemis.Core
|
||||
PinDisconnected?.Invoke(this, new SingleValueEventArgs<IPin>(pin));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DisconnectAll()
|
||||
{
|
||||
List<IPin> connectedPins = new(_connectedTo);
|
||||
@ -84,11 +104,6 @@ namespace Artemis.Core
|
||||
PinDisconnected?.Invoke(this, new SingleValueEventArgs<IPin>(pin));
|
||||
}
|
||||
|
||||
private void OnNodeResetting(object sender, EventArgs e)
|
||||
{
|
||||
IsEvaluated = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -6,34 +6,22 @@ using Artemis.Core.Events;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <inheritdoc cref="IPinCollection"/>
|
||||
public abstract class PinCollection : IPinCollection
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public INode Node { get; }
|
||||
public string Name { get; }
|
||||
|
||||
public abstract PinDirection Direction { get; }
|
||||
public abstract Type Type { get; }
|
||||
|
||||
private readonly ObservableCollection<IPin> _pins = new();
|
||||
public ReadOnlyObservableCollection<IPin> Pins => new(_pins);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
||||
public event EventHandler<SingleValueEventArgs<IPin>> PinAdded;
|
||||
public event EventHandler<SingleValueEventArgs<IPin>> PinRemoved;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of the <see cref="PinCollection" /> class
|
||||
/// </summary>
|
||||
/// <param name="node">The node the pin collection belongs to</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 output pin collection</returns>
|
||||
protected PinCollection(INode node, string name, int initialCount)
|
||||
{
|
||||
this.Node = node;
|
||||
this.Name = name;
|
||||
Node = node ?? throw new ArgumentNullException(nameof(node));
|
||||
Name = name;
|
||||
|
||||
for (int i = 0; i < initialCount; i++)
|
||||
AddPin();
|
||||
@ -41,9 +29,38 @@ namespace Artemis.Core
|
||||
|
||||
#endregion
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<SingleValueEventArgs<IPin>>? PinAdded;
|
||||
|
||||
/// <inheritdoc />
|
||||
public event EventHandler<SingleValueEventArgs<IPin>>? PinRemoved;
|
||||
|
||||
#region Properties & Fields
|
||||
|
||||
/// <inheritdoc />
|
||||
public INode Node { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract PinDirection Direction { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public abstract Type Type { get; }
|
||||
|
||||
private readonly ObservableCollection<IPin> _pins = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a read only observable collection of the pins
|
||||
/// </summary>
|
||||
public ReadOnlyObservableCollection<IPin> Pins => new(_pins);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public IPin AddPin()
|
||||
{
|
||||
IPin pin = CreatePin();
|
||||
@ -54,6 +71,7 @@ namespace Artemis.Core
|
||||
return pin;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Remove(IPin pin)
|
||||
{
|
||||
bool removed = _pins.Remove(pin);
|
||||
@ -64,11 +82,30 @@ namespace Artemis.Core
|
||||
return removed;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Reset()
|
||||
{
|
||||
foreach (IPin pin in _pins)
|
||||
pin.Reset();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new pin to be used in this collection
|
||||
/// </summary>
|
||||
/// <returns>The resulting pin</returns>
|
||||
protected abstract IPin CreatePin();
|
||||
|
||||
public IEnumerator<IPin> GetEnumerator() => Pins.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
/// <inheritdoc />
|
||||
public IEnumerator<IPin> GetEnumerator()
|
||||
{
|
||||
return Pins.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,18 @@
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a direction in which pin data flows
|
||||
/// </summary>
|
||||
public enum PinDirection
|
||||
{
|
||||
/// <summary>
|
||||
/// An input direction
|
||||
/// </summary>
|
||||
Input,
|
||||
|
||||
/// <summary>
|
||||
/// An output direction
|
||||
/// </summary>
|
||||
Output
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,7 +63,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
|
||||
}
|
||||
}
|
||||
|
||||
private void DataBindingOnDataBindingToggled(object? sender, DataBindingEventArgs e)
|
||||
private void DataBindingOnDataBindingToggled(object sender, DataBindingEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(nameof(DataBindingEnabled));
|
||||
}
|
||||
|
||||
@ -22,8 +22,7 @@ namespace Artemis.UI.Stylet
|
||||
{
|
||||
base.Dispose();
|
||||
ScreenExtensions.TryDispose(_rootViewModel);
|
||||
if (Kernel != null)
|
||||
Kernel.Dispose();
|
||||
Kernel?.Dispose();
|
||||
}
|
||||
|
||||
protected override void ConfigureBootstrapper()
|
||||
|
||||
@ -277,7 +277,7 @@ namespace Artemis.VisualScripting.Editor.Controls
|
||||
FitScript();
|
||||
}
|
||||
|
||||
private void OnVisualScriptNodeCollectionChanged(object? sender, EventArgs e)
|
||||
private void OnVisualScriptNodeCollectionChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (AutoFitScript)
|
||||
FitScript();
|
||||
|
||||
@ -24,7 +24,7 @@
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Padding="{TemplateBinding Padding}"
|
||||
<Border Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}">
|
||||
@ -103,19 +103,18 @@
|
||||
<Setter Property="ItemTemplate">
|
||||
<Setter.Value>
|
||||
<DataTemplate DataType="{x:Type wrapper:VisualScriptPinCollection}">
|
||||
<StackPanel Margin="0,4" Orientation="Vertical">
|
||||
<StackPanel Margin="0,2" Orientation="Vertical">
|
||||
<TextBlock Text="{Binding PinCollection.Name}" Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type controls:VisualScriptNodePresenter}}}" />
|
||||
<ItemsControl Margin="0,4"
|
||||
Style="{StaticResource StylePinListInput}"
|
||||
<ItemsControl Margin="0,5"
|
||||
Style="{StaticResource StylePinListInput}"
|
||||
ItemsSource="{Binding Pins}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type core:Pin}">
|
||||
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
|
||||
<controls:VisualScriptPinPresenter Margin="0,5,-3,3"
|
||||
Pin="{Binding .}" />
|
||||
<StackPanel HorizontalAlignment="Left" Orientation="Horizontal" Margin="0 8 0 0">
|
||||
<controls:VisualScriptPinPresenter Pin="{Binding .}" Margin="0 0 2 0" />
|
||||
<Button Style="{StaticResource StyleButtonPinsModify}"
|
||||
Command="{Binding DataContext.RemovePinCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
|
||||
CommandParameter="{Binding .}"/>
|
||||
CommandParameter="{Binding .}" />
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
@ -139,14 +138,14 @@
|
||||
<StackPanel Margin="0,4" Orientation="Vertical">
|
||||
<TextBlock Text="{Binding PinCollection.Name}" Foreground="{Binding Foreground, RelativeSource={RelativeSource AncestorType={x:Type controls:VisualScriptNodePresenter}}}" />
|
||||
<ItemsControl Margin="0,4"
|
||||
Style="{StaticResource StylePinListOutput}"
|
||||
Style="{StaticResource StylePinListOutput}"
|
||||
ItemsSource="{Binding Pins}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate DataType="{x:Type core:Pin}">
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
<Button Style="{StaticResource StyleButtonPinsModify}"
|
||||
Command="{Binding DataContext.RemovePinCommand, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
|
||||
CommandParameter="{Binding .}"/>
|
||||
CommandParameter="{Binding .}" />
|
||||
<controls:VisualScriptPinPresenter Margin="-3,5,0,3"
|
||||
Pin="{Binding .}" />
|
||||
</StackPanel>
|
||||
@ -182,9 +181,9 @@
|
||||
<!-- Placeholder -->
|
||||
</Border>
|
||||
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="14" FontWeight="Bold"
|
||||
Text="{Binding Node.Node.Name, RelativeSource={RelativeSource TemplatedParent}}"/>
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="14" FontWeight="Bold"
|
||||
Text="{Binding Node.Node.Name, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
@ -199,24 +198,24 @@
|
||||
|
||||
<Border x:Name="BrdInputPins" Grid.Column="0">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<ItemsControl Style="{StaticResource StylePinListInput}"
|
||||
<ItemsControl Style="{StaticResource StylePinListInput}"
|
||||
ItemsSource="{Binding Node.InputPins, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
|
||||
<ItemsControl Style="{StaticResource StylePinCollectionListInput}"
|
||||
<ItemsControl Style="{StaticResource StylePinCollectionListInput}"
|
||||
ItemsSource="{Binding Node.InputPinCollections, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<Border x:Name="BrdCustomView" Grid.Column="1">
|
||||
<ContentControl s:View.Model="{TemplateBinding CustomViewModel}"/>
|
||||
<ContentControl s:View.Model="{TemplateBinding CustomViewModel}" />
|
||||
</Border>
|
||||
|
||||
<Border x:Name="BrdOutputPins" Grid.Column="2">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<ItemsControl Style="{StaticResource StylePinListOutput}"
|
||||
<ItemsControl Style="{StaticResource StylePinListOutput}"
|
||||
ItemsSource="{Binding Node.OutputPins, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
|
||||
<ItemsControl Style="{StaticResource StylePinCollectionListOutput}"
|
||||
<ItemsControl Style="{StaticResource StylePinCollectionListOutput}"
|
||||
ItemsSource="{Binding Node.OutputPinCollections, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
@ -226,12 +225,12 @@
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
|
||||
<Style x:Key="StyleVisualScriptNodePresenter"
|
||||
<Style x:Key="StyleVisualScriptNodePresenter"
|
||||
TargetType="{x:Type controls:VisualScriptNodePresenter}">
|
||||
|
||||
<Setter Property="Padding" Value="8,10" />
|
||||
|
||||
<Setter Property="Foreground" Value="#FFFFFFFF"/>
|
||||
<Setter Property="Foreground" Value="#FFFFFFFF" />
|
||||
|
||||
<Setter Property="Background" Value="#80101010" />
|
||||
<Setter Property="TitleBrush" Value="#FF444444" />
|
||||
|
||||
@ -110,7 +110,7 @@ namespace Artemis.VisualScripting.Nodes
|
||||
CreateOutputPin(dataBindingRegistration.ValueType, dataBindingRegistration.DisplayName);
|
||||
}
|
||||
|
||||
private void ProfileOnChildRemoved(object? sender, EventArgs e)
|
||||
private void ProfileOnChildRemoved(object sender, EventArgs e)
|
||||
{
|
||||
if (Script.Context is not Profile profile)
|
||||
return;
|
||||
|
||||
@ -8,7 +8,7 @@ using NoStringEvaluating.Models.Values;
|
||||
|
||||
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", InputType = typeof(float), OutputType = typeof(float))]
|
||||
public class MathExpressionNode : Node<string, MathExpressionNodeCustomViewModel>
|
||||
{
|
||||
private readonly INoStringEvaluator _evaluator;
|
||||
@ -42,6 +42,7 @@ namespace Artemis.VisualScripting.Nodes.Maths
|
||||
|
||||
public override void Evaluate()
|
||||
{
|
||||
var test = _evaluator.ToString();
|
||||
if (Storage != null)
|
||||
Output.Value = (float) _evaluator.CalcNumber(Storage, _variables);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user