Contextual Node Creation
This commit is contained in:
parent
370504dcfc
commit
4cd9878a97
@ -26,28 +26,27 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
|||||||
public void OnDropOutsidePort(Edge edge, Vector2 position)
|
public void OnDropOutsidePort(Edge edge, Vector2 position)
|
||||||
{
|
{
|
||||||
window.searchProvider.target = (VisualElement)window.focusController.focusedElement;
|
window.searchProvider.target = (VisualElement)window.focusController.focusedElement;
|
||||||
SearchWindow.Open(new SearchWindowContext(position), window.searchProvider);
|
|
||||||
|
// ⚡ Override the search window open with a customized search tree
|
||||||
|
SearchWindow.Open(new SearchWindowContext(position), new ImageProcessingGraphSearchProvider.CustomSearchProviderForEdge(window.searchProvider, edge, (IPTPort)edge.input, (IPTPort)edge.output));
|
||||||
|
|
||||||
|
// Remove connections as you did
|
||||||
List<GraphConnection> connections = new List<GraphConnection>();
|
List<GraphConnection> connections = new List<GraphConnection>();
|
||||||
|
|
||||||
foreach (var conn in window.asset.Connections)
|
foreach (var conn in window.asset.Connections)
|
||||||
{
|
{
|
||||||
if (conn.internalEdge == edge)
|
if (conn.internalEdge == edge)
|
||||||
{
|
|
||||||
connections.Add(conn);
|
connections.Add(conn);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var VARIABLE in connections)
|
foreach (var VARIABLE in connections)
|
||||||
{
|
{
|
||||||
window.asset.Connections.Remove(VARIABLE);
|
window.asset.Connections.Remove(VARIABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(edge.input != null)
|
if (edge.input != null)
|
||||||
if(edge.input.node != null)
|
if (edge.input.node != null)
|
||||||
((ImageProcessingGraphNodeVisual)edge.input.node).ToggleExposedVariable((IPTPort)edge.input, true);
|
((ImageProcessingGraphNodeVisual)edge.input.node).ToggleExposedVariable((IPTPort)edge.input, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void OnDrop(UnityEditor.Experimental.GraphView.GraphView graphView, Edge edge)
|
public void OnDrop(UnityEditor.Experimental.GraphView.GraphView graphView, Edge edge)
|
||||||
|
@ -8,6 +8,7 @@ using UnityEditor;
|
|||||||
using UnityEditor.Experimental.GraphView;
|
using UnityEditor.Experimental.GraphView;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.UIElements;
|
using UnityEngine.UIElements;
|
||||||
|
using Input = ImageProcessingGraph.Editor.Nodes.NodeAttributes.Input;
|
||||||
|
|
||||||
namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows
|
namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows
|
||||||
{
|
{
|
||||||
@ -16,13 +17,21 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
|||||||
public object target { get; private set; }
|
public object target { get; private set; }
|
||||||
public string title { get; private set; }
|
public string title { get; private set; }
|
||||||
|
|
||||||
public SearchContextElement(object target, string title)
|
public Dictionary<int, Type> ImportPortTypes { get; private set; }
|
||||||
|
public Dictionary<int, Type> ExportPortTypes { get; private set; }
|
||||||
|
public int portID;
|
||||||
|
|
||||||
|
public SearchContextElement(object target, string title, Dictionary<int, Type> importPortTypes,
|
||||||
|
Dictionary<int, Type> exportPortTypes, int portID)
|
||||||
{
|
{
|
||||||
this.target = target;
|
this.target = target;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
|
this.ImportPortTypes = importPortTypes;
|
||||||
|
this.ExportPortTypes = exportPortTypes;
|
||||||
|
this.portID = portID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImageProcessingGraphSearchProvider : ScriptableObject, ISearchWindowProvider
|
public class ImageProcessingGraphSearchProvider : ScriptableObject, ISearchWindowProvider
|
||||||
{
|
{
|
||||||
public ImageProcessingGraphViewWindow graph;
|
public ImageProcessingGraphViewWindow graph;
|
||||||
@ -30,44 +39,34 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
|||||||
|
|
||||||
public static List<SearchContextElement> elements;
|
public static List<SearchContextElement> elements;
|
||||||
private Assembly[] assemblies;
|
private Assembly[] assemblies;
|
||||||
|
|
||||||
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
||||||
{
|
{
|
||||||
List<SearchTreeEntry> tree = new List<SearchTreeEntry>();
|
List<SearchTreeEntry> tree = new List<SearchTreeEntry>();
|
||||||
tree.Add(new SearchTreeGroupEntry(new GUIContent("Nodes"), 0));
|
tree.Add(new SearchTreeGroupEntry(new GUIContent("Nodes"), 0));
|
||||||
|
|
||||||
elements = new List<SearchContextElement>();
|
|
||||||
|
|
||||||
/*
|
|
||||||
assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*foreach (var assembly in assemblies)
|
elements = new List<SearchContextElement>();
|
||||||
{
|
|
||||||
foreach (Type type in assembly.GetTypes())
|
|
||||||
{
|
|
||||||
if (type.CustomAttributes.ToList() != null)
|
|
||||||
{
|
|
||||||
var attr = type.GetCustomAttribute(typeof(NodeInfoAttribute));
|
|
||||||
if (attr != null)
|
|
||||||
{
|
|
||||||
NodeInfoAttribute info = attr as NodeInfoAttribute;
|
|
||||||
var node = Activator.CreateInstance(type);
|
|
||||||
if(string.IsNullOrEmpty(info.MenuItem)) continue;
|
|
||||||
|
|
||||||
elements.Add(new SearchContextElement(node, info.MenuItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
foreach (var type in TypeCache.GetTypesWithAttribute<NodeInfoAttribute>())
|
foreach (var type in TypeCache.GetTypesWithAttribute<NodeInfoAttribute>())
|
||||||
{
|
{
|
||||||
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
||||||
NodeInfoAttribute info = attr as NodeInfoAttribute;
|
NodeInfoAttribute info = attr as NodeInfoAttribute;
|
||||||
var node = Activator.CreateInstance(type);
|
var node = Activator.CreateInstance(type);
|
||||||
if(string.IsNullOrEmpty(info.MenuItem)) continue;
|
if (string.IsNullOrEmpty(info.MenuItem)) continue;
|
||||||
|
|
||||||
elements.Add(new SearchContextElement(node, info.MenuItem));
|
var Fields = type.GetFields();
|
||||||
|
Dictionary<int, Type> ImportPortTypes = new Dictionary<int, Type>();
|
||||||
|
Dictionary<int, Type> OutputPortTypes = new Dictionary<int, Type>();
|
||||||
|
|
||||||
|
foreach (var field in Fields)
|
||||||
|
{
|
||||||
|
if (field.GetCustomAttribute<Input>() != null)
|
||||||
|
ImportPortTypes.Add(ImportPortTypes.Count, field.FieldType);
|
||||||
|
if (field.GetCustomAttribute<Output>() != null)
|
||||||
|
OutputPortTypes.Add(OutputPortTypes.Count, field.FieldType);
|
||||||
|
}
|
||||||
|
|
||||||
|
elements.Add(new SearchContextElement(node, info.MenuItem, ImportPortTypes, OutputPortTypes, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
elements.Sort((entry1, entry2) =>
|
elements.Sort((entry1, entry2) =>
|
||||||
@ -78,20 +77,20 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
|||||||
for (int i = 0; i < splits1.Length; i++)
|
for (int i = 0; i < splits1.Length; i++)
|
||||||
{
|
{
|
||||||
if (i >= splits2.Length) return 1;
|
if (i >= splits2.Length) return 1;
|
||||||
|
|
||||||
int value = splits1[i].CompareTo(splits2[i]);
|
int value = splits1[i].CompareTo(splits2[i]);
|
||||||
if (value != 0)
|
if (value != 0)
|
||||||
{
|
{
|
||||||
if(splits1.Length != splits2.Length && (i == splits1.Length - 1 || i == splits2.Length - 1))
|
if (splits1.Length != splits2.Length && (i == splits1.Length - 1 || i == splits2.Length - 1))
|
||||||
return splits1.Length < splits2.Length ? 1 : -1;
|
return splits1.Length < splits2.Length ? 1 : -1;
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
List<string> groups = new List<string>();
|
List<string> groups = new List<string>();
|
||||||
|
|
||||||
foreach (var element in elements)
|
foreach (var element in elements)
|
||||||
@ -108,12 +107,13 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
|||||||
tree.Add(new SearchTreeGroupEntry(new GUIContent(groupName), i + 1));
|
tree.Add(new SearchTreeGroupEntry(new GUIContent(groupName), i + 1));
|
||||||
groups.Add(groupName);
|
groups.Add(groupName);
|
||||||
}
|
}
|
||||||
|
|
||||||
groupName += '/';
|
groupName += '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchTreeEntry entry = new SearchTreeEntry(new GUIContent(entryTitle.Last()));
|
SearchTreeEntry entry = new SearchTreeEntry(new GUIContent(entryTitle.Last()));
|
||||||
entry.level = entryTitle.Length;
|
entry.level = entryTitle.Length;
|
||||||
entry.userData = new SearchContextElement(element.target, element.title);
|
entry.userData = element;
|
||||||
tree.Add(entry);
|
tree.Add(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,11 +122,12 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
|||||||
|
|
||||||
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context)
|
public bool OnSelectEntry(SearchTreeEntry SearchTreeEntry, SearchWindowContext context)
|
||||||
{
|
{
|
||||||
var mousePos = graph.ChangeCoordinatesTo(graph, context.screenMousePosition - graph.Window.position.position);
|
var mousePos =
|
||||||
|
graph.ChangeCoordinatesTo(graph, context.screenMousePosition - graph.Window.position.position);
|
||||||
var graphMousePosition = graph.contentViewContainer.WorldToLocal(mousePos);
|
var graphMousePosition = graph.contentViewContainer.WorldToLocal(mousePos);
|
||||||
|
|
||||||
SearchContextElement element = (SearchContextElement)SearchTreeEntry.userData;
|
SearchContextElement element = (SearchContextElement)SearchTreeEntry.userData;
|
||||||
|
|
||||||
BaseImageNode node = (BaseImageNode)element.target;
|
BaseImageNode node = (BaseImageNode)element.target;
|
||||||
node.SetPosition(new Rect(graphMousePosition, new Vector2()));
|
node.SetPosition(new Rect(graphMousePosition, new Vector2()));
|
||||||
graph.Add(node);
|
graph.Add(node);
|
||||||
@ -134,5 +135,148 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<SearchTreeEntry> CreateSearchTreeForEdge(SearchWindowContext context, Edge edge)
|
||||||
|
{
|
||||||
|
var tree = new List<SearchTreeEntry>();
|
||||||
|
tree.Add(new SearchTreeGroupEntry(new GUIContent("Compatible Nodes"), 0));
|
||||||
|
|
||||||
|
elements = new List<SearchContextElement>();
|
||||||
|
var groups = new List<string>();
|
||||||
|
|
||||||
|
var sourcePort = edge.output ?? edge.input;
|
||||||
|
bool isSourceOutput = edge.output != null;
|
||||||
|
Type targetType = (sourcePort as IPTPort)?.portType;
|
||||||
|
|
||||||
|
if (targetType == null)
|
||||||
|
{
|
||||||
|
Debug.LogWarning("Could not determine port type from edge!");
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var type in TypeCache.GetTypesWithAttribute<NodeInfoAttribute>())
|
||||||
|
{
|
||||||
|
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
||||||
|
if (string.IsNullOrEmpty(attr.MenuItem)) continue;
|
||||||
|
|
||||||
|
var node = Activator.CreateInstance(type);
|
||||||
|
var fields = type.GetFields();
|
||||||
|
|
||||||
|
// Get all ports
|
||||||
|
var inputPorts = fields.Where(f => f.GetCustomAttribute<Input>() != null).ToList();
|
||||||
|
var outputPorts = fields.Where(f => f.GetCustomAttribute<Output>() != null).ToList();
|
||||||
|
|
||||||
|
// REVERSED LOGIC:
|
||||||
|
// If dragging from output, we want compatible INPUT ports
|
||||||
|
// If dragging from input, we want compatible OUTPUT ports
|
||||||
|
var compatiblePorts = isSourceOutput
|
||||||
|
? inputPorts.Where(f => f.FieldType.IsAssignableFrom(targetType)).ToList()
|
||||||
|
: outputPorts.Where(f => targetType.IsAssignableFrom(f.FieldType)).ToList();
|
||||||
|
|
||||||
|
if (compatiblePorts.Count == 0) continue;
|
||||||
|
|
||||||
|
// Build group hierarchy
|
||||||
|
var menuPath = attr.MenuItem.Split('/');
|
||||||
|
var currentGroupPath = "";
|
||||||
|
|
||||||
|
for (int i = 0; i < menuPath.Length - 1; i++)
|
||||||
|
{
|
||||||
|
currentGroupPath += menuPath[i];
|
||||||
|
if (!groups.Contains(currentGroupPath))
|
||||||
|
{
|
||||||
|
tree.Add(new SearchTreeGroupEntry(new GUIContent(menuPath[i]), i + 1));
|
||||||
|
groups.Add(currentGroupPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentGroupPath += "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Add node entry
|
||||||
|
// var nodeTitle = $"{type.Name}: {menuPath.Last()}";
|
||||||
|
// tree.Add(new SearchTreeEntry(new GUIContent(nodeTitle))
|
||||||
|
// {
|
||||||
|
// level = menuPath.Length,
|
||||||
|
// userData = new SearchContextElement(
|
||||||
|
// node,
|
||||||
|
// nodeTitle,
|
||||||
|
// inputPorts.ToDictionary(f => inputPorts.IndexOf(f), f => f.FieldType),
|
||||||
|
// outputPorts.ToDictionary(f => outputPorts.IndexOf(f), f => f.FieldType))
|
||||||
|
// });
|
||||||
|
|
||||||
|
// Add compatible port entries
|
||||||
|
foreach (var portField in compatiblePorts)
|
||||||
|
{
|
||||||
|
var portList = portField.GetCustomAttribute<Input>() != null ? inputPorts : outputPorts;
|
||||||
|
int portIndex = portList.IndexOf(portField);
|
||||||
|
|
||||||
|
var portTitle = $"{attr.Title}: {portField.Name}";
|
||||||
|
tree.Add(new SearchTreeEntry(new GUIContent(portTitle))
|
||||||
|
{
|
||||||
|
level = menuPath.Length,
|
||||||
|
userData = new SearchContextElement(
|
||||||
|
node,
|
||||||
|
portTitle,
|
||||||
|
inputPorts.ToDictionary(f => inputPorts.IndexOf(f), f => f.FieldType),
|
||||||
|
outputPorts.ToDictionary(f => outputPorts.IndexOf(f), f => f.FieldType),
|
||||||
|
portIndex)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CustomSearchProviderForEdge : ScriptableObject, ISearchWindowProvider
|
||||||
|
{
|
||||||
|
private readonly ImageProcessingGraphSearchProvider original;
|
||||||
|
private readonly Edge edge;
|
||||||
|
private readonly IPTPort inputPort;
|
||||||
|
private readonly IPTPort outputPort;
|
||||||
|
|
||||||
|
public CustomSearchProviderForEdge(ImageProcessingGraphSearchProvider original, Edge edge, IPTPort inputPort, IPTPort outputPort)
|
||||||
|
{
|
||||||
|
this.original = original;
|
||||||
|
this.edge = edge;
|
||||||
|
this.inputPort = inputPort;
|
||||||
|
this.outputPort = outputPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
||||||
|
{
|
||||||
|
return original.CreateSearchTreeForEdge(context, edge);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnSelectEntry(SearchTreeEntry selectedEntry, SearchWindowContext context)
|
||||||
|
{
|
||||||
|
var mousePos =
|
||||||
|
original.graph.ChangeCoordinatesTo(original.graph, context.screenMousePosition - original.graph.Window.position.position);
|
||||||
|
var graphMousePosition = original.graph.contentViewContainer.WorldToLocal(mousePos);
|
||||||
|
|
||||||
|
SearchContextElement element = (SearchContextElement)selectedEntry.userData;
|
||||||
|
|
||||||
|
BaseImageNode node = (BaseImageNode)element.target;
|
||||||
|
node.SetPosition(new Rect(graphMousePosition, new Vector2()));
|
||||||
|
original.graph.Add(node);
|
||||||
|
node.asset = original.graph.asset;
|
||||||
|
|
||||||
|
|
||||||
|
Edge edge = new Edge();
|
||||||
|
|
||||||
|
if (inputPort != null)
|
||||||
|
{
|
||||||
|
edge = inputPort.ConnectTo(original.graph.nodeDictionary[node.ID].OutputPorts[element.portID]);
|
||||||
|
}
|
||||||
|
else if (outputPort != null)
|
||||||
|
{
|
||||||
|
edge = outputPort.ConnectTo(original.graph.nodeDictionary[node.ID].InputPorts[element.portID]);
|
||||||
|
}
|
||||||
|
|
||||||
|
original.graph.CreateEdge(edge);
|
||||||
|
original.graph.AddElement((GraphElement)edge);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -299,7 +299,7 @@ namespace ImageProcessingGraph.Editor
|
|||||||
|
|
||||||
#region Edges
|
#region Edges
|
||||||
|
|
||||||
void CreateEdge(Edge edge)
|
public void CreateEdge(Edge edge)
|
||||||
{
|
{
|
||||||
ImageProcessingGraphNodeVisual outputNode = (ImageProcessingGraphNodeVisual)edge.output.node;
|
ImageProcessingGraphNodeVisual outputNode = (ImageProcessingGraphNodeVisual)edge.output.node;
|
||||||
ImageProcessingGraphNodeVisual inputNode = (ImageProcessingGraphNodeVisual)edge.input.node;
|
ImageProcessingGraphNodeVisual inputNode = (ImageProcessingGraphNodeVisual)edge.input.node;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user