diff options
-rw-r--r-- | core/input_map.cpp | 10 | ||||
-rw-r--r-- | core/project_settings.cpp | 14 | ||||
-rw-r--r-- | doc/classes/Input.xml | 5 | ||||
-rw-r--r-- | doc/classes/InstancePlaceholder.xml | 2 | ||||
-rw-r--r-- | main/SCsub | 2 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 31 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.cpp | 27 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 2 | ||||
-rw-r--r-- | scene/gui/option_button.cpp | 7 | ||||
-rw-r--r-- | scene/gui/option_button.h | 1 | ||||
-rw-r--r-- | scene/gui/popup_menu.cpp | 116 | ||||
-rw-r--r-- | scene/gui/scroll_bar.cpp | 56 | ||||
-rw-r--r-- | scene/gui/slider.cpp | 26 | ||||
-rw-r--r-- | scene/gui/tree.cpp | 518 | ||||
-rw-r--r-- | scene/gui/tree.h | 4 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 3 |
16 files changed, 423 insertions, 401 deletions
diff --git a/core/input_map.cpp b/core/input_map.cpp index a9ea1d9545..bd03d61196 100644 --- a/core/input_map.cpp +++ b/core/input_map.cpp @@ -282,6 +282,16 @@ void InputMap::load_default() { key->set_scancode(KEY_PAGEDOWN); action_add_event("ui_page_down", key); + add_action("ui_home"); + key.instance(); + key->set_scancode(KEY_HOME); + action_add_event("ui_home", key); + + add_action("ui_end"); + key.instance(); + key->set_scancode(KEY_END); + action_add_event("ui_end", key); + //set("display/window/handheld/orientation", "landscape"); } diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 3eb8ad7bf5..20d91e7940 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -1030,6 +1030,20 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("input/ui_page_down", va); input_presets.push_back("input/ui_page_down"); + va = Array(); + key.instance(); + key->set_scancode(KEY_HOME); + va.push_back(key); + GLOBAL_DEF("input/ui_home", va); + input_presets.push_back("input/ui_home"); + + va = Array(); + key.instance(); + key->set_scancode(KEY_END); + va.push_back(key); + GLOBAL_DEF("input/ui_end", va); + input_presets.push_back("input/ui_end"); + //GLOBAL_DEF("display/window/handheld/orientation", "landscape"); custom_prop_info["display/window/handheld/orientation"] = PropertyInfo(Variant::STRING, "display/window/handheld/orientation", PROPERTY_HINT_ENUM, "landscape,portrait,reverse_landscape,reverse_portrait,sensor_landscape,sensor_portrait,sensor"); diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 5b2e019c4c..f3bff5a146 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -182,7 +182,8 @@ <argument index="0" name="action" type="String"> </argument> <description> - Returns [code]true[/code] when you start pressing the action event. + Returns [code]true[/code] when the user starts pressing the action event, meaning it's true only on the frame that the user pressed down the button. + This is useful for code that needs to run only once when an action is pressed, instead of every frame while it's pressed. </description> </method> <method name="is_action_just_released" qualifiers="const"> @@ -191,7 +192,7 @@ <argument index="0" name="action" type="String"> </argument> <description> - Returns [code]true[/code] when you stop pressing the action event. + Returns [code]true[/code] when the user stops pressing the action event, meaning it's true only on the frame that the user released the button. </description> </method> <method name="is_action_pressed" qualifiers="const"> diff --git a/doc/classes/InstancePlaceholder.xml b/doc/classes/InstancePlaceholder.xml index 249c6921c4..5945e1068f 100644 --- a/doc/classes/InstancePlaceholder.xml +++ b/doc/classes/InstancePlaceholder.xml @@ -4,7 +4,7 @@ Placeholder for the root [Node] of a [PackedScene]. </brief_description> <description> - Turning on the option [b]Load As Placeholder[/b] for an instanced scene in the editor causes it to be replaced by an InstacePlaceholder when running the game. This makes it possible to delay actually loading the scene until calling [method replace_by_instance]. This is useful to avoid loading large scenes all at once by loading parts of it selectively. + Turning on the option [b]Load As Placeholder[/b] for an instanced scene in the editor causes it to be replaced by an InstancePlaceholder when running the game. This makes it possible to delay actually loading the scene until calling [method replace_by_instance]. This is useful to avoid loading large scenes all at once by loading parts of it selectively. The InstancePlaceholder does not have a transform. This causes any child nodes to be positioned relatively to the Viewport from point (0,0), rather than their parent as displayed in the editor. Replacing the placeholder with a scene with a transform will transform children relatively to their parent again. </description> <tutorials> diff --git a/main/SCsub b/main/SCsub index dd16437d5c..9eddc4f5b6 100644 --- a/main/SCsub +++ b/main/SCsub @@ -74,7 +74,7 @@ def make_default_controller_mappings(target, source, env): platform_mappings = OrderedDict() for src in source: src_path = src.srcnode().abspath - with open(src_path, "rb") as f: + with open(src_path, "r") as f: # read mapping file and skip header mapping_file_lines = f.readlines()[2:] diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 1ebef04561..0646580eaa 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -74,7 +74,31 @@ void gdmono_MonoPrintCallback(const char *string, mono_bool is_stdout) { GDMono *GDMono::singleton = NULL; +namespace { + +void setup_runtime_main_args() { + CharString execpath = OS::get_singleton()->get_executable_path().utf8(); + + List<String> cmdline_args = OS::get_singleton()->get_cmdline_args(); + + List<CharString> cmdline_args_utf8; + Vector<char *> main_args; + main_args.resize(cmdline_args.size() + 1); + + main_args[0] = execpath.ptrw(); + + int i = 1; + for (List<String>::Element *E = cmdline_args.front(); E; E = E->next()) { + CharString &stored = cmdline_args_utf8.push_back(E->get().utf8())->get(); + main_args[i] = stored.ptrw(); + i++; + } + + mono_runtime_set_main_args(main_args.size(), main_args.ptrw()); +} + #ifdef DEBUG_ENABLED + static bool _wait_for_debugger_msecs(uint32_t p_msecs) { do { @@ -96,9 +120,7 @@ static bool _wait_for_debugger_msecs(uint32_t p_msecs) { return mono_is_debugger_attached(); } -#endif -#ifdef DEBUG_ENABLED void gdmono_debug_init() { mono_debug_init(MONO_DEBUG_FORMAT_MONO); @@ -125,8 +147,11 @@ void gdmono_debug_init() { }; mono_jit_parse_options(2, (char **)options); } + #endif +} // namespace + void GDMono::initialize() { ERR_FAIL_NULL(Engine::get_singleton()); @@ -179,6 +204,8 @@ void GDMono::initialize() { GDMonoUtils::set_main_thread(GDMonoUtils::get_current_thread()); + setup_runtime_main_args(); // Required for System.Environment.GetCommandLineArgs + runtime_initialized = true; OS::get_singleton()->print("Mono: Runtime initialized\n"); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 2ce1b0a9df..d062d56dcf 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -85,19 +85,22 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d path = search_dir.plus_file(name); if (FileAccess::exists(path)) { res = _load_assembly_from(name.get_basename(), path, refonly); - break; + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { res = _load_assembly_from(name, path, refonly); - break; + if (res != NULL) + break; } path = search_dir.plus_file(name + ".exe"); if (FileAccess::exists(path)) { res = _load_assembly_from(name, path, refonly); - break; + if (res != NULL) + break; } } } @@ -123,6 +126,7 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse const char *rootdir = mono_assembly_getrootdir(); if (rootdir) { search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5")); + search_dirs.push_back(String(rootdir).plus_file("mono").plus_file("4.5").plus_file("Facades")); } if (assemblies_path) { @@ -151,19 +155,15 @@ MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **asse path = search_dir.plus_file(name); if (FileAccess::exists(path)) { res = _load_assembly_from(name.get_basename(), path, refonly); - break; + if (res != NULL) + break; } } else { path = search_dir.plus_file(name + ".dll"); if (FileAccess::exists(path)) { res = _load_assembly_from(name, path, refonly); - break; - } - - path = search_dir.plus_file(name + ".exe"); - if (FileAccess::exists(path)) { - res = _load_assembly_from(name, path, refonly); - break; + if (res != NULL) + break; } } } @@ -212,14 +212,15 @@ Error GDMonoAssembly::load(bool p_refonly) { String image_filename(path); - MonoImageOpenStatus status; + MonoImageOpenStatus status = MONO_IMAGE_OK; image = mono_image_open_from_data_with_name( (char *)&data[0], data.size(), true, &status, refonly, image_filename.utf8().get_data()); - ERR_FAIL_COND_V(status != MONO_IMAGE_OK || image == NULL, ERR_FILE_CANT_OPEN); + ERR_FAIL_COND_V(status != MONO_IMAGE_OK, ERR_FILE_CANT_OPEN); + ERR_FAIL_NULL_V(image, ERR_FILE_CANT_OPEN); #ifdef DEBUG_ENABLED String pdb_path(path + ".pdb"); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 03dc6686b8..5c0e8fefc7 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -373,12 +373,14 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { case KEY_UP: { shift_selection_check_pre(k->get_shift()); + if (get_cursor_position() == 0) handled = false; set_cursor_position(0); shift_selection_check_post(k->get_shift()); } break; case KEY_DOWN: { shift_selection_check_pre(k->get_shift()); + if (get_cursor_position() == text.length()) handled = false; set_cursor_position(text.length()); shift_selection_check_post(k->get_shift()); } break; diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 71c14810f6..6e53f11b99 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -75,6 +75,10 @@ void OptionButton::_notification(int p_what) { } } +void OptionButton::_focused(int p_which) { + emit_signal("item_focused", p_which); +} + void OptionButton::_selected(int p_which) { int selid = -1; @@ -290,6 +294,7 @@ void OptionButton::get_translatable_strings(List<String> *p_strings) const { void OptionButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_selected"), &OptionButton::_selected); + ClassDB::bind_method(D_METHOD("_focused"), &OptionButton::_focused); ClassDB::bind_method(D_METHOD("add_item", "label", "id"), &OptionButton::add_item, DEFVAL(-1)); ClassDB::bind_method(D_METHOD("add_icon_item", "texture", "label", "id"), &OptionButton::add_icon_item); @@ -322,6 +327,7 @@ void OptionButton::_bind_methods() { // "selected" property must come after "items", otherwise GH-10213 occurs ADD_PROPERTY(PropertyInfo(Variant::INT, "selected"), "_select_int", "get_selected"); ADD_SIGNAL(MethodInfo("item_selected", PropertyInfo(Variant::INT, "ID"))); + ADD_SIGNAL(MethodInfo("item_focused", PropertyInfo(Variant::INT, "ID"))); } OptionButton::OptionButton() { @@ -336,6 +342,7 @@ OptionButton::OptionButton() { popup->set_as_toplevel(true); popup->set_pass_on_modal_close_click(false); popup->connect("id_pressed", this, "_selected"); + popup->connect("id_focused", this, "_focused"); } OptionButton::~OptionButton() { diff --git a/scene/gui/option_button.h b/scene/gui/option_button.h index f65fa1b631..d5f866d806 100644 --- a/scene/gui/option_button.h +++ b/scene/gui/option_button.h @@ -43,6 +43,7 @@ class OptionButton : public Button { PopupMenu *popup; int current; + void _focused(int p_which); void _selected(int p_which); void _select(int p_which, bool p_emit = false); void _select_int(int p_which); diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 89000fcde1..747230e69f 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -211,86 +211,69 @@ void PopupMenu::_scroll(float p_factor, const Point2 &p_over) { 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: { - - int search_from = mouse_over + 1; - if (search_from >= items.size()) - search_from = 0; - - for (int i = search_from; i < items.size(); i++) { + if (p_event->is_action("ui_down") && p_event->is_pressed()) { - if (i < 0 || i >= items.size()) - continue; + int search_from = mouse_over + 1; + if (search_from >= items.size()) + search_from = 0; - if (!items[i].separator && !items[i].disabled) { + for (int i = search_from; i < items.size(); i++) { - mouse_over = i; - update(); - break; - } - } - } break; - case KEY_UP: { - - int search_from = mouse_over - 1; - if (search_from < 0) - search_from = items.size() - 1; - - for (int i = search_from; i >= 0; i--) { - - if (i < 0 || i >= items.size()) - continue; - - if (!items[i].separator && !items[i].disabled) { + if (i < 0 || i >= items.size()) + continue; - mouse_over = i; - update(); - break; - } - } - } break; + if (!items[i].separator && !items[i].disabled) { - case KEY_LEFT: { + mouse_over = i; + emit_signal("id_focused", i); + update(); + accept_event(); + break; + } + } + } else if (p_event->is_action("ui_up") && p_event->is_pressed()) { - Node *n = get_parent(); - if (!n) - break; + int search_from = mouse_over - 1; + if (search_from < 0) + search_from = items.size() - 1; - PopupMenu *pm = Object::cast_to<PopupMenu>(n); - if (!pm) - break; + for (int i = search_from; i >= 0; i--) { - hide(); - } break; + if (i < 0 || i >= items.size()) + continue; - case KEY_RIGHT: { + if (!items[i].separator && !items[i].disabled) { - if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) - _activate_submenu(mouse_over); - } break; + mouse_over = i; + emit_signal("id_focused", i); + update(); + accept_event(); + break; + } + } + } else if (p_event->is_action("ui_left") && p_event->is_pressed()) { - case KEY_ENTER: - case KEY_KP_ENTER: { + Node *n = get_parent(); + if (n && Object::cast_to<PopupMenu>(n)) { + hide(); + accept_event(); + } + } else if (p_event->is_action("ui_right") && p_event->is_pressed()) { - if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { + if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) { + _activate_submenu(mouse_over); + accept_event(); + } + } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { - if (items[mouse_over].submenu != "" && submenu_over != mouse_over) { - _activate_submenu(mouse_over); - break; - } + if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) { - activate_item(mouse_over); - } - } break; + if (items[mouse_over].submenu != "" && submenu_over != mouse_over) { + _activate_submenu(mouse_over); + } else { + activate_item(mouse_over); + } + accept_event(); } } @@ -1229,6 +1212,7 @@ void PopupMenu::_bind_methods() { ADD_PROPERTYNO(PropertyInfo(Variant::BOOL, "hide_on_state_item_selection"), "set_hide_on_state_item_selection", "is_hide_on_state_item_selection"); ADD_SIGNAL(MethodInfo("id_pressed", PropertyInfo(Variant::INT, "ID"))); + ADD_SIGNAL(MethodInfo("id_focused", PropertyInfo(Variant::INT, "ID"))); ADD_SIGNAL(MethodInfo("index_pressed", PropertyInfo(Variant::INT, "index"))); } diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp index 95fcda2db3..e1cabd3f88 100644 --- a/scene/gui/scroll_bar.cpp +++ b/scene/gui/scroll_bar.cpp @@ -199,54 +199,40 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) { } } - Ref<InputEventKey> k = p_event; + if (p_event->is_pressed()) { - if (k.is_valid()) { + if (p_event->is_action("ui_left")) { - if (!k->is_pressed()) - return; - - switch (k->get_scancode()) { - - case KEY_LEFT: { - - if (orientation != HORIZONTAL) - return; - set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); + if (orientation != HORIZONTAL) + return; + set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); - } break; - case KEY_RIGHT: { + } else if (p_event->is_action("ui_right")) { - if (orientation != HORIZONTAL) - return; - set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - - } break; - case KEY_UP: { + if (orientation != HORIZONTAL) + return; + set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - if (orientation != VERTICAL) - return; + } else if (p_event->is_action("ui_up")) { - set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); + if (orientation != VERTICAL) + return; - } break; - case KEY_DOWN: { + set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); - if (orientation != VERTICAL) - return; - set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); + } else if (p_event->is_action("ui_down")) { - } break; - case KEY_HOME: { + if (orientation != VERTICAL) + return; + set_value(get_value() + (custom_step >= 0 ? custom_step : get_step())); - set_value(get_min()); + } else if (p_event->is_action("ui_home")) { - } break; - case KEY_END: { + set_value(get_min()); - set_value(get_max()); + } else if (p_event->is_action("ui_end")) { - } break; + set_value(get_max()); } } } diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp index a7a1b499c3..46215c9277 100644 --- a/scene/gui/slider.cpp +++ b/scene/gui/slider.cpp @@ -118,28 +118,14 @@ void Slider::_gui_input(Ref<InputEvent> p_event) { return; set_value(get_value() - (custom_step >= 0 ? custom_step : get_step())); accept_event(); + } else if (p_event->is_action("ui_home") && p_event->is_pressed()) { - } else { - - Ref<InputEventKey> k = p_event; - - if (!k.is_valid() || !k->is_pressed()) - return; - - switch (k->get_scancode()) { - - case KEY_HOME: { - - set_value(get_min()); - accept_event(); - } break; - case KEY_END: { - - set_value(get_max()); - accept_event(); + set_value(get_min()); + accept_event(); + } else if (p_event->is_action("ui_end") && p_event->is_pressed()) { - } break; - } + set_value(get_max()); + accept_event(); } } } diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index b8fd2ce16e..e7f63997f2 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2061,322 +2061,318 @@ void Tree::popup_select(int p_option) { item_edited(popup_edited_item_col, popup_edited_item); } -void Tree::_gui_input(Ref<InputEvent> p_event) { - - Ref<InputEventKey> k = p_event; +void Tree::_go_left() { + if (selected_col == 0) { + if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) { + selected_item->set_collapsed(true); + } else { + if (columns.size() == 1) { // goto parent with one column + TreeItem *parent = selected_item->get_parent(); + if (selected_item != get_root() && parent && parent->is_selectable(selected_col) && !(hide_root && parent == get_root())) { + select_single_item(parent, get_root(), selected_col); + } + } else if (selected_item->get_prev_visible()) { + selected_col = columns.size() - 1; + _go_up(); // go to upper column if possible + } + } + } else { + if (select_mode == SELECT_MULTI) { + selected_col--; + emit_signal("cell_selected"); + } else { - if (k.is_valid()) { + selected_item->select(selected_col - 1); + } + } + update(); + accept_event(); + ensure_cursor_is_visible(); +} - if (!k->is_pressed()) - return; - if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) - return; - if (!root) +void Tree::_go_right() { + if (selected_col == (columns.size() - 1)) { + if (selected_item->get_children() != NULL && selected_item->is_collapsed()) { + selected_item->set_collapsed(false); + } else if (selected_item->get_next_visible()) { + selected_item->select(0); + _go_down(); return; + } + } else { + if (select_mode == SELECT_MULTI) { + selected_col++; + emit_signal("cell_selected"); + } else { - if (hide_root && !root->get_next_visible()) + selected_item->select(selected_col + 1); + } + } + update(); + ensure_cursor_is_visible(); + accept_event(); +} + +void Tree::_go_up() { + TreeItem *prev = NULL; + if (!selected_item) { + prev = get_last_item(); + selected_col = 0; + } else { + + prev = selected_item->get_prev_visible(); + if (last_keypress != 0) { + //incr search next + int col; + prev = _search_item_text(prev, incr_search, &col, true, true); + if (!prev) { + accept_event(); + return; + } + } + } + + if (select_mode == SELECT_MULTI) { + + if (!prev) return; + selected_item = prev; + emit_signal("cell_selected"); + update(); + } else { - switch (k->get_scancode()) { -#define EXIT_BREAK \ - { \ - if (!cursor_can_exit_tree) accept_event(); \ - break; \ + int col = selected_col < 0 ? 0 : selected_col; + while (prev && !prev->cells[col].selectable) + prev = prev->get_prev_visible(); + if (!prev) + return; // do nothing.. + prev->select(col); } - case KEY_RIGHT: { - bool dobreak = true; - //TreeItem *next = NULL; - if (!selected_item) - break; - if (select_mode == SELECT_ROW) { - EXIT_BREAK; - } - if (selected_col > (columns.size() - 1)) { - EXIT_BREAK; - } - if (k->get_alt()) { - selected_item->set_collapsed(false); - TreeItem *next = selected_item->get_children(); - while (next && next != selected_item->next) { - next->set_collapsed(false); - next = next->get_next_visible(); - } - } else if (selected_col == (columns.size() - 1)) { - if (selected_item->get_children() != NULL && selected_item->is_collapsed()) { - selected_item->set_collapsed(false); - } else { - selected_col = 0; - dobreak = false; // fall through to key_down - } - } else { - if (select_mode == SELECT_MULTI) { - selected_col++; - emit_signal("cell_selected"); - } else { + ensure_cursor_is_visible(); + accept_event(); +} - selected_item->select(selected_col + 1); - } - } - update(); - ensure_cursor_is_visible(); +void Tree::_go_down() { + TreeItem *next = NULL; + if (!selected_item) { + + next = hide_root ? root->get_next_visible() : root; + selected_item = 0; + } else { + + next = selected_item->get_next_visible(); + + if (last_keypress != 0) { + //incr search next + int col; + next = _search_item_text(next, incr_search, &col, true); + if (!next) { accept_event(); - if (dobreak) { - break; - } + return; } - case KEY_DOWN: { + } + } - TreeItem *next = NULL; - if (!selected_item) { + if (select_mode == SELECT_MULTI) { - next = hide_root ? root->get_next_visible() : root; - selected_item = 0; - } else { + if (!next) { + return; + } - next = selected_item->get_next_visible(); + selected_item = next; + emit_signal("cell_selected"); + update(); + } else { - //if (diff < uint64_t(GLOBAL_DEF("gui/incr_search_max_interval_msec",2000))) { - if (last_keypress != 0) { - //incr search next - int col; - next = _search_item_text(next, incr_search, &col, true); - if (!next) { - accept_event(); - return; - } - } - } + int col = selected_col < 0 ? 0 : selected_col; - if (select_mode == SELECT_MULTI) { + while (next && !next->cells[col].selectable) + next = next->get_next_visible(); + if (!next) { + return; // do nothing.. + } + next->select(col); + } - if (!next) - EXIT_BREAK; + ensure_cursor_is_visible(); + accept_event(); +} - selected_item = next; - emit_signal("cell_selected"); - update(); - } else { +void Tree::_gui_input(Ref<InputEvent> p_event) { - int col = selected_col < 0 ? 0 : selected_col; + Ref<InputEventKey> k = p_event; - while (next && !next->cells[col].selectable) - next = next->get_next_visible(); - if (!next) - EXIT_BREAK; // do nothing.. - next->select(col); - } + if (p_event->is_action("ui_right") && p_event->is_pressed()) { - ensure_cursor_is_visible(); - accept_event(); + if (!cursor_can_exit_tree) accept_event(); - } break; - case KEY_LEFT: { - bool dobreak = true; + if (!selected_item || select_mode == SELECT_ROW || selected_col > (columns.size() - 1)) { + return; + } + if (k.is_valid() && k->get_alt()) { + selected_item->set_collapsed(false); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(false); + next = next->get_next_visible(); + } + } else { + _go_right(); + } + } else if (p_event->is_action("ui_left") && p_event->is_pressed()) { - //TreeItem *next = NULL; - if (!selected_item) - break; - if (select_mode == SELECT_ROW) { - EXIT_BREAK; - } - if (selected_col < 0) { - EXIT_BREAK; - } - if (k->get_alt()) { - selected_item->set_collapsed(true); - TreeItem *next = selected_item->get_children(); - while (next && next != selected_item->next) { - next->set_collapsed(true); - next = next->get_next_visible(); - } - } else if (selected_col == 0) { - if (selected_item->get_children() != NULL && !selected_item->is_collapsed()) { - selected_item->set_collapsed(true); - } else { - if (columns.size() == 1) { // goto parent with one column - TreeItem *parent = selected_item->get_parent(); - if (selected_item != get_root() && parent && parent->is_selectable(selected_col) && !(hide_root && parent == get_root())) { - select_single_item(parent, get_root(), selected_col); - } - } else { - selected_col = columns.size() - 1; - dobreak = false; // fall through to key_up - } - } - } else { - if (select_mode == SELECT_MULTI) { - selected_col--; - emit_signal("cell_selected"); - } else { + if (!cursor_can_exit_tree) accept_event(); - selected_item->select(selected_col - 1); - } - } - update(); - accept_event(); - ensure_cursor_is_visible(); + if (!selected_item || select_mode == SELECT_ROW || selected_col < 0) { + return; + } - if (dobreak) { - break; - } + if (k.is_valid() && k->get_alt()) { + selected_item->set_collapsed(true); + TreeItem *next = selected_item->get_children(); + while (next && next != selected_item->next) { + next->set_collapsed(true); + next = next->get_next_visible(); } - case KEY_UP: { + } else { + _go_left(); + } - TreeItem *prev = NULL; - if (!selected_item) { - prev = get_last_item(); - selected_col = 0; - } else { + } else if (p_event->is_action("ui_up") && p_event->is_pressed()) { - prev = selected_item->get_prev_visible(); - if (last_keypress != 0) { - //incr search next - int col; - prev = _search_item_text(prev, incr_search, &col, true, true); - if (!prev) { - accept_event(); - return; - } - } - } + if (!cursor_can_exit_tree) accept_event(); - if (select_mode == SELECT_MULTI) { + _go_up(); - if (!prev) - break; - selected_item = prev; - emit_signal("cell_selected"); - update(); - } else { + } else if (p_event->is_action("ui_down") && p_event->is_pressed()) { - int col = selected_col < 0 ? 0 : selected_col; - while (prev && !prev->cells[col].selectable) - prev = prev->get_prev_visible(); - if (!prev) - break; // do nothing.. - prev->select(col); - } + if (!cursor_can_exit_tree) accept_event(); - ensure_cursor_is_visible(); - accept_event(); + _go_down(); - } break; - case KEY_PAGEDOWN: { + } else if (p_event->is_action("ui_page_down") && p_event->is_pressed()) { - TreeItem *next = NULL; - if (!selected_item) - break; - next = selected_item; + if (!cursor_can_exit_tree) accept_event(); - for (int i = 0; i < 10; i++) { + TreeItem *next = NULL; + if (!selected_item) + return; + next = selected_item; - TreeItem *_n = next->get_next_visible(); - if (_n) { - next = _n; - } else { + for (int i = 0; i < 10; i++) { - break; - } - } - if (next == selected_item) - break; + TreeItem *_n = next->get_next_visible(); + if (_n) { + next = _n; + } else { - if (select_mode == SELECT_MULTI) { + return; + } + } + if (next == selected_item) + return; - selected_item = next; - emit_signal("cell_selected"); - update(); - } else { + if (select_mode == SELECT_MULTI) { - while (next && !next->cells[selected_col].selectable) - next = next->get_next_visible(); - if (!next) - EXIT_BREAK; // do nothing.. - next->select(selected_col); - } + selected_item = next; + emit_signal("cell_selected"); + update(); + } else { - ensure_cursor_is_visible(); - } break; - case KEY_PAGEUP: { + while (next && !next->cells[selected_col].selectable) + next = next->get_next_visible(); + if (!next) { + return; // do nothing.. + } + next->select(selected_col); + } - TreeItem *prev = NULL; - if (!selected_item) - break; - prev = selected_item; + ensure_cursor_is_visible(); + } else if (p_event->is_action("ui_page_up") && p_event->is_pressed()) { - for (int i = 0; i < 10; i++) { + if (!cursor_can_exit_tree) accept_event(); - TreeItem *_n = prev->get_prev_visible(); - if (_n) { - prev = _n; - } else { + TreeItem *prev = NULL; + if (!selected_item) + return; + prev = selected_item; - break; - } - } - if (prev == selected_item) - break; + for (int i = 0; i < 10; i++) { - if (select_mode == SELECT_MULTI) { + TreeItem *_n = prev->get_prev_visible(); + if (_n) { + prev = _n; + } else { - selected_item = prev; - emit_signal("cell_selected"); - update(); - } else { + return; + } + } + if (prev == selected_item) + return; - while (prev && !prev->cells[selected_col].selectable) - prev = prev->get_prev_visible(); - if (!prev) - EXIT_BREAK; // do nothing.. - prev->select(selected_col); - } + if (select_mode == SELECT_MULTI) { - ensure_cursor_is_visible(); + selected_item = prev; + emit_signal("cell_selected"); + update(); + } else { - } break; - case KEY_F2: - case KEY_ENTER: - case KEY_KP_ENTER: { - - if (selected_item) { - //bring up editor if possible - if (!edit_selected()) { - emit_signal("item_activated"); - incr_search.clear(); - } - } - accept_event(); + while (prev && !prev->cells[selected_col].selectable) + prev = prev->get_prev_visible(); + if (!prev) { + return; // do nothing.. + } + prev->select(selected_col); + } + ensure_cursor_is_visible(); + } else if (p_event->is_action("ui_accept") && p_event->is_pressed()) { - } break; - case KEY_SPACE: { - if (select_mode == SELECT_MULTI) { - if (!selected_item) - break; - if (selected_item->is_selected(selected_col)) { - selected_item->deselect(selected_col); - emit_signal("multi_selected", selected_item, selected_col, false); - } else if (selected_item->is_selectable(selected_col)) { - selected_item->select(selected_col); - emit_signal("multi_selected", selected_item, selected_col, true); - } - } - accept_event(); + if (selected_item) { + //bring up editor if possible + if (!edit_selected()) { + emit_signal("item_activated"); + incr_search.clear(); + } + } + accept_event(); + } else if (p_event->is_action("ui_select") && p_event->is_pressed()) { - } break; - default: { + if (select_mode == SELECT_MULTI) { + if (!selected_item) + return; + if (selected_item->is_selected(selected_col)) { + selected_item->deselect(selected_col); + emit_signal("multi_selected", selected_item, selected_col, false); + } else if (selected_item->is_selectable(selected_col)) { + selected_item->select(selected_col); + emit_signal("multi_selected", selected_item, selected_col, true); + } + } + accept_event(); + } + + if (k.is_valid()) { // Incremental search + + if (!k->is_pressed()) + return; + if (k->get_command() || (k->get_shift() && k->get_unicode() == 0) || k->get_metakey()) + return; + if (!root) + return; + + if (hide_root && !root->get_next_visible()) + return; - if (k->get_unicode() > 0) { + if (k->get_unicode() > 0) { - _do_incr_search(String::chr(k->get_unicode())); - accept_event(); + _do_incr_search(String::chr(k->get_unicode())); + accept_event(); - return; - } else { - if (k->get_scancode() != KEY_SHIFT) - last_keypress = 0; - } - } break; + return; + } else { + if (k->get_scancode() != KEY_SHIFT) + last_keypress = 0; } } diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 2a8546a743..5af66c5faa 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -507,6 +507,10 @@ private: ValueEvaluator *evaluator; int _count_selected_items(TreeItem *p_from) const; + void _go_left(); + void _go_right(); + void _go_down(); + void _go_up(); protected: static void _bind_methods(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index d4ec878bdf..08fbf44469 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2028,6 +2028,9 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { top->notification(Control::NOTIFICATION_MODAL_CLOSE); top->_modal_stack_remove(); top->hide(); + // Close modal, set input as handled + get_tree()->set_input_as_handled(); + return; } } |