diff options
25 files changed, 315 insertions, 111 deletions
diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index d655f52f5d..ec984e480a 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1297,6 +1297,8 @@ void CodeTextEditor::_on_settings_change() { text_editor->set_callhint_settings( EDITOR_DEF("text_editor/completion/put_callhint_tooltip_below_current_line", true), EDITOR_DEF("text_editor/completion/callhint_tooltip_offset", Vector2())); + + idle->set_wait_time(EDITOR_DEF("text_editor/completion/idle_parse_delay", 2.0)); } void CodeTextEditor::_text_changed_idle_timeout() { @@ -1411,7 +1413,7 @@ CodeTextEditor::CodeTextEditor() { idle = memnew(Timer); add_child(idle); idle->set_one_shot(true); - idle->set_wait_time(EDITOR_DEF("text_editor/completion/idle_parse_delay", 2)); + idle->set_wait_time(EDITOR_DEF("text_editor/completion/idle_parse_delay", 2.0)); code_complete_timer = memnew(Timer); add_child(code_complete_timer); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index bf582ca004..b65a484b16 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -459,7 +459,8 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/cursor/right_click_moves_caret", true); // Completion - _initial_set("text_editor/completion/idle_parse_delay", 2); + _initial_set("text_editor/completion/idle_parse_delay", 2.0); + hints["text_editor/completion/idle_parse_delay"] = PropertyInfo(Variant::REAL, "text_editor/completion/idle_parse_delay", PROPERTY_HINT_RANGE, "0.1, 10, 0.01"); _initial_set("text_editor/completion/auto_brace_complete", false); _initial_set("text_editor/completion/put_callhint_tooltip_below_current_line", true); _initial_set("text_editor/completion/callhint_tooltip_offset", Vector2()); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 0a6e4c0607..66766f7ccf 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -987,6 +987,24 @@ void ProjectManager::_update_project_buttons() { open_btn->set_disabled(empty_selection); rename_btn->set_disabled(empty_selection); run_btn->set_disabled(empty_selection); + + bool missing_projects = false; + Map<String, String> list_all_projects; + for (int i = 0; i < scroll_children->get_child_count(); i++) { + HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_children->get_child(i)); + if (hb) { + list_all_projects.insert(hb->get_meta("name"), hb->get_meta("main_scene")); + } + } + for (Map<String, String>::Element *E = list_all_projects.front(); E; E = E->next()) { + String project_name = E->key().replace("::", "/") + "/project.godot"; + if (!FileAccess::exists(project_name)) { + missing_projects = true; + break; + } + } + + erase_missing_btn->set_visible(missing_projects); } void ProjectManager::_panel_input(const Ref<InputEvent> &p_ev, Node *p_hb) { @@ -1700,6 +1718,39 @@ void ProjectManager::_erase_project_confirm() { _load_recent_projects(); } +void ProjectManager::_erase_missing_projects_confirm() { + + Map<String, String> list_all_projects; + for (int i = 0; i < scroll_children->get_child_count(); i++) { + HBoxContainer *hb = Object::cast_to<HBoxContainer>(scroll_children->get_child(i)); + if (hb) { + list_all_projects.insert(hb->get_meta("name"), hb->get_meta("main_scene")); + } + } + + if (list_all_projects.size() == 0) { + return; + } + + int deleted_projects = 0; + int remaining_projects = 0; + for (Map<String, String>::Element *E = list_all_projects.front(); E; E = E->next()) { + String project_name = E->key().replace("::", "/") + "/project.godot"; + if (!FileAccess::exists(project_name)) { + deleted_projects++; + EditorSettings::get_singleton()->erase("projects/" + E->key()); + EditorSettings::get_singleton()->erase("favorite_projects/" + E->key()); + } else { + remaining_projects++; + } + } + print_line("Deleted " + itos(deleted_projects) + " projects, remaining " + itos(remaining_projects) + " projects"); + EditorSettings::get_singleton()->save(); + selected_list.clear(); + last_clicked = ""; + _load_recent_projects(); +} + void ProjectManager::_erase_project() { if (selected_list.size() == 0) @@ -1716,6 +1767,12 @@ void ProjectManager::_erase_project() { erase_ask->popup_centered_minsize(); } +void ProjectManager::_erase_missing_projects() { + + erase_missing_ask->set_text(TTR("Remove all missing projects from the list? (Folders contents will not be modified)")); + erase_missing_ask->popup_centered_minsize(); +} + void ProjectManager::_language_selected(int p_id) { String lang = language_btn->get_item_metadata(p_id); @@ -1812,7 +1869,9 @@ void ProjectManager::_bind_methods() { ClassDB::bind_method("_new_project", &ProjectManager::_new_project); ClassDB::bind_method("_rename_project", &ProjectManager::_rename_project); ClassDB::bind_method("_erase_project", &ProjectManager::_erase_project); + ClassDB::bind_method("_erase_missing_projects", &ProjectManager::_erase_missing_projects); ClassDB::bind_method("_erase_project_confirm", &ProjectManager::_erase_project_confirm); + ClassDB::bind_method("_erase_missing_projects_confirm", &ProjectManager::_erase_missing_projects_confirm); ClassDB::bind_method("_language_selected", &ProjectManager::_language_selected); ClassDB::bind_method("_restart_confirm", &ProjectManager::_restart_confirm); ClassDB::bind_method("_exit_dialog", &ProjectManager::_exit_dialog); @@ -2050,6 +2109,12 @@ ProjectManager::ProjectManager() { erase->connect("pressed", this, "_erase_project"); erase_btn = erase; + Button *erase_missing = memnew(Button); + erase_missing->set_text(TTR("Remove Missing")); + tree_vb->add_child(erase_missing); + erase_missing->connect("pressed", this, "_erase_missing_projects"); + erase_missing_btn = erase_missing; + tree_vb->add_spacer(); if (StreamPeerSSL::is_available()) { @@ -2113,6 +2178,11 @@ ProjectManager::ProjectManager() { language_restart_ask->get_cancel()->set_text(TTR("Continue")); gui_base->add_child(language_restart_ask); + erase_missing_ask = memnew(ConfirmationDialog); + erase_missing_ask->get_ok()->set_text(TTR("Remove All")); + erase_missing_ask->get_ok()->connect("pressed", this, "_erase_missing_projects_confirm"); + gui_base->add_child(erase_missing_ask); + erase_ask = memnew(ConfirmationDialog); erase_ask->get_ok()->set_text(TTR("Remove")); erase_ask->get_ok()->connect("pressed", this, "_erase_project_confirm"); diff --git a/editor/project_manager.h b/editor/project_manager.h index 1fdd7dbe06..382e9fc8fb 100644 --- a/editor/project_manager.h +++ b/editor/project_manager.h @@ -45,6 +45,7 @@ class ProjectManager : public Control { GDCLASS(ProjectManager, Control); Button *erase_btn; + Button *erase_missing_btn; Button *open_btn; Button *rename_btn; Button *run_btn; @@ -57,6 +58,7 @@ class ProjectManager : public Control { FileDialog *scan_dir; ConfirmationDialog *language_restart_ask; ConfirmationDialog *erase_ask; + ConfirmationDialog *erase_missing_ask; ConfirmationDialog *multi_open_ask; ConfirmationDialog *multi_run_ask; ConfirmationDialog *multi_scan_ask; @@ -89,7 +91,9 @@ class ProjectManager : public Control { void _new_project(); void _rename_project(); void _erase_project(); + void _erase_missing_projects(); void _erase_project_confirm(); + void _erase_missing_projects_confirm(); void _update_project_buttons(); void _language_selected(int p_id); void _restart_confirm(); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index f8f48d01ad..71bddebcf5 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -1592,6 +1592,7 @@ void ProjectSettingsEditor::_toggle_search_bar(bool p_pressed) { search_box->select_all(); } else { + search_box->clear(); search_bar->hide(); add_prop_bar->show(); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 1dca542138..a41f10607b 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -2625,6 +2625,7 @@ SceneTreeDock::SceneTreeDock(EditorNode *p_editor, Node *p_scene_root, EditorSel add_child(rename_dialog); script_create_dialog = memnew(ScriptCreateDialog); + script_create_dialog->set_inheritance_base_type("Node"); add_child(script_create_dialog); script_create_dialog->connect("script_created", this, "_script_created"); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index a7b179753f..292cb8ddc3 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -34,6 +34,7 @@ #include "core/os/file_access.h" #include "core/project_settings.h" #include "core/script_language.h" +#include "editor/create_dialog.h" #include "editor/editor_node.h" #include "editor/editor_scale.h" #include "editor_file_system.h" @@ -45,11 +46,28 @@ void ScriptCreateDialog::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { path_button->set_icon(get_icon("Folder", "EditorIcons")); parent_browse_button->set_icon(get_icon("Folder", "EditorIcons")); + parent_search_button->set_icon(get_icon("ClassList", "EditorIcons")); status_panel->add_style_override("panel", get_stylebox("bg", "Tree")); } break; } } +void ScriptCreateDialog::_path_hbox_sorted() { + if (is_visible()) { + int filename_start_pos = initial_bp.find_last("/") + 1; + int filename_end_pos = initial_bp.length(); + + file_path->select(filename_start_pos, filename_end_pos); + + // First set cursor to the end of line to scroll LineEdit view + // to the right and then set the actual cursor position. + file_path->set_cursor_position(file_path->get_text().length()); + file_path->set_cursor_position(filename_start_pos); + + file_path->grab_focus(); + } +} + bool ScriptCreateDialog::_can_be_built_in() { return (supports_built_in && built_in_enabled); } @@ -77,6 +95,11 @@ void ScriptCreateDialog::config(const String &p_base_name, const String &p_base_ _path_changed(file_path->get_text()); } +void ScriptCreateDialog::set_inheritance_base_type(const String &p_base) { + + base_type = p_base; +} + bool ScriptCreateDialog::_validate(const String &p_string) { if (p_string.length() == 0) @@ -362,6 +385,17 @@ void ScriptCreateDialog::_file_selected(const String &p_file) { } } +void ScriptCreateDialog::_create() { + + parent_name->set_text(select_class->get_selected_type()); +} + +void ScriptCreateDialog::_browse_class_in_tree() { + + select_class->set_base_type(base_type); + select_class->popup_create(true); +} + void ScriptCreateDialog::_path_changed(const String &p_path) { is_path_valid = false; @@ -586,6 +620,7 @@ void ScriptCreateDialog::_update_dialog() { void ScriptCreateDialog::_bind_methods() { + ClassDB::bind_method("_path_hbox_sorted", &ScriptCreateDialog::_path_hbox_sorted); ClassDB::bind_method("_class_name_changed", &ScriptCreateDialog::_class_name_changed); ClassDB::bind_method("_parent_name_changed", &ScriptCreateDialog::_parent_name_changed); ClassDB::bind_method("_lang_changed", &ScriptCreateDialog::_lang_changed); @@ -595,6 +630,8 @@ void ScriptCreateDialog::_bind_methods() { ClassDB::bind_method("_path_changed", &ScriptCreateDialog::_path_changed); ClassDB::bind_method("_path_entered", &ScriptCreateDialog::_path_entered); ClassDB::bind_method("_template_changed", &ScriptCreateDialog::_template_changed); + ClassDB::bind_method("_create", &ScriptCreateDialog::_create); + ClassDB::bind_method("_browse_class_in_tree", &ScriptCreateDialog::_browse_class_in_tree); ClassDB::bind_method(D_METHOD("config", "inherits", "path", "built_in_enabled"), &ScriptCreateDialog::config, DEFVAL(true)); @@ -707,12 +744,18 @@ ScriptCreateDialog::ScriptCreateDialog() { /* Inherits */ + base_type = "Object"; + hb = memnew(HBoxContainer); hb->set_h_size_flags(SIZE_EXPAND_FILL); parent_name = memnew(LineEdit); parent_name->connect("text_changed", this, "_parent_name_changed"); parent_name->set_h_size_flags(SIZE_EXPAND_FILL); hb->add_child(parent_name); + parent_search_button = memnew(Button); + parent_search_button->set_flat(true); + parent_search_button->connect("pressed", this, "_browse_class_in_tree"); + hb->add_child(parent_search_button); parent_browse_button = memnew(Button); parent_browse_button->set_flat(true); parent_browse_button->connect("pressed", this, "_browse_path", varray(true, false)); @@ -760,6 +803,7 @@ ScriptCreateDialog::ScriptCreateDialog() { /* Path */ hb = memnew(HBoxContainer); + hb->connect("sort_children", this, "_path_hbox_sorted"); file_path = memnew(LineEdit); file_path->connect("text_changed", this, "_path_changed"); file_path->connect("text_entered", this, "_path_entered"); @@ -777,6 +821,10 @@ ScriptCreateDialog::ScriptCreateDialog() { /* Dialog Setup */ + select_class = memnew(CreateDialog); + select_class->connect("create", this, "_create"); + add_child(select_class); + file_browse = memnew(EditorFileDialog); file_browse->connect("file_selected", this, "_file_selected"); file_browse->set_mode(EditorFileDialog::MODE_OPEN_FILE); diff --git a/editor/script_create_dialog.h b/editor/script_create_dialog.h index 15e838d69f..f5c335c00a 100644 --- a/editor/script_create_dialog.h +++ b/editor/script_create_dialog.h @@ -40,6 +40,8 @@ #include "scene/gui/option_button.h" #include "scene/gui/panel_container.h" +class CreateDialog; + class ScriptCreateDialog : public ConfirmationDialog { GDCLASS(ScriptCreateDialog, ConfirmationDialog); @@ -49,6 +51,7 @@ class ScriptCreateDialog : public ConfirmationDialog { PanelContainer *status_panel; LineEdit *parent_name; Button *parent_browse_button; + Button *parent_search_button; OptionButton *language_menu; OptionButton *template_menu; LineEdit *file_path; @@ -57,6 +60,7 @@ class ScriptCreateDialog : public ConfirmationDialog { CheckButton *internal; VBoxContainer *path_vb; AcceptDialog *alert; + CreateDialog *select_class; bool path_valid; bool create_new; bool is_browsing_parent; @@ -74,7 +78,9 @@ class ScriptCreateDialog : public ConfirmationDialog { bool re_check_path; String script_template; Vector<String> template_list; + String base_type; + void _path_hbox_sorted(); bool _can_be_built_in(); void _path_changed(const String &p_path = String()); void _path_entered(const String &p_path = String()); @@ -86,6 +92,8 @@ class ScriptCreateDialog : public ConfirmationDialog { void _template_changed(int p_template = 0); void _browse_path(bool browse_parent, bool p_save); void _file_selected(const String &p_file); + void _create(); + void _browse_class_in_tree(); virtual void ok_pressed(); void _create_new(); void _load_exist(); @@ -99,6 +107,7 @@ protected: public: void config(const String &p_base_name, const String &p_base_path, bool p_built_in_enabled = true); + void set_inheritance_base_type(const String &p_base); ScriptCreateDialog(); }; diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp index eac8e26160..c3f8688adb 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp @@ -227,7 +227,7 @@ void ARVRInterfaceGDNative::notification(int p_what) { // this is only available in interfaces that implement 1.1 or later if ((interface->version.major > 1) || ((interface->version.major == 1) && (interface->version.minor > 0))) { - interface->notification(p_what); + interface->notification(data, p_what); } } diff --git a/modules/gdnative/include/arvr/godot_arvr.h b/modules/gdnative/include/arvr/godot_arvr.h index 60bad27618..657090fa70 100644 --- a/modules/gdnative/include/arvr/godot_arvr.h +++ b/modules/gdnative/include/arvr/godot_arvr.h @@ -63,7 +63,7 @@ typedef struct { void (*process)(void *); // only in 1.1 onwards godot_int (*get_external_texture_for_eye)(void *, godot_int); - void (*notification)(godot_int); + void (*notification)(void *, godot_int); } godot_arvr_interface_gdnative; void GDAPI godot_arvr_register_interface(const godot_arvr_interface_gdnative *p_interface); diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 27e579935f..ef09e76d11 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -2285,8 +2285,9 @@ bool CSharpScript::_get_member_export(GDMonoClass *p_class, IMonoClassMember *p_ hint = PROPERTY_HINT_RESOURCE_TYPE; hint_string = NATIVE_GDMONOCLASS_NAME(field_native_class); } else if (variant_type == Variant::ARRAY && export_info.array.element_type != Variant::NIL) { + String elem_type_str = itos(export_info.array.element_type); hint = PROPERTY_HINT_TYPE_STRING; - hint_string = itos(export_info.array.element_type) + ":"; + hint_string = elem_type_str + "/" + elem_type_str + ":" + export_info.array.element_native_name; } else if (variant_type == Variant::DICTIONARY && export_info.dictionary.key_type != Variant::NIL && export_info.dictionary.value_type != Variant::NIL) { // TODO: There is no hint for this yet } else { diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index de4f3650bd..d586b73cf9 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -184,8 +184,13 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, ExportInfo *r_e reftype, &key_reftype, &value_reftype, &exc); UNLIKELY_UNHANDLED_EXCEPTION(exc); - r_export_info->dictionary.key_type = managed_to_variant_type(ManagedType::from_reftype(key_reftype)); - r_export_info->dictionary.value_type = managed_to_variant_type(ManagedType::from_reftype(value_reftype)); + ManagedType key_type = ManagedType::from_reftype(key_reftype); + ManagedType value_type = ManagedType::from_reftype(value_reftype); + + r_export_info->dictionary.key_type = managed_to_variant_type(key_type); + r_export_info->dictionary.key_native_name = NATIVE_GDMONOCLASS_NAME(key_type.type_class); + r_export_info->dictionary.value_type = managed_to_variant_type(value_type); + r_export_info->dictionary.value_native_name = NATIVE_GDMONOCLASS_NAME(value_type.type_class); } return Variant::DICTIONARY; @@ -205,7 +210,10 @@ Variant::Type managed_to_variant_type(const ManagedType &p_type, ExportInfo *r_e reftype, &elem_reftype, &exc); UNLIKELY_UNHANDLED_EXCEPTION(exc); - r_export_info->array.element_type = managed_to_variant_type(ManagedType::from_reftype(elem_reftype)); + ManagedType elem_type = ManagedType::from_reftype(elem_reftype); + + r_export_info->array.element_type = managed_to_variant_type(elem_type); + r_export_info->array.element_native_name = NATIVE_GDMONOCLASS_NAME(elem_type.type_class); } return Variant::ARRAY; diff --git a/modules/mono/mono_gd/gd_mono_marshal.h b/modules/mono/mono_gd/gd_mono_marshal.h index 4a73f9e3e6..8d3fd4b349 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.h +++ b/modules/mono/mono_gd/gd_mono_marshal.h @@ -61,13 +61,16 @@ T unbox(MonoObject *p_obj) { struct ExportInfo { struct ArrayInfo { Variant::Type element_type; + String element_native_name; ArrayInfo() : element_type(Variant::NIL) {} } array; struct DictionaryInfo { Variant::Type key_type; + String key_native_name; Variant::Type value_type; + String value_native_name; DictionaryInfo() : key_type(Variant::NIL), diff --git a/modules/theora/video_stream_theora.cpp b/modules/theora/video_stream_theora.cpp index 8db0799b47..ae542713ea 100644 --- a/modules/theora/video_stream_theora.cpp +++ b/modules/theora/video_stream_theora.cpp @@ -94,15 +94,15 @@ void VideoStreamPlaybackTheora::video_write(void) { if (px_fmt == TH_PF_444) { - yuv444_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); + yuv444_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2); } else if (px_fmt == TH_PF_422) { - yuv422_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); + yuv422_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2); } else if (px_fmt == TH_PF_420) { - yuv420_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[2].data, (uint8_t *)yuv[1].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2, 0); + yuv420_2_rgb8888((uint8_t *)dst, (uint8_t *)yuv[0].data, (uint8_t *)yuv[1].data, (uint8_t *)yuv[2].data, size.x, size.y, yuv[0].stride, yuv[1].stride, size.x << 2); }; format = Image::FORMAT_RGBA8; diff --git a/modules/webm/video_stream_webm.cpp b/modules/webm/video_stream_webm.cpp index f2497eeec1..6485c95360 100644 --- a/modules/webm/video_stream_webm.cpp +++ b/modules/webm/video_stream_webm.cpp @@ -32,6 +32,7 @@ #include "OpusVorbisDecoder.hpp" #include "VPXDecoder.hpp" +#include <vpx/vpx_image.h> #include "mkvparser/mkvparser.h" @@ -314,19 +315,37 @@ void VideoStreamPlaybackWebm::update(float p_delta) { PoolVector<uint8_t>::Write w = frame_data.write(); bool converted = false; - if (image.chromaShiftW == 1 && image.chromaShiftH == 1) { + if (image.chromaShiftW == 0 && image.chromaShiftH == 0 && image.cs == VPX_CS_SRGB) { + + uint8_t *wp = w.ptr(); + unsigned char *rRow = image.planes[2]; + unsigned char *gRow = image.planes[0]; + unsigned char *bRow = image.planes[1]; + for (int i = 0; i < image.h; i++) { + for (int j = 0; j < image.w; j++) { + *wp++ = rRow[j]; + *wp++ = gRow[j]; + *wp++ = bRow[j]; + *wp++ = 255; + } + rRow += image.linesize[2]; + gRow += image.linesize[0]; + bRow += image.linesize[1]; + } + converted = true; + } else if (image.chromaShiftW == 1 && image.chromaShiftH == 1) { - yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); + yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); // libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) { - yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); + yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); // libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) { - yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[2], image.planes[1], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2, 0); + yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2); // libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h); converted = true; } else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) { diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index d8b2cfb5b9..bca3471091 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -38,8 +38,6 @@ #include "editor_scale.h" #include "editor_settings.h" #endif - -#include "scene/gui/separator.h" #include "scene/main/viewport.h" void ColorPicker::_notification(int p_what) { @@ -469,7 +467,7 @@ void ColorPicker::_preset_input(const Ref<InputEvent> &p_event) { set_pick_color(presets[index]); _update_color(); emit_signal("color_changed", color); - } else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT) { + } else if (bev->is_pressed() && bev->get_button_index() == BUTTON_RIGHT && presets_enabled) { int index = bev->get_position().x / (preset->get_size().x / presets.size()); Color clicked_preset = presets[index]; erase_preset(clicked_preset); @@ -565,6 +563,31 @@ void ColorPicker::_html_focus_exit() { _focus_exit(); } +void ColorPicker::set_presets_enabled(bool p_enabled) { + presets_enabled = p_enabled; + if (!p_enabled) { + bt_add_preset->set_disabled(true); + bt_add_preset->set_focus_mode(FOCUS_NONE); + } else { + bt_add_preset->set_disabled(false); + bt_add_preset->set_focus_mode(FOCUS_ALL); + } +} + +bool ColorPicker::are_presets_enabled() const { + return presets_enabled; +} + +void ColorPicker::set_presets_visible(bool p_visible) { + presets_visible = p_visible; + preset_separator->set_visible(p_visible); + preset_container->set_visible(p_visible); +} + +bool ColorPicker::are_presets_visible() const { + return presets_visible; +} + void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pick_color", "color"), &ColorPicker::set_pick_color); @@ -575,6 +598,10 @@ void ColorPicker::_bind_methods() { ClassDB::bind_method(D_METHOD("is_deferred_mode"), &ColorPicker::is_deferred_mode); ClassDB::bind_method(D_METHOD("set_edit_alpha", "show"), &ColorPicker::set_edit_alpha); ClassDB::bind_method(D_METHOD("is_editing_alpha"), &ColorPicker::is_editing_alpha); + ClassDB::bind_method(D_METHOD("set_presets_enabled", "enabled"), &ColorPicker::set_presets_enabled); + ClassDB::bind_method(D_METHOD("are_presets_enabled"), &ColorPicker::are_presets_enabled); + ClassDB::bind_method(D_METHOD("set_presets_visible", "visible"), &ColorPicker::set_presets_visible); + ClassDB::bind_method(D_METHOD("are_presets_visible"), &ColorPicker::are_presets_visible); ClassDB::bind_method(D_METHOD("add_preset", "color"), &ColorPicker::add_preset); ClassDB::bind_method(D_METHOD("erase_preset", "color"), &ColorPicker::erase_preset); ClassDB::bind_method(D_METHOD("get_presets"), &ColorPicker::get_presets); @@ -598,6 +625,8 @@ void ColorPicker::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "edit_alpha"), "set_edit_alpha", "is_editing_alpha"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "raw_mode"), "set_raw_mode", "is_raw_mode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "deferred_mode"), "set_deferred_mode", "is_deferred_mode"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_enabled"), "set_presets_enabled", "are_presets_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "presets_visible"), "set_presets_visible", "are_presets_visible"); ADD_SIGNAL(MethodInfo("color_changed", PropertyInfo(Variant::COLOR, "color"))); ADD_SIGNAL(MethodInfo("preset_added", PropertyInfo(Variant::COLOR, "color"))); @@ -613,6 +642,8 @@ ColorPicker::ColorPicker() : raw_mode_enabled = false; deferred_mode_enabled = false; changing_color = false; + presets_enabled = true; + presets_visible = true; screen = NULL; HBoxContainer *hb_smpl = memnew(HBoxContainer); @@ -725,18 +756,19 @@ ColorPicker::ColorPicker() : set_pick_color(Color(1, 1, 1)); - add_child(memnew(HSeparator)); + preset_separator = memnew(HSeparator); + add_child(preset_separator); - HBoxContainer *bbc = memnew(HBoxContainer); - add_child(bbc); + preset_container = memnew(HBoxContainer); + add_child(preset_container); preset = memnew(TextureRect); - bbc->add_child(preset); + preset_container->add_child(preset); preset->connect("gui_input", this, "_preset_input"); preset->connect("draw", this, "_update_presets"); bt_add_preset = memnew(Button); - bbc->add_child(bt_add_preset); + preset_container->add_child(bt_add_preset); bt_add_preset->set_tooltip(TTR("Add current color as a preset.")); bt_add_preset->connect("pressed", this, "_add_preset_pressed"); } diff --git a/scene/gui/color_picker.h b/scene/gui/color_picker.h index b78844839a..b5ddf2d0c2 100644 --- a/scene/gui/color_picker.h +++ b/scene/gui/color_picker.h @@ -37,6 +37,7 @@ #include "scene/gui/label.h" #include "scene/gui/line_edit.h" #include "scene/gui/popup.h" +#include "scene/gui/separator.h" #include "scene/gui/slider.h" #include "scene/gui/spin_box.h" #include "scene/gui/texture_rect.h" @@ -52,6 +53,8 @@ private: Control *w_edit; TextureRect *sample; TextureRect *preset; + HBoxContainer *preset_container; + HSeparator *preset_separator; Button *bt_add_preset; List<Color> presets; ToolButton *btn_pick; @@ -70,6 +73,8 @@ private: bool deferred_mode_enabled; bool updating; bool changing_color; + bool presets_enabled; + bool presets_visible; float h, s, v; Color last_hsv; @@ -114,6 +119,12 @@ public: void set_deferred_mode(bool p_enabled); bool is_deferred_mode() const; + void set_presets_enabled(bool p_enabled); + bool are_presets_enabled() const; + + void set_presets_visible(bool p_visible); + bool are_presets_visible() const; + void set_focus_on_line_edit(); ColorPicker(); diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 026374ded1..f5e979e9e6 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -369,6 +369,7 @@ void ItemList::clear() { update(); shape_changed = true; defer_select_single = -1; + scroll_bar->set_value(0); } void ItemList::set_fixed_column_width(int p_size) { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index ebd4e8094b..fbf6550362 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -5849,6 +5849,7 @@ void TextEdit::_update_completion_candidates() { bool inquote = false; int first_quote = -1; + int restore_quotes = -1; int c = cofs - 1; while (c >= 0) { @@ -5856,6 +5857,11 @@ void TextEdit::_update_completion_candidates() { inquote = !inquote; if (first_quote == -1) first_quote = c; + restore_quotes = 0; + } else if (restore_quotes == 0 && l[c] == '$') { + restore_quotes = 1; + } else if (restore_quotes == 0 && !_is_whitespace(l[c])) { + restore_quotes = -1; } c--; } @@ -5923,6 +5929,11 @@ void TextEdit::_update_completion_candidates() { completion_strings.write[i] = completion_strings[i].unquote().quote("'"); } + if (inquote && restore_quotes == 1 && !completion_strings[i].is_quoted()) { + String quote = single_quote ? "'" : "\""; + completion_strings.write[i] = completion_strings[i].quote(quote); + } + if (completion_strings[i].begins_with(s)) { completion_options.push_back(completion_strings[i]); } else if (completion_strings[i].to_lower().begins_with(s.to_lower())) { diff --git a/thirdparty/README.md b/thirdparty/README.md index e2c2334c0f..b4a9b83331 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -185,18 +185,21 @@ Files extracted from upstream source: ## libsimplewebm - Upstream: https://github.com/zaps166/libsimplewebm -- Version: git (05cfdc2, 2016) -- License: MIT, BSD-3-Clause +- Version: git (fe57fd3, 2019) +- License: MIT (main), BSD-3-Clause (libwebm) + +This contains libwebm, but the version in use is updated from the one used by libsimplewebm, +and may have *unmarked* alterations from that. Files extracted from upstream source: -TODO. +- all the .cpp, .hpp files in the main folder except `example.cpp` +- LICENSE Important: Some files have Godot-made changes. They are marked with `// -- GODOT start --` and `// -- GODOT end --` comments. - ## libtheora - Upstream: https://www.theora.org diff --git a/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp b/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp index c9e71eb733..b5824b17be 100644 --- a/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp +++ b/thirdparty/libsimplewebm/OpusVorbisDecoder.cpp @@ -122,6 +122,7 @@ bool OpusVorbisDecoder::getPCMS16(WebMFrame &frame, short *buffer, int &numOutSa return false; } +// -- GODOT begin -- bool OpusVorbisDecoder::getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples) { if (m_vorbis) { m_vorbis->op.packet = frame.buffer; @@ -158,6 +159,7 @@ bool OpusVorbisDecoder::getPCMF(WebMFrame &frame, float *buffer, int &numOutSamp } return false; } +// -- GODOT end -- bool OpusVorbisDecoder::openVorbis(const WebMDemuxer &demuxer) { diff --git a/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp b/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp index b7619d6a25..f285b3fbd6 100644 --- a/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp +++ b/thirdparty/libsimplewebm/OpusVorbisDecoder.hpp @@ -44,8 +44,10 @@ public: { return m_numSamples; } - bool getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples); bool getPCMS16(WebMFrame &frame, short *buffer, int &numOutSamples); +// -- GODOT begin -- + bool getPCMF(WebMFrame &frame, float *buffer, int &numOutSamples); +// -- GODOT end -- private: bool openVorbis(const WebMDemuxer &demuxer); diff --git a/thirdparty/libsimplewebm/VPXDecoder.cpp b/thirdparty/libsimplewebm/VPXDecoder.cpp index 3f77b8f5cd..e2606f83ba 100644 --- a/thirdparty/libsimplewebm/VPXDecoder.cpp +++ b/thirdparty/libsimplewebm/VPXDecoder.cpp @@ -33,7 +33,8 @@ VPXDecoder::VPXDecoder(const WebMDemuxer &demuxer, unsigned threads) : m_ctx(NULL), m_iter(NULL), - m_delay(0) + m_delay(0), + m_last_space(VPX_CS_UNKNOWN) { if (threads > 8) threads = 8; @@ -86,6 +87,11 @@ VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image) IMAGE_ERROR err = NO_FRAME; if (vpx_image_t *img = vpx_codec_get_frame(m_ctx, &m_iter)) { + // It seems to be a common problem that UNKNOWN comes up a lot, yet FFMPEG is somehow getting accurate colour-space information. + // After checking FFMPEG code, *they're* getting colour-space information, so I'm assuming something like this is going on. + // It appears to work, at least. + if (img->cs != VPX_CS_UNKNOWN) + m_last_space = img->cs; if ((img->fmt & VPX_IMG_FMT_PLANAR) && !(img->fmt & (VPX_IMG_FMT_HAS_ALPHA | VPX_IMG_FMT_HIGHBITDEPTH))) { if (img->stride[0] && img->stride[1] && img->stride[2]) @@ -95,6 +101,7 @@ VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image) image.w = img->d_w; image.h = img->d_h; + image.cs = m_last_space; image.chromaShiftW = img->x_chroma_shift; image.chromaShiftH = img->y_chroma_shift; @@ -119,7 +126,9 @@ VPXDecoder::IMAGE_ERROR VPXDecoder::getImage(Image &image) /**/ +// -- GODOT begin -- #if 0 +// -- GODOT end -- static inline int ceilRshift(int val, int shift) { @@ -139,4 +148,7 @@ int VPXDecoder::Image::getHeight(int plane) const return ceilRshift(h, chromaShiftH); } +// -- GODOT begin -- #endif +// -- GODOT end -- + diff --git a/thirdparty/libsimplewebm/VPXDecoder.hpp b/thirdparty/libsimplewebm/VPXDecoder.hpp index 6108395871..5071b069cb 100644 --- a/thirdparty/libsimplewebm/VPXDecoder.hpp +++ b/thirdparty/libsimplewebm/VPXDecoder.hpp @@ -37,12 +37,17 @@ public: class Image { public: +// -- GODOT begin -- #if 0 +// -- GODOT end -- int getWidth(int plane) const; int getHeight(int plane) const; +// -- GODOT begin -- #endif +// -- GODOT end -- int w, h; + int cs; int chromaShiftW, chromaShiftH; unsigned char *planes[3]; int linesize[3]; @@ -75,6 +80,7 @@ private: vpx_codec_ctx *m_ctx; const void *m_iter; int m_delay; + int m_last_space; }; #endif // VPXDECODER_HPP diff --git a/thirdparty/misc/yuv2rgb.h b/thirdparty/misc/yuv2rgb.h index 3ec8388246..d8f7fd6de2 100644 --- a/thirdparty/misc/yuv2rgb.h +++ b/thirdparty/misc/yuv2rgb.h @@ -24,6 +24,14 @@ does not infringe any patents that apply in your area before you ship it. */ +/* + * Please note that this version has been modified for various reasons: + * 1. Using the Godot core typedefs + * 2. At some point or another the code relied on the byte order of a uint32_t, this has been fixed + * 3. Output has been reordered to struct { uint8_t r, g, b, a; } precisely in accordance with the function names + * 4. Removing unused 'dither' parameter + */ + #ifndef YUV2RGB_H #define YUV2RGB_H @@ -803,6 +811,8 @@ static const uint32_t tables[256*3] = { 0xE6365800U }; +/* -- Common -- */ + #define FLAGS 0x40080100 #define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)]) #define READY(Y) tables[Y] @@ -820,12 +830,14 @@ do { \ #define STORE(Y,DSTPTR) \ do { \ - *(DSTPTR)++ = (Y); \ - *(DSTPTR)++ = (Y)>>22; \ *(DSTPTR)++ = (Y)>>11; \ - *(DSTPTR)++ = 255; \ + *(DSTPTR)++ = (Y)>>22; \ + *(DSTPTR)++ = (Y); \ + *(DSTPTR)++ = 255; \ } while (0 == 1) +/* -- End Common -- */ + static void yuv422_2_rgb8888(uint8_t *dst_ptr, const uint8_t *y_ptr, const uint8_t *u_ptr, @@ -834,8 +846,7 @@ static void yuv422_2_rgb8888(uint8_t *dst_ptr, int32_t height, int32_t y_span, int32_t uv_span, - int32_t dst_span, - int32_t dither) + int32_t dst_span) { height -= 1; while (height > 0) @@ -909,35 +920,7 @@ static void yuv422_2_rgb8888(uint8_t *dst_ptr, } } - -#undef FLAGS -#undef READUV -#undef READY -#undef FIXUP -#undef STORE - - -#define FLAGS 0x40080100 -#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)]) -#define READY(Y) tables[Y] -#define FIXUP(Y) \ -do { \ - int tmp = (Y) & FLAGS; \ - if (tmp != 0) \ - { \ - tmp -= tmp>>8; \ - (Y) |= tmp; \ - tmp = FLAGS & ~(Y>>1); \ - (Y) += tmp>>8; \ - } \ -} while (0 == 1) - -#define STORE(Y,DSTPTR) \ -do { \ - (DSTPTR) = 0xFF000000 | (Y & 0xFF) | (0xFF00 & (Y>>14)) | (0xFF0000 & (Y<<5));\ -} while (0 == 1) - -static void yuv420_2_rgb8888(uint8_t *dst_ptr_, +static void yuv420_2_rgb8888(uint8_t *dst_ptr, const uint8_t *y_ptr, const uint8_t *u_ptr, const uint8_t *v_ptr, @@ -945,12 +928,9 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_, int32_t height, int32_t y_span, int32_t uv_span, - int32_t dst_span, - int32_t dither) + int32_t dst_span) { - uint32_t *dst_ptr = (uint32_t *)(void *)dst_ptr_; - dst_span >>= 2; - + /* The 'dst_ptr as uint32_t' thing is not endianness-aware, so that's been removed. */ height -= 1; while (height > 0) { @@ -960,36 +940,38 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_, { /* Do 2 column pairs */ uint32_t uv, y0, y1; + uint8_t * dst_ptr_1span = dst_ptr + dst_span; uv = READUV(*u_ptr++,*v_ptr++); y1 = uv + READY(y_ptr[y_span]); y0 = uv + READY(*y_ptr++); FIXUP(y1); FIXUP(y0); - STORE(y1, dst_ptr[dst_span]); - STORE(y0, *dst_ptr++); + STORE(y1, dst_ptr_1span); + STORE(y0, dst_ptr); y1 = uv + READY(y_ptr[y_span]); y0 = uv + READY(*y_ptr++); FIXUP(y1); FIXUP(y0); - STORE(y1, dst_ptr[dst_span]); - STORE(y0, *dst_ptr++); + STORE(y1, dst_ptr_1span); + STORE(y0, dst_ptr); height += (2<<16); } if ((height>>16) == 0) { /* Trailing column pair */ uint32_t uv, y0, y1; + uint8_t * dst_ptr_1span = dst_ptr + dst_span; uv = READUV(*u_ptr,*v_ptr); y1 = uv + READY(y_ptr[y_span]); y0 = uv + READY(*y_ptr++); FIXUP(y1); FIXUP(y0); - STORE(y0, dst_ptr[dst_span]); - STORE(y1, *dst_ptr++); + STORE(y0, dst_ptr_1span); + STORE(y1, dst_ptr); } - dst_ptr += dst_span*2-width; + dst_ptr += (dst_span * 2) - (width * 4); y_ptr += y_span*2-width; u_ptr += uv_span-(width>>1); v_ptr += uv_span-(width>>1); @@ -1011,8 +993,8 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_, y0 = uv + READY(*y_ptr++); FIXUP(y1); FIXUP(y0); - STORE(y1, *dst_ptr++); - STORE(y0, *dst_ptr++); + STORE(y1, dst_ptr); + STORE(y0, dst_ptr); height += (2<<16); } if ((height>>16) == 0) @@ -1023,42 +1005,11 @@ static void yuv420_2_rgb8888(uint8_t *dst_ptr_, uv = READUV(*u_ptr++,*v_ptr++); y0 = uv + READY(*y_ptr++); FIXUP(y0); - STORE(y0, *dst_ptr++); + STORE(y0, dst_ptr); } } } - - -#undef FLAGS -#undef READUV -#undef READY -#undef FIXUP -#undef STORE - -#define FLAGS 0x40080100 -#define READUV(U,V) (tables[256 + (U)] + tables[512 + (V)]) -#define READY(Y) tables[Y] -#define FIXUP(Y) \ -do { \ - int tmp = (Y) & FLAGS; \ - if (tmp != 0) \ - { \ - tmp -= tmp>>8; \ - (Y) |= tmp; \ - tmp = FLAGS & ~(Y>>1); \ - (Y) += tmp>>8; \ - } \ -} while (0 == 1) - -#define STORE(Y,DSTPTR) \ -do { \ - *(DSTPTR)++ = (Y); \ - *(DSTPTR)++ = (Y)>>22; \ - *(DSTPTR)++ = (Y)>>11; \ - *(DSTPTR)++ = 255; \ -} while (0 == 1) - static void yuv444_2_rgb8888(uint8_t *dst_ptr, const uint8_t *y_ptr, const uint8_t *u_ptr, @@ -1067,8 +1018,7 @@ static void yuv444_2_rgb8888(uint8_t *dst_ptr, int32_t height, int32_t y_span, int32_t uv_span, - int32_t dst_span, - int32_t dither) + int32_t dst_span) { height -= 1; while (height > 0) @@ -1143,4 +1093,11 @@ static void yuv444_2_rgb8888(uint8_t *dst_ptr, height -= 1; } } + +#undef FLAGS +#undef READUV +#undef READY +#undef FIXUP +#undef STORE + #endif // YUV2RGB_H |