diff options
-rw-r--r-- | editor/create_dialog.cpp | 55 | ||||
-rw-r--r-- | editor/editor_node.cpp | 64 | ||||
-rw-r--r-- | editor/editor_node.h | 9 | ||||
-rw-r--r-- | editor/editor_themes.cpp | 47 | ||||
-rw-r--r-- | editor/export_template_manager.cpp | 135 | ||||
-rw-r--r-- | editor/export_template_manager.h | 2 | ||||
-rw-r--r-- | editor/import/resource_importer_wav.cpp | 4 | ||||
-rw-r--r-- | editor/plugins/spatial_editor_plugin.cpp | 4 | ||||
-rw-r--r-- | editor/project_export.cpp | 1 | ||||
-rw-r--r-- | editor/project_manager.cpp | 2 | ||||
-rw-r--r-- | editor/project_settings_editor.cpp | 1 | ||||
-rw-r--r-- | modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj | 5 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 7 | ||||
-rw-r--r-- | platform/android/SCsub | 22 | ||||
-rw-r--r-- | platform/android/export/export.cpp | 9 | ||||
-rw-r--r-- | scene/gui/spin_box.cpp | 20 | ||||
-rw-r--r-- | scene/gui/tab_container.cpp | 14 | ||||
-rw-r--r-- | scene/gui/tab_container.h | 3 |
18 files changed, 259 insertions, 145 deletions
diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index 8a8d52c6f1..d5f0dc01ee 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -191,34 +191,41 @@ void CreateDialog::add_type(const String &p_type, HashMap<String, TreeItem *> &p item->set_custom_color(0, get_color("disabled_font_color", "Editor")); item->set_selectable(0, false); } else if (!(*to_select && (*to_select)->get_text(0) == search_box->get_text())) { - bool current_type_prefered = _is_type_prefered(p_type); - bool selected_type_prefered = *to_select ? _is_type_prefered((*to_select)->get_text(0).split(" ")[0]) : false; - String search_term = search_box->get_text().to_lower(); - bool is_subsequence_of_type = search_box->get_text().is_subsequence_ofi(p_type); - bool is_substring_of_type = p_type.to_lower().find(search_term) >= 0; - bool is_substring_of_selected = false; - bool is_subsequence_of_selected = false; - bool is_selected_equal = false; - - if (*to_select) { - String name = (*to_select)->get_text(0).split(" ")[0].to_lower(); - is_substring_of_selected = name.find(search_term) >= 0; - is_subsequence_of_selected = search_term.is_subsequence_of(name); - is_selected_equal = name == search_term; - } - if (is_subsequence_of_type && !is_selected_equal) { - if (is_substring_of_type) { - if (!is_substring_of_selected || (current_type_prefered && !selected_type_prefered)) { - *to_select = item; - } - } else { - // substring results weigh more than subsequences, so let's make sure we don't override them - if (!is_substring_of_selected) { - if (!is_subsequence_of_selected || (current_type_prefered && !selected_type_prefered)) { + // if the node name matches exactly as the search, the node should be selected. + // this also fixes when the user clicks on recent nodes. + if (p_type.to_lower() == search_term) { + *to_select = item; + } else { + bool current_type_prefered = _is_type_prefered(p_type); + bool selected_type_prefered = *to_select ? _is_type_prefered((*to_select)->get_text(0).split(" ")[0]) : false; + + bool is_subsequence_of_type = search_box->get_text().is_subsequence_ofi(p_type); + bool is_substring_of_type = p_type.to_lower().find(search_term) >= 0; + bool is_substring_of_selected = false; + bool is_subsequence_of_selected = false; + bool is_selected_equal = false; + + if (*to_select) { + String name = (*to_select)->get_text(0).split(" ")[0].to_lower(); + is_substring_of_selected = name.find(search_term) >= 0; + is_subsequence_of_selected = search_term.is_subsequence_of(name); + is_selected_equal = name == search_term; + } + + if (is_subsequence_of_type && !is_selected_equal) { + if (is_substring_of_type) { + if (!is_substring_of_selected || (current_type_prefered && !selected_type_prefered)) { *to_select = item; } + } else { + // substring results weigh more than subsequences, so let's make sure we don't override them + if (!is_substring_of_selected) { + if (!is_subsequence_of_selected || (current_type_prefered && !selected_type_prefered)) { + *to_select = item; + } + } } } } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 635f6d4fc7..8ed6cec779 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2632,11 +2632,8 @@ void EditorNode::_exit_editor() { resource_preview->stop(); //stop early to avoid crashes _save_docks(); - // Dim the editor window while it's quitting to make it clearer that it's busy. - // No transition is applied, as the effect needs to be visible immediately - float c = 0.4f; - Color dim_color = Color(c, c, c); - gui_base->set_modulate(dim_color); + // Dim the editor window while it's quitting to make it clearer that it's busy + dim_editor(true, true); get_tree()->quit(); } @@ -5133,46 +5130,12 @@ void EditorNode::_open_imported() { load_scene(open_import_request, true, false, true, true); } -void EditorNode::dim_editor(bool p_dimming) { - static int dim_count = 0; - bool dim_ui = EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup"); - if (p_dimming) { - if (dim_ui && dim_count == 0) { - _start_dimming(true); - } - dim_count++; - } else { - if (dim_count == 1) { - _start_dimming(false); - } - if (dim_count > 0) { - dim_count--; - } else { - ERR_PRINT("Undimmed before dimming!"); - } - } -} - -void EditorNode::_start_dimming(bool p_dimming) { - _dimming = p_dimming; - _dim_time = 0.0f; - _dim_timer->start(); -} - -void EditorNode::_dim_timeout() { - - _dim_time += _dim_timer->get_wait_time(); - float wait_time = 0.08f; - float c = 0.4f; - - Color base = _dimming ? Color(1, 1, 1) : Color(c, c, c); - Color final = _dimming ? Color(c, c, c) : Color(1, 1, 1); - - if (_dim_time + _dim_timer->get_wait_time() >= wait_time) { - gui_base->set_modulate(final); - _dim_timer->stop(); +void EditorNode::dim_editor(bool p_dimming, bool p_force_dim) { + // Dimming can be forced regardless of the editor setting, which is useful when quitting the editor + if ((p_force_dim || EditorSettings::get_singleton()->get("interface/editor/dim_editor_on_dialog_popup")) && p_dimming) { + gui_base->set_modulate(Color(0.5, 0.5, 0.5)); } else { - gui_base->set_modulate(base.linear_interpolate(final, _dim_time / wait_time)); + gui_base->set_modulate(Color(1, 1, 1)); } } @@ -5356,7 +5319,6 @@ void EditorNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_open_imported"), &EditorNode::_open_imported); ClassDB::bind_method(D_METHOD("_inherit_imported"), &EditorNode::_inherit_imported); - ClassDB::bind_method(D_METHOD("_dim_timeout"), &EditorNode::_dim_timeout); ClassDB::bind_method("_copy_warning", &EditorNode::_copy_warning); @@ -5818,6 +5780,7 @@ EditorNode::EditorNode() { dock_slot[i]->set_drag_to_rearrange_enabled(true); dock_slot[i]->set_tabs_rearrange_group(1); dock_slot[i]->connect("tab_changed", this, "_dock_tab_changed"); + dock_slot[i]->set_use_hidden_tabs_for_min_size(true); } dock_drag_timer = memnew(Timer); @@ -6411,13 +6374,13 @@ EditorNode::EditorNode() { gui_base->add_child(custom_build_manage_templates); install_android_build_template = memnew(ConfirmationDialog); - install_android_build_template->set_text(TTR("This will install the Android project for custom builds.\nNote that, in order to use it, it needs to be enabled per export preset.")); + install_android_build_template->set_text(TTR("This will set up your project for custom Android builds by installing the source template to \"res://android/build\".\nYou can then apply modifications and build your own custom APK on export (adding modules, changing the AndroidManifest.xml, etc.).\nNote that in order to make custom builds instead of using pre-built APKs, the \"Use Custom Build\" option should be enabled in the Android export preset.")); install_android_build_template->get_ok()->set_text(TTR("Install")); install_android_build_template->connect("confirmed", this, "_menu_confirm_current"); gui_base->add_child(install_android_build_template); remove_android_build_template = memnew(ConfirmationDialog); - remove_android_build_template->set_text(TTR("Android build template is already installed and it won't be overwritten.\nRemove the \"build\" directory manually before attempting this operation again.")); + remove_android_build_template->set_text(TTR("The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"res://android/build\" directory manually before attempting this operation again.")); remove_android_build_template->get_ok()->set_text(TTR("Show in File Manager")); remove_android_build_template->connect("confirmed", this, "_menu_option", varray(FILE_EXPLORE_ANDROID_BUILD_TEMPLATES)); gui_base->add_child(remove_android_build_template); @@ -6687,13 +6650,6 @@ EditorNode::EditorNode() { waiting_for_first_scan = true; - _dimming = false; - _dim_time = 0.0f; - _dim_timer = memnew(Timer); - _dim_timer->set_wait_time(0.01666f); - _dim_timer->connect("timeout", this, "_dim_timeout"); - add_child(_dim_timer); - print_handler.printfunc = _print_handler; print_handler.userdata = this; add_print_handler(&print_handler); diff --git a/editor/editor_node.h b/editor/editor_node.h index 61bbb7b86d..54bcf14c1b 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -633,13 +633,6 @@ private: static int build_callback_count; static EditorBuildCallback build_callbacks[MAX_BUILD_CALLBACKS]; - bool _dimming; - float _dim_time; - Timer *_dim_timer; - - void _start_dimming(bool p_dimming); - void _dim_timeout(); - void _license_tree_selected(); void _update_update_spinner(); @@ -849,7 +842,7 @@ public: void save_scene_list(Vector<String> p_scene_filenames); void restart_editor(); - void dim_editor(bool p_dimming); + void dim_editor(bool p_dimming, bool p_force_dim = false); void edit_current() { _edit_current(); }; diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index 56eed96e31..c15d24719f 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -108,16 +108,17 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = #ifdef SVG_ENABLED Dictionary dark_icon_color_dictionary; if (!p_dark_theme) { - //convert color: FROM TO - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#4f4f4f"); // common icon color - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#000000"); // white - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#000000"); // script darker color + // convert color: FROM TO + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#e0e0e0", "#5a5a5a"); // common icon color + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ffffff", "#414141"); // white + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b4b4b4", "#363636"); // script darker color + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#f9f9f9", "#606060"); // scrollbar grabber highlight color ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#cea4f1", "#a85de9"); // animation ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fc9c9c", "#cd3838"); // spatial ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5b7f3", "#3d64dd"); // 2d ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#708cea", "#1a3eac"); // 2d dark - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#2aa235"); // control + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#a5efac", "#2fa139"); // control // rainbow ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ff7070", "#ff2929"); // red @@ -145,9 +146,14 @@ void editor_register_and_generate_icons(Ref<Theme> p_theme, bool p_dark_theme = ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#ea9568", "#bd5e2c"); // 3D Transform track ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#66f376", "#16a827"); // Call Method track ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#5792f6", "#236be6"); // Bezier Curve track - ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#eae668", "#aea923"); // Audio Playback track + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#eae668", "#9f9722"); // Audio Playback track ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#b76ef0", "#9853ce"); // Animation Playback track + // TileSet editor icons + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#fce844", "#aa8d24"); // New Single Tile + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#4490fc", "#0350bd"); // New Autotile + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#c9cfd4", "#828f9b"); // New Atlas + ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#69ecbd", "#25e3a0"); // VS variant ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#8da6f0", "#6d8eeb"); // VS bool ADD_CONVERT_COLOR(dark_icon_color_dictionary, "#7dc6ef", "#4fb2e9"); // VS int @@ -339,6 +345,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color color_disabled = mono_color.inverted().linear_interpolate(base_color, 0.7); const Color color_disabled_bg = mono_color.inverted().linear_interpolate(base_color, 0.9); + Color icon_color_hover = Color(1, 1, 1) * (dark_theme ? 1.15 : 1.45); + icon_color_hover.a = 1.0; + // Make the pressed icon color overbright because icons are not completely white on a dark theme. + // On a light theme, icons are dark, so we need to modulate them with an even brighter color. + Color icon_color_pressed = accent_color * (dark_theme ? 1.15 : 3.5); + icon_color_pressed.a = 1.0; + const Color separator_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.1); const Color highlight_color = Color(mono_color.r, mono_color.g, mono_color.b, 0.2); @@ -565,9 +578,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color_hover", "Button", font_color_hl); theme->set_color("font_color_pressed", "Button", accent_color); theme->set_color("font_color_disabled", "Button", font_color_disabled); - theme->set_color("icon_color_hover", "Button", font_color_hl); - // make icon color value bigger because icon image is not complete white - theme->set_color("icon_color_pressed", "Button", Color(accent_color.r * 1.15, accent_color.g * 1.15, accent_color.b * 1.15, accent_color.a)); + theme->set_color("icon_color_hover", "Button", icon_color_hover); + theme->set_color("icon_color_pressed", "Button", icon_color_pressed); // OptionButton theme->set_stylebox("normal", "OptionButton", style_widget); @@ -580,7 +592,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color_hover", "OptionButton", font_color_hl); theme->set_color("font_color_pressed", "OptionButton", accent_color); theme->set_color("font_color_disabled", "OptionButton", font_color_disabled); - theme->set_color("icon_color_hover", "OptionButton", font_color_hl); + theme->set_color("icon_color_hover", "OptionButton", icon_color_hover); theme->set_icon("arrow", "OptionButton", theme->get_icon("GuiOptionArrow", "EditorIcons")); theme->set_constant("arrow_margin", "OptionButton", default_margin_size * EDSCALE); theme->set_constant("modulate_arrow", "OptionButton", true); @@ -601,7 +613,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color_hover", "CheckButton", font_color_hl); theme->set_color("font_color_pressed", "CheckButton", accent_color); theme->set_color("font_color_disabled", "CheckButton", font_color_disabled); - theme->set_color("icon_color_hover", "CheckButton", font_color_hl); + theme->set_color("icon_color_hover", "CheckButton", icon_color_hover); theme->set_constant("hseparation", "CheckButton", 4 * EDSCALE); theme->set_constant("check_vadjust", "CheckButton", 0 * EDSCALE); @@ -626,7 +638,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("font_color_hover", "CheckBox", font_color_hl); theme->set_color("font_color_pressed", "CheckBox", accent_color); theme->set_color("font_color_disabled", "CheckBox", font_color_disabled); - theme->set_color("icon_color_hover", "CheckBox", font_color_hl); + theme->set_color("icon_color_hover", "CheckBox", icon_color_hover); theme->set_constant("hseparation", "CheckBox", 4 * EDSCALE); theme->set_constant("check_vadjust", "CheckBox", 0 * EDSCALE); @@ -983,8 +995,13 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { // GraphEdit theme->set_stylebox("bg", "GraphEdit", style_tree_bg); - theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.15)); - theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.07)); + if (dark_theme) { + theme->set_color("grid_major", "GraphEdit", Color(1.0, 1.0, 1.0, 0.15)); + theme->set_color("grid_minor", "GraphEdit", Color(1.0, 1.0, 1.0, 0.07)); + } else { + theme->set_color("grid_major", "GraphEdit", Color(0.0, 0.0, 0.0, 0.15)); + theme->set_color("grid_minor", "GraphEdit", Color(0.0, 0.0, 0.0, 0.07)); + } theme->set_color("activity", "GraphEdit", accent_color); theme->set_icon("minus", "GraphEdit", theme->get_icon("ZoomLess", "EditorIcons")); theme->set_icon("more", "GraphEdit", theme->get_icon("ZoomMore", "EditorIcons")); @@ -1068,7 +1085,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("folder", "FileDialog", theme->get_icon("Folder", "EditorIcons")); // Use a different color for folder icons to make them easier to distinguish from files. // On a light theme, the icon will be dark, so we need to lighten it before blending it with the accent color. - theme->set_color("folder_icon_modulate", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(5, 5, 5)).linear_interpolate(accent_color, 0.7)); + theme->set_color("folder_icon_modulate", "FileDialog", (dark_theme ? Color(1, 1, 1) : Color(4.25, 4.25, 4.25)).linear_interpolate(accent_color, 0.7)); theme->set_color("files_disabled", "FileDialog", font_color_disabled); // color picker diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 1447a143d4..536cfaa1dd 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -542,7 +542,6 @@ void ExportTemplateManager::_notification(int p_what) { template_list_state->set_text(status); if (errored) { set_process(false); - ; } } @@ -555,25 +554,33 @@ void ExportTemplateManager::_notification(int p_what) { bool ExportTemplateManager::can_install_android_template() { - return FileAccess::exists(EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG).plus_file("android_source.zip")); + const String templates_dir = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); + return FileAccess::exists(templates_dir.plus_file("android_source.zip")) && + FileAccess::exists(templates_dir.plus_file("android_release.apk")) && + FileAccess::exists(templates_dir.plus_file("android_debug.apk")); } Error ExportTemplateManager::install_android_template() { + // To support custom Android builds, we install various things to the project's res://android folder. + // First is the Java source code and buildsystem from android_source.zip. + // Then we extract the Godot Android libraries from pre-build android_release.apk + // and android_debug.apk, to place them in the libs folder. + DirAccessRef da = DirAccess::open("res://"); ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); - //make android dir (if it does not exist) + // Make res://android dir (if it does not exist). da->make_dir("android"); { - //add an empty .gdignore file to avoid scan + // Add an empty .gdignore file to avoid scan. FileAccessRef f = FileAccess::open("res://android/.gdignore", FileAccess::WRITE); ERR_FAIL_COND_V(!f, ERR_CANT_CREATE); f->store_line(""); f->close(); } { - //add version, to ensure building won't work if template and Godot version don't match + // Add version, to ensure building won't work if template and Godot version don't match. FileAccessRef f = FileAccess::open("res://android/.build_version", FileAccess::WRITE); ERR_FAIL_COND_V(!f, ERR_CANT_CREATE); f->store_line(VERSION_FULL_CONFIG); @@ -583,7 +590,10 @@ Error ExportTemplateManager::install_android_template() { Error err = da->make_dir_recursive("android/build"); ERR_FAIL_COND_V(err != OK, err); - String source_zip = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG).plus_file("android_source.zip"); + // Uncompress source template. + + const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); + const String &source_zip = templates_path.plus_file("android_source.zip"); ERR_FAIL_COND_V(!FileAccess::exists(source_zip), ERR_CANT_OPEN); FileAccess *src_f = NULL; @@ -593,37 +603,33 @@ Error ExportTemplateManager::install_android_template() { ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android sources not in ZIP format."); int ret = unzGoToFirstFile(pkg); - int total_files = 0; - //count files + // Count files to unzip. while (ret == UNZ_OK) { total_files++; ret = unzGoToNextFile(pkg); } - ret = unzGoToFirstFile(pkg); - //decompress files - ProgressDialog::get_singleton()->add_task("uncompress", TTR("Uncompressing Android Build Sources"), total_files); - Set<String> dirs_tested; + ProgressDialog::get_singleton()->add_task("uncompress_src", TTR("Uncompressing Android Build Sources"), total_files); + Set<String> dirs_tested; int idx = 0; while (ret == UNZ_OK) { - //get filename + // Get file path. unz_file_info info; - char fname[16384]; - ret = unzGetCurrentFileInfo(pkg, &info, fname, 16384, NULL, 0, NULL, 0); - - String name = fname; + char fpath[16384]; + ret = unzGetCurrentFileInfo(pkg, &info, fpath, 16384, NULL, 0, NULL, 0); - String base_dir = name.get_base_dir(); + String path = fpath; + String base_dir = path.get_base_dir(); - if (!name.ends_with("/")) { + if (!path.ends_with("/")) { Vector<uint8_t> data; data.resize(info.uncompressed_size); - //read + // Read. unzOpenCurrentFile(pkg); unzReadCurrentFile(pkg, data.ptrw(), data.size()); unzCloseCurrentFile(pkg); @@ -633,7 +639,7 @@ Error ExportTemplateManager::install_android_template() { dirs_tested.insert(base_dir); } - String to_write = String("res://android/build").plus_file(name); + String to_write = String("res://android/build").plus_file(path); FileAccess *f = FileAccess::open(to_write, FileAccess::WRITE); if (f) { f->store_buffer(data.ptr(), data.size()); @@ -646,13 +652,96 @@ Error ExportTemplateManager::install_android_template() { } } - ProgressDialog::get_singleton()->task_step("uncompress", name, idx); + ProgressDialog::get_singleton()->task_step("uncompress_src", path, idx); + + idx++; + ret = unzGoToNextFile(pkg); + } + + ProgressDialog::get_singleton()->end_task("uncompress_src"); + unzClose(pkg); + + // Extract libs from pre-built APKs. + err = _extract_libs_from_apk("release"); + ERR_FAIL_COND_V_MSG(err != OK, err, "Can't extract Android libs from android_release.apk."); + err = _extract_libs_from_apk("debug"); + ERR_FAIL_COND_V_MSG(err != OK, err, "Can't extract Android libs from android_debug.apk."); + + return OK; +} + +Error ExportTemplateManager::_extract_libs_from_apk(const String &p_target_name) { + + const String &templates_path = EditorSettings::get_singleton()->get_templates_dir().plus_file(VERSION_FULL_CONFIG); + const String &apk_file = templates_path.plus_file("android_" + p_target_name + ".apk"); + ERR_FAIL_COND_V(!FileAccess::exists(apk_file), ERR_CANT_OPEN); + + FileAccess *src_f = NULL; + zlib_filefunc_def io = zipio_create_io_from_file(&src_f); + + unzFile pkg = unzOpen2(apk_file.utf8().get_data(), &io); + ERR_FAIL_COND_V_MSG(!pkg, ERR_CANT_OPEN, "Android APK can't be extracted."); + + DirAccessRef da = DirAccess::open("res://"); + ERR_FAIL_COND_V(!da, ERR_CANT_CREATE); + + // 8 steps because 4 arches, 2 libs per arch. + ProgressDialog::get_singleton()->add_task("extract_libs_from_apk", TTR("Extracting Android Libraries From APKs"), 8); + + int ret = unzGoToFirstFile(pkg); + Set<String> dirs_tested; + int idx = 0; + while (ret == UNZ_OK) { + // Get file path. + unz_file_info info; + char fpath[16384]; + ret = unzGetCurrentFileInfo(pkg, &info, fpath, 16384, NULL, 0, NULL, 0); + + String path = fpath; + String base_dir = path.get_base_dir(); + String file = path.get_file(); + + if (!base_dir.begins_with("lib") || path.ends_with("/")) { + ret = unzGoToNextFile(pkg); + continue; + } + + Vector<uint8_t> data; + data.resize(info.uncompressed_size); + + // Read. + unzOpenCurrentFile(pkg); + unzReadCurrentFile(pkg, data.ptrw(), data.size()); + unzCloseCurrentFile(pkg); + + // We have a "lib" folder in the APK, but it should be "libs/{release,debug}" in the source dir. + String target_base_dir = base_dir.replace_first("lib", String("libs").plus_file(p_target_name)); + + if (!dirs_tested.has(base_dir)) { + da->make_dir_recursive(String("android/build").plus_file(target_base_dir)); + dirs_tested.insert(base_dir); + } + + String to_write = String("res://android/build").plus_file(target_base_dir.plus_file(path.get_file())); + FileAccess *f = FileAccess::open(to_write, FileAccess::WRITE); + if (f) { + f->store_buffer(data.ptr(), data.size()); + memdelete(f); +#ifndef WINDOWS_ENABLED + // We can't retrieve Unix permissions from the APK it seems, so simply set 0755 as should be. + FileAccess::set_unix_permissions(to_write, 0755); +#endif + } else { + ERR_PRINTS("Can't uncompress file: " + to_write); + } + + ProgressDialog::get_singleton()->task_step("extract_libs_from_apk", path, idx); idx++; ret = unzGoToNextFile(pkg); } - ProgressDialog::get_singleton()->end_task("uncompress"); + ProgressDialog::get_singleton()->end_task("extract_libs_from_apk"); unzClose(pkg); return OK; diff --git a/editor/export_template_manager.h b/editor/export_template_manager.h index ad3ab507b3..ecb8e85b21 100644 --- a/editor/export_template_manager.h +++ b/editor/export_template_manager.h @@ -72,6 +72,8 @@ class ExportTemplateManager : public ConfirmationDialog { virtual void ok_pressed(); bool _install_from_file(const String &p_file, bool p_use_progress = true); + Error _extract_libs_from_apk(const String &p_target_name); + void _http_download_mirror_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); void _http_download_templates_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data); diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index 4fd4ab2f2e..f1de71e25e 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -83,8 +83,8 @@ void ResourceImporterWAV::get_import_options(List<ImportOption> *r_options, int r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/mono"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "force/max_rate", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::REAL, "force/max_rate_hz", PROPERTY_HINT_EXP_RANGE, "11025,192000,1"), 44100)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), true)); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/trim"), false)); + r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/normalize"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "edit/loop"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "compress/mode", PROPERTY_HINT_ENUM, "Disabled,RAM (Ima-ADPCM)"), 0)); } diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 2eb3ce1ec3..85ddcb8b9d 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -5298,6 +5298,10 @@ void SpatialEditor::_notification(int p_what) { tool_button[SpatialEditor::TOOL_MODE_ROTATE]->set_icon(get_icon("ToolRotate", "EditorIcons")); tool_button[SpatialEditor::TOOL_MODE_SCALE]->set_icon(get_icon("ToolScale", "EditorIcons")); tool_button[SpatialEditor::TOOL_MODE_LIST_SELECT]->set_icon(get_icon("ListSelect", "EditorIcons")); + tool_button[SpatialEditor::TOOL_LOCK_SELECTED]->set_icon(get_icon("Lock", "EditorIcons")); + tool_button[SpatialEditor::TOOL_UNLOCK_SELECTED]->set_icon(get_icon("Unlock", "EditorIcons")); + tool_button[SpatialEditor::TOOL_GROUP_SELECTED]->set_icon(get_icon("Group", "EditorIcons")); + tool_button[SpatialEditor::TOOL_UNGROUP_SELECTED]->set_icon(get_icon("Ungroup", "EditorIcons")); tool_option_button[SpatialEditor::TOOL_OPT_LOCAL_COORDS]->set_icon(get_icon("Object", "EditorIcons")); tool_option_button[SpatialEditor::TOOL_OPT_USE_SNAP]->set_icon(get_icon("Snap", "EditorIcons")); diff --git a/editor/project_export.cpp b/editor/project_export.cpp index 956da92c35..c54103f6f7 100644 --- a/editor/project_export.cpp +++ b/editor/project_export.cpp @@ -1116,6 +1116,7 @@ ProjectExportDialog::ProjectExportDialog() { sections = memnew(TabContainer); sections->set_tab_align(TabContainer::ALIGN_LEFT); + sections->set_use_hidden_tabs_for_min_size(true); settings_vb->add_child(sections); sections->set_v_size_flags(SIZE_EXPAND_FILL); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 98335c8367..c6e3dc1e32 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1754,7 +1754,7 @@ void ProjectManager::_dim_window() { // Dim the project manager window while it's quitting to make it clearer that it's busy. // No transition is applied, as the effect needs to be visible immediately - float c = 0.4f; + float c = 0.5f; Color dim_color = Color(c, c, c); gui_base->set_modulate(dim_color); } diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 1c588a45f1..a0d2332ffc 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -1674,6 +1674,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { tab_container = memnew(TabContainer); tab_container->set_tab_align(TabContainer::ALIGN_LEFT); + tab_container->set_use_hidden_tabs_for_min_size(true); add_child(tab_container); VBoxContainer *props_base = memnew(VBoxContainer); diff --git a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj index c745fe321b..ab3a5d1aea 100644 --- a/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj +++ b/modules/mono/editor/GodotTools/GodotTools.ProjectEditor/GodotTools.ProjectEditor.csproj @@ -37,9 +37,8 @@ entire solution. $(SolutionDir) is not defined in that case, so we need to workaround that. We make SCons restore the NuGet packages in the project directory instead in this case. --> - <HintPath Condition=" '$(SolutionDir)' != '' ">$(SolutionDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll</HintPath> - <HintPath>$(ProjectDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll</HintPath> - <HintPath>packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll</HintPath> <!-- Are you happy CI? --> + <HintPath Condition=" '$(SolutionDir)' != '' And Exists('$(SolutionDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll') ">$(SolutionDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll</HintPath> + <HintPath Condition=" '$(SolutionDir)' == '' Or !Exists('$(SolutionDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll') ">$(ProjectDir)\packages\DotNet.Glob.2.1.1\lib\net45\DotNet.Glob.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index aa69803a58..cd111abd4d 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -317,6 +317,13 @@ void GDMono::initialize() { return; #endif +#if !defined(WINDOWS_ENABLED) && !defined(NO_MONO_THREADS_SUSPEND_WORKAROUND) + // FIXME: Temporary workaround. See: https://github.com/godotengine/godot/issues/29812 + if (!OS::get_singleton()->has_environment("MONO_THREADS_SUSPEND")) { + OS::get_singleton()->set_environment("MONO_THREADS_SUSPEND", "preemptive"); + } +#endif + root_domain = mono_jit_init_version("GodotEngine.RootDomain", "v4.0.30319"); ERR_FAIL_NULL_MSG(root_domain, "Mono: Failed to initialize runtime."); diff --git a/platform/android/SCsub b/platform/android/SCsub index d2f27817c6..1bd8161fa7 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -55,3 +55,25 @@ if lib_arch_dir != '': stl_lib_path = str(env['ANDROID_NDK_ROOT']) + '/sources/cxx-stl/llvm-libc++/libs/' + lib_arch_dir + '/libc++_shared.so' env_android.Command(out_dir + '/libc++_shared.so', stl_lib_path, Copy("$TARGET", "$SOURCE")) + +# Zip android/java folder for the source export template. +print("Archiving platform/android/java as bin/android_source.zip...") +import os +import zipfile +# Change dir to avoid have zipped paths start from the android/java folder. +olddir = os.getcwd() +os.chdir(Dir('#platform/android/java').abspath) +bindir = Dir('#bin').abspath +# Make 'bin' dir if missing, can happen on fresh clone. +if not os.path.exists(bindir): + os.makedirs(bindir) +zipf = zipfile.ZipFile(os.path.join(bindir, 'android_source.zip'), 'w', zipfile.ZIP_DEFLATED) +exclude_dirs = ['.gradle', 'build', 'libs', 'patches'] +for root, dirs, files in os.walk('.', topdown=True): + # Change 'dirs' in place to exclude folders we don't want. + # https://stackoverflow.com/a/19859907 + dirs[:] = [d for d in dirs if d not in exclude_dirs] + for f in files: + zipf.write(os.path.join(root, f)) +zipf.close() +os.chdir(olddir) diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp index 16e49e8a38..441fa38bff 100644 --- a/platform/android/export/export.cpp +++ b/platform/android/export/export.cpp @@ -1610,19 +1610,16 @@ public: valid = false; } else { Error errn; - DirAccess *da = DirAccess::open(sdk_path.plus_file("tools"), &errn); + DirAccessRef da = DirAccess::open(sdk_path.plus_file("tools"), &errn); if (errn != OK) { err += TTR("Invalid Android SDK path for custom build in Editor Settings.") + "\n"; valid = false; } - if (da) { - memdelete(da); - } } if (!FileAccess::exists("res://android/build/build.gradle")) { - err += TTR("Android project is not installed for compiling. Install from Editor menu.") + "\n"; + err += TTR("Android build template not installed in the project. Install it from the Project menu.") + "\n"; valid = false; } } @@ -2513,7 +2510,7 @@ void register_android_exporter() { EDITOR_DEF("export/android/debug_keystore_pass", "android"); EDITOR_DEF("export/android/force_system_user", false); EDITOR_DEF("export/android/custom_build_sdk_path", ""); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/custom_build_sdk_path", PROPERTY_HINT_GLOBAL_DIR, "*.keystore")); + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/custom_build_sdk_path", PROPERTY_HINT_GLOBAL_DIR)); EDITOR_DEF("export/android/timestamping_authority_url", ""); EDITOR_DEF("export/android/shutdown_adb_on_exit", true); diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 6ada0cba97..3c63f6b2c7 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "spin_box.h" +#include "core/math/expression.h" #include "core/os/input.h" Size2 SpinBox::get_minimum_size() const { @@ -50,15 +51,18 @@ void SpinBox::_value_changed(double) { void SpinBox::_text_entered(const String &p_string) { - /* - if (!p_string.is_numeric()) + Ref<Expression> expr; + expr.instance(); + Error err = expr->parse(p_string); + if (err != OK) { return; - */ - String value = p_string; - if (prefix != "" && p_string.begins_with(prefix)) - value = p_string.substr(prefix.length(), p_string.length() - prefix.length()); - set_value(value.to_double()); - _value_changed(0); + } + + Variant value = expr->execute(Array(), NULL, false); + if (value.get_type() != Variant::NIL) { + set_value(value); + _value_changed(0); + } } LineEdit *SpinBox::get_line_edit() { diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp index be8f1cf36e..292d80be9d 100644 --- a/scene/gui/tab_container.cpp +++ b/scene/gui/tab_container.cpp @@ -840,7 +840,7 @@ Size2 TabContainer::get_minimum_size() const { Control *c = tabs[i]; - if (!c->is_visible_in_tree()) + if (!c->is_visible_in_tree() && !use_hidden_tabs_for_min_size) continue; Size2 cms = c->get_combined_minimum_size(); @@ -887,6 +887,13 @@ int TabContainer::get_tabs_rearrange_group() const { return tabs_rearrange_group; } +void TabContainer::set_use_hidden_tabs_for_min_size(bool p_use_hidden_tabs) { + use_hidden_tabs_for_min_size = p_use_hidden_tabs; +} + +bool TabContainer::get_use_hidden_tabs_for_min_size() const { + return use_hidden_tabs_for_min_size; +} void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &TabContainer::_gui_input); @@ -913,6 +920,9 @@ void TabContainer::_bind_methods() { ClassDB::bind_method(D_METHOD("set_tabs_rearrange_group", "group_id"), &TabContainer::set_tabs_rearrange_group); ClassDB::bind_method(D_METHOD("get_tabs_rearrange_group"), &TabContainer::get_tabs_rearrange_group); + ClassDB::bind_method(D_METHOD("set_use_hidden_tabs_for_min_size", "enabled"), &TabContainer::set_use_hidden_tabs_for_min_size); + ClassDB::bind_method(D_METHOD("get_use_hidden_tabs_for_min_size"), &TabContainer::get_use_hidden_tabs_for_min_size); + ClassDB::bind_method(D_METHOD("_child_renamed_callback"), &TabContainer::_child_renamed_callback); ClassDB::bind_method(D_METHOD("_on_theme_changed"), &TabContainer::_on_theme_changed); ClassDB::bind_method(D_METHOD("_update_current_tab"), &TabContainer::_update_current_tab); @@ -925,6 +935,7 @@ void TabContainer::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "current_tab", PROPERTY_HINT_RANGE, "-1,4096,1", PROPERTY_USAGE_EDITOR), "set_current_tab", "get_current_tab"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "tabs_visible"), "set_tabs_visible", "are_tabs_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "drag_to_rearrange_enabled"), "set_drag_to_rearrange_enabled", "get_drag_to_rearrange_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hidden_tabs_for_min_size"), "set_use_hidden_tabs_for_min_size", "get_use_hidden_tabs_for_min_size"); BIND_ENUM_CONSTANT(ALIGN_LEFT); BIND_ENUM_CONSTANT(ALIGN_CENTER); @@ -945,4 +956,5 @@ TabContainer::TabContainer() { popup = NULL; drag_to_rearrange_enabled = false; tabs_rearrange_group = -1; + use_hidden_tabs_for_min_size = false; } diff --git a/scene/gui/tab_container.h b/scene/gui/tab_container.h index f7a9fb64fd..0314f86837 100644 --- a/scene/gui/tab_container.h +++ b/scene/gui/tab_container.h @@ -59,6 +59,7 @@ private: int _get_top_margin() const; Popup *popup; bool drag_to_rearrange_enabled; + bool use_hidden_tabs_for_min_size; int tabs_rearrange_group; Vector<Control *> _get_tabs() const; @@ -118,6 +119,8 @@ public: bool get_drag_to_rearrange_enabled() const; void set_tabs_rearrange_group(int p_group_id); int get_tabs_rearrange_group() const; + void set_use_hidden_tabs_for_min_size(bool p_use_hidden_tabs); + bool get_use_hidden_tabs_for_min_size() const; TabContainer(); }; |