public static bool ButtonBehavior(Rect bb, int id, out bool outHovered, out bool outHeld, ButtonFlags flags = 0) { GUIContext g = Form.current.uiContext; WindowManager w = g.WindowManager; Window window = w.CurrentWindow; if (flags.HaveFlag(ButtonFlags.Disabled)) { outHovered = false; outHeld = false; if (g.ActiveId == id) { g.SetActiveID(0); } return(false); } if (!flags.HaveFlag(ButtonFlags.PressedOnClickRelease | ButtonFlags.PressedOnClick | ButtonFlags.PressedOnRelease | ButtonFlags.PressedOnDoubleClick)) { flags |= ButtonFlags.PressedOnClickRelease; } bool pressed = false; bool hovered = g.IsHovered(bb, id, flags.HaveFlag(ButtonFlags.FlattenChilds)); if (hovered) { g.SetHoverID(id); if (!flags.HaveFlag(ButtonFlags.NoKeyModifiers) || (!Keyboard.Instance.KeyPressed(Key.LeftControl) && !Keyboard.Instance.KeyPressed(Key.LeftShift) && !Keyboard.Instance.KeyPressed(Key.LeftAlt))) { // | CLICKING | HOLDING with ButtonFlags.Repeat // PressedOnClickRelease | <on release>* | <on repeat> <on repeat> .. (NOT on release) <-- MOST COMMON! (*) only if both click/release were over bounds // PressedOnClick | <on click> | <on click> <on repeat> <on repeat> .. // PressedOnRelease | <on release> | <on repeat> <on repeat> .. (NOT on release) // PressedOnDoubleClick | <on dclick> | <on dclick> <on repeat> <on repeat> .. if (flags.HaveFlag(ButtonFlags.PressedOnClickRelease) && Mouse.Instance.LeftButtonPressed) { g.SetActiveID(id, window); // Hold on ID w.FocusWindow(window); g.ActiveIdClickOffset = Mouse.Instance.Position - bb.Min; } if (((flags.HaveFlag(ButtonFlags.PressedOnClick) && Mouse.Instance.LeftButtonPressed) || (flags.HaveFlag(ButtonFlags.PressedOnDoubleClick) && Mouse.Instance.LeftButtonDoubleClicked))) { pressed = true; g.SetActiveID(0); w.FocusWindow(window); } if (flags.HaveFlag(ButtonFlags.PressedOnRelease) && Mouse.Instance.LeftButtonReleased) { if (!(flags.HaveFlag(ButtonFlags.Repeat) && Mouse.Instance.LeftButtonDownDurationPrev >= Keyboard.KeyRepeatDelay)) // Repeat mode trumps <on release> { pressed = true; } g.SetActiveID(0); } // 'Repeat' mode acts when held regardless of _PressedOn flags (see table above). // Relies on repeat logic of IsMouseClicked() but we may as well do it ourselves if we end up exposing finer RepeatDelay/RepeatRate settings. if (flags.HaveFlag(ButtonFlags.Repeat) && g.ActiveId == id && Mouse.Instance.LeftButtonDownDuration > 0.0f && g.IsMouseLeftButtonClicked(true)) { pressed = true; } } } bool held = false; if (g.ActiveId == id) { if (Mouse.Instance.LeftButtonState == KeyState.Down) { held = true; } else { if (hovered && flags.HaveFlag(ButtonFlags.PressedOnClickRelease)) { if (!(flags.HaveFlag(ButtonFlags.Repeat) && Mouse.Instance.LeftButtonDownDurationPrev >= Keyboard.KeyRepeatDelay)) // Repeat mode trumps <on release> { pressed = true; } } g.SetActiveID(0); } } // AllowOverlap mode (rarely used) requires previous frame HoveredId to be null or to match. This allows using patterns where a later submitted widget overlaps a previous one. if (hovered && flags.HaveFlag(ButtonFlags.AllowOverlapMode) && (g.HoveredIdPreviousFrame != id && g.HoveredIdPreviousFrame != 0)) { hovered = pressed = held = false; } outHovered = hovered; outHeld = held; return(pressed); }