Added RelayNodeView;
Chnaged GraphView to multiple files for better organization;
This commit is contained in:
@@ -1,441 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Misaki.GraphView.Editor
|
||||
{
|
||||
public class GraphView : UnityEditor.Experimental.GraphView.GraphView
|
||||
{
|
||||
private readonly Dictionary<string, Node> _nodeViewsMap = new();
|
||||
private readonly Dictionary<Edge, SlotConnection> _slotConnections = new();
|
||||
|
||||
private readonly GraphBlackboardView _blackboardView;
|
||||
private readonly GraphInspectorView _graphInspectorView;
|
||||
|
||||
private readonly GraphViewConfig _graphViewConfig;
|
||||
private GraphObject _graphObject => _graphViewConfig.graphObject;
|
||||
|
||||
public EditorWindow EditorWindow { get; }
|
||||
public GraphViewConfig GraphViewConfig => _graphViewConfig;
|
||||
|
||||
public GraphView(EditorWindow editorWindow, GraphViewConfig graphViewConfig)
|
||||
{
|
||||
EditorWindow = editorWindow;
|
||||
_graphViewConfig = graphViewConfig;
|
||||
|
||||
var gridBackground = new GridBackground { name = "gridBackground" };
|
||||
Add(gridBackground);
|
||||
gridBackground.SendToBack();
|
||||
|
||||
var minimapConfig = _graphViewConfig.miniMapConfig;
|
||||
if (minimapConfig is { enable: true })
|
||||
{
|
||||
var minimap = new MiniMap()
|
||||
{
|
||||
anchored = true
|
||||
};
|
||||
minimap.SetPosition(minimapConfig.position);
|
||||
Add(minimap);
|
||||
}
|
||||
|
||||
_blackboardView = new GraphBlackboardView(_graphObject, this, _graphViewConfig.serializedObject, _graphViewConfig.exposedPropertyTypeManager);
|
||||
_blackboardView.OnPropertySelected += ChangeInspectorView;
|
||||
|
||||
foreach (var property in _graphObject.ExposedProperties)
|
||||
{
|
||||
_blackboardView.AddProperty(property);
|
||||
}
|
||||
|
||||
_graphInspectorView = new GraphInspectorView();
|
||||
|
||||
Add(_blackboardView);
|
||||
Add(_graphInspectorView);
|
||||
|
||||
this.StretchToParentSize();
|
||||
|
||||
this.AddManipulator(new ContentDragger());
|
||||
this.AddManipulator(new SelectionDragger());
|
||||
this.AddManipulator(new RectangleSelector());
|
||||
this.AddManipulator(new ClickSelector());
|
||||
|
||||
var zoomConfig = _graphViewConfig.zoomConfig;
|
||||
var zoomer = new ContentZoomer();
|
||||
if (zoomConfig !=null)
|
||||
{
|
||||
zoomer.minScale = zoomConfig.minScale;
|
||||
zoomer.maxScale = zoomConfig.maxScale;
|
||||
zoomer.scaleStep = zoomConfig.scaleStep;
|
||||
}
|
||||
this.AddManipulator(zoomer);
|
||||
|
||||
InitializeAssetElements();
|
||||
|
||||
graphViewChanged += OnGraphViewChanged;
|
||||
|
||||
RegisterCallback<DragPerformEvent>(OnDragPerform);
|
||||
RegisterCallbackOnce<GeometryChangedEvent>(_ => _graphInspectorView?.DockToParent(layout, DockingPosition.Right, false));
|
||||
}
|
||||
|
||||
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
|
||||
{
|
||||
base.BuildContextualMenu(evt);
|
||||
var mousePosition = (evt.currentTarget as VisualElement).ChangeCoordinatesTo(contentViewContainer, evt.localMousePosition);
|
||||
|
||||
if (selection.Count == 0)
|
||||
{
|
||||
evt.menu.InsertAction(1, "Create Sticky Note", e =>
|
||||
{
|
||||
var stickyNote = new StickyNoteData
|
||||
{
|
||||
title = "Sticky Note",
|
||||
contents = "Contents",
|
||||
theme = StickyNoteTheme.Classic,
|
||||
fontSize = StickyNoteFontSize.Medium,
|
||||
position = new Rect(mousePosition, new Vector2(200, 200))
|
||||
};
|
||||
|
||||
AddStickyNote(stickyNote);
|
||||
}, DropdownMenuAction.AlwaysEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeAssetElements()
|
||||
{
|
||||
var searchProvider = ScriptableObject.CreateInstance<NodeSearchProvider>();
|
||||
searchProvider.SetOwner(this);
|
||||
|
||||
nodeCreationRequest = context =>
|
||||
{
|
||||
SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), searchProvider);
|
||||
};
|
||||
|
||||
foreach (var node in _graphObject.Nodes)
|
||||
{
|
||||
AddNodeView(node);
|
||||
}
|
||||
|
||||
foreach (var noteData in _graphObject.StickyNotes)
|
||||
{
|
||||
AddStickyNoteView(noteData);
|
||||
}
|
||||
|
||||
foreach (var connection in _graphObject.Connections)
|
||||
{
|
||||
AddConnectionView(connection);
|
||||
}
|
||||
}
|
||||
|
||||
private GraphViewChange OnGraphViewChanged(GraphViewChange graphViewChange)
|
||||
{
|
||||
if (graphViewChange.elementsToRemove != null)
|
||||
{
|
||||
var removedElements = graphViewChange.elementsToRemove;
|
||||
Undo.RecordObject(_graphObject, "Remove elements");
|
||||
|
||||
for (var i = removedElements.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (removedElements[i] is Node { userData: ExecutableNode node })
|
||||
{
|
||||
RemoveNode(node);
|
||||
}
|
||||
|
||||
if (removedElements[i] is StickyNote {userData : StickyNoteData stickyNote})
|
||||
{
|
||||
RemoveStickyNote(stickyNote);
|
||||
}
|
||||
|
||||
if (removedElements[i] is Edge edge)
|
||||
{
|
||||
if (_slotConnections.Remove(edge, out var connection))
|
||||
{
|
||||
var inputNode = _graphObject.GetNode(connection.InputSlotData.nodeID);
|
||||
var outputNode = _graphObject.GetNode(connection.OutputSlotData.nodeID);
|
||||
|
||||
if (inputNode is ISlotContainer inputSlotContainer && outputNode is ISlotContainer outputSlotContainer)
|
||||
{
|
||||
var inputSlot = inputSlotContainer.GetSlot(connection.InputSlotData.slotIndex, connection.InputSlotData.direction);
|
||||
var outputSlot = outputSlotContainer.GetSlot(connection.OutputSlotData.slotIndex, connection.OutputSlotData.direction);
|
||||
|
||||
inputSlot.Unlink(outputSlot);
|
||||
}
|
||||
|
||||
RemoveConnection(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (graphViewChange.movedElements != null)
|
||||
// {
|
||||
// var movedElements = graphViewChange.movedElements;
|
||||
// Undo.RecordObject(_graphObject, $"Move {movedElements.FirstOrDefault()?.GetType().Name}");
|
||||
//
|
||||
// foreach (var element in graphViewChange.movedElements)
|
||||
// {
|
||||
// element.SetPosition(element.GetPosition());
|
||||
// }
|
||||
// }
|
||||
|
||||
if (graphViewChange.edgesToCreate != null)
|
||||
{
|
||||
var createdEdges = graphViewChange.edgesToCreate;
|
||||
Undo.RecordObject(_graphObject, $"Connect {createdEdges.FirstOrDefault()?.GetType().Name}");
|
||||
|
||||
foreach (var edge in createdEdges)
|
||||
if (edge.input.userData is Slot inputSlot && edge.output.userData is Slot outputSlot)
|
||||
{
|
||||
var connection = new SlotConnection(inputSlot.slotData, outputSlot.slotData);
|
||||
_slotConnections.Add(edge, connection);
|
||||
|
||||
outputSlot.Link(inputSlot);
|
||||
AddConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
_graphObject.SetGraphTransform(viewTransform);
|
||||
|
||||
_graphViewConfig.serializedObject.Update();
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
|
||||
return graphViewChange;
|
||||
}
|
||||
|
||||
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
|
||||
{
|
||||
var compatiblePorts = new List<Port>();
|
||||
|
||||
foreach (var port in ports)
|
||||
{
|
||||
if (startPort == port || startPort.node == port.node || startPort.direction == port.direction)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (startPort.portType != port.portType &&
|
||||
_graphObject.ValueConverterManager != null &&
|
||||
!_graphObject.ValueConverterManager.CanConvert(startPort.portType, port.portType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
compatiblePorts.Add(port);
|
||||
}
|
||||
|
||||
return compatiblePorts;
|
||||
}
|
||||
|
||||
private void OnDragPerform(DragPerformEvent evt)
|
||||
{
|
||||
var data = DragAndDrop.GetGenericData("DragSelection");
|
||||
if (data is List<ISelectable> selectables)
|
||||
{
|
||||
var propertyViews = selectables.OfType<BlackboardPropertyView>().ToArray();
|
||||
if (propertyViews.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddNode(ExecutableNode executableNode)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Add {executableNode.GetType().Name}");
|
||||
|
||||
_graphObject.AddNode(executableNode);
|
||||
AddNodeView(executableNode);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void AddNodeView(DataNode node)
|
||||
{
|
||||
var nodeView = CreateNodeView(node);
|
||||
if (nodeView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nodeView.SetPosition(node.position);
|
||||
|
||||
if (nodeView is IInspectable inspectable)
|
||||
{
|
||||
inspectable.OnItemSelected += ChangeInspectorView;
|
||||
}
|
||||
|
||||
AddElement(nodeView);
|
||||
_nodeViewsMap.Add(node.Id, nodeView);
|
||||
}
|
||||
|
||||
protected virtual Node CreateNodeView(DataNode node)
|
||||
{
|
||||
var types = TypeCache.GetTypesWithAttribute<CustomInspectorAttribute>();
|
||||
var type = types.FirstOrDefault(t =>
|
||||
t.GetCustomAttribute<CustomInspectorAttribute>().InspectorType == node.GetType());
|
||||
|
||||
if (node is PropertyInput propertyInputNode)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
private void RemoveNodeView(ExecutableNode executableNode)
|
||||
{
|
||||
if (_nodeViewsMap.Remove(executableNode.Id, out var nodeView))
|
||||
{
|
||||
RemoveElement(nodeView);
|
||||
|
||||
if (nodeView is IInspectable inspectable)
|
||||
{
|
||||
inspectable.OnItemSelected -= ChangeInspectorView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddStickyNote(StickyNoteData stickyNote)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Add {stickyNote.title}");
|
||||
|
||||
_graphObject.AddStickyNote(stickyNote);
|
||||
|
||||
AddStickyNoteView(stickyNote);
|
||||
}
|
||||
|
||||
private void AddStickyNoteView(StickyNoteData stickyNote)
|
||||
{
|
||||
var stickyNoteView = new StickyNoteView(stickyNote);
|
||||
stickyNoteView.SetPosition(stickyNote.position);
|
||||
AddElement(stickyNoteView);
|
||||
}
|
||||
|
||||
public void RemoveStickyNote(StickyNoteData stickyNote)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Remove {stickyNote.title}");
|
||||
|
||||
_graphObject.RemoveStickyNote(stickyNote);
|
||||
|
||||
RemoveStickyNoteView(stickyNote);
|
||||
}
|
||||
|
||||
private void RemoveStickyNoteView(StickyNoteData stickyNote)
|
||||
{
|
||||
// var stickyNoteView = GetStickyNoteView(stickyNote);
|
||||
// if (stickyNoteView != null)
|
||||
// {
|
||||
// RemoveElement(stickyNoteView);
|
||||
// }
|
||||
}
|
||||
|
||||
public void AddConnection(SlotConnection connection)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Add {connection.GetType().Name}");
|
||||
|
||||
_graphObject.AddConnection(connection);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void RemoveConnection(SlotConnection connection)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Remove {connection.GetType().Name}");
|
||||
|
||||
_graphObject.RemoveConnection(connection);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void AddConnectionView(SlotConnection connection)
|
||||
{
|
||||
var inputSlotData = connection.InputSlotData;
|
||||
var outputSlotData = connection.OutputSlotData;
|
||||
|
||||
if (!_nodeViewsMap.TryGetValue(inputSlotData.nodeID, out var inputNodeView) ||
|
||||
!_nodeViewsMap.TryGetValue(outputSlotData.nodeID, out var outputNodeView))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputNodeView is not IPortContainer inputPortContainer || outputNodeView is not IPortContainer outputPortContainer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inputPort = inputPortContainer.InputPorts[inputSlotData.slotIndex];
|
||||
var outputPort = outputPortContainer.OutputPorts[outputSlotData.slotIndex];
|
||||
|
||||
var edge = inputPort.ConnectTo(outputPort);
|
||||
AddElement(edge);
|
||||
_slotConnections.Add(edge, connection);
|
||||
}
|
||||
|
||||
public void ToggleBlackboardViewVisibility()
|
||||
{
|
||||
if (_blackboardView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_blackboardView.style.visibility = _blackboardView.style.visibility == Visibility.Hidden
|
||||
? Visibility.Visible
|
||||
: Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void ChangeInspectorView(IInspectable inspectable)
|
||||
{
|
||||
if (_graphInspectorView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_graphInspectorView.OnNodeSelectionChanged(inspectable);
|
||||
}
|
||||
|
||||
public void ToggleInspectorViewVisibility()
|
||||
{
|
||||
if (_graphInspectorView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_graphInspectorView.style.visibility = _graphInspectorView.style.visibility == Visibility.Hidden
|
||||
? Visibility.Visible
|
||||
: Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66c6b56270850cc458f01ab2bbd9429e
|
||||
8
Editor/Views/GraphView.meta
Normal file
8
Editor/Views/GraphView.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e691d14381aaee54fb5214d0fcc9cfd4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
197
Editor/Views/GraphView/GraphView.cs
Normal file
197
Editor/Views/GraphView/GraphView.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Misaki.GraphView.Editor
|
||||
{
|
||||
public partial class GraphView : UnityEditor.Experimental.GraphView.GraphView
|
||||
{
|
||||
private readonly Dictionary<string, Node> _nodeViewsMap = new();
|
||||
private readonly Dictionary<Edge, SlotConnection> _slotConnections = new();
|
||||
|
||||
private readonly GraphBlackboardView _blackboardView;
|
||||
private readonly GraphInspectorView _graphInspectorView;
|
||||
|
||||
private readonly GraphViewConfig _graphViewConfig;
|
||||
private GraphObject _graphObject => _graphViewConfig.graphObject;
|
||||
|
||||
public EditorWindow EditorWindow
|
||||
{
|
||||
get;
|
||||
}
|
||||
public GraphViewConfig GraphViewConfig => _graphViewConfig;
|
||||
|
||||
public GraphView(EditorWindow editorWindow, GraphViewConfig graphViewConfig)
|
||||
{
|
||||
EditorWindow = editorWindow;
|
||||
_graphViewConfig = graphViewConfig;
|
||||
|
||||
var gridBackground = new GridBackground { name = "gridBackground" };
|
||||
Add(gridBackground);
|
||||
gridBackground.SendToBack();
|
||||
|
||||
var minimapConfig = _graphViewConfig.miniMapConfig;
|
||||
if (minimapConfig is { enable: true })
|
||||
{
|
||||
var minimap = new MiniMap()
|
||||
{
|
||||
anchored = true
|
||||
};
|
||||
minimap.SetPosition(minimapConfig.position);
|
||||
Add(minimap);
|
||||
}
|
||||
|
||||
_blackboardView = new GraphBlackboardView(_graphObject, this, _graphViewConfig.serializedObject, _graphViewConfig.exposedPropertyTypeManager);
|
||||
_blackboardView.OnPropertySelected += ChangeInspectorView;
|
||||
|
||||
foreach (var property in _graphObject.ExposedProperties)
|
||||
{
|
||||
_blackboardView.AddProperty(property);
|
||||
}
|
||||
|
||||
_graphInspectorView = new GraphInspectorView();
|
||||
|
||||
Add(_blackboardView);
|
||||
Add(_graphInspectorView);
|
||||
|
||||
this.StretchToParentSize();
|
||||
|
||||
this.AddManipulator(new ContentDragger());
|
||||
this.AddManipulator(new SelectionDragger());
|
||||
this.AddManipulator(new RectangleSelector());
|
||||
this.AddManipulator(new ClickSelector());
|
||||
|
||||
var zoomConfig = _graphViewConfig.zoomConfig;
|
||||
var zoomer = new ContentZoomer();
|
||||
if (zoomConfig != null)
|
||||
{
|
||||
zoomer.minScale = zoomConfig.minScale;
|
||||
zoomer.maxScale = zoomConfig.maxScale;
|
||||
zoomer.scaleStep = zoomConfig.scaleStep;
|
||||
}
|
||||
this.AddManipulator(zoomer);
|
||||
|
||||
InitializeAssetElements();
|
||||
|
||||
graphViewChanged += OnGraphViewChanged;
|
||||
|
||||
RegisterCallback<DragPerformEvent>(OnDragPerform);
|
||||
RegisterCallbackOnce<GeometryChangedEvent>(_ => _graphInspectorView?.DockToParent(layout, DockingPosition.Right, false));
|
||||
}
|
||||
|
||||
private void InitializeAssetElements()
|
||||
{
|
||||
var searchProvider = ScriptableObject.CreateInstance<NodeSearchProvider>();
|
||||
searchProvider.SetOwner(this);
|
||||
|
||||
nodeCreationRequest = context =>
|
||||
{
|
||||
SearchWindow.Open(new SearchWindowContext(context.screenMousePosition), searchProvider);
|
||||
};
|
||||
|
||||
foreach (var node in _graphObject.Nodes)
|
||||
{
|
||||
AddNodeView(node);
|
||||
}
|
||||
|
||||
foreach (var noteData in _graphObject.StickyNotes)
|
||||
{
|
||||
AddStickyNoteView(noteData);
|
||||
}
|
||||
|
||||
foreach (var connection in _graphObject.Connections)
|
||||
{
|
||||
AddConnectionView(connection);
|
||||
}
|
||||
}
|
||||
|
||||
public override List<Port> GetCompatiblePorts(Port startPort, NodeAdapter nodeAdapter)
|
||||
{
|
||||
var compatiblePorts = new List<Port>();
|
||||
|
||||
foreach (var port in ports)
|
||||
{
|
||||
if (startPort == port || startPort.node == port.node || startPort.direction == port.direction)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (startPort.portType != port.portType &&
|
||||
_graphObject.ValueConverterManager != null &&
|
||||
!_graphObject.ValueConverterManager.CanConvert(startPort.portType, port.portType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
compatiblePorts.Add(port);
|
||||
}
|
||||
|
||||
return compatiblePorts;
|
||||
}
|
||||
|
||||
private void OnDragPerform(DragPerformEvent evt)
|
||||
{
|
||||
var data = DragAndDrop.GetGenericData("DragSelection");
|
||||
if (data is List<ISelectable> selectables)
|
||||
{
|
||||
var propertyViews = selectables.OfType<BlackboardPropertyView>().ToArray();
|
||||
if (propertyViews.Length <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleBlackboardViewVisibility()
|
||||
{
|
||||
if (_blackboardView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_blackboardView.style.visibility = _blackboardView.style.visibility == Visibility.Hidden
|
||||
? Visibility.Visible
|
||||
: Visibility.Hidden;
|
||||
}
|
||||
|
||||
private void ChangeInspectorView(IInspectable inspectable)
|
||||
{
|
||||
if (_graphInspectorView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_graphInspectorView.OnNodeSelectionChanged(inspectable);
|
||||
}
|
||||
|
||||
public void ToggleInspectorViewVisibility()
|
||||
{
|
||||
if (_graphInspectorView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_graphInspectorView.style.visibility = _graphInspectorView.style.visibility == Visibility.Hidden
|
||||
? Visibility.Visible
|
||||
: Visibility.Hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Editor/Views/GraphView/GraphView.cs.meta
Normal file
2
Editor/Views/GraphView/GraphView.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 85dea80825e410d4093cc4d10f33931b
|
||||
45
Editor/Views/GraphView/GraphView_ContextualMenu.cs
Normal file
45
Editor/Views/GraphView/GraphView_ContextualMenu.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace Misaki.GraphView.Editor
|
||||
{
|
||||
public partial class GraphView
|
||||
{
|
||||
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
|
||||
{
|
||||
base.BuildContextualMenu(evt);
|
||||
var mousePosition = (evt.currentTarget as VisualElement).ChangeCoordinatesTo(contentViewContainer, evt.localMousePosition);
|
||||
|
||||
if (evt.target is GraphView)
|
||||
{
|
||||
evt.menu.InsertAction(1, "Create Sticky Note", e =>
|
||||
{
|
||||
var stickyNote = new StickyNoteData
|
||||
{
|
||||
title = "Sticky Note",
|
||||
contents = "Contents",
|
||||
theme = StickyNoteTheme.Classic,
|
||||
fontSize = StickyNoteFontSize.Medium,
|
||||
position = new Rect(mousePosition, new Vector2(200, 200))
|
||||
};
|
||||
|
||||
AddStickyNote(stickyNote);
|
||||
}, DropdownMenuAction.AlwaysEnabled);
|
||||
}
|
||||
|
||||
if (evt.target is Edge)
|
||||
{
|
||||
evt.menu.AppendAction("Create Relay Node", e =>
|
||||
{
|
||||
var relayNode = new RelayNode
|
||||
{
|
||||
position = new Rect(mousePosition, Vector2.zero)
|
||||
};
|
||||
|
||||
AddRelayNode(relayNode);
|
||||
}, DropdownMenuAction.AlwaysEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Editor/Views/GraphView/GraphView_ContextualMenu.cs.meta
Normal file
2
Editor/Views/GraphView/GraphView_ContextualMenu.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8daa8d0ebadc4a40872f6613533e4bd
|
||||
84
Editor/Views/GraphView/GraphView_GraphChanged.cs
Normal file
84
Editor/Views/GraphView/GraphView_GraphChanged.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
|
||||
namespace Misaki.GraphView.Editor
|
||||
{
|
||||
public partial class GraphView
|
||||
{
|
||||
private GraphViewChange OnGraphViewChanged(GraphViewChange graphViewChange)
|
||||
{
|
||||
if (graphViewChange.elementsToRemove != null)
|
||||
{
|
||||
var removedElements = graphViewChange.elementsToRemove;
|
||||
Undo.RecordObject(_graphObject, "Remove elements");
|
||||
|
||||
for (var i = removedElements.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (removedElements[i] is Node { userData: DataNode node })
|
||||
{
|
||||
RemoveNode(node);
|
||||
}
|
||||
|
||||
if (removedElements[i] is StickyNote { userData: StickyNoteData stickyNote })
|
||||
{
|
||||
RemoveStickyNote(stickyNote);
|
||||
}
|
||||
|
||||
if (removedElements[i] is Edge edge)
|
||||
{
|
||||
if (_slotConnections.Remove(edge, out var connection))
|
||||
{
|
||||
var inputNode = _graphObject.GetNode(connection.InputSlotData.nodeID);
|
||||
var outputNode = _graphObject.GetNode(connection.OutputSlotData.nodeID);
|
||||
|
||||
if (inputNode is ISlotContainer inputSlotContainer && outputNode is ISlotContainer outputSlotContainer)
|
||||
{
|
||||
var inputSlot = inputSlotContainer.GetSlot(connection.InputSlotData.slotIndex, connection.InputSlotData.direction);
|
||||
var outputSlot = outputSlotContainer.GetSlot(connection.OutputSlotData.slotIndex, connection.OutputSlotData.direction);
|
||||
|
||||
inputSlot.Unlink(outputSlot);
|
||||
}
|
||||
|
||||
RemoveConnection(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if (graphViewChange.movedElements != null)
|
||||
// {
|
||||
// var movedElements = graphViewChange.movedElements;
|
||||
// Undo.RecordObject(_graphObject, $"Move {movedElements.FirstOrDefault()?.GetType().Name}");
|
||||
//
|
||||
// foreach (var element in graphViewChange.movedElements)
|
||||
// {
|
||||
// element.SetPosition(element.GetPosition());
|
||||
// }
|
||||
// }
|
||||
|
||||
if (graphViewChange.edgesToCreate != null)
|
||||
{
|
||||
var createdEdges = graphViewChange.edgesToCreate;
|
||||
Undo.RecordObject(_graphObject, $"Connect {createdEdges.FirstOrDefault()?.GetType().Name}");
|
||||
|
||||
foreach (var edge in createdEdges)
|
||||
if (edge.input.userData is Slot inputSlot && edge.output.userData is Slot outputSlot)
|
||||
{
|
||||
var connection = new SlotConnection(inputSlot.slotData, outputSlot.slotData);
|
||||
_slotConnections.Add(edge, connection);
|
||||
|
||||
outputSlot.Link(inputSlot);
|
||||
AddConnection(connection);
|
||||
}
|
||||
}
|
||||
|
||||
_graphObject.SetGraphTransform(viewTransform);
|
||||
|
||||
_graphViewConfig.serializedObject.Update();
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
|
||||
return graphViewChange;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Editor/Views/GraphView/GraphView_GraphChanged.cs.meta
Normal file
2
Editor/Views/GraphView/GraphView_GraphChanged.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c31e6279987ed0f449f1b23a385eb4be
|
||||
176
Editor/Views/GraphView/GraphView_GraphElement.cs
Normal file
176
Editor/Views/GraphView/GraphView_GraphElement.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
|
||||
namespace Misaki.GraphView.Editor
|
||||
{
|
||||
public partial class GraphView
|
||||
{
|
||||
public void AddNode(ExecutableNode executableNode)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Add {executableNode.GetType().Name}");
|
||||
|
||||
_graphObject.AddNode(executableNode);
|
||||
AddNodeView(executableNode);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void AddNodeView(DataNode node)
|
||||
{
|
||||
var nodeView = CreateNodeView(node);
|
||||
if (nodeView == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nodeView.SetPosition(node.position);
|
||||
|
||||
if (nodeView is IInspectable inspectable)
|
||||
{
|
||||
inspectable.OnItemSelected += ChangeInspectorView;
|
||||
}
|
||||
|
||||
AddElement(nodeView);
|
||||
_nodeViewsMap.Add(node.Id, nodeView);
|
||||
}
|
||||
|
||||
protected virtual Node CreateNodeView(DataNode node)
|
||||
{
|
||||
var types = TypeCache.GetTypesWithAttribute<CustomInspectorAttribute>();
|
||||
var type = types.FirstOrDefault(t =>
|
||||
t.GetCustomAttribute<CustomInspectorAttribute>().InspectorType == node.GetType());
|
||||
|
||||
if (node is PropertyInput propertyInputNode)
|
||||
{
|
||||
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(DataNode dataNode)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Remove {dataNode.GetType().Name}");
|
||||
|
||||
_graphObject.RemoveNode(dataNode);
|
||||
RemoveNodeView(dataNode);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void RemoveNodeView(DataNode dataNode)
|
||||
{
|
||||
if (_nodeViewsMap.Remove(dataNode.Id, out var nodeView))
|
||||
{
|
||||
RemoveElement(nodeView);
|
||||
|
||||
if (nodeView is IInspectable inspectable)
|
||||
{
|
||||
inspectable.OnItemSelected -= ChangeInspectorView;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void AddStickyNote(StickyNoteData stickyNote)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Add {stickyNote.title}");
|
||||
|
||||
_graphObject.AddStickyNote(stickyNote);
|
||||
AddStickyNoteView(stickyNote);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void AddStickyNoteView(StickyNoteData stickyNote)
|
||||
{
|
||||
var stickyNoteView = new StickyNoteView(stickyNote);
|
||||
stickyNoteView.SetPosition(stickyNote.position);
|
||||
AddElement(stickyNoteView);
|
||||
}
|
||||
|
||||
public void RemoveStickyNote(StickyNoteData stickyNote)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Remove {stickyNote.title}");
|
||||
|
||||
_graphObject.RemoveStickyNote(stickyNote);
|
||||
|
||||
RemoveStickyNoteView(stickyNote);
|
||||
}
|
||||
|
||||
private void RemoveStickyNoteView(StickyNoteData stickyNote)
|
||||
{
|
||||
// var stickyNoteView = GetStickyNoteView(stickyNote);
|
||||
// if (stickyNoteView != null)
|
||||
// {
|
||||
// RemoveElement(stickyNoteView);
|
||||
// }
|
||||
}
|
||||
|
||||
public void AddConnection(SlotConnection connection)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Add {connection.GetType().Name}");
|
||||
|
||||
_graphObject.AddConnection(connection);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void RemoveConnection(SlotConnection connection)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Remove {connection.GetType().Name}");
|
||||
|
||||
_graphObject.RemoveConnection(connection);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void AddConnectionView(SlotConnection connection)
|
||||
{
|
||||
var inputSlotData = connection.InputSlotData;
|
||||
var outputSlotData = connection.OutputSlotData;
|
||||
|
||||
if (!_nodeViewsMap.TryGetValue(inputSlotData.nodeID, out var inputNodeView) ||
|
||||
!_nodeViewsMap.TryGetValue(outputSlotData.nodeID, out var outputNodeView))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputNodeView is not IPortContainer inputPortContainer || outputNodeView is not IPortContainer outputPortContainer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var inputPort = inputPortContainer.GetPort(inputSlotData.slotIndex, Direction.Input);
|
||||
var outputPort = outputPortContainer.GetPort(outputSlotData.slotIndex, Direction.Output);
|
||||
|
||||
var edge = inputPort.ConnectTo(outputPort);
|
||||
AddElement(edge);
|
||||
_slotConnections.Add(edge, connection);
|
||||
}
|
||||
|
||||
public void AddRelayNode(RelayNode relayNode)
|
||||
{
|
||||
Undo.RecordObject(_graphObject, $"Add {relayNode.GetType().Name}");
|
||||
|
||||
_graphObject.AddNode(relayNode);
|
||||
AddRelayNodeView(relayNode);
|
||||
|
||||
EditorUtility.SetDirty(_graphObject);
|
||||
}
|
||||
|
||||
private void AddRelayNodeView(RelayNode relayNode)
|
||||
{
|
||||
var relayNodeView = new RelayNodeView(relayNode, _graphViewConfig.portColorManager);
|
||||
relayNodeView.SetPosition(relayNode.position);
|
||||
AddElement(relayNodeView);
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Editor/Views/GraphView/GraphView_GraphElement.cs.meta
Normal file
2
Editor/Views/GraphView/GraphView_GraphElement.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d01a10830ebed08498c09668ee5d0c74
|
||||
@@ -15,19 +15,19 @@ namespace Misaki.GraphView.Editor
|
||||
private readonly ExecutableNode _dataNode;
|
||||
private readonly Type _nodeType;
|
||||
private readonly NodeInfoAttribute _nodeInfo;
|
||||
|
||||
private readonly List<Port> _inputPorts = new ();
|
||||
private readonly List<Port> _outputPorts = new ();
|
||||
|
||||
|
||||
private readonly List<Port> _inputPorts = new();
|
||||
private readonly List<Port> _outputPorts = new();
|
||||
|
||||
private readonly IPortColorManager _portColorManager;
|
||||
private readonly SerializedObject _serializedObject;
|
||||
|
||||
|
||||
private readonly VisualElement _logContainer = new();
|
||||
|
||||
public List<Port> InputPorts => _inputPorts;
|
||||
public List<Port> OutputPorts => _outputPorts;
|
||||
|
||||
public Action<IInspectable> OnItemSelected { get; set; }
|
||||
|
||||
public Action<IInspectable> OnItemSelected
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public string InspectorName => _nodeInfo.Name ?? _nodeType.Name;
|
||||
|
||||
@@ -37,19 +37,19 @@ namespace Misaki.GraphView.Editor
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_dataNode = dataNode;
|
||||
_portColorManager = portColorManager;
|
||||
_serializedObject = serializedObject;
|
||||
|
||||
|
||||
userData = dataNode;
|
||||
|
||||
|
||||
_nodeType = dataNode.GetType();
|
||||
_nodeInfo = _nodeType.GetCustomAttribute<NodeInfoAttribute>();
|
||||
|
||||
|
||||
name = _nodeInfo.Name ?? _nodeType.Name;
|
||||
title = _nodeInfo.Name ?? _nodeType.Name;
|
||||
|
||||
|
||||
// Add the category as a class to the node so that we can style the node based on the category
|
||||
var depths = _nodeInfo.Category.Split('/').ToList();
|
||||
depths.Add(_nodeInfo.Name);
|
||||
@@ -57,13 +57,13 @@ namespace Misaki.GraphView.Editor
|
||||
{
|
||||
AddToClassList(depth.ToLower().Replace(" ", "-"));
|
||||
}
|
||||
|
||||
|
||||
var inputs = _nodeType.GetProperty(nameof(ExecutableNode.Inputs));
|
||||
|
||||
if (inputs != null)
|
||||
{
|
||||
var inputSlots = (IList<Slot>)inputs.GetValue(_dataNode);
|
||||
|
||||
|
||||
if (inputSlots == null || inputSlots.Count == 0)
|
||||
{
|
||||
inputContainer.style.display = DisplayStyle.None;
|
||||
@@ -94,7 +94,7 @@ namespace Misaki.GraphView.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_logContainer.style.position = Position.Absolute;
|
||||
_logContainer.style.top = 8;
|
||||
Add(_logContainer);
|
||||
@@ -107,15 +107,15 @@ namespace Misaki.GraphView.Editor
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLogElement(ExecutableNode node, string message, LogType type)
|
||||
private void CreateLogElement(DataNode node, string message, LogType type)
|
||||
{
|
||||
if (node.Id != _dataNode.Id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_logContainer.style.left = layout.width;
|
||||
|
||||
|
||||
var logIcon = new Image()
|
||||
{
|
||||
image = type switch
|
||||
@@ -129,12 +129,12 @@ namespace Misaki.GraphView.Editor
|
||||
{
|
||||
width = 24,
|
||||
height = 24,
|
||||
|
||||
|
||||
borderBottomLeftRadius = 4,
|
||||
borderTopRightRadius = 4,
|
||||
borderTopLeftRadius = 4,
|
||||
borderBottomRightRadius = 4,
|
||||
|
||||
|
||||
flexDirection = FlexDirection.Row,
|
||||
alignItems = Align.Center,
|
||||
paddingBottom = 1,
|
||||
@@ -150,7 +150,7 @@ namespace Misaki.GraphView.Editor
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
_logContainer.Add(logIcon);
|
||||
}
|
||||
|
||||
@@ -205,20 +205,30 @@ namespace Misaki.GraphView.Editor
|
||||
base.OnSelected();
|
||||
OnItemSelected?.Invoke(this);
|
||||
}
|
||||
|
||||
|
||||
public override void OnUnselected()
|
||||
{
|
||||
base.OnUnselected();
|
||||
OnItemSelected?.Invoke(null);
|
||||
}
|
||||
|
||||
public Port GetPort(int index, Direction direction)
|
||||
{
|
||||
return direction switch
|
||||
{
|
||||
Direction.Input => _inputPorts[index],
|
||||
Direction.Output => _outputPorts[index],
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays the inspector for the node.
|
||||
/// </summary>
|
||||
public virtual VisualElement CreateInspector()
|
||||
{
|
||||
var root = new VisualElement();
|
||||
|
||||
|
||||
if (_serializedObject.targetObject is not GraphObject graphObject)
|
||||
{
|
||||
return root;
|
||||
@@ -239,7 +249,7 @@ namespace Misaki.GraphView.Editor
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var serializedProperty = _serializedObject.FindProperty("_nodes")?.GetArrayElementAtIndex(i)?.FindPropertyRelative(field.Name);
|
||||
|
||||
|
||||
if (serializedProperty == null)
|
||||
{
|
||||
continue;
|
||||
@@ -249,7 +259,7 @@ namespace Misaki.GraphView.Editor
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
var propertyName = field.GetCustomAttribute<InspectorInputAttribute>().Name ?? ObjectNames.NicifyVariableName(field.Name);
|
||||
|
||||
if (field.GetCustomAttribute<NodeInputAttribute>() is not null)
|
||||
@@ -263,16 +273,16 @@ namespace Misaki.GraphView.Editor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var inputField = new PropertyField(serializedProperty, propertyName);
|
||||
inputField.Bind(_serializedObject);
|
||||
|
||||
|
||||
root.Add(inputField);
|
||||
}
|
||||
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
|
||||
protected VisualElement CreateFieldForConnectedSlot(Slot slot, string propertyName)
|
||||
{
|
||||
var root = new VisualElement()
|
||||
@@ -288,7 +298,7 @@ namespace Misaki.GraphView.Editor
|
||||
marginRight = 3
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var label = new Label(propertyName)
|
||||
{
|
||||
style =
|
||||
@@ -297,7 +307,7 @@ namespace Misaki.GraphView.Editor
|
||||
}
|
||||
};
|
||||
label.AddToClassList("unity-base-field__label");
|
||||
|
||||
|
||||
var value = new Label($"Connected to {ObjectNames.NicifyVariableName(slot.LinkedSlotData[0].slotName)}");
|
||||
value.AddToClassList("unity-base-field__input");
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NUnit.Framework;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
@@ -9,54 +6,49 @@ namespace Misaki.GraphView.Editor
|
||||
{
|
||||
public class PropertyInputNodeView : TokenNode, IPortContainer
|
||||
{
|
||||
private readonly List<Port> _outputPorts = new List<Port>();
|
||||
|
||||
private readonly Port _outputPort;
|
||||
|
||||
private readonly PropertyInput _data;
|
||||
//private readonly ExposedPropertyEditor _editor;
|
||||
|
||||
|
||||
public PropertyInput Data => _data;
|
||||
|
||||
public List<Port> InputPorts => null;
|
||||
public List<Port> OutputPorts => _outputPorts;
|
||||
|
||||
|
||||
public PropertyInputNodeView(PropertyInput data, Port output) : base(null, output)
|
||||
{
|
||||
_data = data;
|
||||
//_editor = editor;
|
||||
_outputPort = output;
|
||||
|
||||
name = data.Property.propertyName;
|
||||
title = data.Property.propertyName;
|
||||
userData = data;
|
||||
|
||||
this.Q<VisualElement>("top").style.minHeight = 24;
|
||||
|
||||
_outputPorts.Add(output);
|
||||
}
|
||||
|
||||
|
||||
public static PropertyInputNodeView Create(PropertyInput data, IPortColorManager portColorManager)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var outputSlot = data.GetSlot(0, SlotDirection.Output);
|
||||
var outputPort = CreateOutputPort(data.Property, outputSlot, portColorManager);
|
||||
var nodeView = new PropertyInputNodeView(data, outputPort);
|
||||
|
||||
|
||||
return nodeView;
|
||||
}
|
||||
|
||||
|
||||
private static Port CreateOutputPort(ExposedProperty property, Slot slot, IPortColorManager portColorManager)
|
||||
{
|
||||
if (property == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
var portType = property.GetValueType();
|
||||
var port = Port.Create<Edge>(Orientation.Horizontal, Direction.Output, Port.Capacity.Single, portType);
|
||||
|
||||
|
||||
port.portName = string.Empty;
|
||||
if (portColorManager != null && portColorManager.TryGetColor(portType, out var portColor))
|
||||
{
|
||||
@@ -64,7 +56,7 @@ namespace Misaki.GraphView.Editor
|
||||
}
|
||||
port.portType = portType;
|
||||
port.userData = slot;
|
||||
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
@@ -75,5 +67,10 @@ namespace Misaki.GraphView.Editor
|
||||
base.SetPosition(newPos);
|
||||
_data.position = newPos;
|
||||
}
|
||||
|
||||
public Port GetPort(int index, Direction direction)
|
||||
{
|
||||
return _outputPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
51
Editor/Views/Nodes/RelayNodeView.cs
Normal file
51
Editor/Views/Nodes/RelayNodeView.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
|
||||
namespace Misaki.GraphView.Editor
|
||||
{
|
||||
public class RelayNodeView : Node, IPortContainer
|
||||
{
|
||||
private RelayNode _dataNode;
|
||||
private IPortColorManager _portColorManager;
|
||||
|
||||
private readonly Port _inputPort;
|
||||
private readonly Port _outputPort;
|
||||
|
||||
public RelayNodeView(RelayNode dataNode, IPortColorManager portColorManager)
|
||||
{
|
||||
_dataNode = dataNode;
|
||||
_portColorManager = portColorManager;
|
||||
|
||||
_inputPort = Port.Create<Edge>(Orientation.Horizontal, Direction.Input, Port.Capacity.Single, typeof(object));
|
||||
_outputPort = Port.Create<Edge>(Orientation.Horizontal, Direction.Output, Port.Capacity.Multi, typeof(object));
|
||||
|
||||
_inputPort.portName = string.Empty;
|
||||
_outputPort.portName = string.Empty;
|
||||
|
||||
SetPortsTypeAndColor(typeof(object));
|
||||
|
||||
inputContainer.Add(_inputPort);
|
||||
outputContainer.Add(_outputPort);
|
||||
}
|
||||
|
||||
private void SetPortsTypeAndColor(Type portType)
|
||||
{
|
||||
_inputPort.portType = portType;
|
||||
_outputPort.portType = portType;
|
||||
|
||||
if (_portColorManager != null)
|
||||
{
|
||||
if (_portColorManager.TryGetColor(portType, out var portColor))
|
||||
{
|
||||
_inputPort.portColor = portColor;
|
||||
_outputPort.portColor = portColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Port GetPort(int index, Direction direction)
|
||||
{
|
||||
return direction == Direction.Input ? _inputPort : _outputPort;
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Editor/Views/Nodes/RelayNodeView.cs.meta
Normal file
2
Editor/Views/Nodes/RelayNodeView.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba1646416a4d47148947945befe2b938
|
||||
Reference in New Issue
Block a user