Added IExecutable and ISlotContainer interface.

Changed SlotContainerNode to ExecutableNode
This commit is contained in:
Misaki
2024-11-05 02:25:15 +09:00
parent 7eec130b39
commit c853994bf5
51 changed files with 443 additions and 400 deletions

View File

@@ -48,8 +48,8 @@ namespace Misaki.GraphView.Editor
_searchContextElements.Clear(); _searchContextElements.Clear();
var types = string.IsNullOrEmpty(_owner.GraphViewConfig.searchNamespace) ? var types = string.IsNullOrEmpty(_owner.GraphViewConfig.searchNamespace) ?
TypeCache.GetTypesDerivedFrom<SlotContainerNode>().ToArray() : TypeCache.GetTypesDerivedFrom<ExecutableNode>().ToArray() :
TypeCache.GetTypesDerivedFrom<SlotContainerNode>().Where(t => !string.IsNullOrEmpty(t.Namespace) && t.Namespace.StartsWith(_owner.GraphViewConfig.searchNamespace)).ToArray(); TypeCache.GetTypesDerivedFrom<ExecutableNode>().Where(t => !string.IsNullOrEmpty(t.Namespace) && t.Namespace.StartsWith(_owner.GraphViewConfig.searchNamespace)).ToArray();
foreach (var type in types) foreach (var type in types)
{ {
@@ -142,14 +142,14 @@ namespace Misaki.GraphView.Editor
var element = (SearchContextElement)searchTreeEntry.userData; var element = (SearchContextElement)searchTreeEntry.userData;
SlotContainerNode node = null; ExecutableNode node = null;
if (element.Target is ExposedProperty property) if (element.Target is ExposedProperty property)
{ {
node = new PropertyInputNode(property); node = new PropertyInput(property);
} }
else if (element.Target is Type nodeType) else if (element.Target is Type nodeType)
{ {
node = Activator.CreateInstance(nodeType) as SlotContainerNode; node = Activator.CreateInstance(nodeType) as ExecutableNode;
} }
if (node == null) if (node == null)

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e395d546cad54c19a0f7bcd3c700f3c8
timeCreated: 1730721678

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a3eccc1eae4c41168ddac1b27a18a4aa
timeCreated: 1730721637

View File

@@ -1,8 +1,5 @@
using System; using System;
using System.Reflection;
using UnityEditor;
using UnityEditor.Experimental.GraphView; using UnityEditor.Experimental.GraphView;
using UnityEditor.UIElements;
using UnityEngine.UIElements; using UnityEngine.UIElements;
namespace Misaki.GraphView.Editor namespace Misaki.GraphView.Editor
@@ -19,6 +16,8 @@ namespace Misaki.GraphView.Editor
_editor = editor; _editor = editor;
} }
public override bool IsDroppable() => true;
public override void OnSelected() public override void OnSelected()
{ {
base.OnSelected(); base.OnSelected();
@@ -31,7 +30,7 @@ namespace Misaki.GraphView.Editor
OnItemSelected?.Invoke(null); OnItemSelected?.Invoke(null);
} }
public virtual EditorNodeView CreateNodeView() public virtual ExecutableNodeView CreateNodeView()
{ {
return null; return null;
} }

View File

@@ -70,7 +70,7 @@ namespace Misaki.GraphView.Editor
exposedProperty.propertyName = newValue; exposedProperty.propertyName = newValue;
_owner.Query<PropertyInputNodeView>().ForEach(n => _owner.Query<PropertyInputNodeView>().ForEach(n =>
{ {
if (n.DataNode.Property.Equals(exposedProperty)) if (n.Data.Property.Equals(exposedProperty))
{ {
n.title = newValue; n.title = newValue;
} }

View File

@@ -1,8 +1,6 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using UnityEditor; using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.UIElements; using UnityEditor.UIElements;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;

View File

@@ -33,7 +33,7 @@ namespace Misaki.GraphView.Editor
gridBackground.SendToBack(); gridBackground.SendToBack();
var minimapConfig = _graphViewConfig.miniMapConfig; var minimapConfig = _graphViewConfig.miniMapConfig;
if (minimapConfig != null && minimapConfig.enable) if (minimapConfig is { enable: true })
{ {
var minimap = new MiniMap() var minimap = new MiniMap()
{ {
@@ -76,6 +76,9 @@ namespace Misaki.GraphView.Editor
InitializeAssetElements(); InitializeAssetElements();
graphViewChanged += OnGraphViewChanged; graphViewChanged += OnGraphViewChanged;
RegisterCallback<DragPerformEvent>(OnDragPerform);
RegisterCallbackOnce<GeometryChangedEvent>(_ => _graphInspectorView?.DockToParent(layout, DockingPosition.Right, false));
} }
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt) public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
@@ -125,10 +128,6 @@ namespace Misaki.GraphView.Editor
{ {
AddConnectionView(connection); AddConnectionView(connection);
} }
RegisterCallback<DragPerformEvent>(OnDragPerform);
RegisterCallbackOnce<GeometryChangedEvent>(_ => _graphInspectorView?.DockToParent(layout, DockingPosition.Right, false));
} }
private GraphViewChange OnGraphViewChanged(GraphViewChange graphViewChange) private GraphViewChange OnGraphViewChanged(GraphViewChange graphViewChange)
@@ -140,7 +139,7 @@ namespace Misaki.GraphView.Editor
for (var i = removedElements.Count - 1; i >= 0; i--) for (var i = removedElements.Count - 1; i >= 0; i--)
{ {
if (removedElements[i] is Node { userData: SlotContainerNode node }) if (removedElements[i] is Node { userData: ExecutableNode node })
{ {
RemoveNode(node); RemoveNode(node);
} }
@@ -154,14 +153,17 @@ namespace Misaki.GraphView.Editor
{ {
if (_slotConnections.Remove(edge, out var connection)) if (_slotConnections.Remove(edge, out var connection))
{ {
var inputSlotData = connection.InputSlotData; var inputNode = _graphObject.GetNode(connection.InputSlotData.nodeID);
var outputSlotData = connection.OutputSlotData; var outputNode = _graphObject.GetNode(connection.OutputSlotData.nodeID);
var inputSlot = _graphObject.GetNode(inputSlotData.nodeID)
.GetSlot(inputSlotData.slotIndex, inputSlotData.direction); if (inputNode is ISlotContainer inputSlotContainer && outputNode is ISlotContainer outputSlotContainer)
var outputSlot = _graphObject.GetNode(outputSlotData.nodeID) {
.GetSlot(outputSlotData.slotIndex, outputSlotData.direction); var inputSlot = inputSlotContainer.GetSlot(connection.InputSlotData.slotIndex, connection.InputSlotData.direction);
var outputSlot = outputSlotContainer.GetSlot(connection.OutputSlotData.slotIndex, connection.OutputSlotData.direction);
inputSlot.Unlink(outputSlot);
}
inputSlot.Unlink(outputSlot);
RemoveConnection(connection); RemoveConnection(connection);
} }
} }
@@ -230,55 +232,50 @@ namespace Misaki.GraphView.Editor
private void OnDragPerform(DragPerformEvent evt) private void OnDragPerform(DragPerformEvent evt)
{ {
var data = DragAndDrop.GetGenericData("DragSelection"); var data = DragAndDrop.GetGenericData("DragSelection");
if (data is List<ExposedProperty> properties) if (data is List<ISelectable> selectables)
{ {
var position = contentViewContainer.WorldToLocal(evt.mousePosition); var propertyViews = selectables.OfType<BlackboardPropertyView>().ToArray();
foreach (var property in properties) if (propertyViews.Length <= 0)
{ {
var baseNode = new PropertyInputNode(property); return;
baseNode.position = new Rect(position, Vector2.zero); }
var position = (evt.currentTarget as VisualElement).ChangeCoordinatesTo(contentViewContainer, evt.localMousePosition);
foreach (var view in propertyViews)
{
if (view.userData is not ExposedProperty property)
{
continue;
}
var baseNode = new PropertyInput(property)
{
position = new Rect(position, Vector2.zero)
};
AddNode(baseNode); AddNode(baseNode);
} }
} }
} }
public void AddNode(SlotContainerNode slotContainerNode) public void AddNode(ExecutableNode executableNode)
{ {
Undo.RecordObject(_graphObject, $"Add {slotContainerNode.GetType().Name}"); Undo.RecordObject(_graphObject, $"Add {executableNode.GetType().Name}");
_graphObject.AddNode(slotContainerNode); _graphObject.AddNode(executableNode);
AddNodeView(slotContainerNode); AddNodeView(executableNode);
EditorUtility.SetDirty(_graphObject); EditorUtility.SetDirty(_graphObject);
} }
public virtual void AddNodeView(SlotContainerNode slotContainerNode) private void AddNodeView(DataNode node)
{ {
Node nodeView; var nodeView = CreateNodeView(node);
var types = TypeCache.GetTypesWithAttribute<CustomInspectorAttribute>();
var type = types.FirstOrDefault(t =>
t.GetCustomAttribute<CustomInspectorAttribute>().InspectorType == slotContainerNode.GetType());
if (slotContainerNode is PropertyInputNode propertyInputNode)
{
// type ??= typeof(PropertyInputNodeView);
// var slot = propertyInputNode.GetSlot(0, SlotDirection.Output);
// nodeView = Activator.CreateInstance(type, propertyInputNode, _graphViewConfig.portColorManager) as PropertyInputNodeView;
nodeView = PropertyInputNodeView.Create(propertyInputNode, _graphViewConfig.portColorManager);
}
else
{
type ??= typeof(EditorNodeView);
nodeView = Activator.CreateInstance(type, slotContainerNode, _graphViewConfig.serializedObject, _graphViewConfig.portColorManager, _graphObject.Logger) as EditorNodeView;
}
if (nodeView == null) if (nodeView == null)
{ {
return; return;
} }
nodeView.SetPosition(slotContainerNode.position); nodeView.SetPosition(node.position);
if (nodeView is IInspectable inspectable) if (nodeView is IInspectable inspectable)
{ {
@@ -286,22 +283,41 @@ namespace Misaki.GraphView.Editor
} }
AddElement(nodeView); AddElement(nodeView);
_nodeViewsMap.Add(slotContainerNode.Id, nodeView); _nodeViewsMap.Add(node.Id, nodeView);
} }
private void RemoveNode(SlotContainerNode slotContainerNode) protected virtual Node CreateNodeView(DataNode node)
{ {
Undo.RecordObject(_graphObject, $"Remove {slotContainerNode.GetType().Name}"); var types = TypeCache.GetTypesWithAttribute<CustomInspectorAttribute>();
var type = types.FirstOrDefault(t =>
t.GetCustomAttribute<CustomInspectorAttribute>().InspectorType == node.GetType());
_graphObject.RemoveNode(slotContainerNode); if (node is PropertyInput propertyInputNode)
RemoveNodeView(slotContainerNode); {
return PropertyInputNodeView.Create(propertyInputNode, _graphViewConfig.portColorManager);
}
else if (node is ExecutableNode executableNode)
{
type ??= typeof(ExecutableNodeView);
return Activator.CreateInstance(type, executableNode, _graphViewConfig.serializedObject, _graphViewConfig.portColorManager, _graphObject.Logger) as ExecutableNodeView;
}
return null;
}
private void RemoveNode(ExecutableNode executableNode)
{
Undo.RecordObject(_graphObject, $"Remove {executableNode.GetType().Name}");
_graphObject.RemoveNode(executableNode);
RemoveNodeView(executableNode);
EditorUtility.SetDirty(_graphObject); EditorUtility.SetDirty(_graphObject);
} }
private void RemoveNodeView(SlotContainerNode slotContainerNode) private void RemoveNodeView(ExecutableNode executableNode)
{ {
if (_nodeViewsMap.Remove(slotContainerNode.Id, out var nodeView)) if (_nodeViewsMap.Remove(executableNode.Id, out var nodeView))
{ {
RemoveElement(nodeView); RemoveElement(nodeView);

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6a9b88871c5c4e728c7d39476e3e4571
timeCreated: 1730721654

View File

@@ -8,7 +8,7 @@ namespace Misaki.GraphView.Editor
{ {
public sealed class GraphInspectorView : GraphSubWindow public sealed class GraphInspectorView : GraphSubWindow
{ {
private const string UIDocumentPath = "Packages/com.misaki.graph-view/Editor/Views/GraphInspectorView.uxml"; private const string UI_Document_Path = "Packages/com.misaki.graph-view/Editor/Views/Inspector/GraphInspectorView.uxml";
private readonly Label _header; private readonly Label _header;
private readonly VisualElement _inspectorPropertiesContainer; private readonly VisualElement _inspectorPropertiesContainer;
@@ -21,7 +21,7 @@ namespace Misaki.GraphView.Editor
style.minWidth = 300; style.minWidth = 300;
style.minHeight = 500; style.minHeight = 500;
var uiDocument = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UIDocumentPath); var uiDocument = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UI_Document_Path);
var inspectorView = uiDocument.Instantiate(); var inspectorView = uiDocument.Instantiate();
inspectorView.style.flexGrow = 1; inspectorView.style.flexGrow = 1;

View File

@@ -10,9 +10,9 @@ using UnityEngine.UIElements;
namespace Misaki.GraphView.Editor namespace Misaki.GraphView.Editor
{ {
public class EditorNodeView : Node, IInspectable, IPortContainer public class ExecutableNodeView : Node, IInspectable, IPortContainer
{ {
private readonly SlotContainerNode _dataNode; private readonly ExecutableNode _dataNode;
private readonly Type _nodeType; private readonly Type _nodeType;
private readonly NodeInfoAttribute _nodeInfo; private readonly NodeInfoAttribute _nodeInfo;
@@ -24,7 +24,6 @@ namespace Misaki.GraphView.Editor
private readonly VisualElement _logContainer = new(); private readonly VisualElement _logContainer = new();
public SlotContainerNode DataNode => _dataNode;
public List<Port> InputPorts => _inputPorts; public List<Port> InputPorts => _inputPorts;
public List<Port> OutputPorts => _outputPorts; public List<Port> OutputPorts => _outputPorts;
@@ -32,7 +31,7 @@ namespace Misaki.GraphView.Editor
public string InspectorName => _nodeInfo.Name ?? _nodeType.Name; public string InspectorName => _nodeInfo.Name ?? _nodeType.Name;
public EditorNodeView(SlotContainerNode dataNode, SerializedObject serializedObject, IPortColorManager portColorManager, ILogger logger) public ExecutableNodeView(ExecutableNode dataNode, SerializedObject serializedObject, IPortColorManager portColorManager, ILogger logger)
{ {
if (dataNode == null) if (dataNode == null)
{ {
@@ -59,7 +58,7 @@ namespace Misaki.GraphView.Editor
AddToClassList(depth.ToLower().Replace(" ", "-")); AddToClassList(depth.ToLower().Replace(" ", "-"));
} }
var inputs = _nodeType.GetProperty(nameof(SlotContainerNode.Inputs)); var inputs = _nodeType.GetProperty(nameof(ExecutableNode.Inputs));
if (inputs != null) if (inputs != null)
{ {
@@ -78,7 +77,7 @@ namespace Misaki.GraphView.Editor
} }
} }
var outputs = _nodeType.GetProperty(nameof(SlotContainerNode.Outputs)); var outputs = _nodeType.GetProperty(nameof(ExecutableNode.Outputs));
if (outputs != null) if (outputs != null)
{ {
@@ -101,14 +100,14 @@ namespace Misaki.GraphView.Editor
Add(_logContainer); Add(_logContainer);
_dataNode.OnExecuteFlagCleared += OnExecuteFlagCleared; _dataNode.OnExecuteFlagCleared += OnExecuteFlagCleared;
_dataNode.OnExecutionFailed += (_) => AddToClassList("node-execution-failed"); _dataNode.OnExecutionFailed += () => AddToClassList("node-execution-failed");
if (logger != null) if (logger != null)
{ {
logger.OnLog += CreateLogElement; logger.OnLog += CreateLogElement;
} }
} }
private void CreateLogElement(SlotContainerNode node, string message, LogType type) private void CreateLogElement(ExecutableNode node, string message, LogType type)
{ {
if (node.Id != _dataNode.Id) if (node.Id != _dataNode.Id)
{ {

View File

@@ -11,38 +11,38 @@ namespace Misaki.GraphView.Editor
{ {
private readonly List<Port> _outputPorts = new List<Port>(); private readonly List<Port> _outputPorts = new List<Port>();
private readonly PropertyInputNode _dataNode; private readonly PropertyInput _data;
//private readonly ExposedPropertyEditor _editor; //private readonly ExposedPropertyEditor _editor;
public PropertyInputNode DataNode => _dataNode; public PropertyInput Data => _data;
public List<Port> InputPorts => null; public List<Port> InputPorts => null;
public List<Port> OutputPorts => _outputPorts; public List<Port> OutputPorts => _outputPorts;
public PropertyInputNodeView(PropertyInputNode dataNode, Port output) : base(null, output) public PropertyInputNodeView(PropertyInput data, Port output) : base(null, output)
{ {
_dataNode = dataNode; _data = data;
//_editor = editor; //_editor = editor;
name = dataNode.Property.propertyName; name = data.Property.propertyName;
title = dataNode.Property.propertyName; title = data.Property.propertyName;
userData = dataNode; userData = data;
this.Q<VisualElement>("top").style.minHeight = 24; this.Q<VisualElement>("top").style.minHeight = 24;
_outputPorts.Add(output); _outputPorts.Add(output);
} }
public static PropertyInputNodeView Create(PropertyInputNode dataNode, IPortColorManager portColorManager) public static PropertyInputNodeView Create(PropertyInput data, IPortColorManager portColorManager)
{ {
if (dataNode == null) if (data == null)
{ {
return null; return null;
} }
var outputSlot = dataNode.GetSlot(0, SlotDirection.Output); var outputSlot = data.GetSlot(0, SlotDirection.Output);
var outputPort = CreateOutputPort(dataNode.Property, outputSlot, portColorManager); var outputPort = CreateOutputPort(data.Property, outputSlot, portColorManager);
var nodeView = new PropertyInputNodeView(dataNode, outputPort); var nodeView = new PropertyInputNodeView(data, outputPort);
return nodeView; return nodeView;
} }
@@ -68,12 +68,12 @@ namespace Misaki.GraphView.Editor
return port; return port;
} }
public string InspectorName => _dataNode.Property.propertyName; public string InspectorName => _data.Property.propertyName;
public override void SetPosition(Rect newPos) public override void SetPosition(Rect newPos)
{ {
base.SetPosition(newPos); base.SetPosition(newPos);
_dataNode.position = newPos; _data.position = newPos;
} }
} }
} }

View File

@@ -9,7 +9,7 @@ namespace Misaki.GraphView
public void UpdateComputeOrder(); public void UpdateComputeOrder();
public void Execute(ReadOnlyCollection<SlotContainerNode> nodes); public void Execute(ReadOnlyCollection<DataNode> nodes);
public void Break(); public void Break();
} }

View File

@@ -5,11 +5,11 @@ namespace Misaki.GraphView
{ {
public interface ILogger public interface ILogger
{ {
public Action<SlotContainerNode, string, LogType> OnLog { get; set; } public Action<ExecutableNode, string, LogType> OnLog { get; set; }
public void LogInfo(SlotContainerNode node, string message); public void LogInfo(ExecutableNode node, string message);
public void LogWarning(SlotContainerNode node, string message); public void LogWarning(ExecutableNode node, string message);
public void LogError(SlotContainerNode node, string message); public void LogError(ExecutableNode node, string message);
public void ClearLogs(); public void ClearLogs();
} }

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6f808cfad7db49a4aecc5cf32d110d83
timeCreated: 1730715252

View File

@@ -0,0 +1,15 @@
namespace Misaki.GraphView
{
public interface IExecutable
{
/// <summary>
/// Execute the node.
/// </summary>
public void Execute();
/// <summary>
/// Clear the execution flag.
/// </summary>
public void ClearExecutionFlag();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e01466f05b7b4e3f8037d2e28845da5c
timeCreated: 1730715301

View File

@@ -0,0 +1,30 @@
namespace Misaki.GraphView
{
public interface ISlotContainer
{
/// <summary>
/// Add the slot to the container.
/// </summary>
/// <param name="slot"> <see cref="Slot"/> The slot want to add </param>
public void AddSlot(Slot slot);
/// <summary>
/// Remove the slot from the container.
/// </summary>
/// <param name="slot"> <see cref="Slot"/> The slot want to remove </param>
public void RemoveSlot(Slot slot);
/// <summary>
/// Get the slot by the index and direction.
/// </summary>
/// <param name="index"> <see cref="int"/> Index of the slot</param>
/// <param name="direction"> <see cref="SlotDirection"/> Direction of the slot </param>
/// <returns> <see cref="Slot"/> The slot that matches the index and direction </returns>
public Slot GetSlot(int index, SlotDirection direction);
/// <summary>
/// Unlink all the slots of the node.
/// </summary>
public void UnlinkAllSlots();
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3ed41f0fefcd4fa58cd60c6ccc6a5953
timeCreated: 1730716599

View File

@@ -1,15 +0,0 @@
using System.Collections.Generic;
namespace Misaki.GraphView
{
public static class BaseNodeExtension
{
public static void ClearAllExecuteFlag(this IList<SlotContainerNode> nodes)
{
foreach (var node in nodes)
{
node.ClearExecuteFlag();
}
}
}
}

View File

@@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace Misaki.GraphView
{
public static class DataNodeExtension
{
public static void ClearAllExecuteFlag(this IList<DataNode> nodes)
{
foreach (var node in nodes)
{
if (node is IExecutable executable)
{
executable.ClearExecutionFlag();
}
}
}
}
}

View File

@@ -13,8 +13,12 @@ namespace Misaki.GraphView
for (var i = 0; i < slotCount; i++) for (var i = 0; i < slotCount; i++)
{ {
var other = slot.LinkedSlotData[i]; var other = slot.LinkedSlotData[i];
var otherSlot = slot.owner.GraphObject.GetNode(other.nodeID).GetSlot(other.slotIndex, other.direction); var otherNode = slot.owner.GraphObject.GetNode(other.nodeID);
otherSlot.owner.GetSlot(other.slotIndex, other.direction)?.Unlink(slot);
if (otherNode is ISlotContainer slotContainer)
{
slotContainer.GetSlot(other.slotIndex, other.direction)?.Unlink(slot);
}
} }
} }

View File

@@ -1,7 +1,7 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using UnityEditor.Experimental.GraphView;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
@@ -10,7 +10,7 @@ namespace Misaki.GraphView
public abstract class GraphObject : ScriptableObject public abstract class GraphObject : ScriptableObject
{ {
[SerializeReference] [SerializeReference]
private List<SlotContainerNode> _nodes = new(); private List<DataNode> _nodes = new();
[SerializeField] [SerializeField]
private List<StickyNoteData> _stickyNotes = new(); private List<StickyNoteData> _stickyNotes = new();
[SerializeField] [SerializeField]
@@ -18,9 +18,9 @@ namespace Misaki.GraphView
[SerializeReference] [SerializeReference]
private List<ExposedProperty> _exposedProperties = new(); 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<StickyNoteData> StickyNotes => _stickyNotes.AsReadOnly();
public ReadOnlyCollection<SlotConnection> Connections => _connections.AsReadOnly(); public ReadOnlyCollection<SlotConnection> Connections => _connections.AsReadOnly();
public ReadOnlyCollection<ExposedProperty> ExposedProperties => _exposedProperties.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); _nodes.Add(executableNode);
TryAddNodeToMap(slotContainerNode); TryAddNodeToMap(executableNode);
slotContainerNode.Initialize(this); executableNode.Initialize(this);
} }
public void RemoveNode(SlotContainerNode slotContainerNode) public void RemoveNode(DataNode node)
{ {
_nodes.Remove(slotContainerNode); _nodes.Remove(node);
RemoveNodeFromMap(slotContainerNode); RemoveNodeFromMap(node);
slotContainerNode.UnLoad(); node.Dispose();
slotContainerNode.UnlinkAllSlots();
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); 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) public void AddStickyNote(StickyNoteData stickyNote)
@@ -128,7 +132,7 @@ namespace Misaki.GraphView
{ {
if (GraphProcessor == null) if (GraphProcessor == null)
{ {
return; throw new ArgumentNullException(nameof(GraphProcessor), "GraphProcessor is null.");
} }
GraphProcessor.UpdateComputeOrder(); GraphProcessor.UpdateComputeOrder();

View 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;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 0e9d8eecbaad45cb8da2c61ae9c6afc4
timeCreated: 1730715419

View File

@@ -1,34 +1,32 @@
using System; using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Reflection; using System.Reflection;
using UnityEngine; using UnityEngine;
namespace Misaki.GraphView namespace Misaki.GraphView
{ {
[Serializable] [Serializable]
public abstract class SlotContainerNode : SlotContainer public abstract class ExecutableNode : DataNode, ISlotContainer, IExecutable
{ {
[SerializeField] [SerializeField]
private GraphObject _graphObject; private List<Slot> _inputs = new ();
[SerializeField] [SerializeField]
private string _id = Guid.NewGuid().ToString(); private List<Slot> _outputs = new ();
public ReadOnlyCollection<Slot> Inputs => _inputs.AsReadOnly();
public ReadOnlyCollection<Slot> Outputs => _outputs.AsReadOnly();
private bool _isExecuted; private bool _isExecuted;
public Rect position; public Action OnExecutoinStarted;
public GraphObject GraphObject => _graphObject;
public string Id => _id;
public Action OnExecutionCompleted; public Action OnExecutionCompleted;
public Action<SlotContainerNode> OnExecutionFailed; public Action OnExecutionFailed;
public Action OnExecuteFlagCleared; public Action OnExecuteFlagCleared;
/// <summary> public override void Initialize(GraphObject graph)
/// 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)
{ {
_graphObject = graph; graphObject = graph;
InitializeSlot(); InitializeSlot();
} }
@@ -53,7 +51,7 @@ namespace Misaki.GraphView
direction = SlotDirection.Input, direction = SlotDirection.Input,
valueType = field.FieldType.FullName valueType = field.FieldType.FullName
}); });
AddInput(inputSlot); AddSlot(inputSlot);
continue; continue;
} }
@@ -69,24 +67,40 @@ namespace Misaki.GraphView
direction = SlotDirection.Output, direction = SlotDirection.Output,
valueType = field.FieldType.FullName valueType = field.FieldType.FullName
}); });
AddOutput(outputSlot); AddSlot(outputSlot);
} }
} }
} }
/// <summary> /// <inheritdoc />
/// Unload the node from the graph, this method is called when the node is removed from the graph. public void AddSlot(Slot slot)
/// </summary>
public virtual void UnLoad()
{ {
switch (slot.slotData.direction)
{
case SlotDirection.Input:
_inputs.Add(slot);
break;
case SlotDirection.Output:
_outputs.Add(slot);
break;
}
} }
/// <summary> /// <inheritdoc />
/// Get the slot by the index and direction. public void RemoveSlot(Slot slot)
/// </summary> {
/// <param name="index"> Index of the slot</param> switch (slot.slotData.direction)
/// <param name="direction"> Direction of the slot </param> {
/// <returns> <see cref="Slot"/> The slot that matches the index and direction </returns> case SlotDirection.Input:
_inputs.Remove(slot);
break;
case SlotDirection.Output:
_outputs.Remove(slot);
break;
}
}
/// <inheritdoc />
public Slot GetSlot(int index, SlotDirection direction) public Slot GetSlot(int index, SlotDirection direction)
{ {
return direction switch return direction switch
@@ -97,27 +111,23 @@ namespace Misaki.GraphView
}; };
} }
/// <summary> /// <inheritdoc />
/// Unlink all the slots of the node.
/// </summary>
public void UnlinkAllSlots() public void UnlinkAllSlots()
{ {
foreach (var input in Inputs) foreach (var input in Inputs)
{ {
input.UnlinkAll(); input.UnlinkAll();
_graphObject.RemoveAllConnectionsForSlot(input); graphObject.RemoveAllConnectionsForSlot(input);
} }
foreach (var output in Outputs) foreach (var output in Outputs)
{ {
output.UnlinkAll(); output.UnlinkAll();
_graphObject.RemoveAllConnectionsForSlot(output); graphObject.RemoveAllConnectionsForSlot(output);
} }
} }
/// <summary> /// <inheritdoc />
/// Execute the node.
/// </summary>
public void Execute() public void Execute()
{ {
if (_isExecuted) if (_isExecuted)
@@ -125,25 +135,35 @@ namespace Misaki.GraphView
return; return;
} }
OnExecutoinStarted?.Invoke();
PullData(); PullData();
if (!_graphObject.GraphProcessor.IsRunning) if (!graphObject.GraphProcessor.IsRunning)
{ {
return; return;
} }
if (!OnExecute()) if (!OnExecute())
{ {
_graphObject.GraphProcessor.Break(); graphObject.GraphProcessor.Break();
OnExecutionFailed?.Invoke(this); OnExecutionFailed?.Invoke();
return; return;
} }
PushData(); PushData();
_isExecuted = true; _isExecuted = true;
OnExecutionCompleted?.Invoke(); OnExecutionCompleted?.Invoke();
} }
/// <inheritdoc />
public void ClearExecutionFlag()
{
_isExecuted = false;
OnExecuteFlagCleared?.Invoke();
}
private void PullData() private void PullData()
{ {
foreach (var input in Inputs) foreach (var input in Inputs)
@@ -184,13 +204,18 @@ namespace Misaki.GraphView
output.value = property.GetValue(this); output.value = property.GetValue(this);
foreach (var slotData in output.LinkedSlotData) 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) if (slotData.valueType == output.slotData.valueType || output.slotData.valueType == typeof(object).FullName)
{ {
slot.ReceiveData(output.value); 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)) slotData.GetValueType(), output.value, out var data))
{ {
slot.ReceiveData(data); slot.ReceiveData(data);
@@ -203,17 +228,6 @@ namespace Misaki.GraphView
{ {
} }
public bool IsExecuted()
{
return _isExecuted;
}
public void ClearExecuteFlag()
{
_isExecuted = false;
OnExecuteFlagCleared?.Invoke();
}
/// <summary> /// <summary>
/// The execution logic of the node. /// The execution logic of the node.
/// </summary> /// </summary>

View File

@@ -3,7 +3,7 @@ using UnityEngine;
namespace Misaki.GraphView namespace Misaki.GraphView
{ {
public class PropertyInputNode : SlotContainerNode public class PropertyInput : ExecutableNode
{ {
[SerializeReference] [SerializeReference]
private ExposedProperty _property; private ExposedProperty _property;
@@ -13,7 +13,7 @@ namespace Misaki.GraphView
[NodeOutput] [NodeOutput]
public object value; public object value;
public PropertyInputNode(ExposedProperty property) public PropertyInput(ExposedProperty property)
{ {
_property = property; _property = property;
} }

View File

@@ -0,0 +1,9 @@
using UnityEngine;
namespace Misaki.GraphView
{
public class RelayNode
{
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4770061645971f7439b85f93d50c6b3b

View File

@@ -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();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 0a8f9433f38644d78ab2a8bc47cc54bd
timeCreated: 1730116658

View File

@@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Reflection;
using UnityEngine; using UnityEngine;
namespace Misaki.GraphView namespace Misaki.GraphView
@@ -50,12 +49,12 @@ namespace Misaki.GraphView
public ReadOnlyCollection<SlotData> LinkedSlotData => _linkedSlotData.AsReadOnly(); public ReadOnlyCollection<SlotData> LinkedSlotData => _linkedSlotData.AsReadOnly();
[SerializeReference] [SerializeReference]
public SlotContainerNode owner; public DataNode owner;
public SlotData slotData; public SlotData slotData;
public object value; public object value;
public Slot(SlotContainerNode owner, SlotData slotData) public Slot(DataNode owner, SlotData slotData)
{ {
this.owner = owner; this.owner = owner;
this.slotData = slotData; this.slotData = slotData;

View File

@@ -13,10 +13,9 @@ MonoBehaviour:
m_Name: GraphAsset m_Name: GraphAsset
m_EditorClassIdentifier: m_EditorClassIdentifier:
_nodes: _nodes:
- rid: 299037523270959196 - rid: 299037570321612880
- rid: 299037523270959197 - rid: 299037570321612881
- rid: 299037523270959199 - rid: 299037570321612882
- rid: 299037535202443351
_stickyNotes: _stickyNotes:
- _id: 940a3025-e571-4b33-8d7c-c86761a95017 - _id: 940a3025-e571-4b33-8d7c-c86761a95017
title: Title title: Title
@@ -30,42 +29,30 @@ MonoBehaviour:
theme: 0 theme: 0
fontSize: 1 fontSize: 1
_connections: _connections:
- _inputSlotData:
slotName: _input
nodeID: 1d18af80-6a54-4cdc-b49c-b53e74f56404
slotIndex: 0
direction: 0
valueType: System.Single
_outputSlotData:
slotName: _result
nodeID: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
slotIndex: 0
direction: 1
valueType: System.Single
- _inputSlotData: - _inputSlotData:
slotName: a slotName: a
nodeID: b055be5b-5e72-4715-8981-d38913599762 nodeID: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
slotIndex: 0 slotIndex: 0
direction: 0 direction: 0
valueType: System.Single valueType: System.Single
_outputSlotData: _outputSlotData:
slotName: value slotName: value
nodeID: 7a3d7992-0465-458a-bbd8-e972d77b1e34 nodeID: 5ee073fb-e411-4061-867a-9ce3afd9a188
slotIndex: 0 slotIndex: 0
direction: 1 direction: 1
valueType: System.Object valueType: System.Object
- _inputSlotData:
slotName: _input
nodeID: e630425e-5b42-4839-9e4a-9b134c1e497c
slotIndex: 0
direction: 0
valueType: System.Single
_outputSlotData:
slotName: _result
nodeID: c45162b3-f131-44ac-a36f-26b579c4626c
slotIndex: 0
direction: 1
valueType: System.Single
- _inputSlotData:
slotName: a
nodeID: c45162b3-f131-44ac-a36f-26b579c4626c
slotIndex: 0
direction: 0
valueType: System.Single
_outputSlotData:
slotName: _result
nodeID: b055be5b-5e72-4715-8981-d38913599762
slotIndex: 0
direction: 1
valueType: System.Single
_exposedProperties: _exposedProperties:
- rid: 299037523270959195 - rid: 299037523270959195
graphPosition: {x: 72, y: 28.666666, z: 0} graphPosition: {x: 72, y: 28.666666, z: 0}
@@ -81,163 +68,111 @@ MonoBehaviour:
propertyType: Misaki.GraphView.Sample.FloatProperty propertyType: Misaki.GraphView.Sample.FloatProperty
showInInspector: 1 showInInspector: 1
value: 1 value: 1
- rid: 299037523270959196 - rid: 299037570321612880
type: {class: PropertyInputNode, ns: Misaki.GraphView, asm: GraphView} type: {class: Add, ns: Misaki.GraphView.Sample, asm: GraphView.Sample}
data: data:
_inputs: [] graphObject: {fileID: 11400000}
_outputs: id: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
- _linkedSlotData:
- slotName: a
nodeID: b055be5b-5e72-4715-8981-d38913599762
slotIndex: 0
direction: 0
valueType: System.Single
owner:
rid: 299037523270959196
slotData:
slotName: value
nodeID: 7a3d7992-0465-458a-bbd8-e972d77b1e34
slotIndex: 0
direction: 1
valueType: System.Object
_graphObject: {fileID: 11400000}
_id: 7a3d7992-0465-458a-bbd8-e972d77b1e34
position: position:
serializedVersion: 2 serializedVersion: 2
x: 328.66666 x: 534
y: 503.99997 y: 418
width: 98.66666 width: 116.66669
height: 36 height: 102.66666
_property:
rid: 299037523270959195
- rid: 299037523270959197
type: {class: OutputNode, ns: Misaki.GraphView.Sample, asm: GraphView.Sample}
data:
_inputs:
- _linkedSlotData:
- slotName: _result
nodeID: c45162b3-f131-44ac-a36f-26b579c4626c
slotIndex: 0
direction: 1
valueType: System.Single
owner:
rid: 299037523270959197
slotData:
slotName: _input
nodeID: e630425e-5b42-4839-9e4a-9b134c1e497c
slotIndex: 0
direction: 0
valueType: System.Single
_outputs: []
_graphObject: {fileID: 11400000}
_id: e630425e-5b42-4839-9e4a-9b134c1e497c
position:
serializedVersion: 2
x: 847.9999
y: 437.3332
width: 124.66669
height: 78.66666
- rid: 299037523270959199
type: {class: AddNode, ns: Misaki.GraphView.Sample, asm: GraphView.Sample}
data:
_inputs: _inputs:
- _linkedSlotData: - _linkedSlotData:
- slotName: value - slotName: value
nodeID: 7a3d7992-0465-458a-bbd8-e972d77b1e34 nodeID: 5ee073fb-e411-4061-867a-9ce3afd9a188
slotIndex: 0 slotIndex: 0
direction: 1 direction: 1
valueType: System.Object valueType: System.Object
owner: owner:
rid: 299037523270959199 rid: 299037570321612880
slotData: slotData:
slotName: a slotName: a
nodeID: b055be5b-5e72-4715-8981-d38913599762 nodeID: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
slotIndex: 0 slotIndex: 0
direction: 0 direction: 0
valueType: System.Single valueType: System.Single
- _linkedSlotData: [] - _linkedSlotData: []
owner: owner:
rid: 299037523270959199 rid: 299037570321612880
slotData: slotData:
slotName: b slotName: b
nodeID: b055be5b-5e72-4715-8981-d38913599762 nodeID: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
slotIndex: 1
direction: 0
valueType: System.Single
_outputs:
- _linkedSlotData:
- slotName: a
nodeID: c45162b3-f131-44ac-a36f-26b579c4626c
slotIndex: 0
direction: 0
valueType: System.Single
owner:
rid: 299037523270959199
slotData:
slotName: _result
nodeID: b055be5b-5e72-4715-8981-d38913599762
slotIndex: 0
direction: 1
valueType: System.Single
_graphObject: {fileID: 11400000}
_id: b055be5b-5e72-4715-8981-d38913599762
position:
serializedVersion: 2
x: 495.33328
y: 437.3333
width: 116.66666
height: 102.66666
a: 1
b: 0
- rid: 299037535202443351
type: {class: AddNode, ns: Misaki.GraphView.Sample, asm: GraphView.Sample}
data:
_inputs:
- _linkedSlotData:
- slotName: _result
nodeID: b055be5b-5e72-4715-8981-d38913599762
slotIndex: 0
direction: 1
valueType: System.Single
owner:
rid: 299037535202443351
slotData:
slotName: a
nodeID: c45162b3-f131-44ac-a36f-26b579c4626c
slotIndex: 0
direction: 0
valueType: System.Single
- _linkedSlotData: []
owner:
rid: 299037535202443351
slotData:
slotName: b
nodeID: c45162b3-f131-44ac-a36f-26b579c4626c
slotIndex: 1 slotIndex: 1
direction: 0 direction: 0
valueType: System.Single valueType: System.Single
_outputs: _outputs:
- _linkedSlotData: - _linkedSlotData:
- slotName: _input - slotName: _input
nodeID: e630425e-5b42-4839-9e4a-9b134c1e497c nodeID: 1d18af80-6a54-4cdc-b49c-b53e74f56404
slotIndex: 0 slotIndex: 0
direction: 0 direction: 0
valueType: System.Single valueType: System.Single
owner: owner:
rid: 299037535202443351 rid: 299037570321612880
slotData: slotData:
slotName: _result slotName: _result
nodeID: c45162b3-f131-44ac-a36f-26b579c4626c nodeID: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
slotIndex: 0 slotIndex: 0
direction: 1 direction: 1
valueType: System.Single valueType: System.Single
_graphObject: {fileID: 11400000} a: 0
_id: c45162b3-f131-44ac-a36f-26b579c4626c b: 0
- rid: 299037570321612881
type: {class: Output, ns: Misaki.GraphView.Sample, asm: GraphView.Sample}
data:
graphObject: {fileID: 11400000}
id: 1d18af80-6a54-4cdc-b49c-b53e74f56404
position: position:
serializedVersion: 2 serializedVersion: 2
x: 679.3334 x: 760
y: 437.3333 y: 418
width: 116.66669 width: 124.66669
height: 102.66666 height: 78.66666
a: 1 _inputs:
b: 0 - _linkedSlotData:
- slotName: _result
nodeID: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
slotIndex: 0
direction: 1
valueType: System.Single
owner:
rid: 299037570321612881
slotData:
slotName: _input
nodeID: 1d18af80-6a54-4cdc-b49c-b53e74f56404
slotIndex: 0
direction: 0
valueType: System.Single
_outputs: []
- rid: 299037570321612882
type: {class: PropertyInput, ns: Misaki.GraphView, asm: GraphView}
data:
graphObject: {fileID: 11400000}
id: 5ee073fb-e411-4061-867a-9ce3afd9a188
position:
serializedVersion: 2
x: 335.3333
y: 484.6667
width: 98.66666
height: 36
_inputs: []
_outputs:
- _linkedSlotData:
- slotName: a
nodeID: 31f46c9e-45f1-418a-bb4b-cc843ea9242a
slotIndex: 0
direction: 0
valueType: System.Single
owner:
rid: 299037570321612882
slotData:
slotName: value
nodeID: 5ee073fb-e411-4061-867a-9ce3afd9a188
slotIndex: 0
direction: 1
valueType: System.Object
_property:
rid: 299037523270959195

View File

@@ -13,14 +13,14 @@ namespace Misaki.GraphView.Sample
{ {
} }
public void Execute(ReadOnlyCollection<SlotContainerNode> nodes) public void Execute(ReadOnlyCollection<DataNode> nodes)
{ {
_isRunning = true; _isRunning = true;
nodes.ClearAllExecuteFlag(); nodes.ClearAllExecuteFlag();
foreach (var node in nodes) foreach (var node in nodes)
{ {
if (node is OutputNode outputNode) if (node is Output outputNode)
{ {
outputNode.Execute(); outputNode.Execute();
} }

View File

@@ -7,21 +7,21 @@ namespace Misaki.GraphView.Sample
{ {
private readonly List<string> _logs = new (); private readonly List<string> _logs = new ();
public Action<SlotContainerNode, string, LogType> OnLog { get; set; } public Action<ExecutableNode, string, LogType> OnLog { get; set; }
public void LogInfo(SlotContainerNode node, string message) public void LogInfo(ExecutableNode node, string message)
{ {
_logs.Add($"Log Info from node {node.GetType().Name}: {message}"); _logs.Add($"Log Info from node {node.GetType().Name}: {message}");
OnLog?.Invoke(node, message, LogType.Info); OnLog?.Invoke(node, message, LogType.Info);
} }
public void LogWarning(SlotContainerNode node, string message) public void LogWarning(ExecutableNode node, string message)
{ {
_logs.Add($"Log Warning from node {node.GetType().Name}: {message}"); _logs.Add($"Log Warning from node {node.GetType().Name}: {message}");
OnLog?.Invoke(node, message, LogType.Warning); OnLog?.Invoke(node, message, LogType.Warning);
} }
public void LogError(SlotContainerNode node, string message) public void LogError(ExecutableNode node, string message)
{ {
_logs.Add($"Log Error from node {node.GetType().Name}: {message}"); _logs.Add($"Log Error from node {node.GetType().Name}: {message}");
OnLog?.Invoke(node, message, LogType.Error); OnLog?.Invoke(node, message, LogType.Error);

View File

@@ -5,7 +5,7 @@ using Misaki.GraphView.Editor;
namespace Misaki.GraphView.Sample namespace Misaki.GraphView.Sample
{ {
[NodeInfo("Add", "Math")] [NodeInfo("Add", "Math")]
public class AddNode : BackTraceNode public class Add : BackTraceExecutableNode
{ {
[NodeInput] [NodeInput]
#if UNITY_EDITOR #if UNITY_EDITOR

View File

@@ -1,6 +1,6 @@
namespace Misaki.GraphView.Sample namespace Misaki.GraphView.Sample
{ {
public abstract class BackTraceNode : SlotContainerNode public abstract class BackTraceExecutableNode : ExecutableNode
{ {
protected override void OnPullData(Slot input) protected override void OnPullData(Slot input)
{ {
@@ -10,7 +10,10 @@ namespace Misaki.GraphView.Sample
} }
var outputNode = GraphObject.GetNode(input.LinkedSlotData[0].nodeID); var outputNode = GraphObject.GetNode(input.LinkedSlotData[0].nodeID);
outputNode.Execute(); if (outputNode is IExecutable executable)
{
executable.Execute();
}
} }
} }
} }

View File

@@ -3,7 +3,7 @@ using UnityEngine;
namespace Misaki.GraphView.Sample namespace Misaki.GraphView.Sample
{ {
[NodeInfo("Output Node", "Output")] [NodeInfo("Output Node", "Output")]
public class OutputNode : BackTraceNode public class Output : BackTraceExecutableNode
{ {
[NodeInput] [NodeInput]
private float _input; private float _input;