Added IExecutable and ISlotContainer interface.
Changed SlotContainerNode to ExecutableNode
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Misaki.GraphView
|
||||
public abstract class GraphObject : ScriptableObject
|
||||
{
|
||||
[SerializeReference]
|
||||
private List<SlotContainerNode> _nodes = new();
|
||||
private List<DataNode> _nodes = new();
|
||||
[SerializeField]
|
||||
private List<StickyNoteData> _stickyNotes = new();
|
||||
[SerializeField]
|
||||
@@ -18,9 +18,9 @@ namespace Misaki.GraphView
|
||||
[SerializeReference]
|
||||
private List<ExposedProperty> _exposedProperties = new();
|
||||
|
||||
private readonly Dictionary<string, SlotContainerNode> _nodeMap = new();
|
||||
private readonly Dictionary<string, DataNode> _nodeMap = new();
|
||||
|
||||
public ReadOnlyCollection<SlotContainerNode> Nodes => _nodes.AsReadOnly();
|
||||
public ReadOnlyCollection<DataNode> Nodes => _nodes.AsReadOnly();
|
||||
public ReadOnlyCollection<StickyNoteData> StickyNotes => _stickyNotes.AsReadOnly();
|
||||
public ReadOnlyCollection<SlotConnection> Connections => _connections.AsReadOnly();
|
||||
public ReadOnlyCollection<ExposedProperty> ExposedProperties => _exposedProperties.AsReadOnly();
|
||||
@@ -41,39 +41,43 @@ namespace Misaki.GraphView
|
||||
}
|
||||
}
|
||||
|
||||
public void AddNode(SlotContainerNode slotContainerNode)
|
||||
public void AddNode(DataNode executableNode)
|
||||
{
|
||||
_nodes.Add(slotContainerNode);
|
||||
TryAddNodeToMap(slotContainerNode);
|
||||
slotContainerNode.Initialize(this);
|
||||
_nodes.Add(executableNode);
|
||||
TryAddNodeToMap(executableNode);
|
||||
executableNode.Initialize(this);
|
||||
}
|
||||
|
||||
public void RemoveNode(SlotContainerNode slotContainerNode)
|
||||
public void RemoveNode(DataNode node)
|
||||
{
|
||||
_nodes.Remove(slotContainerNode);
|
||||
RemoveNodeFromMap(slotContainerNode);
|
||||
slotContainerNode.UnLoad();
|
||||
slotContainerNode.UnlinkAllSlots();
|
||||
_nodes.Remove(node);
|
||||
RemoveNodeFromMap(node);
|
||||
node.Dispose();
|
||||
|
||||
if (node is ISlotContainer slotContainer)
|
||||
{
|
||||
slotContainer.UnlinkAllSlots();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryAddNodeToMap(SlotContainerNode slotContainerNode)
|
||||
public bool TryAddNodeToMap(DataNode executable)
|
||||
{
|
||||
return _nodeMap.TryAdd(slotContainerNode.Id, slotContainerNode);
|
||||
return _nodeMap.TryAdd(executable.Id, executable);
|
||||
}
|
||||
|
||||
public void RemoveNodeFromMap(SlotContainerNode slotContainerNode)
|
||||
public void RemoveNodeFromMap(DataNode executableNode)
|
||||
{
|
||||
_nodeMap.Remove(slotContainerNode.Id);
|
||||
_nodeMap.Remove(executableNode.Id);
|
||||
}
|
||||
|
||||
public SlotContainerNode GetNode(string id)
|
||||
public DataNode GetNode(string id)
|
||||
{
|
||||
return _nodeMap.GetValueOrDefault(id);
|
||||
}
|
||||
|
||||
public bool TryGetNode(string id, out SlotContainerNode slotContainerNode)
|
||||
public bool TryGetNode(string id, out DataNode executable)
|
||||
{
|
||||
return _nodeMap.TryGetValue(id, out slotContainerNode);
|
||||
return _nodeMap.TryGetValue(id, out executable);
|
||||
}
|
||||
|
||||
public void AddStickyNote(StickyNoteData stickyNote)
|
||||
@@ -128,7 +132,7 @@ namespace Misaki.GraphView
|
||||
{
|
||||
if (GraphProcessor == null)
|
||||
{
|
||||
return;
|
||||
throw new ArgumentNullException(nameof(GraphProcessor), "GraphProcessor is null.");
|
||||
}
|
||||
|
||||
GraphProcessor.UpdateComputeOrder();
|
||||
|
||||
35
Runtime/Models/Nodes/DataNode.cs
Normal file
35
Runtime/Models/Nodes/DataNode.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.GraphView
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class DataNode
|
||||
{
|
||||
[SerializeField]
|
||||
protected GraphObject graphObject;
|
||||
[SerializeField]
|
||||
protected string id = Guid.NewGuid().ToString();
|
||||
|
||||
public Rect position;
|
||||
|
||||
public GraphObject GraphObject => graphObject;
|
||||
public string Id => id;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the node with the graph object, this method is called when the node is added to the graph.
|
||||
/// </summary>
|
||||
public virtual void Initialize(GraphObject graph)
|
||||
{
|
||||
graphObject = graph;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unload the node, this method is called when the node is removed from the graph.
|
||||
/// </summary>
|
||||
public virtual void Dispose()
|
||||
{
|
||||
graphObject = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Runtime/Models/Nodes/DataNode.cs.meta
Normal file
3
Runtime/Models/Nodes/DataNode.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0e9d8eecbaad45cb8da2c61ae9c6afc4
|
||||
timeCreated: 1730715419
|
||||
@@ -1,34 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.GraphView
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class SlotContainerNode : SlotContainer
|
||||
public abstract class ExecutableNode : DataNode, ISlotContainer, IExecutable
|
||||
{
|
||||
[SerializeField]
|
||||
private GraphObject _graphObject;
|
||||
[SerializeField]
|
||||
private string _id = Guid.NewGuid().ToString();
|
||||
[SerializeField]
|
||||
private List<Slot> _inputs = new ();
|
||||
[SerializeField]
|
||||
private List<Slot> _outputs = new ();
|
||||
|
||||
public ReadOnlyCollection<Slot> Inputs => _inputs.AsReadOnly();
|
||||
public ReadOnlyCollection<Slot> Outputs => _outputs.AsReadOnly();
|
||||
|
||||
private bool _isExecuted;
|
||||
|
||||
public Rect position;
|
||||
|
||||
public GraphObject GraphObject => _graphObject;
|
||||
public string Id => _id;
|
||||
|
||||
public Action OnExecutoinStarted;
|
||||
public Action OnExecutionCompleted;
|
||||
public Action<SlotContainerNode> OnExecutionFailed;
|
||||
public Action OnExecutionFailed;
|
||||
public Action OnExecuteFlagCleared;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the node with the graph object, this method is called when the node is added to the graph.
|
||||
/// </summary>
|
||||
public void Initialize(GraphObject graph)
|
||||
|
||||
public override void Initialize(GraphObject graph)
|
||||
{
|
||||
_graphObject = graph;
|
||||
graphObject = graph;
|
||||
|
||||
InitializeSlot();
|
||||
}
|
||||
@@ -53,7 +51,7 @@ namespace Misaki.GraphView
|
||||
direction = SlotDirection.Input,
|
||||
valueType = field.FieldType.FullName
|
||||
});
|
||||
AddInput(inputSlot);
|
||||
AddSlot(inputSlot);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -69,24 +67,40 @@ namespace Misaki.GraphView
|
||||
direction = SlotDirection.Output,
|
||||
valueType = field.FieldType.FullName
|
||||
});
|
||||
AddOutput(outputSlot);
|
||||
AddSlot(outputSlot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unload the node from the graph, this method is called when the node is removed from the graph.
|
||||
/// </summary>
|
||||
public virtual void UnLoad()
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddSlot(Slot slot)
|
||||
{
|
||||
switch (slot.slotData.direction)
|
||||
{
|
||||
case SlotDirection.Input:
|
||||
_inputs.Add(slot);
|
||||
break;
|
||||
case SlotDirection.Output:
|
||||
_outputs.Add(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void RemoveSlot(Slot slot)
|
||||
{
|
||||
switch (slot.slotData.direction)
|
||||
{
|
||||
case SlotDirection.Input:
|
||||
_inputs.Remove(slot);
|
||||
break;
|
||||
case SlotDirection.Output:
|
||||
_outputs.Remove(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the slot by the index and direction.
|
||||
/// </summary>
|
||||
/// <param name="index"> Index of the slot</param>
|
||||
/// <param name="direction"> Direction of the slot </param>
|
||||
/// <returns> <see cref="Slot"/> The slot that matches the index and direction </returns>
|
||||
/// <inheritdoc />
|
||||
public Slot GetSlot(int index, SlotDirection direction)
|
||||
{
|
||||
return direction switch
|
||||
@@ -97,27 +111,23 @@ namespace Misaki.GraphView
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unlink all the slots of the node.
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public void UnlinkAllSlots()
|
||||
{
|
||||
foreach (var input in Inputs)
|
||||
{
|
||||
input.UnlinkAll();
|
||||
_graphObject.RemoveAllConnectionsForSlot(input);
|
||||
graphObject.RemoveAllConnectionsForSlot(input);
|
||||
}
|
||||
|
||||
foreach (var output in Outputs)
|
||||
{
|
||||
output.UnlinkAll();
|
||||
_graphObject.RemoveAllConnectionsForSlot(output);
|
||||
graphObject.RemoveAllConnectionsForSlot(output);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute the node.
|
||||
/// </summary>
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Execute()
|
||||
{
|
||||
if (_isExecuted)
|
||||
@@ -125,24 +135,34 @@ namespace Misaki.GraphView
|
||||
return;
|
||||
}
|
||||
|
||||
OnExecutoinStarted?.Invoke();
|
||||
|
||||
PullData();
|
||||
|
||||
if (!_graphObject.GraphProcessor.IsRunning)
|
||||
if (!graphObject.GraphProcessor.IsRunning)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!OnExecute())
|
||||
{
|
||||
_graphObject.GraphProcessor.Break();
|
||||
OnExecutionFailed?.Invoke(this);
|
||||
graphObject.GraphProcessor.Break();
|
||||
OnExecutionFailed?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
PushData();
|
||||
|
||||
_isExecuted = true;
|
||||
OnExecutionCompleted?.Invoke();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ClearExecutionFlag()
|
||||
{
|
||||
_isExecuted = false;
|
||||
OnExecuteFlagCleared?.Invoke();
|
||||
}
|
||||
|
||||
private void PullData()
|
||||
{
|
||||
@@ -184,13 +204,18 @@ namespace Misaki.GraphView
|
||||
output.value = property.GetValue(this);
|
||||
foreach (var slotData in output.LinkedSlotData)
|
||||
{
|
||||
var slot = _graphObject.GetNode(slotData.nodeID).GetSlot(slotData.slotIndex, slotData.direction);
|
||||
|
||||
var node = graphObject.GetNode(slotData.nodeID);
|
||||
if (node is not ISlotContainer slotContainer)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var slot = slotContainer.GetSlot(slotData.slotIndex, SlotDirection.Input);
|
||||
if (slotData.valueType == output.slotData.valueType || output.slotData.valueType == typeof(object).FullName)
|
||||
{
|
||||
slot.ReceiveData(output.value);
|
||||
}
|
||||
else if (_graphObject.ValueConverterManager != null && _graphObject.ValueConverterManager.TryConvert(output.slotData.GetValueType(),
|
||||
else if (graphObject.ValueConverterManager != null && graphObject.ValueConverterManager.TryConvert(output.slotData.GetValueType(),
|
||||
slotData.GetValueType(), output.value, out var data))
|
||||
{
|
||||
slot.ReceiveData(data);
|
||||
@@ -202,17 +227,6 @@ namespace Misaki.GraphView
|
||||
protected virtual void OnPushData(Slot output)
|
||||
{
|
||||
}
|
||||
|
||||
public bool IsExecuted()
|
||||
{
|
||||
return _isExecuted;
|
||||
}
|
||||
|
||||
public void ClearExecuteFlag()
|
||||
{
|
||||
_isExecuted = false;
|
||||
OnExecuteFlagCleared?.Invoke();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The execution logic of the node.
|
||||
@@ -3,7 +3,7 @@ using UnityEngine;
|
||||
|
||||
namespace Misaki.GraphView
|
||||
{
|
||||
public class PropertyInputNode : SlotContainerNode
|
||||
public class PropertyInput : ExecutableNode
|
||||
{
|
||||
[SerializeReference]
|
||||
private ExposedProperty _property;
|
||||
@@ -13,7 +13,7 @@ namespace Misaki.GraphView
|
||||
[NodeOutput]
|
||||
public object value;
|
||||
|
||||
public PropertyInputNode(ExposedProperty property)
|
||||
public PropertyInput(ExposedProperty property)
|
||||
{
|
||||
_property = property;
|
||||
}
|
||||
9
Runtime/Models/Nodes/RelayNode.cs
Normal file
9
Runtime/Models/Nodes/RelayNode.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.GraphView
|
||||
{
|
||||
public class RelayNode
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
2
Runtime/Models/Nodes/RelayNode.cs.meta
Normal file
2
Runtime/Models/Nodes/RelayNode.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4770061645971f7439b85f93d50c6b3b
|
||||
@@ -1,40 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace Misaki.GraphView
|
||||
{
|
||||
[Serializable]
|
||||
public abstract class SlotContainer
|
||||
{
|
||||
[SerializeField]
|
||||
private List<Slot> _inputs = new ();
|
||||
[SerializeField]
|
||||
private List<Slot> _outputs = new ();
|
||||
|
||||
public ReadOnlyCollection<Slot> Inputs => _inputs.AsReadOnly();
|
||||
public ReadOnlyCollection<Slot> Outputs => _outputs.AsReadOnly();
|
||||
|
||||
public void AddInput(Slot input)
|
||||
{
|
||||
_inputs.Add(input);
|
||||
}
|
||||
|
||||
public void AddOutput(Slot output)
|
||||
{
|
||||
_outputs.Add(output);
|
||||
}
|
||||
|
||||
public void ClearInputs()
|
||||
{
|
||||
_inputs.Clear();
|
||||
}
|
||||
|
||||
public void ClearOutputs()
|
||||
{
|
||||
_outputs.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0a8f9433f38644d78ab2a8bc47cc54bd
|
||||
timeCreated: 1730116658
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Misaki.GraphView
|
||||
@@ -50,12 +49,12 @@ namespace Misaki.GraphView
|
||||
public ReadOnlyCollection<SlotData> LinkedSlotData => _linkedSlotData.AsReadOnly();
|
||||
|
||||
[SerializeReference]
|
||||
public SlotContainerNode owner;
|
||||
public DataNode owner;
|
||||
public SlotData slotData;
|
||||
|
||||
public object value;
|
||||
|
||||
public Slot(SlotContainerNode owner, SlotData slotData)
|
||||
public Slot(DataNode owner, SlotData slotData)
|
||||
{
|
||||
this.owner = owner;
|
||||
this.slotData = slotData;
|
||||
|
||||
Reference in New Issue
Block a user