Unity3D Draggable GUI.Box 带 GUI 控件
Unity3D Draggable GUI.Box with GUI controls
我正在 Unity 中构建自定义节点编辑器 window,我查看了各种资源,例如 this one,它使用 GUI.Box
构建节点 windows.
效果很好,我可以随意拖动这些 windows,但是一旦我将控件添加到 GUI.Box
,我希望它们覆盖 [=17] =] 我写的函数。
这是一个问题示例 - 当我向上移动垂直滑块时,整个框都随之拖动。
有没有办法使用 GUI.Box
修复此行为,或者我应该返回到 GUI.Window
的内置 GUI.DragWindow()
?
这是我使用的代码的简化版本:
EditorMouseInput.cs:
private bool ActionLeftMouseDown()
{
mouseDownNode = editor.GetSelectedNode(Input.current.mousePosition);
if (mouseDownNode == null)
editor.StartMovingEditorCanvas();
else
mouseDownNode.IsSelected = true;
}
BaseNodeEditor.cs:
public BaseNode GetSelectedNode(Vector2 mousePos)
{
foreach (BaseNode node in Nodes)
{
if (node.WindowRect.Contains(mousePos))
return node;
}
return null;
}
public void Drag(Vector2 delta)
{
if (!MoveEditorMode && !ConnectionMode)
{
foreach (BaseNode node in Nodes)
{
node.Drag(delta);
}
}
BaseNode.cs:
public void Drag(Vector2 delta)
{
if (IsSelected)
draggedDistance += delta;
}
在派生的 JumpNode 中添加了垂直滑块 class。构造滑块的助手 class 的摘录:
Vector2 pos = node.WindowRect.position + rect.position * GridSpacing;
value = GUI.VerticalSlider(new Rect(pos, rect.size * GridSpacing), value, maxValue, minValue);
我明白为什么这不符合我的要求,但我不知道如何去做,因为 GUI 控件不是 GUI.Box 的一部分。
任何帮助或建议,甚至是对其他来源的推动,我们都将不胜感激 - 我觉得我已经使用了我脑海中存在的所有搜索词!
编辑 - 已解决: 感谢 Kleber 为我解决了这个问题。万一其他人遇到这个或类似的问题,我的解决方案是意识到 GUI 控件会自动消耗左鼠标按下事件,因此单击滑块意味着不会传播到 Box 以检查它是否被单击。
我需要做的是在节点 class 中分离 IsSelected 和 IsDragged 标志,并清除 mouseUp 上的 IsDragged。我最初使用 IsSelected 来标记拖动已启用和已选择(可以一次选择和拖动多个节点)。
这是一个相当复杂的教程,所以我没有完全阅读它,但问题似乎是 MouseDrag
检测。好吧,基本上您想在单击 Box 内的 GUI 元素时停止事件传播,对吗?为此,您致电:
Event.current.Use()
每次用户将鼠标拖到您的组件之一上时。
使用您提到的资源,我更改了 Node
class 并在 Draw()
方法中添加了一个滑块,这样结束:
public void Draw() {
inPoint.Draw();
outPoint.Draw();
GUI.Box(rect, title, style);
GUI.BeginGroup(rect);
_value = GUI.HorizontalSlider(new Rect(20, 0, 50, 20), _value, 100, -100);
GUI.EndGroup();
}
您可以做的另一件事是改变您的画法 window。这是我在最新的 Unity 版本 (5.6) 上测试过的一个简单示例:
private void OnGUI() {
GUI.Box(_rect, string.Empty);
GUI.BeginGroup(_rect);
_value = GUI.VerticalSlider(new Rect(145, 100, 20, 100), _value, 100, -100);
GUI.EndGroup();
var e = Event.current;
if (e.type == EventType.MouseDrag && _rect.Contains(e.mousePosition)) {
_rect.x += e.delta.x;
_rect.y += e.delta.y;
Repaint();
}
}
如您所见,此示例不需要 Event.current.Use()
即可正常工作。
我正在 Unity 中构建自定义节点编辑器 window,我查看了各种资源,例如 this one,它使用 GUI.Box
构建节点 windows.
效果很好,我可以随意拖动这些 windows,但是一旦我将控件添加到 GUI.Box
,我希望它们覆盖 [=17] =] 我写的函数。
这是一个问题示例 - 当我向上移动垂直滑块时,整个框都随之拖动。
有没有办法使用 GUI.Box
修复此行为,或者我应该返回到 GUI.Window
的内置 GUI.DragWindow()
?
这是我使用的代码的简化版本:
EditorMouseInput.cs:
private bool ActionLeftMouseDown()
{
mouseDownNode = editor.GetSelectedNode(Input.current.mousePosition);
if (mouseDownNode == null)
editor.StartMovingEditorCanvas();
else
mouseDownNode.IsSelected = true;
}
BaseNodeEditor.cs:
public BaseNode GetSelectedNode(Vector2 mousePos)
{
foreach (BaseNode node in Nodes)
{
if (node.WindowRect.Contains(mousePos))
return node;
}
return null;
}
public void Drag(Vector2 delta)
{
if (!MoveEditorMode && !ConnectionMode)
{
foreach (BaseNode node in Nodes)
{
node.Drag(delta);
}
}
BaseNode.cs:
public void Drag(Vector2 delta)
{
if (IsSelected)
draggedDistance += delta;
}
在派生的 JumpNode 中添加了垂直滑块 class。构造滑块的助手 class 的摘录:
Vector2 pos = node.WindowRect.position + rect.position * GridSpacing;
value = GUI.VerticalSlider(new Rect(pos, rect.size * GridSpacing), value, maxValue, minValue);
我明白为什么这不符合我的要求,但我不知道如何去做,因为 GUI 控件不是 GUI.Box 的一部分。
任何帮助或建议,甚至是对其他来源的推动,我们都将不胜感激 - 我觉得我已经使用了我脑海中存在的所有搜索词!
编辑 - 已解决: 感谢 Kleber 为我解决了这个问题。万一其他人遇到这个或类似的问题,我的解决方案是意识到 GUI 控件会自动消耗左鼠标按下事件,因此单击滑块意味着不会传播到 Box 以检查它是否被单击。
我需要做的是在节点 class 中分离 IsSelected 和 IsDragged 标志,并清除 mouseUp 上的 IsDragged。我最初使用 IsSelected 来标记拖动已启用和已选择(可以一次选择和拖动多个节点)。
这是一个相当复杂的教程,所以我没有完全阅读它,但问题似乎是 MouseDrag
检测。好吧,基本上您想在单击 Box 内的 GUI 元素时停止事件传播,对吗?为此,您致电:
Event.current.Use()
每次用户将鼠标拖到您的组件之一上时。
使用您提到的资源,我更改了 Node
class 并在 Draw()
方法中添加了一个滑块,这样结束:
public void Draw() {
inPoint.Draw();
outPoint.Draw();
GUI.Box(rect, title, style);
GUI.BeginGroup(rect);
_value = GUI.HorizontalSlider(new Rect(20, 0, 50, 20), _value, 100, -100);
GUI.EndGroup();
}
您可以做的另一件事是改变您的画法 window。这是我在最新的 Unity 版本 (5.6) 上测试过的一个简单示例:
private void OnGUI() {
GUI.Box(_rect, string.Empty);
GUI.BeginGroup(_rect);
_value = GUI.VerticalSlider(new Rect(145, 100, 20, 100), _value, 100, -100);
GUI.EndGroup();
var e = Event.current;
if (e.type == EventType.MouseDrag && _rect.Contains(e.mousePosition)) {
_rect.x += e.delta.x;
_rect.y += e.delta.y;
Repaint();
}
}
如您所见,此示例不需要 Event.current.Use()
即可正常工作。