[toc]

# 蓝图开发

# 1. 实现蓝图组

主要功能点有几个:

  1. 更改功能组的标题
  2. 拖拽右下角可以对功能组的大小进行调整
  3. 可以吸附功能组内的元素一起移动
  4. 保证在所有元素最下方

# 1. 更改功能组标题

这个比较简单,直接暴露一个标题参数,然后在 Editor 的 OnHeaderGUI 重载中刷新题头

1
2
3
4
5
public override void OnHeaderGUI()
{
var self = group;
GUILayout.Label(self.title, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
}

# 2. 拖拽右下角对功能组大小进行调整

  1. 首先在鼠标触发 MouseDown 事件时判断是否在包围盒的右下角

这里可以使用 OnGui 中的 Event 进行鼠标事件的捕获 https://blog.csdn.net/qq_36383623/article/details/100184153 在 XNode 中的 OnXXXGUI 实际上都是从 OnGUI 中延伸出来的:

1
NodeEditorWindow.OnGUI -> DrawNodes() -> graph.nodes.OnHeaderGUI()/OnBodyGUI()

这样,所以在 OnBodyGUI 中实际上也可以直接使用 OnGUI 中的 Event

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public override void OnBodyGUI()
{
Event e = Event.current;
switch (e.type)
{
case EventType.MouseDrag:
break;
case EventType.MouseDown:
if (e.button != 0) return;
if(NodeEditorWindow.current.nodeSizes.TryGetValue(target,out size))
{
Rect lowerRight = new Rect(size.x - 34, size.y - 34, 30, 30);
if (lowerRight.Contains(e.mousePosition))
{
isDragging = true;
}
}
break;
case EventType.MouseUp:
break;
case EventType.Repaint:
break;

}
}

如上述代码,直接在 Node 的 Boundary 中进行判断当前鼠标是否在右下角即可

如果鼠标在右下角进行的点击,则进入拖拽态

  1. 拖拽时对 Node 的 Gui 进行重绘,更新 Node 的长和宽,同时重新绘制 Node

其中有一个小 trick, 就是显示拖拽指针的效果

1
2
3
4
5
6
7
8
9
10
11
12
13
if (NodeEditorWindow.current.nodeSizes.TryGetValue(target, out size))
{
Rect lowerRight = new Rect(target.position, new Vector2(30, 30));
lowerRight.y += size.y - 34;
lowerRight.x += size.x - 34;
lowerRight = NodeEditorWindow.current.GridToWindowRect(lowerRight);
NodeEditorWindow.current.onLateGUI += () => AddMouseRect(lowerRight);
}

public static void AddMouseRect(Rect rect)
{
EditorGUIUtility.AddCursorRect(rect, MouseCursor.ResizeUpLeft);
}

其实只需要当鼠标在可拖拽的范围内时更改鼠标的滚轮样式即可 Editor 下更改鼠标滚轮的样式可以使用: EditorGUIUtility.AddCursorRect(rect, MouseCursor.ResizeUpLeft);

# 3. 吸附包围盒内的元素一起移动

  1. 直接判断有哪些元素在包围盒内 (包里 for nodes, 以及判断 每个 node 是否在当前 NodeGroup 的范围内)
  2. 加到 Selection Node 中即可
1
Selection.objects = selection.Distinct().ToArray();

# 4. 保证在所有元素最下方

1
2
3
4
5
6
//移到最下层
if (target.graph.nodes.IndexOf(target) != 0)
{
target.graph.nodes.Remove(target);
target.graph.nodes.Insert(0, target);
}

每次 Repaint 判断是否在最下方,不是就移到最下方

# 附:大佬画的 XNode 架构图