2017-05-13 1 views
0

Ich baue ein benutzerdefiniertes Knoten-Editor-Fenster in Unity, und ich habe mir verschiedene Ressourcen wie this one angesehen, die GUI.Box verwenden, um Knotenfenster zu erstellen.Unity3D Draggable GUI.Box mit GUI-Steuerelementen

Das funktioniert gut, und ich kann diese Fenster so ziehen, wie ich möchte, aber sobald ich die Steuerelemente zu GUI.Box hinzufügen, will ich, dass sie die Drag() Funktion überschreiben, die ich geschrieben habe.

Hier ist ein Beispiel für das Problem: Wenn ich den vertikalen Schieberegler nach oben ziehe, zieht sich der gesamte Rahmen mit ihm zusammen.

Vertical Slider issues

Gibt es eine Möglichkeit, dieses Verhalten zu beheben GUI.Box, oder soll ich gehen zurück auf GUI.Window mit seinem eingebauten in GUI.DragWindow()?

Hier ist eine vereinfachte Version des Codes Ich verwende:

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; 
} 

Der vertikale Schieberegler wird in der abgeleiteten JumpNode-Klasse hinzugefügt. Auszug aus der Hilfsklasse, die den Schieber konstruiert:

Vector2 pos = node.WindowRect.position + rect.position * GridSpacing; 
value = GUI.VerticalSlider(new Rect(pos, rect.size * GridSpacing), value, maxValue, minValue); 

Ich kann sehen, warum dies nicht tut, was ich will, aber ich weiß nicht, wie es die GUI-Kontrollen gegeben geht etwa ist nicht Teil die GUI.Box.

Jede Hilfe oder Vorschläge, auch ein Anstupsen in Richtung einer anderen Quelle würde sehr geschätzt werden - ich habe das Gefühl, dass ich alle Suchbegriffe verwendet habe, die in meinem Kopf existieren!

Bearbeiten - Gelöst: Danke Kleber für die Lösung dieses für mich. Falls jemand anderes auf dieses oder ein ähnliches Problem stößt, bestand die Lösung für mich darin, zu erkennen, dass GUI-Steuerungen linke Mousedown-Ereignisse automatisch verbrauchen. Wenn Sie also auf einen Schieberegler klicken, wird keine Weiterleitung an die Box angezeigt.

Was ich tun musste, war die IsSelected und IsDragged Flags in der Node-Klasse zu trennen, und deaktivieren Sie IsDragged auf MouseUp. Ich habe ursprünglich IsSelected verwendet, um beide Ziehen aktiviert und ausgewählt (mehrere Knoten konnten ausgewählt und auf einmal gezogen werden).

Antwort

1

Es ist ein ziemlich komplexes Tutorial, also habe ich es nicht vollständig gelesen, aber das Problem scheint die MouseDrag Erkennung zu sein. Nun, im Grunde möchten Sie die Ereignisausbreitung stoppen, wenn Sie auf ein GUI-Element in der Box klicken, richtig? Um dies zu tun, rufen Sie:

jedes Mal, wenn der Benutzer die Maus auf eine Ihrer Komponenten zieht.

Verwenden der Ressource, die Sie erwähnt haben, geändert ich die Node Klasse und einen Schieberegler in der Draw() Methode hinzugefügt, wie diese Endung:

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

Eine andere Sache, die Sie ändern tun können, wie du zeichnest dein Fenster. Hier ist ein einfaches Beispiel, dass ich auf dem neuesten Unity Version getestet haben (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(); 
    } 
} 

Wie Sie sehen können, dieses Beispiel nicht eine Event.current.Use() braucht um richtig zu arbeiten.

Second example

+0

danke für die Antwort! Event.current.Use() würde definitiv funktionieren, obwohl mein Problem darin liegt, dass das Schieberegler-Steuerelement (oder irgendein Steuerelement) nicht in der Box vorhanden ist, es wird nur oben drauf gezeichnet. Ich verwende auch eingebaute GUI-Steuerelemente, so dass ich die Ereignisse nicht sehe, wenn angeklickt, ausgewählt, gezogen usw. – Aspekt

+1

'Event.current' ist nur innerhalb von' OnGUI() 'zugänglich, also nur für das IMGUI-System. Die Ressource, die Sie gesendet haben, hat eine Verwendung von 'Event.current', die zum Beispiel als ein Parameter der 'ProcessEvents()' - Methode gesendet wird. Ich habe meine Antwort bearbeitet und andere Lösungen hinzugefügt, die funktionieren könnten. – Kleber

+1

Zunächst möchte ich nur einen großen Dank dafür aussprechen, dass Sie sich die Zeit genommen haben. Ich habe das Problem erkannt - es hat ein bisschen nachgedacht und du hast mir definitiv geholfen. Ich hatte ein einzelnes MouseEventHandler-Skript, das bei mouseup keine Auswahl löschte (um die Auswahl mehrerer Kästchen zu ermöglichen). Ich habe nicht bemerkt, dass die Steuerung das Ereignis automatisch verbraucht, also habe ich an der falschen Stelle gesucht. Das Ziehen der Box bedeutete, dass es ausgewählt blieb, als ich den Schieberegler zog. – Aspekt