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() 即可正常工作。