Contextual Node Creation
This commit is contained in:
parent
370504dcfc
commit
4cd9878a97
@ -26,25 +26,24 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
public void OnDropOutsidePort(Edge edge, Vector2 position)
|
||||
{
|
||||
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>();
|
||||
|
||||
foreach (var conn in window.asset.Connections)
|
||||
{
|
||||
if (conn.internalEdge == edge)
|
||||
{
|
||||
connections.Add(conn);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var VARIABLE in connections)
|
||||
{
|
||||
window.asset.Connections.Remove(VARIABLE);
|
||||
}
|
||||
|
||||
if(edge.input != null)
|
||||
if(edge.input.node != null)
|
||||
if (edge.input != null)
|
||||
if (edge.input.node != null)
|
||||
((ImageProcessingGraphNodeVisual)edge.input.node).ToggleExposedVariable((IPTPort)edge.input, true);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ using UnityEditor;
|
||||
using UnityEditor.Experimental.GraphView;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using Input = ImageProcessingGraph.Editor.Nodes.NodeAttributes.Input;
|
||||
|
||||
namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows
|
||||
{
|
||||
@ -16,10 +17,18 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
public object target { 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.title = title;
|
||||
this.ImportPortTypes = importPortTypes;
|
||||
this.ExportPortTypes = exportPortTypes;
|
||||
this.portID = portID;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,6 +39,7 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
|
||||
public static List<SearchContextElement> elements;
|
||||
private Assembly[] assemblies;
|
||||
|
||||
public List<SearchTreeEntry> CreateSearchTree(SearchWindowContext context)
|
||||
{
|
||||
List<SearchTreeEntry> tree = new List<SearchTreeEntry>();
|
||||
@ -37,37 +47,26 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
|
||||
elements = new List<SearchContextElement>();
|
||||
|
||||
/*
|
||||
assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
*/
|
||||
|
||||
/*foreach (var assembly in assemblies)
|
||||
{
|
||||
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>())
|
||||
{
|
||||
var attr = type.GetCustomAttribute<NodeInfoAttribute>();
|
||||
NodeInfoAttribute info = attr as NodeInfoAttribute;
|
||||
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) =>
|
||||
@ -82,7 +81,7 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
int value = splits1[i].CompareTo(splits2[i]);
|
||||
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 value;
|
||||
@ -108,12 +107,13 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
tree.Add(new SearchTreeGroupEntry(new GUIContent(groupName), i + 1));
|
||||
groups.Add(groupName);
|
||||
}
|
||||
|
||||
groupName += '/';
|
||||
}
|
||||
|
||||
SearchTreeEntry entry = new SearchTreeEntry(new GUIContent(entryTitle.Last()));
|
||||
entry.level = entryTitle.Length;
|
||||
entry.userData = new SearchContextElement(element.target, element.title);
|
||||
entry.userData = element;
|
||||
tree.Add(entry);
|
||||
}
|
||||
|
||||
@ -122,7 +122,8 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
|
||||
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);
|
||||
|
||||
SearchContextElement element = (SearchContextElement)SearchTreeEntry.userData;
|
||||
@ -134,5 +135,148 @@ namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Wind
|
||||
|
||||
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
|
||||
|
||||
void CreateEdge(Edge edge)
|
||||
public void CreateEdge(Edge edge)
|
||||
{
|
||||
ImageProcessingGraphNodeVisual outputNode = (ImageProcessingGraphNodeVisual)edge.output.node;
|
||||
ImageProcessingGraphNodeVisual inputNode = (ImageProcessingGraphNodeVisual)edge.input.node;
|
||||
|
Loading…
x
Reference in New Issue
Block a user