diff options
59 files changed, 434 insertions, 161 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 32b94b9b02..8f1a57e363 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -264,6 +264,10 @@ Size2 _OS::get_window_size() const { return OS::get_singleton()->get_window_size(); } +Size2 _OS::get_real_window_size() const { + return OS::get_singleton()->get_real_window_size(); +} + void _OS::set_window_size(const Size2 &p_size) { OS::get_singleton()->set_window_size(p_size); } @@ -929,6 +933,11 @@ void _OS::request_attention() { OS::get_singleton()->request_attention(); } +void _OS::center_window() { + + OS::get_singleton()->center_window(); +} + bool _OS::is_debug_build() const { #ifdef DEBUG_ENABLED @@ -1017,6 +1026,8 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("set_window_maximized", "enabled"), &_OS::set_window_maximized); ClassDB::bind_method(D_METHOD("is_window_maximized"), &_OS::is_window_maximized); ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention); + ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size); + ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window); ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window); ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 2353b6d09f..6b688a65f8 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -155,6 +155,7 @@ public: virtual Point2 get_window_position() const; virtual void set_window_position(const Point2 &p_position); virtual Size2 get_window_size() const; + virtual Size2 get_real_window_size() const; virtual void set_window_size(const Size2 &p_size); virtual void set_window_fullscreen(bool p_enabled); virtual bool is_window_fullscreen() const; @@ -165,6 +166,7 @@ public: virtual void set_window_maximized(bool p_enabled); virtual bool is_window_maximized() const; virtual void request_attention(); + virtual void center_window(); virtual void set_borderless_window(bool p_borderless); virtual bool get_borderless_window() const; diff --git a/core/os/os.cpp b/core/os/os.cpp index c6e5de703c..422acf95dc 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -616,6 +616,17 @@ bool OS::has_feature(const String &p_feature) { return false; } +void OS::center_window() { + + if (is_window_fullscreen()) return; + + Size2 scr = get_screen_size(get_current_screen()); + Size2 wnd = get_real_window_size(); + int x = scr.width / 2 - wnd.width / 2; + int y = scr.height / 2 - wnd.height / 2; + set_window_position(Vector2(x, y)); +} + OS::OS() { void *volatile stack_bottom; diff --git a/core/os/os.h b/core/os/os.h index 248e1dbefa..1ec488df06 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -182,6 +182,7 @@ public: virtual Point2 get_window_position() const { return Vector2(); } virtual void set_window_position(const Point2 &p_position) {} virtual Size2 get_window_size() const = 0; + virtual Size2 get_real_window_size() const { return get_window_size(); } virtual void set_window_size(const Size2 p_size) {} virtual void set_window_fullscreen(bool p_enabled) {} virtual bool is_window_fullscreen() const { return true; } @@ -192,6 +193,7 @@ public: virtual void set_window_maximized(bool p_enabled) {} virtual bool is_window_maximized() const { return true; } virtual void request_attention() {} + virtual void center_window(); virtual void set_borderless_window(bool p_borderless) {} virtual bool get_borderless_window() { return 0; } diff --git a/doc/classes/@GDScript.xml b/doc/classes/@GDScript.xml index d4bd937f49..4e9a6a5fc0 100644 --- a/doc/classes/@GDScript.xml +++ b/doc/classes/@GDScript.xml @@ -608,6 +608,7 @@ <description> Parse JSON text to a Variant (use [method typeof] to check if it is what you expect). Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to [float] types. + Note that JSON objects do not preserve key order like Godot dictionaries, thus you should not rely on keys being in a certain order if a dictionary is constructed from JSON. In contrast, JSON arrays retain the order of their elements: [codeblock] p = parse_json('["a", "b", "c"]') if typeof(p) == TYPE_ARRAY: diff --git a/doc/classes/EditorPlugin.xml b/doc/classes/EditorPlugin.xml index 8f4784334d..b3aca798a4 100644 --- a/doc/classes/EditorPlugin.xml +++ b/doc/classes/EditorPlugin.xml @@ -274,6 +274,17 @@ Remove the control from the bottom panel. Don't forget to call this if you added one, so the editor can remove it cleanly. </description> </method> + <method name="remove_control_from_container"> + <return type="void"> + </return> + <argument index="0" name="container" type="int" enum="EditorPlugin.CustomControlContainer"> + </argument> + <argument index="1" name="control" type="Control"> + </argument> + <description> + Remove the control from the specified container. Use it when cleaning up after adding a control with [method add_control_to_container]. Note that you can simply free the control if you won't use it anymore. + </description> + </method> <method name="remove_control_from_docks"> <return type="void"> </return> diff --git a/doc/classes/JSON.xml b/doc/classes/JSON.xml index e69c05c3df..078c293fc0 100644 --- a/doc/classes/JSON.xml +++ b/doc/classes/JSON.xml @@ -4,7 +4,7 @@ Helper class for parsing JSON data. </brief_description> <description> - Helper class for parsing JSON data. For usage example, see [JSONParseResult]. + Helper class for parsing JSON data. For usage example and other important hints, see [JSONParseResult]. </description> <tutorials> </tutorials> diff --git a/doc/classes/JSONParseResult.xml b/doc/classes/JSONParseResult.xml index 424720a871..18313beaf8 100644 --- a/doc/classes/JSONParseResult.xml +++ b/doc/classes/JSONParseResult.xml @@ -4,7 +4,7 @@ Data class wrapper for decoded JSON. </brief_description> <description> - Returned by [method JSON.parse], [code]JSONParseResult[/code] contains decoded JSON or error information if JSON source not successfully parsed. You can check if JSON source was successfully parsed with [code]if json_result.error == 0[/code]. + Returned by [method JSON.parse], [code]JSONParseResult[/code] contains decoded JSON or error information if JSON source not successfully parsed. You can check if JSON source was successfully parsed with [code]if json_result.error == OK[/code]. </description> <tutorials> </tutorials> @@ -24,11 +24,12 @@ </member> <member name="result" type="Variant" setter="set_result" getter="get_result"> A [Variant] containing the parsed JSON. Use typeof() to check if it is what you expect. For example, if JSON source starts with curly braces ([code]{}[/code]) a [Dictionary] will be returned, if JSON source starts with braces ([code][][/code]) an [Array] will be returned. - [i]Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to float types.[/i] + [i]Be aware that the JSON specification does not define integer or float types, but only a number type. Therefore, parsing a JSON text will convert all numerical values to float types. + Note that JSON objects do not preserve key order like Godot dictionaries, thus you should not rely on keys being in a certain order if a dictionary is constructed from JSON. In contrast, JSON arrays retain the order of their elements:[/i] [codeblock] - p = JSON.parse('["hello", "world", "!"]') - if typeof(p) == TYPE_ARRAY: - print(p[0]) # prints 'hello' + var p = JSON.parse('["hello", "world", "!"]') + if typeof(p.result) == TYPE_ARRAY: + print(p.result[0]) # prints 'hello' else: print("unexpected results") [/codeblock] diff --git a/editor/animation_editor.cpp b/editor/animation_editor.cpp index 91aa189c8f..cd8233e460 100644 --- a/editor/animation_editor.cpp +++ b/editor/animation_editor.cpp @@ -1359,7 +1359,7 @@ void AnimationKeyEditor::_track_editor_draw() { Color ncol = color; if (n && editor_selection->is_selected(n)) ncol = track_select_color; - te->draw_string(font, Point2(ofs + Point2(left_check_ofs + sep + type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (type_icon[0]->get_width() + sep) - 5); + te->draw_string(font, Point2(ofs + Point2(left_check_ofs + sep + type_icon[0]->get_width() + sep, y + font->get_ascent() + (sep / 2))).floor(), np, ncol, name_limit - (left_check_ofs + sep) - (type_icon[0]->get_width() + sep) - 5); // Draw separator line below track area if (!obj) diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 98991cd7c0..bec6d581f8 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -339,7 +339,7 @@ void EditorNode::_notification(int p_what) { if (ScriptEditor::get_singleton()->get_debugger()->is_visible()) bottom_panel->add_style_override("panel", gui_base->get_stylebox("BottomPanelDebuggerOverride", "EditorStyles")); - //_update_icons + // update_icons for (int i = 0; i < singleton->main_editor_buttons.size(); i++) { Ref<Texture> icon = singleton->main_editor_buttons[i]->get_icon(); @@ -709,7 +709,7 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) { case ERR_CANT_OPEN: { - accept->set_text(vformat(TTR("Can't open '%s'."), p_file.get_file())); + accept->set_text(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_file.get_file())); } break; case ERR_PARSE_ERROR: { @@ -1110,7 +1110,7 @@ void EditorNode::_dialog_action(String p_file) { if (res.is_null()) { current_option = -1; - accept->get_ok()->set_text("ok :("); + accept->get_ok()->set_text("Ugh"); accept->set_text(TTR("Failed to load resource.")); return; }; @@ -1145,6 +1145,7 @@ void EditorNode::_dialog_action(String p_file) { _save_default_environment(); _save_scene_with_preview(p_file, scene_idx); + _add_to_recent_scenes(p_file); if (scene_idx != -1) _discard_changes(); @@ -1919,7 +1920,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!scene) { current_option = -1; - //confirmation->get_cancel()->hide(); accept->get_ok()->set_text(TTR("I see..")); accept->set_text(TTR("This operation can't be done without a tree root.")); accept->popup_centered_minsize(); @@ -1937,7 +1937,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { file->add_filter("*." + extensions[i] + " ; " + extensions[i].to_upper()); } - //file->set_current_path(current_path); if (scene->get_filename() != "") { file->set_current_path(scene->get_filename()); if (extensions.size()) { @@ -1987,7 +1986,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!editor_data.get_edited_scene_root()) { current_option = -1; - //confirmation->get_cancel()->hide(); accept->get_ok()->set_text(TTR("I see..")); accept->set_text(TTR("This operation can't be done without a scene.")); accept->popup_centered_minsize(); @@ -2036,8 +2034,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case FILE_IMPORT_SUBSCENE: { - //import_subscene->popup_centered_ratio(); - if (!editor_data.get_edited_scene_root()) { current_option = -1; @@ -2056,7 +2052,6 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (unsaved_cache && !p_confirmed) { confirmation->get_ok()->set_text(TTR("Open")); - //confirmation->get_cancel()->show(); confirmation->set_text(TTR("Current scene not saved. Open anyway?")); confirmation->popup_centered_minsize(); break; @@ -2843,7 +2838,7 @@ void EditorNode::_remove_scene(int index) { //Scene to remove is current scene _remove_edited_scene(); } else { - // Scene to remove is not active scene + //Scene to remove is not active scene editor_data.remove_scene(index); } } @@ -3240,48 +3235,47 @@ void EditorNode::_show_messages() { void EditorNode::_add_to_recent_scenes(const String &p_scene) { - String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::"); - Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array()); - String name = p_scene; - name = name.replace("res://", ""); - if (rc.find(name) != -1) - rc.erase(name); - rc.insert(0, name); + Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array()); + if (rc.find(p_scene) != -1) + rc.erase(p_scene); + rc.push_front(p_scene); if (rc.size() > 10) rc.resize(10); - EditorSettings::get_singleton()->set(base + "/_recent_scenes", rc); - EditorSettings::get_singleton()->save(); + EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", rc); _update_recent_scenes(); } void EditorNode::_open_recent_scene(int p_idx) { - String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::"); - if (p_idx == recent_scenes->get_item_count() - 1) { - EditorSettings::get_singleton()->erase(base + "/_recent_scenes"); + EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", Array()); call_deferred("_update_recent_scenes"); } else { - Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array()); + Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array()); ERR_FAIL_INDEX(p_idx, rc.size()); - String path = "res://" + rc[p_idx]; - load_scene(path); + if (load_scene(rc[p_idx]) != OK) { + + rc.remove(p_idx); + EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", rc); + _update_recent_scenes(); + } } } void EditorNode::_update_recent_scenes() { - String base = "_" + ProjectSettings::get_singleton()->get_resource_path().replace("\\", "::").replace("/", "::"); - Vector<String> rc = EDITOR_DEF(base + "/_recent_scenes", Array()); + Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array()); recent_scenes->clear(); + String path; for (int i = 0; i < rc.size(); i++) { - recent_scenes->add_item(rc[i], i); + path = rc[i]; + recent_scenes->add_item(path.replace("res://", ""), i); } recent_scenes->add_separator(); @@ -5118,7 +5112,6 @@ EditorNode::EditorNode() { gui_base->add_child(dependency_fixer); settings_config_dialog = memnew(EditorSettingsDialog); - // settings_config_dialog->add_style_override("panel", gui_base->get_stylebox("EditorSettingsDialog", "EditorStyles")); gui_base->add_child(settings_config_dialog); project_settings = memnew(ProjectSettingsEditor(&editor_data)); @@ -5192,7 +5185,6 @@ EditorNode::EditorNode() { p->add_item(TTR("Project Settings"), RUN_SETTINGS); p->add_separator(); p->connect("id_pressed", this, "_menu_option"); - //p->add_item(TTR("Run Script"), FILE_RUN_SCRIPT, KEY_MASK_SHIFT + KEY_MASK_CMD + KEY_R); p->add_item(TTR("Export"), FILE_EXPORT_PROJECT); PopupMenu *tool_menu = memnew(PopupMenu); @@ -5283,7 +5275,6 @@ EditorNode::EditorNode() { menu_hb->add_child(play_cc); play_button_panel = memnew(PanelContainer); - // play_button_panel->add_style_override("panel", gui_base->get_stylebox("PlayButtonPanel", "EditorStyles")); play_cc->add_child(play_button_panel); HBoxContainer *play_hb = memnew(HBoxContainer); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index b1a0efaea6..733680645f 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -373,6 +373,53 @@ void EditorPlugin::add_control_to_container(CustomControlContainer p_location, C } } +void EditorPlugin::remove_control_from_container(CustomControlContainer p_location, Control *p_control) { + + switch (p_location) { + + case CONTAINER_TOOLBAR: { + + EditorNode::get_menu_hb()->remove_child(p_control); + } break; + + case CONTAINER_SPATIAL_EDITOR_MENU: { + + SpatialEditor::get_singleton()->remove_control_from_menu_panel(p_control); + + } break; + case CONTAINER_SPATIAL_EDITOR_SIDE: { + + SpatialEditor::get_singleton()->get_palette_split()->remove_child(p_control); + + } break; + case CONTAINER_SPATIAL_EDITOR_BOTTOM: { + + SpatialEditor::get_singleton()->get_shader_split()->remove_child(p_control); + + } break; + case CONTAINER_CANVAS_EDITOR_MENU: { + + CanvasItemEditor::get_singleton()->remove_control_from_menu_panel(p_control); + + } break; + case CONTAINER_CANVAS_EDITOR_SIDE: { + + CanvasItemEditor::get_singleton()->get_palette_split()->remove_child(p_control); + + } break; + case CONTAINER_CANVAS_EDITOR_BOTTOM: { + + CanvasItemEditor::get_singleton()->get_bottom_split()->remove_child(p_control); + + } break; + case CONTAINER_PROPERTY_EDITOR_BOTTOM: { + + EditorNode::get_singleton()->get_property_editor_vb()->remove_child(p_control); + + } break; + } +} + void EditorPlugin::add_tool_menu_item(const String &p_name, Object *p_handler, const String &p_callback, const Variant &p_ud) { //EditorNode::get_singleton()->add_tool_menu_item(p_name, p_handler, p_callback, p_ud); @@ -651,6 +698,7 @@ void EditorPlugin::_bind_methods() { ClassDB::bind_method(D_METHOD("add_control_to_dock", "slot", "control"), &EditorPlugin::add_control_to_dock); ClassDB::bind_method(D_METHOD("remove_control_from_docks", "control"), &EditorPlugin::remove_control_from_docks); ClassDB::bind_method(D_METHOD("remove_control_from_bottom_panel", "control"), &EditorPlugin::remove_control_from_bottom_panel); + ClassDB::bind_method(D_METHOD("remove_control_from_container", "container", "control"), &EditorPlugin::remove_control_from_container); //ClassDB::bind_method(D_METHOD("add_tool_menu_item", "name", "handler", "callback", "ud"),&EditorPlugin::add_tool_menu_item,DEFVAL(Variant())); ClassDB::bind_method(D_METHOD("add_tool_submenu_item", "name", "submenu"), &EditorPlugin::add_tool_submenu_item); //ClassDB::bind_method(D_METHOD("remove_tool_menu_item", "name"),&EditorPlugin::remove_tool_menu_item); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 3d585120c0..e3e405479c 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -148,6 +148,7 @@ public: //TODO: send a resource for editing to the editor node? void add_control_to_container(CustomControlContainer p_location, Control *p_control); + void remove_control_from_container(CustomControlContainer p_location, Control *p_control); ToolButton *add_control_to_bottom_panel(Control *p_control, const String &p_title); void add_control_to_dock(DockSlot p_slot, Control *p_control); void remove_control_from_docks(Control *p_control); diff --git a/editor/editor_plugin_settings.cpp b/editor/editor_plugin_settings.cpp index 8803a03f2d..ea1e0fe99e 100644 --- a/editor/editor_plugin_settings.cpp +++ b/editor/editor_plugin_settings.cpp @@ -83,8 +83,6 @@ void EditorPluginSettings::update_plugins() { plugins.sort(); - Vector<String> active_plugins = ProjectSettings::get_singleton()->get("editor_plugins/enabled"); - for (int i = 0; i < plugins.size(); i++) { Ref<ConfigFile> cf; diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 433f501fc8..c6676a1f0f 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -382,8 +382,6 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { _initial_set("text_editor/completion/callhint_tooltip_offset", Vector2()); _initial_set("text_editor/files/restore_scripts_on_load", true); _initial_set("text_editor/completion/complete_file_paths", true); - _initial_set("text_editor/files/maximum_recent_files", 20); - hints["text_editor/files/maximum_recent_files"] = PropertyInfo(Variant::INT, "text_editor/files/maximum_recent_files", PROPERTY_HINT_RANGE, "1, 200, 1"); _initial_set("docks/scene_tree/start_create_dialog_fully_expanded", false); _initial_set("docks/scene_tree/draw_relationship_lines", false); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 915132c75c..b8bf2b97f6 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -316,7 +316,6 @@ EditorAssetLibraryItemDescription::EditorAssetLibraryItemDescription() { void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int p_code, const PoolStringArray &headers, const PoolByteArray &p_data) { String error_text; - print_line("COMPLETED: " + itos(p_status) + " code: " + itos(p_code) + " data size: " + itos(p_data.size())); switch (p_status) { @@ -371,7 +370,6 @@ void EditorAssetLibraryItemDownload::_http_download_completed(int p_status, int progress->set_max(download->get_body_size()); progress->set_value(download->get_downloaded_bytes()); - print_line("max: " + itos(download->get_body_size()) + " bytes: " + itos(download->get_downloaded_bytes())); install->set_disabled(false); progress->set_value(download->get_downloaded_bytes()); @@ -747,8 +745,6 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons if (p_status == HTTPRequest::RESULT_SUCCESS) { - print_line("GOT IMAGE YAY!"); - if (p_code != HTTPClient::RESPONSE_NOT_MODIFIED) { for (int i = 0; i < headers.size(); i++) { if (headers[i].findn("ETag:") == 0) { // Save etag @@ -811,7 +807,6 @@ void EditorAssetLibrary::_update_image_queue() { } } - print_line("REQUEST ICON FOR: " + itos(E->get().asset_id)); Error err = E->get().request->request(E->get().image_url, headers); if (err != OK) { to_delete.push_back(E->key()); @@ -855,7 +850,6 @@ void EditorAssetLibrary::_request_image(ObjectID p_for, String p_image_url, Imag void EditorAssetLibrary::_repository_changed(int p_repository_id) { host = repository->get_item_metadata(p_repository_id); - print_line(".." + host); if (templates_only) { _api_request("configure", REQUESTING_CONFIG, "?type=project"); } else { @@ -1066,8 +1060,6 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const return; } - print_line("response: " + itos(p_status) + " code: " + itos(p_code)); - Dictionary d; { Variant js; @@ -1077,8 +1069,6 @@ void EditorAssetLibrary::_http_request_completed(int p_status, int p_code, const d = js; } - print_line(Variant(d).get_construct_string()); - RequestType requested = requesting; requesting = REQUESTING_NONE; diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 7d6025cb03..4a05d401cb 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -4002,6 +4002,11 @@ void CanvasItemEditor::add_control_to_menu_panel(Control *p_control) { hb->add_child(p_control); } +void CanvasItemEditor::remove_control_from_menu_panel(Control *p_control) { + + hb->remove_child(p_control); +} + HSplitContainer *CanvasItemEditor::get_palette_split() { return palette_split; @@ -4225,9 +4230,9 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { p = view_menu->get_popup(); p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_grid", TTR("Show Grid"), KEY_G), SHOW_GRID); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show helpers"), KEY_H), SHOW_HELPERS); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show rulers"), KEY_R), SHOW_RULERS); - p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show guides"), KEY_Y), SHOW_GUIDES); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_helpers", TTR("Show Helpers"), KEY_H), SHOW_HELPERS); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_rulers", TTR("Show Rulers"), KEY_R), SHOW_RULERS); + p->add_check_shortcut(ED_SHORTCUT("canvas_item_editor/show_guides", TTR("Show Guides"), KEY_Y), SHOW_GUIDES); p->add_separator(); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/center_selection", TTR("Center Selection"), KEY_F), VIEW_CENTER_TO_SELECTION); p->add_shortcut(ED_SHORTCUT("canvas_item_editor/frame_selection", TTR("Frame Selection"), KEY_MASK_SHIFT | KEY_F), VIEW_FRAME_TO_SELECTION); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index ace87f9fe2..ee9be86cce 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -509,6 +509,7 @@ public: void set_state(const Dictionary &p_state); void add_control_to_menu_panel(Control *p_control); + void remove_control_from_menu_panel(Control *p_control); HSplitContainer *get_palette_split(); VSplitContainer *get_bottom_split(); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index d18422c0c0..d7331d4f77 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -429,36 +429,32 @@ void ScriptEditor::_add_recent_script(String p_path) { return; } - // remove if already stored - int already_recent = previous_scripts.find(p_path); - if (already_recent >= 0) { - previous_scripts.remove(already_recent); + Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scripts", Array()); + if (rc.find(p_path) != -1) { + rc.erase(p_path); + } + rc.push_front(p_path); + if (rc.size() > 10) { + rc.resize(10); } - // add to list - previous_scripts.insert(0, p_path); - + EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", rc); _update_recent_scripts(); } void ScriptEditor::_update_recent_scripts() { - // make sure we don't exceed max size - const int max_history = EDITOR_DEF("text_editor/files/maximum_recent_files", 20); - if (previous_scripts.size() > max_history) { - previous_scripts.resize(max_history); - } - + Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scripts", Array()); recent_scripts->clear(); recent_scripts->add_shortcut(ED_SHORTCUT("script_editor/open_recent", TTR("Open Recent"), KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_T)); recent_scripts->add_separator(); - const int max_shown = 8; - for (int i = 0; i < previous_scripts.size() && i <= max_shown; i++) { - String path = previous_scripts.get(i); - // just show script name and last dir - recent_scripts->add_item(path.get_slice("/", path.get_slice_count("/") - 2) + "/" + path.get_file()); + String path; + for (int i = 0; i < rc.size(); i++) { + + path = rc[i]; + recent_scripts->add_item(path.replace("res://", "")); } recent_scripts->add_separator(); @@ -471,7 +467,7 @@ void ScriptEditor::_open_recent_script(int p_idx) { // clear button if (p_idx == recent_scripts->get_item_count() - 1) { - previous_scripts.clear(); + EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", Array()); call_deferred("_update_recent_scripts"); return; } @@ -481,22 +477,34 @@ void ScriptEditor::_open_recent_script(int p_idx) { p_idx -= 2; } - if (p_idx < previous_scripts.size() && p_idx >= 0) { + Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scripts", Array()); + ERR_FAIL_INDEX(p_idx, rc.size()); - String path = previous_scripts.get(p_idx); - // if its not on disk its a help file or deleted - if (FileAccess::exists(path)) { - Ref<Script> script = ResourceLoader::load(path); - if (script.is_valid()) { - edit(script, true); - } - // if it's a path then its most likely a delted file not help - } else if (!path.is_resource_file()) { - _help_class_open(path); + String path = rc[p_idx]; + // if its not on disk its a help file or deleted + if (FileAccess::exists(path)) { + Ref<Script> script = ResourceLoader::load(path); + if (script.is_valid()) { + edit(script, true); + return; } - previous_scripts.remove(p_idx); - _update_recent_scripts(); + + // if it's a path then its most likely a deleted file not help + } else if (!path.is_resource_file()) { + _help_class_open(path); + return; } + + rc.remove(p_idx); + EditorSettings::get_singleton()->set_project_metadata("recent_files", "scripts", rc); + _update_recent_scripts(); + _show_error_dialog(path); +} + +void ScriptEditor::_show_error_dialog(String p_path) { + + error_dialog->set_text(vformat(TTR("Can't open '%s'. The file could have been moved or deleted."), p_path)); + error_dialog->popup_centered_minsize(); } void ScriptEditor::_close_tab(int p_idx, bool p_save) { @@ -508,14 +516,10 @@ void ScriptEditor::_close_tab(int p_idx, bool p_save) { Node *tselected = tab_container->get_child(selected); ScriptEditorBase *current = Object::cast_to<ScriptEditorBase>(tab_container->get_child(selected)); if (current) { - _add_recent_script(current->get_edited_script()->get_path()); if (p_save) { apply_scripts(); } notify_script_close(current->get_edited_script()); - } else { - EditorHelp *help = Object::cast_to<EditorHelp>(tab_container->get_child(selected)); - _add_recent_script(help->get_class()); } // roll back to previous tab @@ -1328,11 +1332,12 @@ void ScriptEditor::_members_overview_selected(int p_idx) { if (!se) { return; } - // Go to the member's line and reset the cursor column. We can't just change scroll_position - // directly, since code might be folded. + // Go to the member's line and reset the cursor column. We can't change scroll_position + // directly until we have gone to the line first, since code might be folded. se->goto_line(members_overview->get_item_metadata(p_idx)); Dictionary state = se->get_edit_state(); state["column"] = 0; + state["scroll_position"] = members_overview->get_item_metadata(p_idx); se->set_edit_state(state); } @@ -1690,28 +1695,42 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool String path = EditorSettings::get_singleton()->get("text_editor/external/exec_path"); String flags = EditorSettings::get_singleton()->get("text_editor/external/exec_flags"); - Dictionary keys; - keys["project"] = ProjectSettings::get_singleton()->get_resource_path(); - keys["file"] = ProjectSettings::get_singleton()->globalize_path(p_script->get_path()); - keys["line"] = p_line >= 0 ? p_line : 0; - keys["col"] = p_col; - - flags = flags.format(keys).strip_edges().replace("\\\\", "\\"); - List<String> args; if (flags.size()) { - int from = 0, to = 0; + String project_path = ProjectSettings::get_singleton()->get_resource_path(); + String script_path = ProjectSettings::get_singleton()->globalize_path(p_script->get_path()); + + flags = flags.replacen("{line}", itos(p_line > 0 ? p_line : 0)); + flags = flags.replacen("{col}", itos(p_col)); + flags = flags.strip_edges().replace("\\\\", "\\"); + + int from = 0; + int num_chars = 0; bool inside_quotes = false; + for (int i = 0; i < flags.size(); i++) { + if (flags[i] == '"' && (!i || flags[i - 1] != '\\')) { + + if (!inside_quotes) { + from++; + } inside_quotes = !inside_quotes; + } else if (flags[i] == '\0' || (!inside_quotes && flags[i] == ' ')) { - args.push_back(flags.substr(from, to)); + + String arg = flags.substr(from, num_chars); + + // do path replacement here, else there will be issues with spaces and quotes + arg = arg.replacen("{project}", project_path); + arg = arg.replacen("{file}", script_path); + args.push_back(arg); + from = i + 1; - to = 0; + num_chars = 0; } else { - to++; + num_chars++; } } } @@ -1787,6 +1806,7 @@ bool ScriptEditor::edit(const Ref<Script> &p_script, int p_line, int p_col, bool se->goto_line(p_line - 1); notify_script_changed(p_script); + _add_recent_script(p_script->get_path()); return true; } @@ -2304,6 +2324,7 @@ void ScriptEditor::_help_class_open(const String &p_class) { _go_to_tab(tab_container->get_tab_count() - 1); eh->go_to_class(p_class, 0); eh->connect("go_to_help", this, "_help_class_goto"); + _add_recent_script(p_class); _update_script_names(); _save_layout(); } @@ -2332,6 +2353,7 @@ void ScriptEditor::_help_class_goto(const String &p_desc) { _go_to_tab(tab_container->get_tab_count() - 1); eh->go_to_help(p_desc); eh->connect("go_to_help", this, "_help_class_goto"); + _add_recent_script(eh->get_class()); _update_script_names(); _save_layout(); } @@ -2738,6 +2760,10 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { add_child(file_dialog); file_dialog->connect("file_selected", this, "_file_dialog_action"); + error_dialog = memnew(AcceptDialog); + add_child(error_dialog); + error_dialog->get_ok()->set_text(TTR("I see..")); + debugger = memnew(ScriptEditorDebugger(editor)); debugger->connect("goto_script_line", this, "_goto_script_line"); debugger->connect("show_debugger", this, "_show_debugger"); diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index e60e4cf8c0..e98a4c97a6 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -198,6 +198,7 @@ class ScriptEditor : public PanelContainer { VSplitContainer *list_split; TabContainer *tab_container; EditorFileDialog *file_dialog; + AcceptDialog *error_dialog; ConfirmationDialog *erase_tab_confirm; ScriptCreateDialog *script_create_dialog; ScriptEditorDebugger *debugger; @@ -227,8 +228,6 @@ class ScriptEditor : public PanelContainer { Vector<ScriptHistory> history; int history_pos; - Vector<String> previous_scripts; - EditorHelpIndex *help_index; void _tab_changed(int p_which); @@ -250,6 +249,8 @@ class ScriptEditor : public PanelContainer { void _update_recent_scripts(); void _open_recent_script(int p_idx); + void _show_error_dialog(String p_path); + void _close_tab(int p_idx, bool p_save = true); void _close_current_tab(); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index a3728a1d46..87e92f0807 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -519,6 +519,7 @@ void ScriptTextEditor::tag_saved_version() { void ScriptTextEditor::goto_line(int p_line, bool p_with_error) { TextEdit *tx = code_editor->get_text_edit(); + tx->deselect(); tx->unfold_line(p_line); tx->call_deferred("cursor_set_line", p_line); } @@ -1283,12 +1284,9 @@ Variant ScriptTextEditor::get_drag_data_fw(const Point2 &p_point, Control *p_fro bool ScriptTextEditor::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { Dictionary d = p_data; - if (d.has("type") && - ( - - String(d["type"]) == "resource" || - String(d["type"]) == "files" || - String(d["type"]) == "nodes")) { + if (d.has("type") && (String(d["type"]) == "resource" || + String(d["type"]) == "files" || + String(d["type"]) == "nodes")) { return true; } @@ -1329,6 +1327,10 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data Dictionary d = p_data; + TextEdit *te = code_editor->get_text_edit(); + int row, col; + te->_get_mouse_pos(p_point, row, col); + if (d.has("type") && String(d["type"]) == "resource") { Ref<Resource> res = d["resource"]; @@ -1341,7 +1343,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data return; } - code_editor->get_text_edit()->insert_text_at_cursor(res->get_path()); + te->cursor_set_line(row); + te->cursor_set_column(col); + te->insert_text_at_cursor(res->get_path()); } if (d.has("type") && String(d["type"]) == "files") { @@ -1356,7 +1360,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data text_to_drop += "\"" + String(files[i]).c_escape() + "\""; } - code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop); + te->cursor_set_line(row); + te->cursor_set_column(col); + te->insert_text_at_cursor(text_to_drop); } if (d.has("type") && String(d["type"]) == "nodes") { @@ -1385,7 +1391,9 @@ void ScriptTextEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data text_to_drop += "\"" + path.c_escape() + "\""; } - code_editor->get_text_edit()->insert_text_at_cursor(text_to_drop); + te->cursor_set_line(row); + te->cursor_set_column(col); + te->insert_text_at_cursor(text_to_drop); } } diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index bd2cdf0dda..63762651d7 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -318,6 +318,9 @@ void SpatialEditorViewport::_select(Spatial *p_node, bool p_append, bool p_singl editor_selection->clear(); editor_selection->add_node(p_node); + if (Engine::get_singleton()->is_editor_hint()) + editor->call("edit_node", p_node); + } else { if (editor_selection->is_selected(p_node) && p_single) { @@ -4775,6 +4778,11 @@ void SpatialEditor::add_control_to_menu_panel(Control *p_control) { hbc_menu->add_child(p_control); } +void SpatialEditor::remove_control_from_menu_panel(Control *p_control) { + + hbc_menu->remove_child(p_control); +} + void SpatialEditor::set_can_preview(Camera *p_preview) { for (int i = 0; i < 4; i++) { diff --git a/editor/plugins/spatial_editor_plugin.h b/editor/plugins/spatial_editor_plugin.h index e12f7affb7..55866cac99 100644 --- a/editor/plugins/spatial_editor_plugin.h +++ b/editor/plugins/spatial_editor_plugin.h @@ -605,6 +605,7 @@ public: UndoRedo *get_undo_redo() { return undo_redo; } void add_control_to_menu_panel(Control *p_control); + void remove_control_from_menu_panel(Control *p_control); VSplitContainer *get_shader_split(); HSplitContainer *get_palette_split(); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 058f517ae9..9625bc19c0 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -1595,7 +1595,7 @@ ProjectSettingsEditor::ProjectSettingsEditor(EditorData *p_data) { hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); props_base->add_child(hbc); - search_button = memnew(ToolButton); + search_button = memnew(Button); search_button->set_toggle_mode(true); search_button->set_pressed(false); search_button->set_text(TTR("Search")); diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index d6c2c0f5a8..452cf5b060 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -67,7 +67,7 @@ class ProjectSettingsEditor : public AcceptDialog { SectionedPropertyEditor *globals_editor; HBoxContainer *search_bar; - ToolButton *search_button; + Button *search_button; LineEdit *search_box; ToolButton *clear_button; diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 41ee5ab286..8506c75a68 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -67,6 +67,9 @@ void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) { if (get_viewport()->get_modal_stack_top()) return; //ignore because of modal window + if (get_focus_owner() && get_focus_owner()->is_text_field()) + return; + if (!p_event->is_pressed() || p_event->is_echo()) return; diff --git a/editor/spatial_editor_gizmos.cpp b/editor/spatial_editor_gizmos.cpp index 72c0f050d2..8c90d86b9e 100644 --- a/editor/spatial_editor_gizmos.cpp +++ b/editor/spatial_editor_gizmos.cpp @@ -308,15 +308,6 @@ void EditorSpatialGizmo::add_solid_box(Ref<Material> &p_material, Vector3 p_size m->add_surface_from_arrays(cubem.surface_get_primitive_type(0), cubem.surface_get_arrays(0)); m->surface_set_material(0, p_material); add_mesh(m); - - Instance ins; - ins.mesh = m; - if (valid) { - ins.create_instance(spatial_node); - VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); - } - - instances.push_back(ins); } void EditorSpatialGizmo::set_spatial_node(Spatial *p_node) { @@ -1130,7 +1121,7 @@ void CameraSpatialGizmo::set_handle(int p_idx, Camera *p_camera, const Point2 &p if (camera->get_projection() == Camera::PROJECTION_PERSPECTIVE) { Transform gt = camera->get_global_transform(); float a = _find_closest_angle_to_half_pi_arc(s[0], s[1], 1.0, gt); - camera->set("fov", a); + camera->set("fov", a * 2.0); } else { Vector3 ra, rb; @@ -1187,7 +1178,8 @@ void CameraSpatialGizmo::redraw() { case Camera::PROJECTION_PERSPECTIVE: { - float fov = camera->get_fov(); + // The real FOV is halved for accurate representation + float fov = camera->get_fov() / 2.0; Vector3 side = Vector3(Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov))); Vector3 nside = side; diff --git a/main/input_default.cpp b/main/input_default.cpp index fb831b7647..5057c5f53a 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -713,6 +713,7 @@ static const char *s_ControllerMappings[] = { "030000005e040000a102000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000005e040000d102000001010000,Microsoft X-Box One pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", + "030000005e040000e302000003020000,Microsoft X-Box One Elite pad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,", "030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,", "030000006d04000016c2000010010000,Logitech Logitech Dual Action,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,", @@ -725,6 +726,7 @@ static const char *s_ControllerMappings[] = { "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,", "030000006f0e00000103000000020000,Logic3 Controller,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", + "030000006f0e00001302000000010000,Afterglow Gamepad for Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000006f0e00001304000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", "030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,", "030000006f0e00001f01000000010000,Generic X-Box pad,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,", diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 51de4998fa..b646fc164d 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -70,8 +70,8 @@ return RID(); \ } -#define AddJointToSpace(body, joint, disableCollisionsBetweenLinkedBodies) \ - body->get_space()->add_constraint(joint, disableCollisionsBetweenLinkedBodies); +#define AddJointToSpace(body, joint) \ + body->get_space()->add_constraint(joint, joint->is_disabled_collisions_between_bodies()); // <--------------- Joint creation asserts btEmptyShape *BulletPhysicsServer::emptyShape(ShapeBullet::create_shape_empty()); @@ -987,6 +987,20 @@ int BulletPhysicsServer::joint_get_solver_priority(RID p_joint) const { return 0; } +void BulletPhysicsServer::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { + JointBullet *joint = joint_owner.get(p_joint); + ERR_FAIL_COND(!joint); + + joint->disable_collisions_between_bodies(p_disable); +} + +bool BulletPhysicsServer::joint_is_disabled_collisions_between_bodies(RID p_joint) const { + JointBullet *joint(joint_owner.get(p_joint)); + ERR_FAIL_COND_V(!joint, false); + + return joint->is_disabled_collisions_between_bodies(); +} + RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { RigidBodyBullet *body_A = rigid_body_owner.get(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); @@ -1003,7 +1017,7 @@ RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A ERR_FAIL_COND_V(body_A == body_B, RID()); JointBullet *joint = bulletnew(PinJointBullet(body_A, p_local_A, body_B, p_local_B)); - AddJointToSpace(body_A, joint, true); + AddJointToSpace(body_A, joint); CreateThenReturnRID(joint_owner, joint); } @@ -1071,7 +1085,7 @@ RID BulletPhysicsServer::joint_create_hinge(RID p_body_A, const Transform &p_hin ERR_FAIL_COND_V(body_A == body_B, RID()); JointBullet *joint = bulletnew(HingeJointBullet(body_A, body_B, p_hinge_A, p_hinge_B)); - AddJointToSpace(body_A, joint, true); + AddJointToSpace(body_A, joint); CreateThenReturnRID(joint_owner, joint); } @@ -1091,7 +1105,7 @@ RID BulletPhysicsServer::joint_create_hinge_simple(RID p_body_A, const Vector3 & ERR_FAIL_COND_V(body_A == body_B, RID()); JointBullet *joint = bulletnew(HingeJointBullet(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B)); - AddJointToSpace(body_A, joint, true); + AddJointToSpace(body_A, joint); CreateThenReturnRID(joint_owner, joint); } @@ -1143,7 +1157,7 @@ RID BulletPhysicsServer::joint_create_slider(RID p_body_A, const Transform &p_lo ERR_FAIL_COND_V(body_A == body_B, RID()); JointBullet *joint = bulletnew(SliderJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B)); - AddJointToSpace(body_A, joint, true); + AddJointToSpace(body_A, joint); CreateThenReturnRID(joint_owner, joint); } @@ -1177,7 +1191,7 @@ RID BulletPhysicsServer::joint_create_cone_twist(RID p_body_A, const Transform & } JointBullet *joint = bulletnew(ConeTwistJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B)); - AddJointToSpace(body_A, joint, true); + AddJointToSpace(body_A, joint); CreateThenReturnRID(joint_owner, joint); } @@ -1213,7 +1227,7 @@ RID BulletPhysicsServer::joint_create_generic_6dof(RID p_body_A, const Transform ERR_FAIL_COND_V(body_A == body_B, RID()); JointBullet *joint = bulletnew(Generic6DOFJointBullet(body_A, body_B, p_local_frame_A, p_local_frame_B, true)); - AddJointToSpace(body_A, joint, true); + AddJointToSpace(body_A, joint); CreateThenReturnRID(joint_owner, joint); } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index e0e46cd369..764ec2387c 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -290,6 +290,9 @@ public: virtual void joint_set_solver_priority(RID p_joint, int p_priority); virtual int joint_get_solver_priority(RID p_joint) const; + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable); + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const; + virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B); virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value); diff --git a/modules/bullet/constraint_bullet.cpp b/modules/bullet/constraint_bullet.cpp index b60e89b6fd..d15fb8de01 100644 --- a/modules/bullet/constraint_bullet.cpp +++ b/modules/bullet/constraint_bullet.cpp @@ -39,7 +39,8 @@ ConstraintBullet::ConstraintBullet() : space(NULL), - constraint(NULL) {} + constraint(NULL), + disabled_collisions_between_bodies(true) {} void ConstraintBullet::setup(btTypedConstraint *p_constraint) { constraint = p_constraint; @@ -53,3 +54,12 @@ void ConstraintBullet::set_space(SpaceBullet *p_space) { void ConstraintBullet::destroy_internal_constraint() { space->remove_constraint(this); } + +void ConstraintBullet::disable_collisions_between_bodies(const bool p_disabled) { + disabled_collisions_between_bodies = p_disabled; + + if (space) { + space->remove_constraint(this); + space->add_constraint(this, disabled_collisions_between_bodies); + } +} diff --git a/modules/bullet/constraint_bullet.h b/modules/bullet/constraint_bullet.h index 23be5a5063..ed3a318cbc 100644 --- a/modules/bullet/constraint_bullet.h +++ b/modules/bullet/constraint_bullet.h @@ -49,6 +49,7 @@ class ConstraintBullet : public RIDBullet { protected: SpaceBullet *space; btTypedConstraint *constraint; + bool disabled_collisions_between_bodies; public: ConstraintBullet(); @@ -57,6 +58,9 @@ public: virtual void set_space(SpaceBullet *p_space); virtual void destroy_internal_constraint(); + void disable_collisions_between_bodies(const bool p_disabled); + _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; } + public: virtual ~ConstraintBullet() { bulletdelete(constraint); diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index 57fdb13b3a..a8919f7130 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -3964,7 +3964,7 @@ "name": "godot_variant_new_bool", "return_type": "void", "arguments": [ - ["godot_variant *", "p_v"], + ["godot_variant *", "r_dest"], ["const godot_bool", "p_b"] ] }, diff --git a/modules/gdnative/include/gdnative/variant.h b/modules/gdnative/include/gdnative/variant.h index d2e8246bfb..6779dc4092 100644 --- a/modules/gdnative/include/gdnative/variant.h +++ b/modules/gdnative/include/gdnative/variant.h @@ -135,7 +135,7 @@ void GDAPI godot_variant_new_copy(godot_variant *r_dest, const godot_variant *p_ void GDAPI godot_variant_new_nil(godot_variant *r_dest); -void GDAPI godot_variant_new_bool(godot_variant *p_v, const godot_bool p_b); +void GDAPI godot_variant_new_bool(godot_variant *r_dest, const godot_bool p_b); void GDAPI godot_variant_new_uint(godot_variant *r_dest, const uint64_t p_i); void GDAPI godot_variant_new_int(godot_variant *r_dest, const int64_t p_i); void GDAPI godot_variant_new_real(godot_variant *r_dest, const double p_r); diff --git a/modules/mono/SCsub b/modules/mono/SCsub index 320bbe7090..aa8626e6da 100644 --- a/modules/mono/SCsub +++ b/modules/mono/SCsub @@ -57,10 +57,10 @@ if env['tools']: vars = Variables() vars.Add(BoolVariable('mono_glue', 'Build with the mono glue sources', True)) vars.Add(BoolVariable('xbuild_fallback', 'If MSBuild is not found, fallback to xbuild', False)) -vars.Update(env) +vars.Update(env_mono) # Glue sources -if env['mono_glue']: +if env_mono['mono_glue']: env_mono.add_source_files(env.modules_sources, 'glue/*.cpp') else: env_mono.Append(CPPDEFINES=['MONO_GLUE_DISABLED']) diff --git a/modules/openssl/stream_peer_openssl.cpp b/modules/openssl/stream_peer_openssl.cpp index e3cb9bbdf8..84c4e85006 100644 --- a/modules/openssl/stream_peer_openssl.cpp +++ b/modules/openssl/stream_peer_openssl.cpp @@ -141,9 +141,6 @@ int StreamPeerOpenSSL::_cert_verify_callback(X509_STORE_CTX *x509_ctx, void *arg X509_NAME_oneline(X509_get_subject_name(server_cert), cert_str, sizeof(cert_str)); - print_line("CERT STR: " + String(cert_str)); - print_line("VALID: " + itos(base_cert_valid)); - if (!base_cert_valid) return 0; @@ -382,7 +379,6 @@ Error StreamPeerOpenSSL::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida // Same as before, try to connect. int result = SSL_connect(ssl); - print_line("CONNECTION RESULT: " + itos(result)); if (result < 1) { ERR_print_errors_fp(stdout); _print_error(result); @@ -392,7 +388,6 @@ Error StreamPeerOpenSSL::connect_to_stream(Ref<StreamPeer> p_base, bool p_valida if (peer) { bool cert_ok = SSL_get_verify_result(ssl) == X509_V_OK; - print_line("cert_ok: " + itos(cert_ok)); } else if (validate_certs) { status = STATUS_ERROR_NO_CERTIFICATE; diff --git a/platform/android/java/src/org/godotengine/godot/Godot.java b/platform/android/java/src/org/godotengine/godot/Godot.java index b5b0afb9e0..0d14211bd0 100644 --- a/platform/android/java/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/src/org/godotengine/godot/Godot.java @@ -404,7 +404,7 @@ public class Godot extends Activity implements SensorEventListener, IDownloaderC new_cmdline = new String[2]; } - new_cmdline[cll] = "--main_pack"; + new_cmdline[cll] = "--main-pack"; new_cmdline[cll + 1] = expansion_pack_path; command_line = new_cmdline; } diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index 4e9e4f6260..2d81d79bf1 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -926,7 +926,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jo } else { //__android_log_print(ANDROID_LOG_INFO,"godot","cmdline arg %i is: %s\n",i,rawString); - if (strcmp(rawString, "-main_pack") == 0) + if (strcmp(rawString, "--main-pack") == 0) use_apk_expansion = true; } diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index d9ad0a7db8..0199bf0fc1 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -167,6 +167,7 @@ public: virtual void set_window_title(const String &p_title); virtual Size2 get_window_size() const; + virtual Size2 get_real_window_size() const; virtual void set_icon(const Ref<Image> &p_icon); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index ab54f62045..c469af410e 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1845,6 +1845,12 @@ Size2 OS_OSX::get_window_size() const { return window_size; }; +Size2 OS_OSX::get_real_window_size() const { + + NSRect frame = [window_object frame]; + return Size2(frame.size.width, frame.size.height); +} + void OS_OSX::set_window_size(const Size2 p_size) { Size2 size = p_size; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index a2a51f10a7..f4b20b6981 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -1487,6 +1487,12 @@ Size2 OS_Windows::get_window_size() const { GetClientRect(hWnd, &r); return Vector2(r.right - r.left, r.bottom - r.top); } +Size2 OS_Windows::get_real_window_size() const { + + RECT r; + GetWindowRect(hWnd, &r); + return Vector2(r.right - r.left, r.bottom - r.top); +} void OS_Windows::set_window_size(const Size2 p_size) { video_mode.width = p_size.width; diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 7308650695..543abe147d 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -201,6 +201,7 @@ public: virtual Point2 get_window_position() const; virtual void set_window_position(const Point2 &p_position); virtual Size2 get_window_size() const; + virtual Size2 get_real_window_size() const; virtual void set_window_size(const Size2 p_size); virtual void set_window_fullscreen(bool p_enabled); virtual bool is_window_fullscreen() const; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index eaf72d4dbf..bd2abc1094 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -924,6 +924,26 @@ Size2 OS_X11::get_window_size() const { return Size2i(current_videomode.width, current_videomode.height); } +Size2 OS_X11::get_real_window_size() const { + XWindowAttributes xwa; + XSync(x11_display, False); + XGetWindowAttributes(x11_display, x11_window, &xwa); + int w = xwa.width; + int h = xwa.height; + Atom prop = XInternAtom(x11_display, "_NET_FRAME_EXTENTS", True); + Atom type; + int format; + unsigned long len; + unsigned long remaining; + unsigned char *data = NULL; + if (XGetWindowProperty(x11_display, x11_window, prop, 0, 4, False, AnyPropertyType, &type, &format, &len, &remaining, &data) == Success) { + long *extents = (long *)data; + w += extents[0] + extents[1]; // left, right + h += extents[2] + extents[3]; // top, bottom + } + return Size2(w, h); +} + void OS_X11::set_window_size(const Size2 p_size) { // If window resizable is disabled we need to update the attributes first if (is_window_resizable() == false) { diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index ee62b89227..3347b37f47 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -251,6 +251,7 @@ public: virtual Point2 get_window_position() const; virtual void set_window_position(const Point2 &p_position); virtual Size2 get_window_size() const; + virtual Size2 get_real_window_size() const; virtual void set_window_size(const Size2 p_size); virtual void set_window_fullscreen(bool p_enabled); virtual bool is_window_fullscreen() const; diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 7a96a54854..329382c034 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -75,8 +75,7 @@ void Joint2D::_update_joint(bool p_only_free) { ba = body_a->get_rid(); bb = body_b->get_rid(); - if (exclude_from_collision) - Physics2DServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); + Physics2DServer::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); } void Joint2D::set_node_a(const NodePath &p_node_a) { diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index fed6d76f65..2e9f1a241a 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -71,8 +71,7 @@ void Joint::_update_joint(bool p_only_free) { ba = body_a->get_rid(); bb = body_b->get_rid(); - if (exclude_from_collision) - PhysicsServer::get_singleton()->body_add_collision_exception(body_a->get_rid(), body_b->get_rid()); + PhysicsServer::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); } void Joint::set_node_a(const NodePath &p_node_a) { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 524a68a116..03dc6686b8 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -30,6 +30,7 @@ #include "line_edit.h" #include "label.h" +#include "message_queue.h" #include "os/keyboard.h" #include "os/os.h" #include "print_string.h" @@ -800,7 +801,12 @@ void LineEdit::paste_text() { if (selection.enabled) selection_delete(); append_at_cursor(paste_buffer); - _text_changed(); + if (!text_changed_dirty) { + if (is_inside_tree()) { + MessageQueue::get_singleton()->push_call(this, "_text_changed"); + } + text_changed_dirty = true; + } } } @@ -974,7 +980,12 @@ void LineEdit::delete_text(int p_from_column, int p_to_column) { window_pos = cursor_pos; } - _text_changed(); + if (!text_changed_dirty) { + if (is_inside_tree()) { + MessageQueue::get_singleton()->push_call(this, "_text_changed"); + } + text_changed_dirty = true; + } } void LineEdit::set_text(String p_text) { @@ -1341,6 +1352,7 @@ void LineEdit::_text_changed() { void LineEdit::_emit_text_change() { emit_signal("text_changed", text); _change_notify("text"); + text_changed_dirty = false; } void LineEdit::_clear_redo() { @@ -1373,6 +1385,7 @@ void LineEdit::_create_undo_state() { void LineEdit::_bind_methods() { + ClassDB::bind_method(D_METHOD("_text_changed"), &LineEdit::_text_changed); ClassDB::bind_method(D_METHOD("_toggle_draw_caret"), &LineEdit::_toggle_draw_caret); #ifdef TOOLS_ENABLED @@ -1458,6 +1471,7 @@ LineEdit::LineEdit() { window_has_focus = true; max_length = 0; pass = false; + text_changed_dirty = false; placeholder_alpha = 0.6; deselect(); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index e15980d3c4..e3ad3b17f1 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -67,6 +67,7 @@ private: bool editable; bool pass; + bool text_changed_dirty; String undo_text; String text; diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 3c5d524d80..145981d498 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -185,17 +185,22 @@ void SpinBox::_line_edit_focus_exit() { _text_entered(line_edit->get_text()); } +inline void SpinBox::_adjust_width_for_icon(const Ref<Texture> icon) { + + int w = icon->get_width(); + if (w != last_w) { + line_edit->set_margin(MARGIN_RIGHT, -w); + last_w = w; + } +} + void SpinBox::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { Ref<Texture> updown = get_icon("updown"); - int w = updown->get_width(); - if (w != last_w) { - line_edit->set_margin(MARGIN_RIGHT, -w); - last_w = w; - } + _adjust_width_for_icon(updown); RID ci = get_canvas_item(); Size2i size = get_size(); @@ -207,6 +212,7 @@ void SpinBox::_notification(int p_what) { //_value_changed(0); } else if (p_what == NOTIFICATION_ENTER_TREE) { + _adjust_width_for_icon(get_icon("updown")); _value_changed(0); } } diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index b8565ec082..8863f44bef 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -62,6 +62,8 @@ class SpinBox : public Range { void _line_edit_focus_exit(); + inline void _adjust_width_for_icon(const Ref<Texture> icon); + protected: void _gui_input(const Ref<InputEvent> &p_event); diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h index a641f06f0c..41789600f6 100644 --- a/servers/physics/constraint_sw.h +++ b/servers/physics/constraint_sw.h @@ -41,6 +41,7 @@ class ConstraintSW : public RID_Data { ConstraintSW *island_next; ConstraintSW *island_list_next; int priority; + bool disabled_collisions_between_bodies; RID self; @@ -50,6 +51,7 @@ protected: _body_count = p_body_count; island_step = 0; priority = 1; + disabled_collisions_between_bodies = true; } public: @@ -71,6 +73,9 @@ public: _FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; } _FORCE_INLINE_ int get_priority() const { return priority; } + _FORCE_INLINE_ void disable_collisions_between_bodies(const bool p_disabled) { disabled_collisions_between_bodies = p_disabled; } + _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; } + virtual bool setup(real_t p_step) = 0; virtual void solve(real_t p_step) = 0; diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp index ea0d372281..0f7c6deaac 100644 --- a/servers/physics/physics_server_sw.cpp +++ b/servers/physics/physics_server_sw.cpp @@ -1093,6 +1093,33 @@ int PhysicsServerSW::joint_get_solver_priority(RID p_joint) const { return joint->get_priority(); } +void PhysicsServerSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { + JointSW *joint = joint_owner.get(p_joint); + ERR_FAIL_COND(!joint); + + joint->disable_collisions_between_bodies(p_disable); + + if (2 == joint->get_body_count()) { + BodySW *body_a = *joint->get_body_ptr(); + BodySW *body_b = *(joint->get_body_ptr() + 1); + + if (p_disable) { + body_add_collision_exception(body_a->get_self(), body_b->get_self()); + body_add_collision_exception(body_b->get_self(), body_a->get_self()); + } else { + body_remove_collision_exception(body_a->get_self(), body_b->get_self()); + body_remove_collision_exception(body_b->get_self(), body_a->get_self()); + } + } +} + +bool PhysicsServerSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { + JointSW *joint = joint_owner.get(p_joint); + ERR_FAIL_COND_V(!joint, true); + + return joint->is_disabled_collisions_between_bodies(); +} + PhysicsServerSW::JointType PhysicsServerSW::joint_get_type(RID p_joint) const { JointSW *joint = joint_owner.get(p_joint); diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h index 132ac78968..923b59d28f 100644 --- a/servers/physics/physics_server_sw.h +++ b/servers/physics/physics_server_sw.h @@ -275,6 +275,9 @@ public: virtual void joint_set_solver_priority(RID p_joint, int p_priority); virtual int joint_get_solver_priority(RID p_joint) const; + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable); + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const; + /* MISC */ virtual void free(RID p_rid); diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h index a08037bb37..c1954935d3 100644 --- a/servers/physics_2d/constraint_2d_sw.h +++ b/servers/physics_2d/constraint_2d_sw.h @@ -40,6 +40,7 @@ class Constraint2DSW : public RID_Data { uint64_t island_step; Constraint2DSW *island_next; Constraint2DSW *island_list_next; + bool disabled_collisions_between_bodies; RID self; @@ -48,6 +49,7 @@ protected: _body_ptr = p_body_ptr; _body_count = p_body_count; island_step = 0; + disabled_collisions_between_bodies = true; } public: @@ -66,6 +68,9 @@ public: _FORCE_INLINE_ Body2DSW **get_body_ptr() const { return _body_ptr; } _FORCE_INLINE_ int get_body_count() const { return _body_count; } + _FORCE_INLINE_ void disable_collisions_between_bodies(const bool p_disabled) { disabled_collisions_between_bodies = p_disabled; } + _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; } + virtual bool setup(real_t p_step) = 0; virtual void solve(real_t p_step) = 0; diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp index 7d7bbbebac..0603287a79 100644 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ b/servers/physics_2d/physics_2d_server_sw.cpp @@ -1015,6 +1015,33 @@ real_t Physics2DServerSW::joint_get_param(RID p_joint, JointParam p_param) const return 0; } +void Physics2DServerSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { + Joint2DSW *joint = joint_owner.get(p_joint); + ERR_FAIL_COND(!joint); + + joint->disable_collisions_between_bodies(p_disable); + + if (2 == joint->get_body_count()) { + Body2DSW *body_a = *joint->get_body_ptr(); + Body2DSW *body_b = *(joint->get_body_ptr() + 1); + + if (p_disable) { + body_add_collision_exception(body_a->get_self(), body_b->get_self()); + body_add_collision_exception(body_b->get_self(), body_a->get_self()); + } else { + body_remove_collision_exception(body_a->get_self(), body_b->get_self()); + body_remove_collision_exception(body_b->get_self(), body_a->get_self()); + } + } +} + +bool Physics2DServerSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { + const Joint2DSW *joint = joint_owner.get(p_joint); + ERR_FAIL_COND_V(!joint, true); + + return joint->is_disabled_collisions_between_bodies(); +} + RID Physics2DServerSW::pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b) { Body2DSW *A = body_owner.get(p_body_a); diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h index 97edb85582..cf9c2957bf 100644 --- a/servers/physics_2d/physics_2d_server_sw.h +++ b/servers/physics_2d/physics_2d_server_sw.h @@ -242,6 +242,9 @@ public: virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value); virtual real_t joint_get_param(RID p_joint, JointParam p_param) const; + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disabled); + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const; + virtual RID pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b = RID()); virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b); virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()); diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h index 276c37c577..d625bc9892 100644 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ b/servers/physics_2d/physics_2d_server_wrap_mt.h @@ -263,6 +263,9 @@ public: FUNC3(joint_set_param, RID, JointParam, real_t); FUNC2RC(real_t, joint_get_param, RID, JointParam); + FUNC2(joint_disable_collisions_between_bodies, RID, const bool); + FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID); + ///FUNC3RID(pin_joint,const Vector2&,RID,RID); ///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID); ///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID); diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h index be447ed137..462244c667 100644 --- a/servers/physics_2d_server.h +++ b/servers/physics_2d_server.h @@ -499,6 +499,9 @@ public: virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value) = 0; virtual real_t joint_get_param(RID p_joint, JointParam p_param) const = 0; + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; + virtual RID pin_joint_create(const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) = 0; virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) = 0; virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0; diff --git a/servers/physics_server.h b/servers/physics_server.h index 94fc8d479d..2ac405293e 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -491,6 +491,9 @@ public: virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0; virtual int joint_get_solver_priority(RID p_joint) const = 0; + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; + virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0; enum PinJointParam { diff --git a/thirdparty/lws/lws_config_private.h b/thirdparty/lws/lws_config_private.h index 235f2ba26d..475d1bd3f8 100644 --- a/thirdparty/lws/lws_config_private.h +++ b/thirdparty/lws/lws_config_private.h @@ -81,7 +81,7 @@ /* Define to 1 if you have the <sys/prctl.h> header file. */ #define LWS_HAVE_SYS_PRCTL_H -#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) +#if defined(OSX_ENABLED) || defined(IPHONE_ENABLED) || defined(__FreeBSD__) || defined(__OpenBSD__) #undef LWS_HAVE_SYS_PRCTL_H #endif |