1
0
mirror of https://github.com/Siccity/xNode.git synced 2025-12-20 17:26:02 +08:00

Merge branch 'context_menu_filter'

This commit is contained in:
Thor Brigsted 2020-12-17 13:53:26 +01:00
commit 6b893fd5a4
7 changed files with 141 additions and 27 deletions

View File

@ -233,7 +233,7 @@ namespace XNodeEditor {
// Open context menu for auto-connection if there is no target node
else if (draggedOutputTarget == null && NodeEditorPreferences.GetSettings().dragToCreate && autoConnectOutput != null) {
GenericMenu menu = new GenericMenu();
graphEditor.AddContextMenuItems(menu);
graphEditor.AddContextMenuItems(menu, draggedOutput.ValueType);
menu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
}
//Release dragged connection
@ -512,6 +512,7 @@ namespace XNodeEditor {
DrawNoodle(gradient, path, stroke, thickness, gridPoints);
GUIStyle portStyle = NodeEditorWindow.current.graphEditor.GetPortStyle(draggedOutput);
Color bgcol = Color.black;
Color frcol = gradient.colorKeys[0].color;
bgcol.a = 0.6f;
@ -524,7 +525,7 @@ namespace XNodeEditor {
rect.position = new Vector2(rect.position.x - 8, rect.position.y - 8);
rect = GridToWindowRect(rect);
NodeEditorGUILayout.DrawPortHandle(rect, bgcol, frcol);
NodeEditorGUILayout.DrawPortHandle(rect, bgcol, frcol, portStyle.normal.background, portStyle.active.background);
}
}
}

View File

@ -118,6 +118,15 @@ namespace XNodeEditor {
contextMenu.AddItem(new GUIContent($"Disconnect({name})"), false, () => hoveredPort.Disconnect(index));
}
contextMenu.AddItem(new GUIContent("Clear Connections"), false, () => hoveredPort.ClearConnections());
//Get compatible nodes with this port
if (NodeEditorPreferences.GetSettings().createFilter) {
contextMenu.AddSeparator("");
if (hoveredPort.direction == XNode.NodePort.IO.Input)
graphEditor.AddContextMenuItems(contextMenu, hoveredPort.ValueType, XNode.NodePort.IO.Output);
else
graphEditor.AddContextMenuItems(contextMenu, hoveredPort.ValueType, XNode.NodePort.IO.Input);
}
contextMenu.DropDown(new Rect(Event.current.mousePosition, Vector2.zero));
if (NodeEditorPreferences.GetSettings().autoSave) AssetDatabase.SaveAssets();
}
@ -334,6 +343,8 @@ namespace XNodeEditor {
if (!_portConnectionPoints.TryGetValue(output, out fromRect)) continue;
Color portColor = graphEditor.GetPortColor(output);
GUIStyle portStyle = graphEditor.GetPortStyle(output);
for (int k = 0; k < output.ConnectionCount; k++) {
XNode.NodePort input = output.GetConnection(k);
@ -367,11 +378,11 @@ namespace XNodeEditor {
// Draw selected reroute points with an outline
if (selectedReroutes.Contains(rerouteRef)) {
GUI.color = NodeEditorPreferences.GetSettings().highlightColor;
GUI.DrawTexture(rect, NodeEditorResources.dotOuter);
GUI.DrawTexture(rect, portStyle.normal.background);
}
GUI.color = portColor;
GUI.DrawTexture(rect, NodeEditorResources.dot);
GUI.DrawTexture(rect, portStyle.active.background);
if (rect.Overlaps(selectionBox)) selection.Add(rerouteRef);
if (rect.Contains(mousePos)) hoveredReroute = rerouteRef;
@ -561,8 +572,7 @@ namespace XNodeEditor {
string tooltip = null;
if (hoveredPort != null) {
tooltip = graphEditor.GetPortTooltip(hoveredPort);
}
else if (hoveredNode != null && IsHoveringNode && IsHoveringTitle(hoveredNode)) {
} else if (hoveredNode != null && IsHoveringNode && IsHoveringTitle(hoveredNode)) {
tooltip = NodeEditor.GetEditor(hoveredNode, this).GetHeaderTooltip();
}
if (string.IsNullOrEmpty(tooltip)) return;

View File

@ -16,7 +16,7 @@ namespace XNodeEditor {
/// <summary> Make a field for a serialized property. Automatically displays relevant node port. </summary>
public static void PropertyField(SerializedProperty property, bool includeChildren = true, params GUILayoutOption[] options) {
PropertyField(property, (GUIContent) null, includeChildren, options);
PropertyField(property, (GUIContent)null, includeChildren, options);
}
/// <summary> Make a field for a serialized property. Automatically displays relevant node port. </summary>
@ -101,7 +101,7 @@ namespace XNodeEditor {
}
rect = GUILayoutUtility.GetLastRect();
float paddingLeft = NodeEditorResources.styles.inputPort.padding.left;
float paddingLeft = NodeEditorWindow.current.graphEditor.GetPortStyle(port).padding.left;
rect.position = rect.position - new Vector2(16 + paddingLeft, -spacePadding);
// If property is an output, display a text label and put a port handle on the right side
} else if (port.direction == XNode.NodePort.IO.Output) {
@ -161,7 +161,7 @@ namespace XNodeEditor {
}
rect = GUILayoutUtility.GetLastRect();
rect.width += NodeEditorResources.styles.outputPort.padding.right;
rect.width += NodeEditorWindow.current.graphEditor.GetPortStyle(port).padding.right;
rect.position = rect.position + new Vector2(rect.width, spacePadding);
}
@ -169,7 +169,8 @@ namespace XNodeEditor {
Color backgroundColor = NodeEditorWindow.current.graphEditor.GetPortBackgroundColor(port);
Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port);
DrawPortHandle(rect, backgroundColor, col);
GUIStyle portStyle = NodeEditorWindow.current.graphEditor.GetPortStyle(port);
DrawPortHandle(rect, backgroundColor, col, portStyle.normal.background, portStyle.active.background);
// Register the handle position
Vector2 portPos = rect.center;
@ -201,7 +202,7 @@ namespace XNodeEditor {
EditorGUILayout.LabelField(content, options);
Rect rect = GUILayoutUtility.GetLastRect();
float paddingLeft = NodeEditorResources.styles.inputPort.padding.left;
float paddingLeft = NodeEditorWindow.current.graphEditor.GetPortStyle(port).padding.left;
position = rect.position - new Vector2(16 + paddingLeft, 0);
}
// If property is an output, display a text label and put a port handle on the right side
@ -210,7 +211,7 @@ namespace XNodeEditor {
EditorGUILayout.LabelField(content, NodeEditorResources.OutputPort, options);
Rect rect = GUILayoutUtility.GetLastRect();
rect.width += NodeEditorResources.styles.outputPort.padding.right;
rect.width += NodeEditorWindow.current.graphEditor.GetPortStyle(port).padding.right;
position = rect.position + new Vector2(rect.width, 0);
}
PortField(position, port);
@ -224,7 +225,9 @@ namespace XNodeEditor {
Color backgroundColor = NodeEditorWindow.current.graphEditor.GetPortBackgroundColor(port);
Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port);
DrawPortHandle(rect, backgroundColor, col);
GUIStyle portStyle = NodeEditorWindow.current.graphEditor.GetPortStyle(port);
DrawPortHandle(rect, backgroundColor, col, portStyle.normal.background, portStyle.active.background);
// Register the handle position
Vector2 portPos = rect.center;
@ -239,12 +242,12 @@ namespace XNodeEditor {
// If property is an input, display a regular property field and put a port handle on the left side
if (port.direction == XNode.NodePort.IO.Input) {
rect = GUILayoutUtility.GetLastRect();
float paddingLeft = NodeEditorResources.styles.inputPort.padding.left;
float paddingLeft = NodeEditorWindow.current.graphEditor.GetPortStyle(port).padding.left;
rect.position = rect.position - new Vector2(16 + paddingLeft, 0);
// If property is an output, display a text label and put a port handle on the right side
} else if (port.direction == XNode.NodePort.IO.Output) {
rect = GUILayoutUtility.GetLastRect();
rect.width += NodeEditorResources.styles.outputPort.padding.right;
rect.width += NodeEditorWindow.current.graphEditor.GetPortStyle(port).padding.right;
rect.position = rect.position + new Vector2(rect.width, 0);
}
@ -252,7 +255,9 @@ namespace XNodeEditor {
Color backgroundColor = NodeEditorWindow.current.graphEditor.GetPortBackgroundColor(port);
Color col = NodeEditorWindow.current.graphEditor.GetPortColor(port);
DrawPortHandle(rect, backgroundColor, col);
GUIStyle portStyle = NodeEditorWindow.current.graphEditor.GetPortStyle(port);
DrawPortHandle(rect, backgroundColor, col, portStyle.normal.background, portStyle.active.background);
// Register the handle position
Vector2 portPos = rect.center;
@ -267,16 +272,25 @@ namespace XNodeEditor {
GUILayout.EndHorizontal();
}
public static void DrawPortHandle(Rect rect, Color backgroundColor, Color typeColor) {
/// <summary>
/// Draw the port
/// </summary>
/// <param name="rect">position and size</param>
/// <param name="backgroundColor">color for background texture of the port. Normaly used to Border</param>
/// <param name="typeColor"></param>
/// <param name="border">texture for border of the dot port</param>
/// <param name="dot">texture for the dot port</param>
public static void DrawPortHandle(Rect rect, Color backgroundColor, Color typeColor, Texture2D border, Texture2D dot) {
Color col = GUI.color;
GUI.color = backgroundColor;
GUI.DrawTexture(rect, NodeEditorResources.dotOuter);
GUI.DrawTexture(rect, border);
GUI.color = typeColor;
GUI.DrawTexture(rect, NodeEditorResources.dot);
GUI.DrawTexture(rect, dot);
GUI.color = col;
}
#region Obsolete
#region Obsolete
[Obsolete("Use IsDynamicPortListPort instead")]
public static bool IsInstancePortListPort(XNode.NodePort port) {
return IsDynamicPortListPort(port);
@ -286,7 +300,7 @@ namespace XNodeEditor {
public static void InstancePortList(string fieldName, Type type, SerializedObject serializedObject, XNode.NodePort.IO io, XNode.Node.ConnectionType connectionType = XNode.Node.ConnectionType.Multiple, XNode.Node.TypeConstraint typeConstraint = XNode.Node.TypeConstraint.None, Action<ReorderableList> onCreation = null) {
DynamicPortList(fieldName, type, serializedObject, io, connectionType, typeConstraint, onCreation);
}
#endregion
#endregion
/// <summary> Is this port part of a DynamicPortList? </summary>
public static bool IsDynamicPortListPort(XNode.NodePort port) {
@ -317,7 +331,7 @@ namespace XNodeEditor {
return new { index = i, port = x };
}
}
return new { index = -1, port = (XNode.NodePort) null };
return new { index = -1, port = (XNode.NodePort)null };
}).Where(x => x.port != null);
List<XNode.NodePort> dynamicPorts = indexedPorts.OrderBy(x => x.index).Select(x => x.port).ToList();
@ -454,7 +468,7 @@ namespace XNodeEditor {
return new { index = i, port = x };
}
}
return new { index = -1, port = (XNode.NodePort) null };
return new { index = -1, port = (XNode.NodePort)null };
}).Where(x => x.port != null);
dynamicPorts = indexedPorts.OrderBy(x => x.index).Select(x => x.port).ToList();

View File

@ -38,6 +38,7 @@ namespace XNodeEditor {
public bool autoSave = true;
public bool openOnCreate = true;
public bool dragToCreate = true;
public bool createFilter = true;
public bool zoomToMouse = true;
public bool portTooltips = true;
[SerializeField] private string typeColorsData = "";
@ -168,6 +169,9 @@ namespace XNodeEditor {
settings.noodleStroke = (NoodleStroke) EditorGUILayout.EnumPopup("Noodle stroke", (Enum) settings.noodleStroke);
settings.portTooltips = EditorGUILayout.Toggle("Port Tooltips", settings.portTooltips);
settings.dragToCreate = EditorGUILayout.Toggle(new GUIContent("Drag to Create", "Drag a port connection anywhere on the grid to create and connect a node"), settings.dragToCreate);
settings.createFilter = EditorGUILayout.Toggle(new GUIContent("Create Filter", "Only show nodes that are compatible with the selected port"), settings.createFilter);
//END
if (GUI.changed) {
SavePrefs(key, settings);
NodeEditorWindow.RepaintAll();

View File

@ -27,10 +27,14 @@ namespace XNodeEditor {
inputPort = new GUIStyle(baseStyle);
inputPort.alignment = TextAnchor.UpperLeft;
inputPort.padding.left = 0;
inputPort.active.background = dot;
inputPort.normal.background = dotOuter;
outputPort = new GUIStyle(baseStyle);
outputPort.alignment = TextAnchor.UpperRight;
outputPort.padding.right = 0;
outputPort.active.background = dot;
outputPort.normal.background = dotOuter;
nodeHeader = new GUIStyle();
nodeHeader.alignment = TextAnchor.MiddleCenter;

View File

@ -127,6 +127,57 @@ namespace XNodeEditor {
return methods.Count() > 0;
}
/// <summary>
/// Looking for ports with value Type compatible with a given type.
/// </summary>
/// <param name="nodeType">Node to search</param>
/// <param name="compatibleType">Type to find compatiblities</param>
/// <param name="direction"></param>
/// <returns>True if NodeType has some port with value type compatible</returns>
public static bool HasCompatiblePortType(Type nodeType, Type compatibleType, XNode.NodePort.IO direction = XNode.NodePort.IO.Input) {
Type findType = typeof(XNode.Node.InputAttribute);
if (direction == XNode.NodePort.IO.Output)
findType = typeof(XNode.Node.OutputAttribute);
//Get All fields from node type and we go filter only field with portAttribute.
//This way is possible to know the values of the all ports and if have some with compatible value tue
foreach (FieldInfo f in XNode.NodeDataCache.GetNodeFields(nodeType)) {
var portAttribute = f.GetCustomAttributes(findType, false).FirstOrDefault();
if (portAttribute != null) {
if (IsCastableTo(f.FieldType, compatibleType)) {
return true;
}
}
}
return false;
}
/// <summary>
/// Filter only node types that contains some port value type compatible with an given type
/// </summary>
/// <param name="nodeTypes">List with all nodes type to filter</param>
/// <param name="compatibleType">Compatible Type to Filter</param>
/// <returns>Return Only Node Types with ports compatible, or an empty list</returns>
public static List<Type> GetCompatibleNodesTypes(Type[] nodeTypes, Type compatibleType, XNode.NodePort.IO direction = XNode.NodePort.IO.Input) {
//Result List
List<Type> filteredTypes = new List<Type>();
//Return empty list
if (nodeTypes == null) { return filteredTypes; }
if (compatibleType == null) { return filteredTypes; }
//Find compatiblity
foreach (Type findType in nodeTypes) {
if (HasCompatiblePortType(findType, compatibleType, direction)) {
filteredTypes.Add(findType);
}
}
return filteredTypes;
}
/// <summary> Return a prettiefied type name. </summary>
public static string PrettyName(this Type type) {
if (type == null) return "null";

View File

@ -57,11 +57,24 @@ namespace XNodeEditor {
return 0;
}
/// <summary> Add items for the context menu when right-clicking this node. Override to add custom menu items. </summary>
public virtual void AddContextMenuItems(GenericMenu menu) {
/// <summary>
/// Add items for the context menu when right-clicking this node.
/// Override to add custom menu items.
/// </summary>
/// <param name="menu"></param>
/// <param name="compatibleType">Use it to filter only nodes with ports value type, compatible with this type</param>
/// <param name="direction">Direction of the compatiblity</param>
public virtual void AddContextMenuItems(GenericMenu menu, Type compatibleType = null, XNode.NodePort.IO direction = XNode.NodePort.IO.Input) {
Vector2 pos = NodeEditorWindow.current.WindowToGridPosition(Event.current.mousePosition);
var nodeTypes = NodeEditorReflection.nodeTypes.OrderBy(type => GetNodeMenuOrder(type)).ToArray();
Type[] nodeTypes = NodeEditorReflection.nodeTypes.OrderBy(type => GetNodeMenuOrder(type)).ToArray();
if (compatibleType != null && NodeEditorPreferences.GetSettings().createFilter) {
nodeTypes = NodeEditorUtilities.GetCompatibleNodesTypes(NodeEditorReflection.nodeTypes, compatibleType, direction).ToArray();
}
for (int i = 0; i < nodeTypes.Length; i++) {
Type type = nodeTypes[i];
//Get node context menu path
@ -141,6 +154,23 @@ namespace XNodeEditor {
return GetTypeColor(port.ValueType);
}
/// <summary>
/// The returned Style is used to configure the paddings and icon texture of the ports.
/// Use these properties to customize your port style.
///
/// The properties used is:
/// <see cref="GUIStyle.padding"/>[Left and Right], <see cref="GUIStyle.normal"/> [Background] = border texture,
/// and <seealso cref="GUIStyle.active"/> [Background] = dot texture;
/// </summary>
/// <param name="port">the owner of the style</param>
/// <returns></returns>
public virtual GUIStyle GetPortStyle(XNode.NodePort port) {
if (port.direction == XNode.NodePort.IO.Input)
return NodeEditorResources.styles.inputPort;
return NodeEditorResources.styles.outputPort;
}
/// <summary> The returned color is used to color the background of the door.
/// Usually used for outer edge effect </summary>
public virtual Color GetPortBackgroundColor(XNode.NodePort port) {