diff options
83 files changed, 750 insertions, 434 deletions
diff --git a/.appveyor.yml b/.appveyor.yml index aeee15e652..708961fd92 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -28,4 +28,4 @@ before_build: - SET "SCONS_CACHE=%SCONS_CACHE_ROOT%\master" build_script: -- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% verbose=yes progress=no +- scons platform=%GD_PLATFORM% target=%TARGET% tools=%TOOLS% verbose=yes progress=no gdnative_wrapper=yes diff --git a/.travis.yml b/.travis.yml index 0dfeaf16e1..9df2388b8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -90,5 +90,5 @@ script: - if [ "$STATIC_CHECKS" = "yes" ]; then sh ./misc/travis/clang-format.sh; else - scons -j2 CC=$CC CXX=$CXX platform=$GODOT_TARGET TOOLS=$TOOLS verbose=yes progress=no openmp=no; + scons -j2 CC=$CC CXX=$CXX platform=$GODOT_TARGET TOOLS=$TOOLS verbose=yes progress=no openmp=no gdnative_wrapper=yes; fi diff --git a/core/os/dir_access.cpp b/core/os/dir_access.cpp index c906fa7333..eadb8e8546 100644 --- a/core/os/dir_access.cpp +++ b/core/os/dir_access.cpp @@ -293,7 +293,7 @@ String DirAccess::get_full_path(const String &p_path, AccessType p_access) { return full; } -Error DirAccess::copy(String p_from, String p_to, int chmod_flags) { +Error DirAccess::copy(String p_from, String p_to, int p_chmod_flags) { //printf("copy %s -> %s\n",p_from.ascii().get_data(),p_to.ascii().get_data()); Error err; @@ -330,9 +330,9 @@ Error DirAccess::copy(String p_from, String p_to, int chmod_flags) { fdst->store_8(fsrc->get_8()); } - if (err == OK && chmod_flags != -1) { + if (err == OK && p_chmod_flags != -1) { fdst->close(); - err = fdst->_chmod(p_to, chmod_flags); + err = fdst->_chmod(p_to, p_chmod_flags); // If running on a platform with no chmod support (i.e., Windows), don't fail if (err == ERR_UNAVAILABLE) err = OK; diff --git a/core/os/dir_access.h b/core/os/dir_access.h index f29f61e838..c94ced657b 100644 --- a/core/os/dir_access.h +++ b/core/os/dir_access.h @@ -92,8 +92,8 @@ public: static bool exists(String p_dir); virtual size_t get_space_left() = 0; - Error copy_dir(String p_from, String p_to, int chmod_flags = -1); - virtual Error copy(String p_from, String p_to, int chmod_flags = -1); + Error copy_dir(String p_from, String p_to, int p_chmod_flags = -1); + virtual Error copy(String p_from, String p_to, int p_chmod_flags = -1); virtual Error rename(String p_from, String p_to) = 0; virtual Error remove(String p_name) = 0; diff --git a/core/os/os.h b/core/os/os.h index c9c228cfaf..a4f07df0e8 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -121,7 +121,7 @@ protected: void add_logger(Logger *p_logger); virtual void initialize_core() = 0; - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0; + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) = 0; virtual void set_main_loop(MainLoop *p_main_loop) = 0; virtual void delete_main_loop() = 0; diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index 6c30a92ed5..680e008ff1 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -632,6 +632,7 @@ Distance between the node's top edge and its parent container, based on [member anchor_top]. </member> <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" enum="Control.MouseFilter"> + Controls whether the control will be able to receive mouse button input events through [Control._gui_input] and how these events should be handled. Use one of the [code]MOUSE_FILTER_*[/code] constants. See the constants to learn what each does. </member> <member name="rect_clip_content" type="bool" setter="set_clip_contents" getter="is_clipping_contents"> </member> @@ -869,10 +870,13 @@ Tells the parent [Container] to align the node with its end, either the bottom or the right edge. It doesn't work with the fill or expand size flags. Use with [member size_flags_horizontal] and [member size_flags_vertical]. </constant> <constant name="MOUSE_FILTER_STOP" value="0" enum="MouseFilter"> + The control will receive mouse button input events through [method Control._gui_input] if clicked on. These events are automatically marked as handled and they will not propogate further to other controls. </constant> <constant name="MOUSE_FILTER_PASS" value="1" enum="MouseFilter"> + The control will receive mouse button input events through [method Control._gui_input] if clicked on. If this control does not handle the event, the parent control (if any) will be considered for a mouse click, and so on until there is no more parent control to potentially handle it. Even if no control handled it at all, the event will still be handled automatically. </constant> <constant name="MOUSE_FILTER_IGNORE" value="2" enum="MouseFilter"> + The control will not receive mouse button input events through [method Control._gui_input] and will not block other controls from receiving these events. These events will also not be handled automatically. </constant> <constant name="GROW_DIRECTION_BEGIN" value="0" enum="GrowDirection"> </constant> diff --git a/doc/classes/Image.xml b/doc/classes/Image.xml index 230978950b..a01ffc99be 100644 --- a/doc/classes/Image.xml +++ b/doc/classes/Image.xml @@ -446,67 +446,65 @@ </constant> <constant name="FORMAT_RGBA5551" value="7" enum="Format"> </constant> - <constant name="FORMAT_RGB10A2" value="8" enum="Format"> + <constant name="FORMAT_RF" value="8" enum="Format"> </constant> - <constant name="FORMAT_RF" value="9" enum="Format"> + <constant name="FORMAT_RGF" value="9" enum="Format"> </constant> - <constant name="FORMAT_RGF" value="10" enum="Format"> + <constant name="FORMAT_RGBF" value="10" enum="Format"> </constant> - <constant name="FORMAT_RGBF" value="11" enum="Format"> + <constant name="FORMAT_RGBAF" value="11" enum="Format"> </constant> - <constant name="FORMAT_RGBAF" value="12" enum="Format"> + <constant name="FORMAT_RH" value="12" enum="Format"> </constant> - <constant name="FORMAT_RH" value="13" enum="Format"> + <constant name="FORMAT_RGH" value="13" enum="Format"> </constant> - <constant name="FORMAT_RGH" value="14" enum="Format"> + <constant name="FORMAT_RGBH" value="14" enum="Format"> </constant> - <constant name="FORMAT_RGBH" value="15" enum="Format"> + <constant name="FORMAT_RGBAH" value="15" enum="Format"> </constant> - <constant name="FORMAT_RGBAH" value="16" enum="Format"> + <constant name="FORMAT_RGBE9995" value="16" enum="Format"> </constant> - <constant name="FORMAT_RGBE9995" value="17" enum="Format"> + <constant name="FORMAT_DXT1" value="17" enum="Format"> </constant> - <constant name="FORMAT_DXT1" value="18" enum="Format"> + <constant name="FORMAT_DXT3" value="18" enum="Format"> </constant> - <constant name="FORMAT_DXT3" value="19" enum="Format"> + <constant name="FORMAT_DXT5" value="19" enum="Format"> </constant> - <constant name="FORMAT_DXT5" value="20" enum="Format"> + <constant name="FORMAT_RGTC_R" value="20" enum="Format"> </constant> - <constant name="FORMAT_RGTC_R" value="21" enum="Format"> + <constant name="FORMAT_RGTC_RG" value="21" enum="Format"> </constant> - <constant name="FORMAT_RGTC_RG" value="22" enum="Format"> + <constant name="FORMAT_BPTC_RGBA" value="22" enum="Format"> </constant> - <constant name="FORMAT_BPTC_RGBA" value="23" enum="Format"> + <constant name="FORMAT_BPTC_RGBF" value="23" enum="Format"> </constant> - <constant name="FORMAT_BPTC_RGBF" value="24" enum="Format"> + <constant name="FORMAT_BPTC_RGBFU" value="24" enum="Format"> </constant> - <constant name="FORMAT_BPTC_RGBFU" value="25" enum="Format"> + <constant name="FORMAT_PVRTC2" value="25" enum="Format"> </constant> - <constant name="FORMAT_PVRTC2" value="26" enum="Format"> + <constant name="FORMAT_PVRTC2A" value="26" enum="Format"> </constant> - <constant name="FORMAT_PVRTC2A" value="27" enum="Format"> + <constant name="FORMAT_PVRTC4" value="27" enum="Format"> </constant> - <constant name="FORMAT_PVRTC4" value="28" enum="Format"> + <constant name="FORMAT_PVRTC4A" value="28" enum="Format"> </constant> - <constant name="FORMAT_PVRTC4A" value="29" enum="Format"> + <constant name="FORMAT_ETC" value="29" enum="Format"> </constant> - <constant name="FORMAT_ETC" value="30" enum="Format"> + <constant name="FORMAT_ETC2_R11" value="30" enum="Format"> </constant> - <constant name="FORMAT_ETC2_R11" value="31" enum="Format"> + <constant name="FORMAT_ETC2_R11S" value="31" enum="Format"> </constant> - <constant name="FORMAT_ETC2_R11S" value="32" enum="Format"> + <constant name="FORMAT_ETC2_RG11" value="32" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RG11" value="33" enum="Format"> + <constant name="FORMAT_ETC2_RG11S" value="33" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RG11S" value="34" enum="Format"> + <constant name="FORMAT_ETC2_RGB8" value="34" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RGB8" value="35" enum="Format"> + <constant name="FORMAT_ETC2_RGBA8" value="35" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RGBA8" value="36" enum="Format"> + <constant name="FORMAT_ETC2_RGB8A1" value="36" enum="Format"> </constant> - <constant name="FORMAT_ETC2_RGB8A1" value="37" enum="Format"> - </constant> - <constant name="FORMAT_MAX" value="38" enum="Format"> + <constant name="FORMAT_MAX" value="37" enum="Format"> </constant> <constant name="INTERPOLATE_NEAREST" value="0" enum="Interpolation"> </constant> diff --git a/doc/classes/Node2D.xml b/doc/classes/Node2D.xml index ae2a67312e..5b7def99dc 100644 --- a/doc/classes/Node2D.xml +++ b/doc/classes/Node2D.xml @@ -157,12 +157,12 @@ <member name="transform" type="Transform2D" setter="set_transform" getter="get_transform"> Local [Transform2D]. </member> - <member name="z_index" type="int" setter="set_z_index" getter="get_z_index"> - Z-index. Controls the order in which the nodes render. A node with a higher Z-index will display in front of others. - </member> <member name="z_as_relative" type="bool" setter="set_z_as_relative" getter="is_z_relative"> If [code]true[/code] the node's Z-index is relative to its parent's Z-index. If this node's Z-index is 2 and its parent's effective Z-index is 3, then this node's effective Z-index will be 2 + 3 = 5. </member> + <member name="z_index" type="int" setter="set_z_index" getter="get_z_index"> + Z-index. Controls the order in which the nodes render. A node with a higher Z-index will display in front of others. + </member> </members> <constants> </constants> diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 0cba132de8..28fb83d572 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -504,26 +504,26 @@ Sets if the canvas item (including its children) is visible. </description> </method> - <method name="canvas_item_set_z"> + <method name="canvas_item_set_z_as_relative_to_parent"> <return type="void"> </return> <argument index="0" name="item" type="RID"> </argument> - <argument index="1" name="z" type="int"> + <argument index="1" name="enabled" type="bool"> </argument> <description> - Sets the [CanvasItem]'s z order position. + If this is enabled, the z-index of the parent will be added to the children's z-index. </description> </method> - <method name="canvas_item_set_z_as_relative_to_parent"> + <method name="canvas_item_set_z_index"> <return type="void"> </return> <argument index="0" name="item" type="RID"> </argument> - <argument index="1" name="enabled" type="bool"> + <argument index="1" name="z_index" type="int"> </argument> <description> - If this is enabled, the z-position of the parent will be added to the childrens z-position. + Sets the [CanvasItem]'s z-index, i.e. its draw order (lower indexes are drawn first). </description> </method> <method name="canvas_light_attach_to_canvas"> diff --git a/doc/tools/makerst.py b/doc/tools/makerst.py index cd0108019b..492f3b6d54 100644 --- a/doc/tools/makerst.py +++ b/doc/tools/makerst.py @@ -276,6 +276,15 @@ def make_type(t): return ':ref:`' + t + '<class_' + t.lower() + '>`' return t +def make_enum(t): + global class_names + p = t.find(".") + if p >= 0: + c = t[0:p] + e = t[p+1:] + if c in class_names: + return ':ref:`' + e + '<enum_' + c.lower() + '_' + e.lower() + '>`' + return t def make_method( f, @@ -470,7 +479,10 @@ def make_rst_class(node): # Leading two spaces necessary to prevent breaking the <ul> f.write(" .. _class_" + name + "_" + c.attrib['name'] + ":\n\n") s = '- ' - s += make_type(c.attrib['type']) + ' ' + if 'enum' in c.attrib: + s += make_enum(c.attrib['enum']) + ' ' + else: + s += make_type(c.attrib['type']) + ' ' s += '**' + c.attrib['name'] + '**' if c.text.strip() != '': s += ' - ' + rstize_text(c.text.strip(), name) @@ -478,9 +490,20 @@ def make_rst_class(node): f.write('\n') constants = node.find('constants') + consts = [] + enum_names = set() + enums = [] if constants != None and len(list(constants)) > 0: - f.write(make_heading('Numeric Constants', '-')) for c in list(constants): + if 'enum' in c.attrib: + enum_names.add(c.attrib['enum']) + enums.append(c) + else: + consts.append(c) + + if len(consts) > 0: + f.write(make_heading('Numeric Constants', '-')) + for c in list(consts): s = '- ' s += '**' + c.attrib['name'] + '**' if 'value' in c.attrib: @@ -489,6 +512,24 @@ def make_rst_class(node): s += ' --- ' + rstize_text(c.text.strip(), name) f.write(s + '\n') f.write('\n') + + if len(enum_names) > 0: + f.write(make_heading('Enums', '-')) + for e in enum_names: + f.write(" .. _enum_" + name + "_" + e + ":\n\n") + f.write("enum **" + e + "**\n\n") + for c in enums: + if c.attrib['enum'] != e: + continue + s = '- ' + s += '**' + c.attrib['name'] + '**' + if 'value' in c.attrib: + s += ' = **' + c.attrib['value'] + '**' + if c.text.strip() != '': + s += ' --- ' + rstize_text(c.text.strip(), name) + f.write(s + '\n') + f.write('\n') + f.write('\n') descr = node.find('description') if descr != None and descr.text.strip() != '': diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 5ce544ecfb..d35d624589 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -6943,6 +6943,10 @@ bool RasterizerStorageGLES3::free(RID p_rid) { glDeleteTextures(1, &cls->distance); canvas_light_shadow_owner.free(p_rid); memdelete(cls); + } else if (particles_owner.owns(p_rid)) { + Particles *particles = particles_owner.get(p_rid); + particles_owner.free(p_rid); + memdelete(particles); } else { return false; } diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 4ef4926a1a..74bd0a3cc1 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -1180,7 +1180,7 @@ public: clear = true; inactive = true; - inactive_time = false; + inactive_time = 0.0; glGenBuffers(2, particle_buffers); glGenVertexArrays(2, particle_vaos); diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index cc4d060c02..e08b58cf5c 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -298,7 +298,7 @@ Error OS_Unix::execute(const String &p_path, const List<String> &p_arguments, bo args.push_back(0); #ifdef __FreeBSD__ - if (p_path.find("/")) { + if (p_path.find("/") != -1) { // exec name contains path so use it execv(p_path.utf8().get_data(), &args[0]); } else { @@ -362,7 +362,20 @@ String OS_Unix::get_locale() const { } Error OS_Unix::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { - p_library_handle = dlopen(p_path.utf8().get_data(), RTLD_NOW); + + String path = p_path; + + if (!FileAccess::exists(path)) { + //this code exists so gdnative can load .so files from within the executable path + path = get_executable_path().get_base_dir().plus_file(p_path.get_file()); + } + + if (!FileAccess::exists(path)) { + //this code exists so gdnative can load .so files from a standard unix location + path = get_executable_path().get_base_dir().plus_file("../lib").plus_file(p_path.get_file()); + } + + p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW); if (!p_library_handle) { ERR_EXPLAIN("Can't open dynamic library: " + p_path + ". Error: " + dlerror()); ERR_FAIL_V(ERR_CANT_OPEN); diff --git a/drivers/unix/os_unix.h b/drivers/unix/os_unix.h index 7929a791cb..d224a55647 100644 --- a/drivers/unix/os_unix.h +++ b/drivers/unix/os_unix.h @@ -55,7 +55,7 @@ protected: virtual void initialize_core(); virtual int unix_initialize_audio(int p_audio_driver); - //virtual void initialize(int p_video_driver,int p_audio_driver); + //virtual Error initialize(int p_video_driver,int p_audio_driver); virtual void finalize_core(); diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index a601c8cd2b..96c3a27ea7 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -37,7 +37,7 @@ #include "print_string.h" #include "scene/gui/box_container.h" -void CreateDialog::popup_create(bool p_dontclear) { +void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { recent->clear(); @@ -89,11 +89,12 @@ void CreateDialog::popup_create(bool p_dontclear) { popup_centered_ratio(); } - if (p_dontclear) + if (p_dont_clear) { search_box->select_all(); - else { + } else { search_box->clear(); } + search_box->grab_focus(); _update_search(); @@ -104,8 +105,19 @@ void CreateDialog::popup_create(bool p_dontclear) { if (enable_rl) { search_options->add_constant_override("draw_relationship_lines", 1); search_options->add_color_override("relationship_line_color", rl_color); - } else + } else { search_options->add_constant_override("draw_relationship_lines", 0); + } + + is_replace_mode = p_replace_mode; + + if (p_replace_mode) { + set_title(vformat(TTR("Change %s Type"), base_type)); + get_ok()->set_text(TTR("Change")); + } else { + set_title(vformat(TTR("Create New %s"), base_type)); + get_ok()->set_text(TTR("Create")); + } } void CreateDialog::_text_changed(const String &p_newtext) { @@ -369,7 +381,11 @@ void CreateDialog::_notification(int p_what) { void CreateDialog::set_base_type(const String &p_base) { base_type = p_base; - set_title(vformat(TTR("Create New %s"), p_base)); + if (is_replace_mode) + set_title(vformat(TTR("Change %s Type"), p_base)); + else + set_title(vformat(TTR("Create New %s"), p_base)); + _update_search(); } @@ -624,6 +640,8 @@ void CreateDialog::_bind_methods() { CreateDialog::CreateDialog() { + is_replace_mode = false; + ClassDB::get_class_list(&type_list); type_list.sort_custom<StringName::AlphCompare>(); @@ -678,7 +696,6 @@ CreateDialog::CreateDialog() { search_box->connect("gui_input", this, "_sbox_input"); search_options = memnew(Tree); vbc->add_margin_child(TTR("Matches:"), search_options, true); - get_ok()->set_text(TTR("Create")); get_ok()->set_disabled(true); register_text_enter(search_box); set_hide_on_ok(false); diff --git a/editor/create_dialog.h b/editor/create_dialog.h index 56ba7f8a3e..ed23fb4ae8 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -52,6 +52,7 @@ class CreateDialog : public ConfirmationDialog { Button *favorite; LineEdit *search_box; Tree *search_options; + bool is_replace_mode; String base_type; String preferred_search_result_type; EditorHelpBit *help_bit; @@ -97,7 +98,7 @@ public: void set_preferred_search_result_type(const String &p_preferred_type); String get_preferred_search_result_type(); - void popup_create(bool p_dontclear); + void popup_create(bool p_dont_clear, bool p_replace_mode = false); CreateDialog(); }; diff --git a/editor/dependency_editor.cpp b/editor/dependency_editor.cpp index f18a966151..4e753cb342 100644 --- a/editor/dependency_editor.cpp +++ b/editor/dependency_editor.cpp @@ -514,7 +514,7 @@ void DependencyRemoveDialog::ok_pressed() { print_line("Moving to trash: " + path); Error err = OS::get_singleton()->move_to_trash(path); if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:\n") + to_delete[i] + "\n"); + EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:") + "\n" + to_delete[i] + "\n"); } } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 4acee1363c..c12a112fa4 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -880,6 +880,7 @@ void EditorSelection::_bind_methods() { ClassDB::bind_method(D_METHOD("remove_node", "node"), &EditorSelection::remove_node); ClassDB::bind_method(D_METHOD("get_selected_nodes"), &EditorSelection::_get_selected_nodes); ClassDB::bind_method(D_METHOD("get_transformable_selected_nodes"), &EditorSelection::_get_transformable_selected_nodes); + ClassDB::bind_method(D_METHOD("_emit_change"), &EditorSelection::_emit_change); ADD_SIGNAL(MethodInfo("selection_changed")); } @@ -923,7 +924,15 @@ void EditorSelection::update() { if (!changed) return; changed = false; + if (!emitted) { + emitted = true; + call_deferred("_emit_change"); + } +} + +void EditorSelection::_emit_change() { emit_signal("selection_changed"); + emitted = false; } List<Node *> &EditorSelection::get_selected_node_list() { @@ -947,6 +956,7 @@ void EditorSelection::clear() { } EditorSelection::EditorSelection() { + emitted = false; changed = false; nl_changed = false; } diff --git a/editor/editor_data.h b/editor/editor_data.h index 2c95c3feea..3bc0e6e75c 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -210,9 +210,10 @@ class EditorSelection : public Object { GDCLASS(EditorSelection, Object); -public: +private: Map<Node *, Object *> selection; + bool emitted; bool changed; bool nl_changed; @@ -224,6 +225,7 @@ public: void _update_nl(); Array _get_selected_nodes(); Array _get_transformable_selected_nodes(); + void _emit_change(); protected: static void _bind_methods(); diff --git a/editor/editor_export.cpp b/editor/editor_export.cpp index 1a10040bac..e6a481eb01 100644 --- a/editor/editor_export.cpp +++ b/editor/editor_export.cpp @@ -1347,7 +1347,7 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr } if (template_path != String() && !FileAccess::exists(template_path)) { - EditorNode::get_singleton()->show_warning(TTR("Template file not found:\n") + template_path); + EditorNode::get_singleton()->show_warning(TTR("Template file not found:") + "\n" + template_path); return ERR_FILE_NOT_FOUND; } @@ -1361,7 +1361,19 @@ Error EditorExportPlatformPC::export_project(const Ref<EditorExportPreset> &p_pr String pck_path = p_path.get_basename() + ".pck"; - return save_pack(p_preset, pck_path); + Vector<SharedObject> so_files; + + err = save_pack(p_preset, pck_path, &so_files); + + if (err != OK || so_files.empty()) + return err; + //if shared object files, copy them + da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); + for (int i = 0; i < so_files.size(); i++) { + da->copy(so_files[i].path, p_path.get_base_dir().plus_file(so_files[i].path.get_file())); + } + memdelete(da); + return OK; } void EditorExportPlatformPC::set_extension(const String &p_extension, const String &p_feature_key) { diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index 1b885adf37..79542f3b5c 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -66,7 +66,9 @@ void EditorLog::_notification(int p_what) { Ref<DynamicFont> df_output_code = get_font("output_source", "EditorFonts"); if (df_output_code.is_valid()) { df_output_code->set_size(int(EDITOR_DEF("run/output/font_size", 13)) * EDSCALE); - log->add_font_override("normal_font", get_font("output_source", "EditorFonts")); + if (log != NULL) { + log->add_font_override("normal_font", get_font("output_source", "EditorFonts")); + } } } diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index b308d28dba..b52161813d 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4423,7 +4423,7 @@ void EditorNode::_dropped_files(const Vector<String> &p_files, int p_screen) { for (int i = 0; i < p_files.size(); i++) { String from = p_files[i]; - if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) < 0)) { + if (!ResourceFormatImporter::get_singleton()->can_be_imported(from) && (just_copy.find(from.get_extension().to_lower()) != -1)) { continue; } String to = to_path.plus_file(from.get_file()); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index b3ac5e4ce5..16e60edda7 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -200,6 +200,14 @@ ScriptEditor *EditorInterface::get_script_editor() { return ScriptEditor::get_singleton(); } +void EditorInterface::select_file(const String &p_file) { + return EditorNode::get_singleton()->get_filesystem_dock()->select_file(p_file); +} + +String EditorInterface::get_selected_path() const { + return EditorNode::get_singleton()->get_filesystem_dock()->get_selected_path(); +} + void EditorInterface::inspect_object(Object *p_obj, const String &p_for_property) { EditorNode::get_singleton()->push_item(p_obj, p_for_property); @@ -259,6 +267,8 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("get_resource_filesystem"), &EditorInterface::get_resource_file_system); ClassDB::bind_method(D_METHOD("get_editor_viewport"), &EditorInterface::get_editor_viewport); ClassDB::bind_method(D_METHOD("make_mesh_previews", "meshes", "preview_size"), &EditorInterface::_make_mesh_previews); + ClassDB::bind_method(D_METHOD("select_file", "p_file"), &EditorInterface::select_file); + ClassDB::bind_method(D_METHOD("get_selected_path"), &EditorInterface::get_selected_path); ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene); ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true)); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 4bfa1fa7cf..887e599208 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -76,6 +76,9 @@ public: Array get_open_scenes() const; ScriptEditor *get_script_editor(); + void select_file(const String &p_file); + String get_selected_path() const; + void inspect_object(Object *p_obj, const String &p_for_property = String()); EditorSelection *get_selection(); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index dc82a02f46..a5001cb1ac 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -1329,8 +1329,44 @@ Ref<ShortCut> ED_GET_SHORTCUT(const String &p_path) { return sc; } +struct ShortCutMapping { + const char *path; + uint32_t keycode; +}; + Ref<ShortCut> ED_SHORTCUT(const String &p_path, const String &p_name, uint32_t p_keycode) { +#ifdef OSX_ENABLED + static const ShortCutMapping macos_mappings[] = { + { "editor/play", KEY_MASK_CMD | KEY_B }, + { "editor/play_scene", KEY_MASK_CMD | KEY_R }, + { "editor/pause_scene", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_Y }, + { "editor/stop", KEY_MASK_CMD | KEY_PERIOD }, + { "editor/play_custom_scene", KEY_MASK_SHIFT | KEY_MASK_CMD | KEY_R }, + { "editor/editor_2d", KEY_MASK_ALT | KEY_1 }, + { "editor/editor_3d", KEY_MASK_ALT | KEY_2 }, + { "editor/editor_script", KEY_MASK_ALT | KEY_3 }, + { "editor/editor_help", KEY_MASK_ALT | KEY_SPACE }, + { "editor/fullscreen_mode", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_F }, + { "editor/distraction_free_mode", KEY_MASK_CMD | KEY_MASK_CTRL | KEY_D }, + { "script_text_editor/contextual_help", KEY_MASK_ALT | KEY_MASK_SHIFT | KEY_SPACE }, + { "script_text_editor/find_next", KEY_MASK_CMD | KEY_G }, + { "script_text_editor/find_previous", KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_G }, + { "script_text_editor/toggle_breakpoint", KEY_MASK_CMD | KEY_MASK_SHIFT | KEY_B } + }; + + if (p_keycode == KEY_DELETE) { + p_keycode = KEY_MASK_CMD | KEY_BACKSPACE; + } else { + for (int i = 0; i < sizeof(macos_mappings) / sizeof(ShortCutMapping); i++) { + if (p_path == macos_mappings[i].path) { + p_keycode = macos_mappings[i].keycode; + break; + } + } + } +#endif + Ref<InputEventKey> ie; if (p_keycode) { ie.instance(); diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index b19d015455..8a3e7e6716 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -332,6 +332,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color font_color = mono_color.linear_interpolate(base_color, 0.25); const Color font_color_hl = mono_color.linear_interpolate(base_color, 0.15); const Color font_color_disabled = Color(mono_color.r, mono_color.g, mono_color.b, 0.3); + const Color font_color_selection = Color::html("#7d7d7d"); const Color color_disabled = mono_color.inverted().linear_interpolate(base_color, 0.7); const Color color_disabled_bg = mono_color.inverted().linear_interpolate(base_color, 0.9); @@ -790,6 +791,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_color("read_only", "LineEdit", font_color_disabled); theme->set_color("font_color", "LineEdit", font_color); theme->set_color("cursor_color", "LineEdit", font_color); + theme->set_color("selection_color", "LineEdit", font_color_selection); // TextEdit theme->set_stylebox("normal", "TextEdit", style_widget); @@ -799,6 +801,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { theme->set_icon("tab", "TextEdit", theme->get_icon("GuiTab", "EditorIcons")); theme->set_color("font_color", "TextEdit", font_color); theme->set_color("caret_color", "TextEdit", highlight_color); + theme->set_color("selection_color", "TextEdit", font_color_selection); // H/VSplitContainer theme->set_stylebox("bg", "VSplitContainer", make_stylebox(theme->get_icon("GuiVsplitBg", "EditorIcons"), 1, 1, 1, 1)); diff --git a/editor/export_template_manager.cpp b/editor/export_template_manager.cpp index 0206e37c43..ccc9a52a3e 100644 --- a/editor/export_template_manager.cpp +++ b/editor/export_template_manager.cpp @@ -250,7 +250,7 @@ void ExportTemplateManager::_install_from_file(const String &p_file, bool p_use_ DirAccess *d = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); Error err = d->make_dir_recursive(template_path); if (err != OK) { - EditorNode::get_singleton()->show_warning(TTR("Error creating path for templates:\n") + template_path); + EditorNode::get_singleton()->show_warning(TTR("Error creating path for templates:") + "\n" + template_path); unzClose(pkg); return; } diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index b18cd6b747..e6bc19b571 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -752,7 +752,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_ return; } else if (!p_item.is_file && new_path.begins_with(old_path)) { //This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/" - EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.\n") + old_path + "\n"); + EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.") + "\n" + old_path + "\n"); return; } @@ -772,7 +772,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_ if (p_item.is_file && FileAccess::exists(old_path + ".import")) { err = da->rename(old_path + ".import", new_path + ".import"); if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error moving:\n") + old_path + ".import\n"); + EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + ".import\n"); } } @@ -796,7 +796,7 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_ print_line(" Remap: " + changed_paths[i] + " -> " + p_renames[changed_paths[i]]); } } else { - EditorNode::get_singleton()->add_io_error(TTR("Error moving:\n") + old_path + "\n"); + EditorNode::get_singleton()->add_io_error(TTR("Error moving:") + "\n" + old_path + "\n"); } memdelete(da); } @@ -813,7 +813,7 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin return; } else if (!p_item.is_file && new_path.begins_with(old_path)) { //This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/" - EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.\n") + old_path + "\n"); + EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.") + "\n" + old_path + "\n"); return; } @@ -825,11 +825,11 @@ void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const Strin if (p_item.is_file && FileAccess::exists(old_path + ".import")) { err = da->copy(old_path + ".import", new_path + ".import"); if (err != OK) { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + ".import\n"); + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + ".import\n"); } } } else { - EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + "\n"); + EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:") + "\n" + old_path + "\n"); } memdelete(da); } @@ -901,7 +901,7 @@ void FileSystemDock::_update_dependencies_after_move(const Map<String, String> & if (ResourceLoader::get_resource_type(file) == "PackedScene") editor->reload_scene(file); } else { - EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies:\n") + remaps[i] + "\n"); + EditorNode::get_singleton()->add_io_error(TTR("Unable to update dependencies:") + "\n" + remaps[i] + "\n"); } } } diff --git a/editor/plugins/baked_lightmap_editor_plugin.cpp b/editor/plugins/baked_lightmap_editor_plugin.cpp index 08f4d06ef7..6849563ae2 100644 --- a/editor/plugins/baked_lightmap_editor_plugin.cpp +++ b/editor/plugins/baked_lightmap_editor_plugin.cpp @@ -20,7 +20,6 @@ void BakedLightmapEditorPlugin::_bake() { case BakedLightmap::BAKE_ERROR_CANT_CREATE_IMAGE: EditorNode::get_singleton()->show_warning(TTR("Failed creating lightmap images, make sure path is writable.")); break; - defaut : {} } } } diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index a52c914096..d116e30cfe 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -3990,6 +3990,7 @@ void CanvasItemEditor::_bind_methods() { ClassDB::bind_method("_snap_changed", &CanvasItemEditor::_snap_changed); ClassDB::bind_method(D_METHOD("_selection_result_pressed"), &CanvasItemEditor::_selection_result_pressed); ClassDB::bind_method(D_METHOD("_selection_menu_hide"), &CanvasItemEditor::_selection_menu_hide); + ClassDB::bind_method(D_METHOD("set_state"), &CanvasItemEditor::set_state); ADD_SIGNAL(MethodInfo("item_lock_status_changed")); ADD_SIGNAL(MethodInfo("item_group_status_changed")); @@ -4348,7 +4349,7 @@ CanvasItemEditor::CanvasItemEditor(EditorNode *p_editor) { additive_selection = false; // Update the menus checkboxes - set_state(get_state()); + call_deferred("set_state", get_state()); } CanvasItemEditor *CanvasItemEditor::singleton = NULL; diff --git a/editor/plugins/curve_editor_plugin.cpp b/editor/plugins/curve_editor_plugin.cpp index c865ddd4b0..3be68f21af 100644 --- a/editor/plugins/curve_editor_plugin.cpp +++ b/editor/plugins/curve_editor_plugin.cpp @@ -347,7 +347,8 @@ void CurveEditor::open_context_menu(Vector2 pos) { _context_menu->set_item_checked(_context_menu->get_item_index(CONTEXT_LINEAR), is_linear); } else { - _context_menu->add_separator(); + if (_selected_point > 0 || _selected_point + 1 < _curve_ref->get_point_count()) + _context_menu->add_separator(); if (_selected_point > 0) { _context_menu->add_check_item(TTR("Left linear"), CONTEXT_LEFT_LINEAR); @@ -367,6 +368,7 @@ void CurveEditor::open_context_menu(Vector2 pos) { _context_menu->add_submenu_item(TTR("Load preset"), _presets_menu->get_name()); + _context_menu->set_size(Size2(0, 0)); _context_menu->popup(); } @@ -566,7 +568,6 @@ static void plot_curve_accurate(const Curve &curve, float step, T plot_func) { Vector2 prev_pos = a; float len = b.x - a.x; - //float step = 4.f / view_size.x; for (float x = step; x < len; x += step) { pos.x = a.x + x; @@ -694,24 +695,6 @@ void CurveEditor::_draw() { CanvasItemPlotCurve plot_func(*this, line_color, edge_line_color); plot_curve_accurate(curve, 4.f / view_size.x, plot_func); - /*// TEST draw baked curve - { - Vector2 pos = Vector2(0, curve.interpolate_baked(0)); - Vector2 prev_pos = pos; - - float len = 1.0; - float step = 4.f / view_size.x; - - for(float x = step; x < len; x += step) { - pos.x = x; - pos.y = curve.interpolate_baked(x); - draw_line(get_point_view_pos(prev_pos), get_point_view_pos(pos), Color(0,1,0)); - prev_pos = pos; - } - - draw_line(get_point_view_pos(prev_pos), get_point_view_pos(Vector2(1, curve.interpolate_baked(1))), Color(0,1,0)); - }//*/ - // Draw points draw_set_transform_matrix(Transform2D()); diff --git a/editor/plugins/navigation_mesh_editor_plugin.cpp b/editor/plugins/navigation_mesh_editor_plugin.cpp index 8c80225db6..933ab36886 100644 --- a/editor/plugins/navigation_mesh_editor_plugin.cpp +++ b/editor/plugins/navigation_mesh_editor_plugin.cpp @@ -107,7 +107,7 @@ NavigationMeshEditor::NavigationMeshEditor() { button_bake->set_text(TTR("Bake!")); button_bake->set_toggle_mode(true); button_reset = memnew(Button); - button_bake->set_tooltip(TTR("Bake the navigation mesh.\n")); + button_bake->set_tooltip(TTR("Bake the navigation mesh.") + "\n"); bake_info = memnew(Label); bake_hbox->add_child(button_bake); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index f6aef52e8b..71f15a4421 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -4947,7 +4947,7 @@ SpatialEditor::SpatialEditor(EditorNode *p_editor) { tool_button[TOOL_MODE_SELECT]->set_pressed(true); button_binds[0] = MENU_TOOL_SELECT; tool_button[TOOL_MODE_SELECT]->connect("pressed", this, "_menu_item_pressed", button_binds); - tool_button[TOOL_MODE_SELECT]->set_tooltip(TTR("Select Mode (Q)\n") + keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection")); + tool_button[TOOL_MODE_SELECT]->set_tooltip(TTR("Select Mode (Q)") + "\n" + keycode_get_string(KEY_MASK_CMD) + TTR("Drag: Rotate\nAlt+Drag: Move\nAlt+RMB: Depth list selection")); tool_button[TOOL_MODE_MOVE] = memnew(ToolButton); hbc_menu->add_child(tool_button[TOOL_MODE_MOVE]); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index eccb11ba12..475cdf07ba 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -238,19 +238,16 @@ void TileSetEditor::_bind_methods() { TileSetEditor::TileSetEditor(EditorNode *p_editor) { - Panel *panel = memnew(Panel); - panel->set_anchors_and_margins_preset(Control::PRESET_WIDE); - add_child(panel); - MenuButton *options = memnew(MenuButton); - panel->add_child(options); - options->set_position(Point2(1, 1)); - options->set_text(TTR("Tile Set")); - options->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); - options->get_popup()->add_item(TTR("Remove Item"), MENU_OPTION_REMOVE_ITEM); - options->get_popup()->add_separator(); - options->get_popup()->add_item(TTR("Create from Scene"), MENU_OPTION_CREATE_FROM_SCENE); - options->get_popup()->add_item(TTR("Merge from Scene"), MENU_OPTION_MERGE_FROM_SCENE); - options->get_popup()->connect("id_pressed", this, "_menu_cbk"); + menu = memnew(MenuButton); + CanvasItemEditor::get_singleton()->add_control_to_menu_panel(menu); + menu->hide(); + menu->set_text(TTR("Tile Set")); + menu->get_popup()->add_item(TTR("Add Item"), MENU_OPTION_ADD_ITEM); + menu->get_popup()->add_item(TTR("Remove Item"), MENU_OPTION_REMOVE_ITEM); + menu->get_popup()->add_separator(); + menu->get_popup()->add_item(TTR("Create from Scene"), MENU_OPTION_CREATE_FROM_SCENE); + menu->get_popup()->add_item(TTR("Merge from Scene"), MENU_OPTION_MERGE_FROM_SCENE); + menu->get_popup()->connect("id_pressed", this, "_menu_cbk"); editor = p_editor; cd = memnew(ConfirmationDialog); add_child(cd); @@ -286,6 +283,7 @@ void TileSetEditorPlugin::make_visible(bool p_visible) { if (p_visible) { tileset_editor->show(); + tileset_editor->menu->show(); autotile_button->show(); autotile_editor->side_panel->show(); if (autotile_button->is_pressed()) { @@ -293,6 +291,7 @@ void TileSetEditorPlugin::make_visible(bool p_visible) { } } else { tileset_editor->hide(); + tileset_editor->menu->hide(); autotile_editor->side_panel->hide(); autotile_editor->hide(); autotile_button->hide(); @@ -343,9 +342,9 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { split->add_child(property_editor); helper = memnew(AutotileEditorHelper(this)); - property_editor->edit(helper); + property_editor->call_deferred("edit", helper); - // Editor + //Editor dragging_point = -1; creating_shape = false; @@ -420,8 +419,6 @@ AutotileEditor::AutotileEditor(EditorNode *p_editor) { p.push_back((int)SHAPE_DELETE); tools[SHAPE_DELETE]->connect("pressed", this, "_on_tool_clicked", p); tool_containers[TOOLBAR_SHAPE]->add_child(tools[SHAPE_DELETE]); - //tools[SHAPE_CREATE_FROM_NOT_BITMASKED] = memnew(ToolButton); - //tool_containers[TOOLBAR_SHAPE]->add_child(tools[SHAPE_CREATE_FROM_NOT_BITMASKED]); tool_containers[TOOLBAR_SHAPE]->add_change_receptor(memnew(VSeparator)); tools[SHAPE_KEEP_INSIDE_TILE] = memnew(ToolButton); tools[SHAPE_KEEP_INSIDE_TILE]->set_toggle_mode(true); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index eb5cec2a2e..3d4ae90c89 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1101,6 +1101,7 @@ void ProjectManager::_load_recent_projects() { hb->add_child(vb); Control *ec = memnew(Control); ec->set_custom_minimum_size(Size2(0, 1)); + ec->set_mouse_filter(MOUSE_FILTER_PASS); vb->add_child(ec); Label *title = memnew(Label(project_name)); title->add_font_override("font", gui_base->get_font("title", "EditorFonts")); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 1dcc5a3231..89dcae0038 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -4135,6 +4135,7 @@ void PropertyEditor::_bind_methods() { ClassDB::bind_method("_resource_preview_done", &PropertyEditor::_resource_preview_done); ClassDB::bind_method("refresh", &PropertyEditor::refresh); ClassDB::bind_method("_draw_transparency", &PropertyEditor::_draw_transparency); + ClassDB::bind_method("edit", &PropertyEditor::edit); ClassDB::bind_method(D_METHOD("get_drag_data_fw"), &PropertyEditor::get_drag_data_fw); ClassDB::bind_method(D_METHOD("can_drop_data_fw"), &PropertyEditor::can_drop_data_fw); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 7e8a6fcb6d..e7da78a35c 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -307,7 +307,7 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { } break; case TOOL_REPLACE: { - create_dialog->popup_create(false); + create_dialog->popup_create(false, true); } break; case TOOL_ATTACH_SCRIPT: { @@ -417,7 +417,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (editor_selection->is_selected(edited_scene)) { current_option = -1; - //accept->get_cancel()->hide(); accept->get_ok()->set_text(TTR("I see..")); accept->set_text(TTR("This operation can't be done on the tree root.")); accept->popup_centered_minsize(); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index ad6ea2180f..96863a59d2 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -232,7 +232,7 @@ void ScriptCreateDialog::_lang_changed(int l) { String path = file_path->get_text(); String extension = ""; if (path != "") { - if (path.find(".") >= 0) { + if (path.find(".") != -1) { extension = path.get_extension(); } @@ -359,16 +359,14 @@ void ScriptCreateDialog::_path_changed(const String &p_path) { return; } - if (p.find("/") || p.find("\\")) { - DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); - if (d->change_dir(p.get_base_dir()) != OK) { - _msg_path_valid(false, TTR("Invalid base path")); - memdelete(d); - _update_dialog(); - return; - } + DirAccess *d = DirAccess::create(DirAccess::ACCESS_RESOURCES); + if (d->change_dir(p.get_base_dir()) != OK) { + _msg_path_valid(false, TTR("Invalid base path")); memdelete(d); + _update_dialog(); + return; } + memdelete(d); /* Does file already exist */ diff --git a/main/main.cpp b/main/main.cpp index ac68fe1296..1cb89e87ef 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -983,7 +983,10 @@ Error Main::setup2(Thread::ID p_main_tid_override) { Thread::_main_thread_id = p_main_tid_override; } - OS::get_singleton()->initialize(video_mode, video_driver_idx, audio_driver_idx); + Error err = OS::get_singleton()->initialize(video_mode, video_driver_idx, audio_driver_idx); + if (err != OK) { + return err; + } if (init_use_custom_pos) { OS::get_singleton()->set_window_position(init_custom_pos); } diff --git a/modules/bullet/bullet_types_converter.cpp b/modules/bullet/bullet_types_converter.cpp index 03247a91ca..42a6f156a5 100644 --- a/modules/bullet/bullet_types_converter.cpp +++ b/modules/bullet/bullet_types_converter.cpp @@ -92,3 +92,14 @@ void G_TO_B(Transform const &inVal, btTransform &outVal) { G_TO_B(inVal.basis, outVal.getBasis()); G_TO_B(inVal.origin, outVal.getOrigin()); } + +void UNSCALE_BT_BASIS(btTransform &scaledBasis) { + btMatrix3x3 &m(scaledBasis.getBasis()); + btVector3 column0(m[0][0], m[1][0], m[2][0]); + btVector3 column1(m[0][1], m[1][1], m[2][1]); + btVector3 column2(m[0][2], m[1][2], m[2][2]); + column0.normalize(); + column1.normalize(); + column2.normalize(); + m.setValue(column0[0], column1[0], column2[0], column0[1], column1[1], column2[1], column0[2], column1[2], column2[2]); +} diff --git a/modules/bullet/bullet_types_converter.h b/modules/bullet/bullet_types_converter.h index 5fa30c1d74..349cad65aa 100644 --- a/modules/bullet/bullet_types_converter.h +++ b/modules/bullet/bullet_types_converter.h @@ -54,4 +54,5 @@ extern void G_TO_B(Basis const &inVal, btMatrix3x3 &outVal); extern void INVERT_G_TO_B(Basis const &inVal, btMatrix3x3 &outVal); extern void G_TO_B(Transform const &inVal, btTransform &outVal); +extern void UNSCALE_BT_BASIS(btTransform &scaledBasis); #endif diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 70d604fa70..1350be20b6 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -57,7 +57,8 @@ CollisionObjectBullet::CollisionObjectBullet(Type p_type) : collisionsEnabled(true), m_isStatic(false), bt_collision_object(NULL), - body_scale(1., 1., 1.) {} + body_scale(1., 1., 1.), + force_shape_reset(false) {} CollisionObjectBullet::~CollisionObjectBullet() { // Remove all overlapping @@ -88,6 +89,7 @@ btVector3 CollisionObjectBullet::get_bt_body_scale() const { } void CollisionObjectBullet::on_body_scale_changed() { + force_shape_reset = true; } void CollisionObjectBullet::destroyBulletCollisionObject() { @@ -289,15 +291,27 @@ void RigidCollisionObjectBullet::on_shape_changed(const ShapeBullet *const p_sha void RigidCollisionObjectBullet::on_shapes_changed() { int i; + // Remove all shapes, reverse order for performance reason (Array resize) for (i = compoundShape->getNumChildShapes() - 1; 0 <= i; --i) { compoundShape->removeChildShapeByIndex(i); } - // Insert all shapes ShapeWrapper *shpWrapper; - const int size = shapes.size(); - for (i = 0; i < size; ++i) { + const int shapes_size = shapes.size(); + + // Reset shape if required + if (force_shape_reset) { + for (i = 0; i < shapes_size; ++i) { + shpWrapper = &shapes[i]; + bulletdelete(shpWrapper->bt_shape); + } + force_shape_reset = false; + } + + // Insert all shapes + + for (i = 0; i < shapes_size; ++i) { shpWrapper = &shapes[i]; if (shpWrapper->active) { if (!shpWrapper->bt_shape) { diff --git a/modules/bullet/collision_object_bullet.h b/modules/bullet/collision_object_bullet.h index 4168133e0d..6a3fbe65ff 100644 --- a/modules/bullet/collision_object_bullet.h +++ b/modules/bullet/collision_object_bullet.h @@ -115,6 +115,7 @@ protected: bool ray_pickable; btCollisionObject *bt_collision_object; Vector3 body_scale; + bool force_shape_reset; SpaceBullet *space; VSet<RID> exceptions; diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index e7342e2ae8..c183b012ab 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -205,41 +205,20 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() { if (!shape_wrapper->active) { continue; } - shapes[i].transform = shape_wrapper->transform; - - btConvexShape *&kin_shape_ref = shapes[i].shape; + shapes[i].transform = shape_wrapper->transform; + shapes[i].transform.getOrigin() *= owner_body_scale; switch (shape_wrapper->shape->get_type()) { - case PhysicsServer::SHAPE_SPHERE: { - SphereShapeBullet *sphere = static_cast<SphereShapeBullet *>(shape_wrapper->shape); - kin_shape_ref = ShapeBullet::create_shape_sphere(sphere->get_radius() * owner_body_scale[0] + safe_margin); - break; - } - case PhysicsServer::SHAPE_BOX: { - BoxShapeBullet *box = static_cast<BoxShapeBullet *>(shape_wrapper->shape); - kin_shape_ref = ShapeBullet::create_shape_box((box->get_half_extents() * owner_body_scale) + btVector3(safe_margin, safe_margin, safe_margin)); - break; - } - case PhysicsServer::SHAPE_CAPSULE: { - CapsuleShapeBullet *capsule = static_cast<CapsuleShapeBullet *>(shape_wrapper->shape); - - kin_shape_ref = ShapeBullet::create_shape_capsule(capsule->get_radius() * owner_body_scale[0] + safe_margin, capsule->get_height() * owner_body_scale[1] + safe_margin); - break; - } - case PhysicsServer::SHAPE_CONVEX_POLYGON: { - ConvexPolygonShapeBullet *godot_convex = static_cast<ConvexPolygonShapeBullet *>(shape_wrapper->shape); - kin_shape_ref = ShapeBullet::create_shape_convex(godot_convex->vertices); - kin_shape_ref->setLocalScaling(owner_body_scale + btVector3(safe_margin, safe_margin, safe_margin)); - break; - } + case PhysicsServer::SHAPE_SPHERE: + case PhysicsServer::SHAPE_BOX: + case PhysicsServer::SHAPE_CAPSULE: + case PhysicsServer::SHAPE_CONVEX_POLYGON: case PhysicsServer::SHAPE_RAY: { - RayShapeBullet *godot_ray = static_cast<RayShapeBullet *>(shape_wrapper->shape); - kin_shape_ref = ShapeBullet::create_shape_ray(godot_ray->length * owner_body_scale[1] + safe_margin); - break; - } + shapes[i].shape = static_cast<btConvexShape *>(shape_wrapper->shape->create_bt_shape(owner_body_scale, safe_margin)); + } break; default: WARN_PRINT("This shape is not supported to be kinematic!"); - kin_shape_ref = NULL; + shapes[i].shape = NULL; } } } diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index 55cc742f0a..d5a89e39e2 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -43,6 +43,17 @@ ShapeBullet::ShapeBullet() {} ShapeBullet::~ShapeBullet() {} +btCollisionShape *ShapeBullet::create_bt_shape() { + btVector3 s(1, 1, 1); + return create_bt_shape(s); +} + +btCollisionShape *ShapeBullet::create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin) { + btVector3 s; + G_TO_B(p_implicit_scale, s); + return create_bt_shape(s, p_margin); +} + btCollisionShape *ShapeBullet::prepare(btCollisionShape *p_btShape) const { p_btShape->setUserPointer(const_cast<ShapeBullet *>(this)); p_btShape->setMargin(0.); @@ -150,7 +161,7 @@ void PlaneShapeBullet::setup(const Plane &p_plane) { notifyShapeChanged(); } -btCollisionShape *PlaneShapeBullet::create_bt_shape() { +btCollisionShape *PlaneShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { btVector3 btPlaneNormal; G_TO_B(plane.normal, btPlaneNormal); return prepare(PlaneShapeBullet::create_shape_plane(btPlaneNormal, plane.d)); @@ -178,8 +189,8 @@ void SphereShapeBullet::setup(real_t p_radius) { notifyShapeChanged(); } -btCollisionShape *SphereShapeBullet::create_bt_shape() { - return prepare(ShapeBullet::create_shape_sphere(radius)); +btCollisionShape *SphereShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { + return prepare(ShapeBullet::create_shape_sphere(radius * p_implicit_scale[0] + p_margin)); } /* Box */ @@ -205,8 +216,8 @@ void BoxShapeBullet::setup(const Vector3 &p_half_extents) { notifyShapeChanged(); } -btCollisionShape *BoxShapeBullet::create_bt_shape() { - return prepare(ShapeBullet::create_shape_box(half_extents)); +btCollisionShape *BoxShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { + return prepare(ShapeBullet::create_shape_box((half_extents * p_implicit_scale) + btVector3(p_margin, p_margin, p_margin))); } /* Capsule */ @@ -238,8 +249,8 @@ void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) { notifyShapeChanged(); } -btCollisionShape *CapsuleShapeBullet::create_bt_shape() { - return prepare(ShapeBullet::create_shape_capsule(radius, height)); +btCollisionShape *CapsuleShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { + return prepare(ShapeBullet::create_shape_capsule(radius * p_implicit_scale[0] + p_margin, height * p_implicit_scale[1] + p_margin)); } /* Convex polygon */ @@ -280,8 +291,12 @@ void ConvexPolygonShapeBullet::setup(const Vector<Vector3> &p_vertices) { notifyShapeChanged(); } -btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape() { - return prepare(ShapeBullet::create_shape_convex(vertices)); +btCollisionShape *ConvexPolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { + btCollisionShape *cs(ShapeBullet::create_shape_convex(vertices)); + cs->setLocalScaling(p_implicit_scale); + prepare(cs); + cs->setMargin(p_margin); + return cs; } /* Concave polygon */ @@ -349,13 +364,15 @@ void ConcavePolygonShapeBullet::setup(PoolVector<Vector3> p_faces) { notifyShapeChanged(); } -btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape() { +btCollisionShape *ConcavePolygonShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { btCollisionShape *cs = ShapeBullet::create_shape_concave(meshShape); - if (!cs) { + if (!cs) // This is necessary since if 0 faces the creation of concave return NULL cs = ShapeBullet::create_shape_empty(); - } - return prepare(cs); + cs->setLocalScaling(p_implicit_scale); + prepare(cs); + cs->setMargin(p_margin); + return cs; } /* Height map shape */ @@ -407,8 +424,12 @@ void HeightMapShapeBullet::setup(PoolVector<real_t> &p_heights, int p_width, int notifyShapeChanged(); } -btCollisionShape *HeightMapShapeBullet::create_bt_shape() { - return prepare(ShapeBullet::create_shape_height_field(heights, width, depth, cell_size)); +btCollisionShape *HeightMapShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { + btCollisionShape *cs(ShapeBullet::create_shape_height_field(heights, width, depth, cell_size)); + cs->setLocalScaling(p_implicit_scale); + prepare(cs); + cs->setMargin(p_margin); + return cs; } /* Ray shape */ @@ -433,6 +454,6 @@ void RayShapeBullet::setup(real_t p_length) { notifyShapeChanged(); } -btCollisionShape *RayShapeBullet::create_bt_shape() { - return prepare(ShapeBullet::create_shape_ray(length)); +btCollisionShape *RayShapeBullet::create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin) { + return prepare(ShapeBullet::create_shape_ray(length * p_implicit_scale[1] + p_margin)); } diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index fa12e95efc..a9782a9333 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -58,7 +58,9 @@ public: ShapeBullet(); virtual ~ShapeBullet(); - virtual btCollisionShape *create_bt_shape() = 0; + btCollisionShape *create_bt_shape(); + btCollisionShape *create_bt_shape(const Vector3 &p_implicit_scale, real_t p_margin = 0); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0) = 0; void add_owner(ShapeOwnerBullet *p_owner); void remove_owner(ShapeOwnerBullet *p_owner, bool p_permanentlyFromThisBody = false); @@ -94,7 +96,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(const Plane &p_plane); @@ -111,7 +113,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(real_t p_radius); @@ -128,7 +130,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(const Vector3 &p_half_extents); @@ -147,7 +149,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(real_t p_height, real_t p_radius); @@ -164,7 +166,7 @@ public: void get_vertices(Vector<Vector3> &out_vertices); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(const Vector<Vector3> &p_vertices); @@ -182,7 +184,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(PoolVector<Vector3> p_faces); @@ -201,7 +203,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(PoolVector<real_t> &p_heights, int p_width, int p_depth, real_t p_cell_size); @@ -217,7 +219,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; virtual PhysicsServer::ShapeType get_type() const; - virtual btCollisionShape *create_bt_shape(); + virtual btCollisionShape *create_bt_shape(const btVector3 &p_scale, real_t p_margin = 0); private: void setup(real_t p_length); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index dc16d8402d..a67c627ba4 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -116,7 +116,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); - btCollisionShape *btShape = shape->create_bt_shape(); + btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); @@ -124,12 +124,9 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra } btConvexShape *btConvex = static_cast<btConvexShape *>(btShape); - btVector3 scale_with_margin; - G_TO_B(p_xform.basis.get_scale(), scale_with_margin); - btConvex->setLocalScaling(scale_with_margin); - btTransform bt_xform; G_TO_B(p_xform, bt_xform); + UNSCALE_BT_BASIS(bt_xform); btCollisionObject collision_object; collision_object.setCollisionShape(btConvex); @@ -138,7 +135,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra GodotAllContactResultCallback btQuery(&collision_object, p_results, p_result_max, &p_exclude); btQuery.m_collisionFilterGroup = 0; btQuery.m_collisionFilterMask = p_collision_mask; - btQuery.m_closestDistanceThreshold = p_margin; + btQuery.m_closestDistanceThreshold = 0; space->dynamicsWorld->contactTest(&collision_object, btQuery); bulletdelete(btConvex); @@ -149,7 +146,7 @@ int BulletPhysicsDirectSpaceState::intersect_shape(const RID &p_shape, const Tra bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set<RID> &p_exclude, uint32_t p_collision_mask, ShapeRestInfo *r_info) { ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); - btCollisionShape *btShape = shape->create_bt_shape(); + btCollisionShape *btShape = shape->create_bt_shape(p_xform.basis.get_scale(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); @@ -160,12 +157,9 @@ bool BulletPhysicsDirectSpaceState::cast_motion(const RID &p_shape, const Transf btVector3 bt_motion; G_TO_B(p_motion, bt_motion); - btVector3 scale_with_margin; - G_TO_B(p_xform.basis.get_scale() + Vector3(p_margin, p_margin, p_margin), scale_with_margin); - bt_convex_shape->setLocalScaling(scale_with_margin); - btTransform bt_xform_from; G_TO_B(p_xform, bt_xform_from); + UNSCALE_BT_BASIS(bt_xform_from); btTransform bt_xform_to(bt_xform_from); bt_xform_to.getOrigin() += bt_motion; @@ -202,7 +196,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); - btCollisionShape *btShape = shape->create_bt_shape(); + btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); @@ -210,12 +204,9 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & } btConvexShape *btConvex = static_cast<btConvexShape *>(btShape); - btVector3 scale_with_margin; - G_TO_B(p_shape_xform.basis.get_scale(), scale_with_margin); - btConvex->setLocalScaling(scale_with_margin); - btTransform bt_xform; G_TO_B(p_shape_xform, bt_xform); + UNSCALE_BT_BASIS(bt_xform); btCollisionObject collision_object; collision_object.setCollisionShape(btConvex); @@ -224,7 +215,7 @@ bool BulletPhysicsDirectSpaceState::collide_shape(RID p_shape, const Transform & GodotContactPairContactResultCallback btQuery(&collision_object, r_results, p_result_max, &p_exclude); btQuery.m_collisionFilterGroup = 0; btQuery.m_collisionFilterMask = p_collision_mask; - btQuery.m_closestDistanceThreshold = p_margin; + btQuery.m_closestDistanceThreshold = 0; space->dynamicsWorld->contactTest(&collision_object, btQuery); r_result_count = btQuery.m_count; @@ -237,7 +228,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh ShapeBullet *shape = space->get_physics_server()->get_shape_owner()->get(p_shape); - btCollisionShape *btShape = shape->create_bt_shape(); + btCollisionShape *btShape = shape->create_bt_shape(p_shape_xform.basis.get_scale(), p_margin); if (!btShape->isConvex()) { bulletdelete(btShape); ERR_PRINTS("The shape is not a convex shape, then is not supported: shape type: " + itos(shape->get_type())); @@ -245,12 +236,9 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh } btConvexShape *btConvex = static_cast<btConvexShape *>(btShape); - btVector3 scale_with_margin; - G_TO_B(p_shape_xform.basis.get_scale() + Vector3(p_margin, p_margin, p_margin), scale_with_margin); - btConvex->setLocalScaling(scale_with_margin); - btTransform bt_xform; G_TO_B(p_shape_xform, bt_xform); + UNSCALE_BT_BASIS(bt_xform); btCollisionObject collision_object; collision_object.setCollisionShape(btConvex); @@ -259,7 +247,7 @@ bool BulletPhysicsDirectSpaceState::rest_info(RID p_shape, const Transform &p_sh GodotRestInfoContactResultCallback btQuery(&collision_object, r_info, &p_exclude); btQuery.m_collisionFilterGroup = 0; btQuery.m_collisionFilterMask = p_collision_mask; - btQuery.m_closestDistanceThreshold = p_margin; + btQuery.m_closestDistanceThreshold = 0; space->dynamicsWorld->contactTest(&collision_object, btQuery); bulletdelete(btConvex); @@ -796,7 +784,9 @@ void SpaceBullet::update_gravity() { /// I'm leaving this here just for future tests. /// Debug motion and normal vector drawing #define debug_test_motion 0 -#define PERFORM_INITIAL_UNSTACK 1 +#define PERFORM_INITIAL_UNSTACK 0 +#define RECOVERING_MOVEMENT_SCALE 0.4 +#define RECOVERING_MOVEMENT_CYCLES 4 #if debug_test_motion @@ -820,6 +810,9 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f SceneTree::get_singleton()->get_current_scene()->add_child(motionVec); SceneTree::get_singleton()->get_current_scene()->add_child(normalLine); + motionVec->set_as_toplevel(true); + normalLine->set_as_toplevel(true); + red_mat = Ref<SpatialMaterial>(memnew(SpatialMaterial)); red_mat->set_flag(SpatialMaterial::FLAG_UNSHADED, true); red_mat->set_line_width(20.0); @@ -850,20 +843,24 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f // } //} - btVector3 recover_initial_position(0, 0, 0); - btTransform body_safe_position; G_TO_B(p_from, body_safe_position); + UNSCALE_BT_BASIS(body_safe_position); - { /// Phase one - multi shapes depenetration using margin #if PERFORM_INITIAL_UNSTACK - if (recover_from_penetration(p_body, body_safe_position, recover_initial_position)) { + btVector3 recover_initial_position(0, 0, 0); + { /// Phase one - multi shapes depenetration using margin + for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { + if (recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recover_initial_position)) { - // Add recover position to "From" and "To" transforms - body_safe_position.getOrigin() += recover_initial_position; + // Add recover position to "From" and "To" transforms + body_safe_position.getOrigin() += recover_initial_position; + } else { + break; + } } -#endif } +#endif btVector3 recovered_motion; G_TO_B(p_motion, recovered_motion); @@ -872,13 +869,13 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f { /// phase two - sweep test, from a secure position without margin #if debug_test_motion - Vector3 sup_line; - B_TO_G(body_safe_position.getOrigin(), sup_line); - motionVec->clear(); - motionVec->begin(Mesh::PRIMITIVE_LINES, NULL); - motionVec->add_vertex(sup_line); - motionVec->add_vertex(sup_line + p_motion * 10); - motionVec->end(); +//Vector3 sup_line; +//B_TO_G(body_safe_position.getOrigin(), sup_line); +//motionVec->clear(); +//motionVec->begin(Mesh::PRIMITIVE_LINES, NULL); +//motionVec->add_vertex(sup_line); +//motionVec->add_vertex(sup_line + p_motion * 10); +//motionVec->end(); #endif for (int shIndex = 0; shIndex < shape_count; ++shIndex) { @@ -892,11 +889,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f } btConvexShape *convex_shape_test(static_cast<btConvexShape *>(p_body->get_bt_shape(shIndex))); - btTransform shape_world_from; - G_TO_B(p_body->get_shape_transform(shIndex), shape_world_from); - - // Add local shape transform - shape_world_from = body_safe_position * shape_world_from; + btTransform shape_world_from = body_safe_position * p_body->get_kinematic_utilities()->shapes[shIndex].transform; btTransform shape_world_to(shape_world_from); shape_world_to.getOrigin() += recovered_motion; @@ -915,59 +908,75 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f } } - bool hasPenetration = false; + bool has_penetration = false; { /// Phase three - Recover + contact test with margin RecoverResult r_recover_result; + bool l_has_penetration; + real_t l_penetration_distance = 1e20; - hasPenetration = recover_from_penetration(p_body, body_safe_position, recovered_motion, &r_recover_result); + for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { + l_has_penetration = recover_from_penetration(p_body, body_safe_position, RECOVERING_MOVEMENT_SCALE, recovered_motion, &r_recover_result); - if (r_result) { - - B_TO_G(recovered_motion + recover_initial_position, r_result->motion); - - if (hasPenetration) { - const btRigidBody *btRigid = static_cast<const btRigidBody *>(r_recover_result.other_collision_object); - CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(btRigid->getUserPointer()); - - r_result->remainder = p_motion - r_result->motion; // is the remaining movements - B_TO_G(r_recover_result.pointWorld, r_result->collision_point); - B_TO_G(r_recover_result.pointNormalWorld, r_result->collision_normal); - B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); // It calculates velocity at point and assign it using special function Bullet_to_Godot - r_result->collider = collisionObject->get_self(); - r_result->collider_id = collisionObject->get_instance_id(); - r_result->collider_shape = r_recover_result.other_compound_shape_index; - r_result->collision_local_shape = r_recover_result.local_shape_most_recovered; + if (r_result) { +#if PERFORM_INITIAL_UNSTACK + B_TO_G(recovered_motion + recover_initial_position, r_result->motion); +#else + B_TO_G(recovered_motion, r_result->motion); +#endif + if (l_has_penetration) { + has_penetration = true; + if (l_penetration_distance <= r_recover_result.penetration_distance) { + continue; + } - //{ /// Add manifold point to manage collisions - // btPersistentManifold* manifold = dynamicsWorld->getDispatcher()->getNewManifold(p_body->getBtBody(), btRigid); - // btManifoldPoint manifoldPoint(result_callabck.m_pointWorld, result_callabck.m_pointWorld, result_callabck.m_pointNormalWorld, result_callabck.m_penetration_distance); - // manifoldPoint.m_index0 = r_result->collision_local_shape; - // manifoldPoint.m_index1 = r_result->collider_shape; - // manifold->addManifoldPoint(manifoldPoint); - // p_body->get_kinematic_utilities()->m_generatedManifold.push_back(manifold); - //} + l_penetration_distance = r_recover_result.penetration_distance; + + const btRigidBody *btRigid = static_cast<const btRigidBody *>(r_recover_result.other_collision_object); + CollisionObjectBullet *collisionObject = static_cast<CollisionObjectBullet *>(btRigid->getUserPointer()); + + r_result->remainder = p_motion - r_result->motion; // is the remaining movements + B_TO_G(r_recover_result.pointWorld, r_result->collision_point); + B_TO_G(r_recover_result.normal, r_result->collision_normal); + B_TO_G(btRigid->getVelocityInLocalPoint(r_recover_result.pointWorld - btRigid->getWorldTransform().getOrigin()), r_result->collider_velocity); // It calculates velocity at point and assign it using special function Bullet_to_Godot + r_result->collider = collisionObject->get_self(); + r_result->collider_id = collisionObject->get_instance_id(); + r_result->collider_shape = r_recover_result.other_compound_shape_index; + r_result->collision_local_shape = r_recover_result.local_shape_most_recovered; + + //{ /// Add manifold point to manage collisions + // btPersistentManifold* manifold = dynamicsWorld->getDispatcher()->getNewManifold(p_body->getBtBody(), btRigid); + // btManifoldPoint manifoldPoint(result_callabck.m_pointWorld, result_callabck.m_pointWorld, result_callabck.m_pointNormalWorld, result_callabck.m_penetration_distance); + // manifoldPoint.m_index0 = r_result->collision_local_shape; + // manifoldPoint.m_index1 = r_result->collider_shape; + // manifold->addManifoldPoint(manifoldPoint); + // p_body->get_kinematic_utilities()->m_generatedManifold.push_back(manifold); + //} #if debug_test_motion - Vector3 sup_line2; - B_TO_G(recovered_motion, sup_line2); - //Vector3 sup_pos; - //B_TO_G( pt.getPositionWorldOnB(), sup_pos); - normalLine->clear(); - normalLine->begin(Mesh::PRIMITIVE_LINES, NULL); - normalLine->add_vertex(r_result->collision_point); - normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10); - normalLine->end(); +//Vector3 sup_line2; +//B_TO_G(recovered_motion, sup_line2); +////Vector3 sup_pos; +////B_TO_G( pt.getPositionWorldOnB(), sup_pos); +//normalLine->clear(); +//normalLine->begin(Mesh::PRIMITIVE_LINES, NULL); +//normalLine->add_vertex(r_result->collision_point); +//normalLine->add_vertex(r_result->collision_point + r_result->collision_normal * 10); +//normalLine->end(); #endif + } else { + r_result->remainder = Vector3(); + } } else { - r_result->remainder = Vector3(); + if (!l_has_penetration) + break; } } } - return hasPenetration; + return has_penetration; } struct RecoverPenetrationBroadPhaseCallback : public btBroadphaseAabbCallback { @@ -1004,7 +1013,7 @@ public: } }; -bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btVector3 &r_recover_position, RecoverResult *r_recover_result) { +bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result) { RecoverPenetrationBroadPhaseCallback recover_broad_result(p_body->get_bt_collision_object(), p_body->get_collision_layer(), p_body->get_collision_mask()); @@ -1045,24 +1054,24 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran for (int x = cs->getNumChildShapes() - 1; 0 <= x; --x) { if (cs->getChildShape(x)->isConvex()) { - if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(x)), otherObject, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), r_recover_position, r_recover_result)) { + if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(cs->getChildShape(x)), otherObject, x, body_shape_position_recovered, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_recover_position, r_recover_result)) { penetration = true; } } else { - if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position, otherObject->getWorldTransform() * cs->getChildTransform(x), r_recover_position, r_recover_result)) { + if (RFP_convex_world_test(kin_shape.shape, cs->getChildShape(x), p_body->get_bt_collision_object(), otherObject, kinIndex, x, body_shape_position_recovered, otherObject->getWorldTransform() * cs->getChildTransform(x), p_recover_movement_scale, r_recover_position, r_recover_result)) { penetration = true; } } } } else if (otherObject->getCollisionShape()->isConvex()) { /// Execute GJK test against object shape - if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, body_shape_position, otherObject->getWorldTransform(), r_recover_position, r_recover_result)) { + if (RFP_convex_convex_test(kin_shape.shape, static_cast<const btConvexShape *>(otherObject->getCollisionShape()), otherObject, 0, body_shape_position_recovered, otherObject->getWorldTransform(), p_recover_movement_scale, r_recover_position, r_recover_result)) { penetration = true; } } else { - if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position, otherObject->getWorldTransform(), r_recover_position, r_recover_result)) { + if (RFP_convex_world_test(kin_shape.shape, otherObject->getCollisionShape(), p_body->get_bt_collision_object(), otherObject, kinIndex, 0, body_shape_position_recovered, otherObject->getWorldTransform(), p_recover_movement_scale, r_recover_position, r_recover_result)) { penetration = true; } @@ -1070,15 +1079,26 @@ bool SpaceBullet::recover_from_penetration(RigidBodyBullet *p_body, const btTran } } +#if debug_test_motion + Vector3 pos; + B_TO_G(p_body_position.getOrigin(), pos); + Vector3 sup_line; + B_TO_G(sum_recover_normals, sup_line); + motionVec->clear(); + motionVec->begin(Mesh::PRIMITIVE_LINES, NULL); + motionVec->add_vertex(pos); + motionVec->add_vertex(pos + (sup_line * 10)); + motionVec->end(); +#endif + return penetration; } -bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result) { +bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result) { // Initialize GJK input btGjkPairDetector::ClosestPointInput gjk_input; gjk_input.m_transformA = p_transformA; - gjk_input.m_transformA.getOrigin() += r_recover_position; gjk_input.m_transformB = p_transformB; // Perform GJK test @@ -1087,30 +1107,28 @@ bool SpaceBullet::RFP_convex_convex_test(const btConvexShape *p_shapeA, const bt gjk_pair_detector.getClosestPoints(gjk_input, result, 0); if (0 > result.m_distance) { // Has penetration - r_recover_position += result.m_normalOnBInWorld * (result.m_distance * -1); + r_recover_position += result.m_normalOnBInWorld * (result.m_distance * -1 * p_recover_movement_scale); if (r_recover_result) { - - r_recover_result->hasPenetration = true; - r_recover_result->other_collision_object = p_objectB; - r_recover_result->other_compound_shape_index = p_shapeId_B; - r_recover_result->penetration_distance = result.m_distance; - r_recover_result->pointNormalWorld = result.m_normalOnBInWorld; - r_recover_result->pointWorld = result.m_pointInWorld; + if (result.m_distance < r_recover_result->penetration_distance) { + r_recover_result->hasPenetration = true; + r_recover_result->other_collision_object = p_objectB; + r_recover_result->other_compound_shape_index = p_shapeId_B; + r_recover_result->penetration_distance = result.m_distance; + r_recover_result->pointWorld = result.m_pointInWorld; + r_recover_result->normal = result.m_normalOnBInWorld; + } } return true; } return false; } -bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result) { +bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result) { /// Contact test - btTransform p_recovered_transformA(p_transformA); - p_recovered_transformA.getOrigin() += r_recover_position; - - btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, p_recovered_transformA, -1, p_shapeId_A); + btCollisionObjectWrapper obA(NULL, p_shapeA, p_objectA, p_transformA, -1, p_shapeId_A); btCollisionObjectWrapper obB(NULL, p_shapeB, p_objectB, p_transformB, -1, p_shapeId_B); btCollisionAlgorithm *algorithm = dispatcher->findAlgorithm(&obA, &obB, NULL, BT_CLOSEST_POINT_ALGORITHMS); @@ -1123,16 +1141,17 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC dispatcher->freeCollisionAlgorithm(algorithm); if (contactPointResult.hasHit()) { - r_recover_position += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1); + r_recover_position += contactPointResult.m_pointNormalWorld * (contactPointResult.m_penetration_distance * -1 * p_recover_movement_scale); if (r_recover_result) { - - r_recover_result->hasPenetration = true; - r_recover_result->other_collision_object = p_objectB; - r_recover_result->other_compound_shape_index = p_shapeId_B; - r_recover_result->penetration_distance = contactPointResult.m_penetration_distance; - r_recover_result->pointNormalWorld = contactPointResult.m_pointNormalWorld; - r_recover_result->pointWorld = contactPointResult.m_pointWorld; + if (contactPointResult.m_penetration_distance < r_recover_result->penetration_distance) { + r_recover_result->hasPenetration = true; + r_recover_result->other_collision_object = p_objectB; + r_recover_result->other_compound_shape_index = p_shapeId_B; + r_recover_result->penetration_distance = contactPointResult.m_penetration_distance; + r_recover_result->pointWorld = contactPointResult.m_pointWorld; + r_recover_result->normal = contactPointResult.m_pointNormalWorld; + } } return true; } diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 6e71a25773..69ea2fcc58 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -178,23 +178,24 @@ private: struct RecoverResult { bool hasPenetration; - btVector3 pointNormalWorld; + btVector3 normal; btVector3 pointWorld; - btScalar penetration_distance; // Negative is penetration + btScalar penetration_distance; // Negative mean penetration int other_compound_shape_index; const btCollisionObject *other_collision_object; int local_shape_most_recovered; RecoverResult() : - hasPenetration(false) {} + hasPenetration(false), + penetration_distance(1e20) {} }; - bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_from, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL); + bool recover_from_penetration(RigidBodyBullet *p_body, const btTransform &p_from, btScalar p_recover_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL); /// This is an API that recover a kinematic object from penetration /// This allow only Convex Convex test and it always use GJK algorithm, With this API we don't benefit of Bullet special accelerated functions - bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result); + bool RFP_convex_convex_test(const btConvexShape *p_shapeA, const btConvexShape *p_shapeB, btCollisionObject *p_objectB, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL); /// This is an API that recover a kinematic object from penetration /// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm - bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btVector3 &r_recover_position, RecoverResult *r_recover_result); + bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_movement_scale, btVector3 &r_recover_position, RecoverResult *r_recover_result = NULL); }; #endif diff --git a/modules/gdnative/SCsub b/modules/gdnative/SCsub index 4e73ebfb9d..c92c3f30a2 100644 --- a/modules/gdnative/SCsub +++ b/modules/gdnative/SCsub @@ -245,6 +245,14 @@ if ARGUMENTS.get('gdnative_wrapper', False): gd_wrapper_env = env.Clone() gd_wrapper_env.Append(CPPPATH=['#modules/gdnative/include/']) + if gd_wrapper_env['use_lto']: + if not env.msvc: + gd_wrapper_env.Append(CCFLAGS=['--no-lto']) + gd_wrapper_env.Append(LINKFLAGS=['--no-lto']) + else: + gd_wrapper_env.Append(CCFLAGS=['/GL-']) + gd_wrapper_env.Append(LINKFLAGS=['/LTCG:OFF']) + if not env.msvc: gd_wrapper_env.Append(CCFLAGS=['-fPIC']) diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 7ab3d0a140..786c2bf051 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -164,6 +164,14 @@ String AudioStreamOGGVorbis::get_stream_name() const { return ""; //return stream_name; } +void AudioStreamOGGVorbis::clear_data() { + if (data) { + AudioServer::get_singleton()->audio_data_free(data); + data = NULL; + data_len = 0; + } +} + void AudioStreamOGGVorbis::set_data(const PoolVector<uint8_t> &p_data) { int src_data_len = p_data.size(); @@ -209,6 +217,9 @@ void AudioStreamOGGVorbis::set_data(const PoolVector<uint8_t> &p_data) { length = stb_vorbis_stream_length_in_seconds(ogg_stream); stb_vorbis_close(ogg_stream); + // free any existing data + clear_data(); + data = AudioServer::get_singleton()->audio_data_alloc(src_data_len, src_datar.ptr()); data_len = src_data_len; @@ -275,3 +286,7 @@ AudioStreamOGGVorbis::AudioStreamOGGVorbis() { decode_mem_size = 0; loop = false; } + +AudioStreamOGGVorbis::~AudioStreamOGGVorbis() { + clear_data(); +} diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.h b/modules/stb_vorbis/audio_stream_ogg_vorbis.h index f920047703..8644e1ba37 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.h +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.h @@ -93,6 +93,7 @@ class AudioStreamOGGVorbis : public AudioStream { float length; bool loop; float loop_offset; + void clear_data(); protected: static void _bind_methods(); @@ -111,6 +112,7 @@ public: PoolVector<uint8_t> get_data() const; AudioStreamOGGVorbis(); + virtual ~AudioStreamOGGVorbis(); }; #endif diff --git a/modules/thekla_unwrap/SCsub b/modules/thekla_unwrap/SCsub index c57bf326ea..d23ba10d4c 100644 --- a/modules/thekla_unwrap/SCsub +++ b/modules/thekla_unwrap/SCsub @@ -1,5 +1,7 @@ #!/usr/bin/env python +import platform + Import('env') Import('env_modules') @@ -60,7 +62,13 @@ if env['builtin_thekla_atlas']: env_thekla_unwrap.Append(CXXFLAGS="-std=c++11") if env["platform"] == 'x11': - env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_LINUX", "-DPOSH_COMPILER_GCC"]) + # if not specifically one of the *BSD, then use LINUX as default + if platform.system() == "FreeBSD": + env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_FREEBSD", "-DPOSH_COMPILER_GCC"]) + elif platform.system() == "OpenBSD": + env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_OPENBSD", "-DPOSH_COMPILER_GCC"]) + else: + env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_LINUX", "-DPOSH_COMPILER_GCC"]) elif env["platform"] == 'osx': env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_DARWIN", "-DPOSH_COMPILER_GCC"]) elif env["platform"] == 'windows': @@ -69,6 +77,6 @@ if env['builtin_thekla_atlas']: else: env_thekla_unwrap.Append(CCFLAGS=["-DNV_OS_MINGW", "-DNV_CC_GNUC", "-DPOSH_COMPILER_GCC", "-U__STRICT_ANSI__"]) env.Append(LIBS=["dbghelp"]) - + # Godot source files env_thekla_unwrap.add_source_files(env.modules_sources, "*.cpp") diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index 97e81874c9..1542f4a5e4 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -120,7 +120,7 @@ void OS_Android::set_opengl_extensions(const char *p_gl_extensions) { gl_extensions = p_gl_extensions; } -void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { use_gl2 = p_video_driver != 1; @@ -146,6 +146,8 @@ void OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int input->set_fallback_mapping("Default Android Gamepad"); //power_manager = memnew(power_android); + + return OK; } void OS_Android::set_main_loop(MainLoop *p_main_loop) { diff --git a/platform/android/os_android.h b/platform/android/os_android.h index adfd88b59b..c0ab2acd2e 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -145,7 +145,7 @@ public: virtual const char *get_audio_driver_name(int p_driver) const; virtual void initialize_core(); - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void set_main_loop(MainLoop *p_main_loop); virtual void delete_main_loop(); diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index 65a220f8ca..1ebadd337e 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -79,7 +79,7 @@ const char *OS_Haiku::get_video_driver_name(int p_driver) const { return "GLES3"; } -void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { main_loop = NULL; current_video_mode = p_desired; @@ -114,7 +114,7 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_ visual_server = memnew(VisualServerRaster(rasterizer)); - ERR_FAIL_COND(!visual_server); + ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); // TODO: enable multithreaded VS /* @@ -132,6 +132,8 @@ void OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p_ AudioDriverManager::initialize(p_audio_driver); power_manager = memnew(PowerHaiku); + + return OK; } void OS_Haiku::finalize() { diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h index 6d69c1997f..9af15eefc0 100644 --- a/platform/haiku/os_haiku.h +++ b/platform/haiku/os_haiku.h @@ -66,7 +66,7 @@ protected: virtual int get_video_driver_count() const; virtual const char *get_video_driver_name(int p_driver) const; - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void finalize(); virtual void set_main_loop(MainLoop *p_main_loop); diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 507d4f22db..d420f95e33 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -97,7 +97,7 @@ void OSIPhone::initialize_core() { set_data_dir(data_dir); }; -void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { supported_orientations = 0; supported_orientations |= ((GLOBAL_DEF("video_mode/allow_horizontal", true) ? 1 : 0) << LandscapeLeft); @@ -144,6 +144,8 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_ //icloud->connect(); #endif Engine::get_singleton()->add_singleton(Engine::Singleton("iOS", memnew(iOS))); + + return OK; }; MainLoop *OSIPhone::get_main_loop() const { diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 8e701a7fab..611bc2d4cb 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -87,7 +87,7 @@ private: virtual const char *get_video_driver_name(int p_driver) const; virtual void initialize_core(); - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void set_main_loop(MainLoop *p_main_loop); virtual MainLoop *get_main_loop() const; diff --git a/platform/javascript/export/export.cpp b/platform/javascript/export/export.cpp index 6c2b6799a6..a3514df05c 100644 --- a/platform/javascript/export/export.cpp +++ b/platform/javascript/export/export.cpp @@ -174,14 +174,14 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese } if (template_path != String() && !FileAccess::exists(template_path)) { - EditorNode::get_singleton()->show_warning(TTR("Template file not found:\n") + template_path); + EditorNode::get_singleton()->show_warning(TTR("Template file not found:") + "\n" + template_path); return ERR_FILE_NOT_FOUND; } String pck_path = p_path.get_basename() + ".pck"; Error error = save_pack(p_preset, pck_path); if (error != OK) { - EditorNode::get_singleton()->show_warning(TTR("Could not write file:\n") + pck_path); + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + pck_path); return error; } @@ -191,12 +191,12 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese if (!pkg) { - EditorNode::get_singleton()->show_warning(TTR("Could not open template for export:\n") + template_path); + EditorNode::get_singleton()->show_warning(TTR("Could not open template for export:") + "\n" + template_path); return ERR_FILE_NOT_FOUND; } if (unzGoToFirstFile(pkg) != UNZ_OK) { - EditorNode::get_singleton()->show_warning(TTR("Invalid export template:\n") + template_path); + EditorNode::get_singleton()->show_warning(TTR("Invalid export template:") + "\n" + template_path); unzClose(pkg); return ERR_FILE_CORRUPT; } @@ -238,7 +238,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese String dst = p_path.get_base_dir().plus_file(file); FileAccess *f = FileAccess::open(dst, FileAccess::WRITE); if (!f) { - EditorNode::get_singleton()->show_warning(TTR("Could not write file:\n") + dst); + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + dst); unzClose(pkg); return ERR_FILE_CANT_WRITE; } @@ -252,7 +252,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese FileAccess *f = FileAccess::open(custom_html, FileAccess::READ); if (!f) { - EditorNode::get_singleton()->show_warning(TTR("Could not read custom HTML shell:\n") + custom_html); + EditorNode::get_singleton()->show_warning(TTR("Could not read custom HTML shell:") + "\n" + custom_html); return ERR_FILE_CANT_READ; } Vector<uint8_t> buf; @@ -263,7 +263,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese f = FileAccess::open(p_path, FileAccess::WRITE); if (!f) { - EditorNode::get_singleton()->show_warning(TTR("Could not write file:\n") + p_path); + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + p_path); return ERR_FILE_CANT_WRITE; } f->store_buffer(buf.ptr(), buf.size()); @@ -277,7 +277,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese splash.instance(); Error err = splash->load(splash_path); if (err) { - EditorNode::get_singleton()->show_warning(TTR("Could not read boot splash image file:\n") + splash_path + "\nUsing default boot splash image"); + EditorNode::get_singleton()->show_warning(TTR("Could not read boot splash image file:") + "\n" + splash_path + "\n" + TTR("Using default boot splash image.")); splash.unref(); } } @@ -286,7 +286,7 @@ Error EditorExportPlatformJavaScript::export_project(const Ref<EditorExportPrese } String png_path = p_path.get_base_dir().plus_file(p_path.get_file().get_basename() + ".png"); if (splash->save_png(png_path) != OK) { - EditorNode::get_singleton()->show_warning(TTR("Could not write file:\n") + png_path); + EditorNode::get_singleton()->show_warning(TTR("Could not write file:") + "\n" + png_path); return ERR_FILE_CANT_WRITE; } return OK; diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index 0bdd090ba9..26fb380aed 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -419,7 +419,7 @@ void send_notification(int notif) { } } -void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { print_line("Init OS"); @@ -429,7 +429,7 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i attributes.antialias = false; attributes.majorVersion = 2; EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context(NULL, &attributes); - ERR_FAIL_COND(emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS); + ERR_FAIL_COND_V(emscripten_webgl_make_context_current(ctx) != EMSCRIPTEN_RESULT_SUCCESS, ERR_UNAVAILABLE); video_mode = p_desired; // can't fulfil fullscreen request due to browser security @@ -507,6 +507,8 @@ void OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, i #undef EM_CHECK visual_server->init(); + + return OK; } void OS_JavaScript::set_main_loop(MainLoop *p_main_loop) { diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 8acaac9ef3..eaf8465be9 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -82,7 +82,7 @@ public: virtual const char *get_audio_driver_name(int p_driver) const; virtual void initialize_core(); - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void set_main_loop(MainLoop *p_main_loop); virtual void delete_main_loop(); diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp index 657a899367..23ca1e3fb9 100644 --- a/platform/osx/export/export.cpp +++ b/platform/osx/export/export.cpp @@ -541,7 +541,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p } else { String pack_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".pck"); - Error err = save_pack(p_preset, pack_path); + + Vector<SharedObject> shared_objects; + Error err = save_pack(p_preset, pack_path, &shared_objects); if (err == OK) { zipOpenNewFileInZip(dst_pkg_zip, @@ -567,11 +569,32 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p break; zipWriteInFileInZip(dst_pkg_zip, buf, r); } + zipCloseFileInZip(dst_pkg_zip); memdelete(pf); } else { err = ERR_CANT_OPEN; } + + //add shared objects + for (int i = 0; i < shared_objects.size(); i++) { + Vector<uint8_t> file = FileAccess::get_file_as_array(shared_objects[i].path); + ERR_CONTINUE(file.empty()); + + zipOpenNewFileInZip(dst_pkg_zip, + (pkg_name + ".app/Contents/MacOS/").plus_file(shared_objects[i].path.get_file()).utf8().get_data(), + NULL, + NULL, + 0, + NULL, + 0, + NULL, + Z_DEFLATED, + Z_DEFAULT_COMPRESSION); + + zipWriteInFileInZip(dst_pkg_zip, file.ptr(), file.size()); + zipCloseFileInZip(dst_pkg_zip); + } } } } diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index 0411b4e72b..2a71de12e9 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -123,7 +123,7 @@ protected: virtual const char *get_video_driver_name(int p_driver) const; virtual void initialize_core(); - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void finalize(); virtual void set_main_loop(MainLoop *p_main_loop); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 99c5995d7a..d8dd2eb1db 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -99,10 +99,28 @@ static Vector2 get_mouse_pos(NSEvent *event) { @implementation GodotApplication -// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost -// This works around an AppKit bug, where key up events while holding -// down the command key don't get sent to the key window. - (void)sendEvent:(NSEvent *)event { + + // special case handling of command-period, which is traditionally a special + // shortcut in macOS and doesn't arrive at our regular keyDown handler. + if ([event type] == NSKeyDown) { + if (([event modifierFlags] & NSEventModifierFlagCommand) && [event keyCode] == 0x2f) { + + Ref<InputEventKey> k; + k.instance(); + + get_key_modifier_state([event modifierFlags], k); + k->set_pressed(true); + k->set_scancode(KEY_PERIOD); + k->set_echo([event isARepeat]); + + OS_OSX::singleton->push_input(k); + } + } + + // From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost + // This works around an AppKit bug, where key up events while holding + // down the command key don't get sent to the key window. if ([event type] == NSKeyUp && ([event modifierFlags] & NSCommandKeyMask)) [[self keyWindow] sendEvent:event]; else @@ -958,7 +976,7 @@ static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplay displays_arrangement_dirty = true; } -void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { /*** OSX INITIALIZATION ***/ /*** OSX INITIALIZATION ***/ @@ -995,7 +1013,7 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au backing:NSBackingStoreBuffered defer:NO]; - ERR_FAIL_COND(window_object == nil); + ERR_FAIL_COND_V(window_object == nil, ERR_UNAVAILABLE); window_view = [[GodotContentView alloc] init]; @@ -1082,11 +1100,11 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au #undef ADD_ATTR2 pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; - ERR_FAIL_COND(pixelFormat == nil); + ERR_FAIL_COND_V(pixelFormat == nil, ERR_UNAVAILABLE); context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil]; - ERR_FAIL_COND(context == nil); + ERR_FAIL_COND_V(context == nil, ERR_UNAVAILABLE); [context setView:window_view]; @@ -1130,6 +1148,8 @@ void OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_au _ensure_user_data_dir(); restore_rect = Rect2(get_window_position(), get_window_size()); + + return OK; } void OS_OSX::finalize() { diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 13264ed46e..410fea153a 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -47,7 +47,7 @@ const char *OS_Server::get_video_driver_name(int p_driver) const { return "Dummy"; } -void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { args = OS::get_singleton()->get_cmdline_args(); current_videomode = p_desired; @@ -67,14 +67,17 @@ void OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int p spatial_sound_2d_server = memnew(SpatialSound2DServerSW); spatial_sound_2d_server->init(); - ERR_FAIL_COND(!visual_server); + ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); visual_server->init(); input = memnew(InputDefault); _ensure_user_data_dir(); + + return OK; } + void OS_Server::finalize() { if (main_loop) diff --git a/platform/server/os_server.h b/platform/server/os_server.h index 7b7d4a38a8..6739375468 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -66,7 +66,7 @@ protected: virtual int get_video_driver_count() const; virtual const char *get_video_driver_name(int p_driver) const; - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void finalize(); virtual void set_main_loop(MainLoop *p_main_loop); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 603a918cca..96f9c895bc 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -194,7 +194,7 @@ void OSUWP::screen_size_changed() { gl_context->reset(); }; -void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { main_loop = NULL; outside = true; @@ -297,6 +297,8 @@ void OSUWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_aud display_request->RequestActive(); set_keep_screen_on(GLOBAL_DEF("display/window/keep_screen_on", true)); + + return OK; } void OSUWP::set_clipboard(const String &p_text) { diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index 976eda1fe1..ad12b6286f 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -158,7 +158,7 @@ protected: virtual const char *get_audio_driver_name(int p_driver) const; virtual void initialize_core(); - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void set_main_loop(MainLoop *p_main_loop); virtual void delete_main_loop(); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index e3af82b629..22294005f6 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -929,7 +929,7 @@ typedef enum _SHC_PROCESS_DPI_AWARENESS { SHC_PROCESS_PER_MONITOR_DPI_AWARE = 2 } SHC_PROCESS_DPI_AWARENESS; -void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { main_loop = NULL; outside = true; @@ -975,7 +975,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int if (!RegisterClassExW(&wc)) { MessageBox(NULL, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); - return; // Return + return ERR_UNAVAILABLE; } pre_fs_valid = true; @@ -1045,7 +1045,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int RECT rect; if (!GetClientRect(hWnd, &rect)) { MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); - return; // Return FALSE + return ERR_UNAVAILABLE; }; video_mode.width = rect.right; video_mode.height = rect.bottom; @@ -1063,7 +1063,7 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int NULL, NULL, hInstance, NULL); if (!hWnd) { MessageBoxW(NULL, L"Window Creation Error.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); - return; // Return FALSE + return ERR_UNAVAILABLE; } }; @@ -1127,6 +1127,8 @@ void OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int SetForegroundWindow(hWnd); // Slightly Higher Priority SetFocus(hWnd); // Sets Keyboard Focus To } + + return OK; } void OS_Windows::set_clipboard(const String &p_text) { @@ -1631,6 +1633,13 @@ void OS_Windows::_update_window_style(bool repaint) { Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) { + String path = p_path; + + if (!FileAccess::exists(path)) { + //this code exists so gdnative can load .dll files from within the executable path + path = get_executable_path().get_base_dir().plus_file(p_path.get_file()); + } + typedef DLL_DIRECTORY_COOKIE(WINAPI * PAddDllDirectory)(PCWSTR); typedef BOOL(WINAPI * PRemoveDllDirectory)(DLL_DIRECTORY_COOKIE); @@ -1641,10 +1650,10 @@ Error OS_Windows::open_dynamic_library(const String p_path, void *&p_library_han DLL_DIRECTORY_COOKIE cookie; if (p_also_set_library_path && has_dll_directory_api) { - cookie = add_dll_directory(p_path.get_base_dir().c_str()); + cookie = add_dll_directory(path.get_base_dir().c_str()); } - p_library_handle = (void *)LoadLibraryExW(p_path.c_str(), NULL, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); + p_library_handle = (void *)LoadLibraryExW(path.c_str(), NULL, (p_also_set_library_path && has_dll_directory_api) ? LOAD_LIBRARY_SEARCH_DEFAULT_DIRS : 0); if (p_also_set_library_path && has_dll_directory_api) { remove_dll_directory(cookie); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 9d254ccf27..1863642f39 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -148,7 +148,7 @@ protected: virtual const char *get_audio_driver_name(int p_driver) const; virtual void initialize_core(); - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void set_main_loop(MainLoop *p_main_loop); virtual void delete_main_loop(); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index e9920b18a4..5ca3ad45b8 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -100,7 +100,7 @@ void OS_X11::initialize_core() { OS_Unix::initialize_core(); } -void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { +Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver) { long im_event_mask = 0; last_button_state = 0; @@ -123,21 +123,24 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au /** XLIB INITIALIZATION **/ x11_display = XOpenDisplay(NULL); + if (!x11_display) { + ERR_PRINT("X11 Display is not available"); + return ERR_UNAVAILABLE; + } + char *modifiers = NULL; Bool xkb_dar = False; - if (x11_display) { - XAutoRepeatOn(x11_display); - xkb_dar = XkbSetDetectableAutoRepeat(x11_display, True, NULL); + XAutoRepeatOn(x11_display); + xkb_dar = XkbSetDetectableAutoRepeat(x11_display, True, NULL); - // Try to support IME if detectable auto-repeat is supported - if (xkb_dar == True) { + // Try to support IME if detectable auto-repeat is supported + if (xkb_dar == True) { #ifdef X_HAVE_UTF8_STRING - // Xutf8LookupString will be used later instead of XmbLookupString before - // the multibyte sequences can be converted to unicode string. - modifiers = XSetLocaleModifiers(""); + // Xutf8LookupString will be used later instead of XmbLookupString before + // the multibyte sequences can be converted to unicode string. + modifiers = XSetLocaleModifiers(""); #endif - } } if (modifiers == NULL) { @@ -331,8 +334,8 @@ void OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_au AudioDriverManager::initialize(p_audio_driver); - ERR_FAIL_COND(!visual_server); - ERR_FAIL_COND(x11_window == 0); + ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(x11_window == 0, ERR_UNAVAILABLE); XSetWindowAttributes new_attr; diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index 04243a9b36..2bf2f3cf26 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -193,7 +193,7 @@ protected: virtual const char *get_audio_driver_name(int p_driver) const; virtual void initialize_core(); - virtual void initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); + virtual Error initialize(const VideoMode &p_desired, int p_video_driver, int p_audio_driver); virtual void finalize(); virtual void set_main_loop(MainLoop *p_main_loop); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 95298f5a18..63478886c6 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -209,6 +209,7 @@ Color ColorPicker::get_pick_color() const { } void ColorPicker::add_preset(const Color &p_color) { + if (presets.find(p_color)) { presets.move_to_back(presets.find(p_color)); } else { diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index 7999f50013..97f7c65cbe 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -122,8 +122,7 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const { for (int i = 0; i < items.size(); i++) { - if (i > 0) - ofs.y += vseparation; + ofs.y += vseparation; float h; if (!items[i].icon.is_null()) { @@ -459,7 +458,7 @@ void PopupMenu::_notification(int p_what) { if (i == mouse_over) { - hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation * 2))); + hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation / 2), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation))); } if (items[i].separator) { diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 4f2cfccd4a..bf048ea1b6 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -371,19 +371,20 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & cw = tab_size * font->get_char_size(' ').width; } - if (underline) { - Color uc = color; - uc.a *= 0.5; - int uy = y + lh - fh + ascent + 2; - float underline_width = 1.0; -#ifdef TOOLS_ENABLED - underline_width *= EDSCALE; -#endif - VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + pofs, uy), p_ofs + Point2(align_ofs + pofs + cw, uy), uc, underline_width); - } ofs += cw; } } + + if (underline) { + Color uc = color; + uc.a *= 0.5; + int uy = y + lh - fh + ascent + 2; + float underline_width = 1.0; +#ifdef TOOLS_ENABLED + underline_width *= EDSCALE; +#endif + VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, underline_width); + } } ADVANCE(fw); @@ -451,6 +452,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & table->columns[i].width = 0; } //compute minimum width for each cell + const int available_width = p_width - hseparation * (table->columns.size() - 1) - wofs; + for (List<Item *>::Element *E = table->subitems.front(); E; E = E->next()) { ERR_CONTINUE(E->get()->type != ITEM_FRAME); //children should all be frames ItemFrame *frame = static_cast<ItemFrame *>(E->get()); @@ -461,7 +464,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < frame->lines.size(); i++) { - _process_line(frame, Point2(), ly, p_width, i, PROCESS_CACHE, cfont, Color()); + _process_line(frame, Point2(), ly, available_width, i, PROCESS_CACHE, cfont, Color()); table->columns[column].min_width = MAX(table->columns[column].min_width, frame->lines[i].minimum_width); } idx++; @@ -470,11 +473,11 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & //compute available width and total ratio (for expanders) int total_ratio = 0; - int available_width = p_width - hseparation * (table->columns.size() - 1); + int remaining_width = available_width; table->total_width = hseparation; for (int i = 0; i < table->columns.size(); i++) { - available_width -= table->columns[i].min_width; + remaining_width -= table->columns[i].min_width; if (table->columns[i].expand) total_ratio += table->columns[i].expand_ratio; } @@ -484,7 +487,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & for (int i = 0; i < table->columns.size(); i++) { table->columns[i].width = table->columns[i].min_width; if (table->columns[i].expand) - table->columns[i].width += table->columns[i].expand_ratio * available_width / total_ratio; + table->columns[i].width += table->columns[i].expand_ratio * remaining_width / total_ratio; table->total_width += table->columns[i].width + hseparation; } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 9247fc943b..95c4b9058d 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1746,15 +1746,15 @@ void TextEdit::indent_left() { void TextEdit::_get_mouse_pos(const Point2i &p_mouse, int &r_row, int &r_col) const { float rows = p_mouse.y; - rows -= cache.style_normal->get_margin(MARGIN_TOP); rows /= get_row_height(); - int lsp = get_line_scroll_pos(true); - int row = cursor.line_ofs + (rows + (round(v_scroll->get_value()) - lsp)); + rows += v_scroll->get_value(); + int row = Math::floor(rows); if (is_hiding_enabled()) { // row will be offset by the hidden rows - int f_ofs = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(rows + 1, text.size() - cursor.line_ofs)) - 1; - row = cursor.line_ofs + (f_ofs + (round(v_scroll->get_value()) - lsp)); + int lsp = get_line_scroll_pos(true); + int f_ofs = num_lines_from(CLAMP(cursor.line_ofs, 0, text.size() - 1), MIN(row + 1 - cursor.line_ofs, text.size() - cursor.line_ofs)) - 1; + row = cursor.line_ofs + f_ofs; row = CLAMP(row, 0, text.size() - num_lines_from(text.size() - 1, -1)); } @@ -1822,10 +1822,18 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { if (mb->is_pressed()) { if (mb->get_button_index() == BUTTON_WHEEL_UP && !mb->get_command()) { - _scroll_up(3 * mb->get_factor()); + if (mb->get_shift()) { + h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); + } else { + _scroll_up(3 * mb->get_factor()); + } } if (mb->get_button_index() == BUTTON_WHEEL_DOWN && !mb->get_command()) { - _scroll_down(3 * mb->get_factor()); + if (mb->get_shift()) { + h_scroll->set_value(h_scroll->get_value() + (100 * mb->get_factor())); + } else { + _scroll_down(3 * mb->get_factor()); + } } if (mb->get_button_index() == BUTTON_WHEEL_LEFT) { h_scroll->set_value(h_scroll->get_value() - (100 * mb->get_factor())); diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 08f1bdff3d..b1a421c24f 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1423,17 +1423,33 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 #endif Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs; - VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color, line_width); + + if (root_pos.y + line_width >= 0) { + VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width); + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), parent_pos, cache.relationship_line_color, line_width); + } + + if (htotal < 0) { + return -1; + } } - int child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c); + if (htotal >= 0) { + int child_h = draw_item(children_pos, p_draw_ofs, p_draw_size, c); - if (child_h < 0 && cache.draw_relationship_lines == 0) - return -1; // break, stop drawing, no need to anymore + if (child_h < 0) { + if (cache.draw_relationship_lines == 0) { + return -1; // break, stop drawing, no need to anymore + } else { + htotal = -1; + children_pos.y = cache.offset.y + p_draw_size.height; + } + } else { + htotal += child_h; + children_pos.y += child_h; + } + } - htotal += child_h; - children_pos.y += child_h; c = c->next; } } @@ -2352,8 +2368,6 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { last_keypress = 0; } } break; - - last_keypress = 0; } } diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 4036735807..998c790c94 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -220,31 +220,17 @@ void register_scene_types() { resource_loader_theme = memnew(ResourceFormatLoaderTheme); ResourceLoader::add_resource_format_loader(resource_loader_theme); - bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false); - ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); - String theme_path = GLOBAL_DEF("gui/theme/custom", ""); - ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); - String font_path = GLOBAL_DEF("gui/theme/custom_font", ""); - ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + resource_saver_text = memnew(ResourceFormatSaverText); + ResourceSaver::add_resource_format_saver(resource_saver_text, true); - bool has_theme = false; - if (theme_path != String()) { - Ref<Theme> theme = ResourceLoader::load(theme_path); - if (theme.is_valid()) { - Theme::set_default(theme); - has_theme = true; - } else { - ERR_PRINTS("Error loading custom theme '" + theme_path + "'"); - } - } + resource_loader_text = memnew(ResourceFormatLoaderText); + ResourceLoader::add_resource_format_loader(resource_loader_text, true); - if (!has_theme) { - Ref<Font> font; - if (font_path != String()) { - font = ResourceLoader::load(font_path); - } - make_default_theme(default_theme_hidpi, font); - } + resource_saver_shader = memnew(ResourceFormatSaverShader); + ResourceSaver::add_resource_format_saver(resource_saver_shader, true); + + resource_loader_shader = memnew(ResourceFormatLoaderShader); + ResourceLoader::add_resource_format_loader(resource_loader_shader, true); OS::get_singleton()->yield(); //may take time to init @@ -604,24 +590,42 @@ void register_scene_types() { OS::get_singleton()->yield(); //may take time to init - resource_saver_text = memnew(ResourceFormatSaverText); - ResourceSaver::add_resource_format_saver(resource_saver_text, true); - - resource_loader_text = memnew(ResourceFormatLoaderText); - ResourceLoader::add_resource_format_loader(resource_loader_text, true); - - resource_saver_shader = memnew(ResourceFormatSaverShader); - ResourceSaver::add_resource_format_saver(resource_saver_shader, true); - - resource_loader_shader = memnew(ResourceFormatLoaderShader); - ResourceLoader::add_resource_format_loader(resource_loader_shader, true); - for (int i = 0; i < 20; i++) { GLOBAL_DEF("layer_names/2d_render/layer_" + itos(i + 1), ""); GLOBAL_DEF("layer_names/2d_physics/layer_" + itos(i + 1), ""); GLOBAL_DEF("layer_names/3d_render/layer_" + itos(i + 1), ""); GLOBAL_DEF("layer_names/3d_physics/layer_" + itos(i + 1), ""); } + + bool default_theme_hidpi = GLOBAL_DEF("gui/theme/use_hidpi", false); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/use_hidpi", PropertyInfo(Variant::BOOL, "gui/theme/use_hidpi", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + String theme_path = GLOBAL_DEF("gui/theme/custom", ""); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom", PropertyInfo(Variant::STRING, "gui/theme/custom", PROPERTY_HINT_FILE, "*.tres,*.res,*.theme", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + String font_path = GLOBAL_DEF("gui/theme/custom_font", ""); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res,*.font", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + + Ref<Font> font; + if (font_path != String()) { + font = ResourceLoader::load(font_path); + if (!font.is_valid()) { + ERR_PRINTS("Error loading custom font '" + font_path + "'"); + } + } + + // Always make the default theme to avoid invalid default font/icon/style in the given theme + make_default_theme(default_theme_hidpi, font); + + if (theme_path != String()) { + Ref<Theme> theme = ResourceLoader::load(theme_path); + if (theme.is_valid()) { + Theme::set_default(theme); + if (font.is_valid()) { + Theme::set_default_font(font); + } + } else { + ERR_PRINTS("Error loading custom theme '" + theme_path + "'"); + } + } } void unregister_scene_types() { diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index b18583dfb1..a4049e4461 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -880,7 +880,7 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) { Ref<StyleBox> default_style; Ref<Texture> default_icon; - Ref<BitmapFont> default_font; + Ref<Font> default_font; if (p_font.is_valid()) { default_font = p_font; } else if (p_hidpi) { @@ -888,7 +888,7 @@ void make_default_theme(bool p_hidpi, Ref<Font> p_font) { } else { default_font = make_font2(_lodpi_font_height, _lodpi_font_ascent, _lodpi_font_charcount, &_lodpi_font_charrects[0][0], _lodpi_font_kerning_pair_count, &_lodpi_font_kerning_pairs[0][0], _lodpi_font_img_width, _lodpi_font_img_height, _lodpi_font_img_data); } - Ref<BitmapFont> large_font = default_font; + Ref<Font> large_font = default_font; fill_default_theme(t, default_font, large_font, default_icon, default_style, p_hidpi ? 2.0 : 1.0); Theme::set_default(t); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index 6216893667..b2c91f90eb 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -1218,7 +1218,7 @@ Environment::Environment() { ssao_radius2 = 0; ssao_intensity2 = 1; ssao_bias = 0.01; - ssao_direct_light_affect = false; + ssao_direct_light_affect = 0.0; ssao_blur = SSAO_BLUR_3x3; set_ssao_edge_sharpness(4); set_ssao_quality(SSAO_QUALITY_LOW); diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 0317fe45ae..f2198bdf2f 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -122,7 +122,6 @@ int AudioDriverManager::get_driver_count() { } void AudioDriverManager::initialize(int p_driver) { - AudioDriver *driver; int failed_driver = -1; // Check if there is a selected driver diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 1828cf8a4b..f0f93ff2a7 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -3209,8 +3209,6 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui var.precision = precision; var.line = tk_line; - p_block->variables[name] = var; - VariableDeclarationNode::Declaration decl; decl.name = name; @@ -3219,7 +3217,7 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui tk = _get_token(); if (tk.type == TK_OP_ASSIGN) { - //variable creted with assignment! must parse an expression + //variable created with assignment! must parse an expression Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); if (!n) return ERR_PARSE_ERROR; @@ -3233,6 +3231,8 @@ Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map<StringName, Bui tk = _get_token(); } + p_block->variables[name] = var; + vardecl->declarations.push_back(decl); if (tk.type == TK_COMMA) { diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index bf6d425fb9..531c6045d6 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -711,7 +711,7 @@ Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_ if (first) { for (int i = 0; i < total_bones; i++) { - r_bone_aabb[i].size == Vector3(-1, -1, -1); //negative means unused + r_bone_aabb[i].size = Vector3(-1, -1, -1); //negative means unused } } |