int ItemList::get_item_at_pos(const Point2& p_pos) const { Vector2 pos=p_pos; Ref<StyleBox> bg = get_stylebox("bg"); pos-=bg->get_offset(); pos.y+=scroll_bar->get_val(); int closest = -1; int closest_dist=0x7FFFFFFF; for(int i=0;i<items.size();i++) { Rect2 rc = items[i].rect_cache; if (i%current_columns==current_columns-1) { rc.size.width=get_size().width; //not right but works } if (rc.has_point(pos)) { closest=i; break; } float dist = rc.distance_to(pos); if (dist<closest_dist) { closest=i; closest_dist=dist; } } return closest; }
void ItemList::_input_event(const InputEvent& p_event) { if (defer_select_single>=0 && p_event.type==InputEvent::MOUSE_MOTION) { defer_select_single=-1; return; } if (defer_select_single>=0 && p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT && !p_event.mouse_button.pressed) { select(defer_select_single,true); emit_signal("multi_selected",defer_select_single,true); defer_select_single=-1; return; } if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_LEFT && p_event.mouse_button.pressed) { const InputEventMouseButton &mb = p_event.mouse_button; search_string=""; //any mousepress cancels Vector2 pos(mb.x,mb.y); Ref<StyleBox> bg = get_stylebox("bg"); pos-=bg->get_offset(); pos.y+=scroll_bar->get_val(); int closest = -1; int closest_dist=0x7FFFFFFF; for(int i=0;i<items.size();i++) { Rect2 rc = items[i].rect_cache; if (i%current_columns==current_columns-1) { rc.size.width=get_size().width; //not right but works } if (rc.has_point(pos)) { closest=i; break; } float dist = rc.distance_to(pos); if (dist<closest_dist) { closest=i; closest_dist=dist; } } if (closest!=-1) { int i = closest; if (select_mode==SELECT_MULTI && items[i].selected && mb.mod.command) { unselect(i); emit_signal("multi_selected",i,false); } else if (select_mode==SELECT_MULTI && mb.mod.shift && current>=0 && current<items.size() && current!=i) { int from = current; int to = i; if (i<current) { SWAP(from,to); } for(int j=from;j<=to;j++) { bool selected = !items[j].selected; select(j,false); if (selected) emit_signal("multi_selected",i,true); } } else { if (!mb.doubleclick && !mb.mod.command && select_mode==SELECT_MULTI && items[i].selectable && items[i].selected) { defer_select_single=i; return; } bool selected = !items[i].selected; select(i,select_mode==SELECT_SINGLE || !mb.mod.command); if (selected) { if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",i); } else emit_signal("multi_selected",i,true); } if (/*select_mode==SELECT_SINGLE &&*/ mb.doubleclick) { emit_signal("item_activated",i); } } return; } } if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_WHEEL_UP && p_event.mouse_button.pressed) { scroll_bar->set_val( scroll_bar->get_val()-scroll_bar->get_page()/8 ); } if (p_event.type==InputEvent::MOUSE_BUTTON && p_event.mouse_button.button_index==BUTTON_WHEEL_DOWN && p_event.mouse_button.pressed) { scroll_bar->set_val( scroll_bar->get_val()+scroll_bar->get_page()/8 ); } if (p_event.is_pressed() && items.size()>0) { if (p_event.is_action("ui_up")) { if (search_string!="") { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now-search_time_msec; if (diff<int(Globals::get_singleton()->get("gui/incr_search_max_interval_msec"))*2) { for(int i=current-1;i>=0;i--) { if (items[i].text.begins_with(search_string)) { set_current(i); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } break; } } accept_event(); return; } } if (current>=current_columns) { set_current(current-current_columns); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } accept_event(); } } else if (p_event.is_action("ui_down")) { if (search_string!="") { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now-search_time_msec; if (diff<int(Globals::get_singleton()->get("gui/incr_search_max_interval_msec"))*2) { for(int i=current+1;i<items.size();i++) { if (items[i].text.begins_with(search_string)) { set_current(i); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } break; } } accept_event(); return; } } if (current<items.size()-current_columns) { set_current(current+current_columns); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } accept_event(); } } else if (p_event.is_action("ui_page_up")) { search_string=""; //any mousepress cancels for(int i=4;i>0;i--) { if (current-current_columns*i >=0 ) { set_current( current- current_columns*i); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } accept_event(); break; } } } else if (p_event.is_action("ui_page_down")) { search_string=""; //any mousepress cancels for(int i=4;i>0;i--) { if (current+current_columns*i < items.size() ) { set_current( current+ current_columns*i); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } accept_event(); break; } } } else if (p_event.is_action("ui_left")) { search_string=""; //any mousepress cancels if (current%current_columns!=0) { set_current(current-1); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } accept_event(); } } else if (p_event.is_action("ui_right")) { search_string=""; //any mousepress cancels if (current%current_columns!=(current_columns-1)) { set_current(current+1); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } accept_event(); } } else if (p_event.is_action("ui_cancel")) { search_string=""; } else if (p_event.is_action("ui_select")) { if (select_mode==SELECT_MULTI && current>=0 && current<items.size()) { if (items[current].selectable && !items[current].selected) { select(current,false); emit_signal("multi_selected",current,true); } else if (items[current].selected) { unselect(current); emit_signal("multi_selected",current,false); } } } else if (p_event.is_action("ui_accept")) { search_string=""; //any mousepress cance if (current>=0 && current<items.size()) { emit_signal("item_activated",current); } } else if (p_event.type==InputEvent::KEY) { if (p_event.key.unicode) { uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t diff = now-search_time_msec; uint64_t max_interval = uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000)); search_time_msec = now; if (diff>max_interval) { search_string=""; } search_string+=String::chr(p_event.key.unicode); for(int i=0;i<items.size();i++) { if (items[i].text.begins_with(search_string)) { set_current(i); ensure_current_is_visible(); if (select_mode==SELECT_SINGLE) { emit_signal("item_selected",current); } break; } } } } } }