1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00
Artemis/src/Artemis.VisualScripting/Nodes/List/ListOperatorPredicateNode.cs
Robert 166cb888c1 Meta - Update RGB.NET
Meta - Fixed warnings
2023-01-11 22:33:47 +01:00

106 lines
3.2 KiB
C#

using System.Collections;
using Artemis.Core;
using Artemis.Core.Events;
using Artemis.VisualScripting.Nodes.List.Screens;
namespace Artemis.VisualScripting.Nodes.List;
[Node("List Operator (Advanced)", "Checks if any/all/no values in the input list match a condition", "List", InputType = typeof(IEnumerable), OutputType = typeof(bool))]
public class ListOperatorPredicateNode : Node<ListOperatorEntity, ListOperatorPredicateNodeCustomViewModel>, IDisposable
{
private readonly object _scriptLock = new();
private readonly ListOperatorPredicateStartNode _startNode;
public ListOperatorPredicateNode()
{
_startNode = new ListOperatorPredicateStartNode {X = -200};
InputList = CreateInputPin<IList>();
Output = CreateOutputPin<bool>();
InputList.PinConnected += InputListOnPinConnected;
}
public InputPin<IList> InputList { get; }
public OutputPin<bool> Output { get; }
public NodeScript<bool>? Script { get; private set; }
public override void Initialize(INodeScript script)
{
Storage ??= new ListOperatorEntity();
lock (_scriptLock)
{
Script = Storage?.Script != null
? new NodeScript<bool>("Is match", "Determines whether the current list item is a match", Storage.Script, script.Context, new List<DefaultNode> {_startNode})
: new NodeScript<bool>("Is match", "Determines whether the current list item is a match", script.Context, new List<DefaultNode> {_startNode});
}
}
/// <inheritdoc />
public override void Evaluate()
{
if (Storage == null)
return;
if (InputList.Value == null)
{
Output.Value = Storage.Operator == ListOperator.None;
return;
}
lock (_scriptLock)
{
if (Script == null)
return;
if (Storage.Operator == ListOperator.Any)
Output.Value = InputList.Value.Cast<object>().Any(EvaluateItem);
else if (Storage.Operator == ListOperator.All)
Output.Value = InputList.Value.Cast<object>().All(EvaluateItem);
else if (Storage.Operator == ListOperator.None)
Output.Value = InputList.Value.Cast<object>().All(v => !EvaluateItem(v));
}
}
private bool EvaluateItem(object item)
{
if (Script == null)
return false;
_startNode.Item = item;
Script.Run();
return Script.Result;
}
private void UpdateStartNode()
{
Type? type = InputList.ConnectedTo.FirstOrDefault()?.Type;
// List must be generic or there's no way to tell what objects it contains in advance, that's not supported for now
if (type is not {IsGenericType: true})
return;
Type listType = type.GetGenericArguments().Single();
_startNode?.ChangeType(listType);
}
private void InputListOnPinConnected(object? sender, SingleValueEventArgs<IPin> e)
{
lock (_scriptLock)
{
UpdateStartNode();
Script?.LoadConnections();
}
}
#region IDisposable
/// <inheritdoc />
public void Dispose()
{
Script?.Dispose();
Script = null;
}
#endregion
}