void PopupMenu::_scroll(float p_factor, const Point2 &p_over) { const float global_y = get_global_position().y; int vseparation = get_constant("vseparation"); Ref<Font> font = get_font("font"); float dy = (vseparation + font->get_height()) * 3 * p_factor; if (dy > 0 && global_y < 0) dy = MIN(dy, -global_y - 1); else if (dy < 0 && global_y + get_size().y > get_viewport_rect().size.y) dy = -MIN(-dy, global_y + get_size().y - get_viewport_rect().size.y - 1); set_position(get_position() + Vector2(0, dy)); Ref<InputEventMouseMotion> ie; ie.instance(); ie->set_position(p_over - Vector2(0, dy)); _gui_input(ie); }
void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventKey> k = p_event; if (k.is_valid()) { if (!k->is_pressed()) return; switch (k->get_scancode()) { case KEY_DOWN: { for (int i = mouse_over + 1; i < items.size(); i++) { if (i < 0 || i >= items.size()) continue; if (!items[i].separator && !items[i].disabled) { mouse_over = i; update(); break; } } } break; case KEY_UP: { for (int i = mouse_over - 1; i >= 0; i--) { if (i < 0 || i >= items.size()) continue; if (!items[i].separator && !items[i].disabled) { mouse_over = i; update(); break; } } } break; case KEY_ENTER: case KEY_KP_ENTER: { if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { activate_item(mouse_over); } } break; } } Ref<InputEventMouseButton> b = p_event; if (b.is_valid()) { if (b->is_pressed()) return; switch (b->get_button_index()) { case BUTTON_WHEEL_DOWN: { if (get_global_position().y + get_size().y > get_viewport_rect().size.y) { int vseparation = get_constant("vseparation"); Ref<Font> font = get_font("font"); Point2 pos = get_position(); int s = (vseparation + font->get_height()) * 3; pos.y -= (s * b->get_factor()); set_position(pos); //update hover Ref<InputEventMouseMotion> ie; ie.instance(); ie->set_position(b->get_position() + Vector2(0, s)); _gui_input(ie); } } break; case BUTTON_WHEEL_UP: { if (get_global_position().y < 0) { int vseparation = get_constant("vseparation"); Ref<Font> font = get_font("font"); Point2 pos = get_position(); int s = (vseparation + font->get_height()) * 3; pos.y += (s * b->get_factor()); set_position(pos); //update hover Ref<InputEventMouseMotion> ie; ie.instance(); ie->set_position(b->get_position() - Vector2(0, s)); _gui_input(ie); } } break; case BUTTON_LEFT: { int over = _get_mouse_over(b->get_position()); if (invalidated_click) { invalidated_click = false; break; } if (over < 0) { hide(); break; //non-activable } if (items[over].separator || items[over].disabled) break; if (items[over].submenu != "") { _activate_submenu(over); return; } activate_item(over); } break; } //update(); } Ref<InputEventMouseMotion> m = p_event; if (m.is_valid()) { if (invalidated_click) { moved += m->get_relative(); if (moved.length() > 4) invalidated_click = false; } for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) { if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) { call_deferred("hide"); return; } } int over = _get_mouse_over(m->get_position()); int id = (over < 0 || items[over].separator || items[over].disabled) ? -1 : (items[over].ID >= 0 ? items[over].ID : over); if (id < 0) { mouse_over = -1; update(); return; } if (items[over].submenu != "" && submenu_over != over) { submenu_over = over; submenu_timer->start(); } if (over != mouse_over) { mouse_over = over; update(); } } }