带有GUI控件的Unity3D Draggable GUI.Box

时间:2017-05-13 16:23:33

标签: user-interface unity3d unity-editor

我在Unity中构建自定义节点编辑器窗口,我已经查看了this one等各种资源,它使用GUI.Box来构建节点窗口。< / p>

这很好用,我可以按照我想要的方式拖动这些窗口,但是一旦我将控件添加到GUI.Box,我希望它们覆盖Drag()函数I& #39;写了。

以下是问题的一个示例 - 当我向上移动垂直滑块时,整个框都会拖动它。

Vertical Slider issues

有没有办法使用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类中添加垂直滑块。构造滑块的辅助类的提取:

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控件自动消耗左侧mousedown事件,因此单击滑块意味着没有传播到Box以检查它是否被点击。

我需要做的是在Node类中分离IsSelected和IsDragged标志,并在mouseUp上清除IsDragged。我最初使用IsSelected标记拖动已启用和已选中(可以一次选择并拖动多个节点)。

1 个答案:

答案 0 :(得分:1)

这是一个非常复杂的教程,所以我没有完全阅读它,但问题似乎是MouseDrag检测。好吧,基本上你想在单击Box内的GUI元素时停止事件传播,对吧?为此,请致电:

Event.current.Use()

每次用户在其中一个组件上拖动鼠标时。

使用您提到的资源,我更改了Node类,并在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();
}

First example

你可以做的另一件事是改变你画窗的方式。这是我在最新的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()才能正常工作。

Second example