246 lines
9.4 KiB
C#
246 lines
9.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using ImageProcessingGraph.Editor.Nodes.NodeAttributes;
|
|
using UnityEditor.Experimental.GraphView;
|
|
using UnityEditor.UIElements;
|
|
using UnityEngine;
|
|
using UnityEngine.UIElements;
|
|
using Input = ImageProcessingGraph.Editor.Nodes.NodeAttributes.Input;
|
|
|
|
namespace ImageProcessingGraph.Editor.Unity_Image_Processing.Scripts.Editor.Windows
|
|
{
|
|
public class ImageProcessingGraphNodeVisual : Node
|
|
{
|
|
private BaseImageNode graphNode;
|
|
public BaseImageNode GraphNode => graphNode;
|
|
|
|
public List<Port> InputPorts { get; }
|
|
public List<Port> OutputPorts { get; }
|
|
|
|
private ImageProcessingGraphViewWindow window;
|
|
|
|
public ImageProcessingGraphNodeVisual(BaseImageNode node, ImageProcessingGraphViewWindow window)
|
|
{
|
|
this.AddToClassList("image-node-visual");
|
|
this.window = window;
|
|
|
|
graphNode = node;
|
|
Type typeInfo = node.GetType();
|
|
|
|
NodeInfoAttribute info = typeInfo.GetCustomAttribute<NodeInfoAttribute>();
|
|
title = info.Title;
|
|
|
|
string[] depths = info.MenuItem.Split('/');
|
|
foreach (var depth in depths)
|
|
{
|
|
this.AddToClassList(depth.ToLower().Replace(' ', '-'));
|
|
}
|
|
|
|
this.InputPorts = new List<Port>();
|
|
this.OutputPorts = new List<Port>();
|
|
|
|
List<Input> inputs = new List<Input>();
|
|
List<FieldInfo> inputFieldInfo = new List<FieldInfo>();
|
|
List<FieldInfo> outputFieldInfo = new List<FieldInfo>();
|
|
|
|
FieldInfo[] fields = typeInfo.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
|
|
foreach (var field in fields)
|
|
{
|
|
if (field.GetCustomAttribute(typeof(Input)) != null)
|
|
{
|
|
Input input = field.GetCustomAttribute<Input>();
|
|
inputs.Add(input);
|
|
inputFieldInfo.Add(field);
|
|
}
|
|
|
|
if (field.GetCustomAttribute(typeof(Output)) != null)
|
|
{
|
|
Output output = field.GetCustomAttribute<Output>();
|
|
outputFieldInfo.Add(field);
|
|
}
|
|
|
|
}
|
|
|
|
CreateInputPorts(inputFieldInfo);
|
|
CreateOutputPorts(outputFieldInfo);
|
|
|
|
this.name = typeInfo.Name;
|
|
}
|
|
|
|
private void CreateInputPorts(List<FieldInfo> fields)
|
|
{
|
|
for (var index = 0; index < fields.Count; index++)
|
|
{
|
|
var field = fields[index];
|
|
/*
|
|
Port port = InstantiatePort(Orientation.Horizontal, Direction.Input, Port.Capacity.Multi, field.FieldType);
|
|
*/
|
|
|
|
var port = IPTPort.Create(window.edgeConnectorListener, true, field.FieldType);
|
|
|
|
string label = field.GetCustomAttribute<Input>().Label;
|
|
if (label != "")
|
|
port.portName = label;
|
|
InputPorts.Add(port);
|
|
|
|
inputContainer.Add(port);
|
|
ExposeVariableToPort(port, field);
|
|
|
|
}
|
|
}
|
|
|
|
private void CreateOutputPorts(List<FieldInfo> fields)
|
|
{
|
|
for (var index = 0; index < fields.Count; index++)
|
|
{
|
|
var field = fields[index];
|
|
var port = IPTPort.Create(window.edgeConnectorListener, false, field.FieldType);
|
|
|
|
string label = field.GetCustomAttribute<Output>().Label;
|
|
if (label != "")
|
|
port.portName = label;
|
|
OutputPorts.Add(port);
|
|
|
|
outputContainer.Add(port);
|
|
}
|
|
}
|
|
|
|
// Exposes a variable on the port for editing when it's not connected
|
|
private void ExposeVariableToPort(Port port, FieldInfo field)
|
|
{
|
|
// Only expose when the port is not connected
|
|
if (port.connections.Count() == 0)
|
|
{
|
|
var propertyFieldContainer = new VisualElement();
|
|
propertyFieldContainer.name = "property-field-container";
|
|
var propertyField = CreatePropertyFieldForType(field.FieldType, field.GetValue(graphNode));
|
|
|
|
if (propertyField != null)
|
|
{
|
|
// Register a callback for when the value changes
|
|
if (propertyField is IntegerField intField)
|
|
{
|
|
intField.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
else if (propertyField is FloatField floatField)
|
|
{
|
|
floatField.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
else if (propertyField is Toggle boolField)
|
|
{
|
|
boolField.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
else if (propertyField is TextField stringField)
|
|
{
|
|
stringField.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
else if (propertyField is ColorField colorField)
|
|
{
|
|
colorField.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
else if (propertyField is Vector3Field vector3Field)
|
|
{
|
|
vector3Field.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
else if (propertyField is Vector2Field vector2Field)
|
|
{
|
|
vector2Field.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
else if (propertyField is ObjectField objectField)
|
|
{
|
|
objectField.RegisterValueChangedCallback(evt =>
|
|
{
|
|
field.SetValue(graphNode, evt.newValue); // Update the field with the new value
|
|
});
|
|
}
|
|
|
|
propertyFieldContainer.Add(propertyField);
|
|
port.Add(propertyFieldContainer);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// If the port is connected, remove the exposed UI element
|
|
var existingPropertyFieldContainer = port.Q<VisualElement>("property-field-container");
|
|
if (existingPropertyFieldContainer != null)
|
|
{
|
|
port.Remove(existingPropertyFieldContainer);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create appropriate property field based on the type of the variable
|
|
private VisualElement CreatePropertyFieldForType(Type type, object value)
|
|
{
|
|
if (type == typeof(int))
|
|
{
|
|
var intField = new IntegerField { value = (int)value };
|
|
return intField;
|
|
}
|
|
else if (type == typeof(float))
|
|
{
|
|
var floatField = new FloatField { value = (float)value };
|
|
return floatField;
|
|
}
|
|
else if (type == typeof(bool))
|
|
{
|
|
var boolField = new Toggle { value = (bool)value };
|
|
return boolField;
|
|
}
|
|
else if (type == typeof(string))
|
|
{
|
|
var stringField = new TextField { value = (string)value };
|
|
return stringField;
|
|
}
|
|
else if (type == typeof(Color))
|
|
{
|
|
var colorField = new ColorField() { value = (Color)value };
|
|
return colorField;
|
|
}
|
|
else if (type == typeof(Vector3))
|
|
{
|
|
var vector3Field = new Vector3Field { value = (Vector3)value };
|
|
return vector3Field;
|
|
}
|
|
else if (type == typeof(Vector2))
|
|
{
|
|
var vector2Field = new Vector2Field { value = (Vector2)value };
|
|
return vector2Field;
|
|
}
|
|
else if (type == typeof(Texture2D))
|
|
{
|
|
var objectField = new ObjectField { value = (Texture2D)value, objectType = typeof(Texture2D) };
|
|
return objectField;
|
|
}
|
|
|
|
// Add more types as needed (Vector3, etc.)
|
|
return null;
|
|
}
|
|
|
|
public void SavePosition() => graphNode.SetPosition(GetPosition());
|
|
}
|
|
}
|