1
0
mirror of https://github.com/Siccity/xNode.git synced 2025-12-20 09:16:01 +08:00
xNode/Scripts/Editor/NodeGroupEditor.cs
Emre Dogan c58648d663 Fixed group resizing code to not jitter anymore.
Can now adjust color of group node resize icon.
Changed header label rendering to always be vertically centered.
Changed group node style.
Changed rename text field style.
2023-10-08 20:08:19 +01:00

282 lines
11 KiB
C#

using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using XNode;
using XNodeEditor.Internal;
namespace XNodeEditor.NodeGroups
{
[CustomNodeEditor(typeof(NodeGroup))]
public class NodeGroupEditor : NodeEditor
{
private NodeGroup group => _group != null ? _group : _group = target as NodeGroup;
private NodeGroup _group;
public static Texture2D corner =>
_corner != null ? _corner : _corner = Resources.Load<Texture2D>("xnode_corner");
private static Texture2D _corner;
private bool _isResizing;
private bool _isResizeHovering;
private Vector2 _size;
private float _currentHeight;
private Vector2 _draggingOffset;
private List<Vector2> _childNodesDragOffsets;
private const int mouseRectPadding = 4;
private const int mouseRectMargin = 30;
private GUIStyle headerStyle;
private GUIStyle headerLabelStyle;
public override void OnCreate()
{
_currentHeight = group.height;
headerLabelStyle = new GUIStyle(NodeEditorResources.styles.nodeHeaderLabel);
headerLabelStyle.fontSize = 24;
headerStyle = new GUIStyle(NodeEditorResources.styles.nodeHeader);
headerStyle.fixedHeight += 18;
}
public override void OnHeaderGUI()
{
Color initColor = GUI.contentColor;
GUI.contentColor = new Color(0.6f, 0.6f, 0.6f, 1.0f);
GUILayout.Label(target.name, headerLabelStyle);
GUI.contentColor = initColor;
}
public override void OnBodyGUI()
{
NodeEditorWindow.current.wantsMouseMove = true;
Event e = Event.current;
switch (e.type)
{
case EventType.MouseMove:
if (NodeEditorWindow.current.nodeSizes.TryGetValue(target, out _size))
{
bool initHovering = _isResizeHovering;
// Mouse position checking is in node local space
Rect lowerRight = new Rect(_size.x - (mouseRectMargin + mouseRectPadding),
_size.y - (mouseRectMargin + mouseRectPadding), mouseRectMargin, mouseRectMargin);
if (lowerRight.Contains(e.mousePosition))
{
_isResizeHovering = true;
}
else
{
_isResizeHovering = false;
}
if (initHovering != _isResizeHovering)
{
NodeEditorWindow.current.Repaint();
}
}
break;
case EventType.MouseDrag:
if (_isResizing)
{
group.width = (int)Mathf.Max(200,
e.mousePosition.x + _draggingOffset.x + (mouseRectMargin + mouseRectPadding));
// magic numbers - otherwise resizing will jump vertically.
group.height = (int)Mathf.Max(100,
e.mousePosition.y + _draggingOffset.y - (31 + (30 - mouseRectMargin)));
_currentHeight = group.height;
NodeEditorWindow.current.Repaint();
}
break;
case EventType.MouseDown:
// Ignore everything except left clicks
if (e.button != 0)
{
return;
}
_childNodesDragOffsets = new List<Vector2>(group.GetNodes().Count);
foreach (Node node in group.GetNodes())
{
_childNodesDragOffsets.Add(node.position -
NodeEditorWindow.current.WindowToGridPosition(
e.mousePosition));
}
if (NodeEditorWindow.current.nodeSizes.TryGetValue(target, out _size))
{
// Mouse position checking is in node local space
Rect lowerRight = new Rect(_size.x - (mouseRectMargin + mouseRectPadding),
_size.y - (mouseRectMargin + mouseRectPadding), mouseRectMargin, mouseRectMargin);
if (lowerRight.Contains(e.mousePosition))
{
_isResizing = true;
_draggingOffset = lowerRight.position - e.mousePosition;
}
}
break;
case EventType.MouseUp:
_isResizing = false;
// Select nodes inside the group
if (false && Selection.Contains(target))
{
var selection = Selection.objects.ToList();
// Select Nodes
selection.AddRange(group.GetNodes());
// Select Reroutes
foreach (Node node in target.graph.nodes)
{
if (node != null)
{
foreach (NodePort port in node.Ports)
{
for (int i = 0; i < port.ConnectionCount; i++)
{
var reroutes = port.GetReroutePoints(i);
for (int k = 0; k < reroutes.Count; k++)
{
Vector2 p = reroutes[k];
if (p.x < group.position.x)
{
continue;
}
if (p.y < group.position.y)
{
continue;
}
if (p.x > group.position.x + group.width)
{
continue;
}
if (p.y > group.position.y + group.height + 30)
{
continue;
}
if (NodeEditorWindow.current.selectedReroutes.Any(x =>
x.port == port && x.connectionIndex == i && x.pointIndex == k))
{
continue;
}
NodeEditorWindow.current.selectedReroutes.Add(
new RerouteReference(port, i, k)
);
}
}
}
}
}
Selection.objects = selection.Distinct().ToArray();
}
break;
case EventType.Repaint:
// Move to bottom
if (target.graph.nodes.IndexOf(target) != 0)
{
target.graph.nodes.Remove(target);
target.graph.nodes.Insert(0, target);
}
// Add scale cursors
if (NodeEditorWindow.current.nodeSizes.TryGetValue(target, out _size))
{
Rect lowerRight = new Rect(target.position, new Vector2(mouseRectMargin, mouseRectMargin));
lowerRight.y += _size.y - (mouseRectMargin + mouseRectPadding);
lowerRight.x += _size.x - (mouseRectMargin + mouseRectPadding);
lowerRight = NodeEditorWindow.current.GridToWindowRect(lowerRight);
NodeEditorWindow.current.onLateGUI += () => AddMouseRect(lowerRight, MouseCursor.ResizeUpLeft);
}
break;
}
GUILayout.Space(_currentHeight);
if (NodeEditorWindow.current.nodeSizes.TryGetValue(target, out _size))
{
Color initColor = GUI.color;
GUI.color = _isResizeHovering
? NodeEditorPreferences.GetSettings().resizeIconHoverColor
: NodeEditorPreferences.GetSettings().resizeIconColor;
GUI.DrawTexture(
new Rect(_size.x - (mouseRectMargin + mouseRectPadding),
_size.y - (mouseRectMargin + mouseRectPadding),
24,
24),
corner);
GUI.color = initColor;
}
}
public override void OnRenameDeactive()
{
_currentHeight = group.height;
}
public override int GetWidth()
{
return group.width;
}
public override GUIStyle GetHeaderStyle()
{
return headerStyle;
}
public override GUIStyle GetHeaderLabelStyle()
{
return headerLabelStyle;
}
public static void AddMouseRect(Rect rect, MouseCursor mouseCursor)
{
EditorGUIUtility.AddCursorRect(rect, mouseCursor);
}
public override void AddContextMenuItems(GenericMenu menu)
{
bool canRemove = true;
menu.AddItem(new GUIContent("Rename Group"), false, RenameNodeGroup);
// Add actions to any number of selected nodes
menu.AddItem(new GUIContent("Copy"), false, NodeEditorWindow.current.CopySelectedNodes);
menu.AddItem(new GUIContent("Duplicate"), false, NodeEditorWindow.current.DuplicateSelectedNodes);
if (canRemove)
{
menu.AddItem(new GUIContent("Remove"), false, NodeEditorWindow.current.RemoveSelectedNodes);
}
else
{
menu.AddItem(new GUIContent("Remove"), false, null);
}
}
public void RenameNodeGroup()
{
var nodeGroups = Selection.objects.ToList().Where(x => x is NodeGroup).ToList();
if (nodeGroups.Count == 1)
{
NodeGroup group = nodeGroups[0] as NodeGroup;
Vector2 size;
if (NodeEditorWindow.current.nodeSizes.TryGetValue(group, out size))
{
RenamePopup.Show(group, size.x);
}
else
{
RenamePopup.Show(group);
}
}
}
}
}