diff options
90 files changed, 696 insertions, 202 deletions
diff --git a/SConstruct b/SConstruct index 628aac42af..8b7b95a600 100644 --- a/SConstruct +++ b/SConstruct @@ -425,8 +425,13 @@ if selected_platform in platform_list: # (SH)LIBSUFFIX will be used for our own built libraries # LIBSUFFIXES contains LIBSUFFIX and SHLIBSUFFIX by default, # so we need to append the default suffixes to keep the ability - # to link against thirdparty libraries (.a, .so, .dll, etc.). - env["LIBSUFFIXES"] += [env["LIBSUFFIX"], env["SHLIBSUFFIX"]] + # to link against thirdparty libraries (.a, .so, .lib, etc.). + if os.name == "nt": + # On Windows, only static libraries and import libraries can be + # statically linked - both using .lib extension + env["LIBSUFFIXES"] += [env["LIBSUFFIX"]] + else: + env["LIBSUFFIXES"] += [env["LIBSUFFIX"], env["SHLIBSUFFIX"]] env["LIBSUFFIX"] = suffix + env["LIBSUFFIX"] env["SHLIBSUFFIX"] = suffix + env["SHLIBSUFFIX"] diff --git a/core/class_db.cpp b/core/class_db.cpp index 6565d242a2..052a4586fe 100644 --- a/core/class_db.cpp +++ b/core/class_db.cpp @@ -936,9 +936,8 @@ void ClassDB::add_property(StringName p_class, const PropertyInfo &p_pinfo, cons } #ifdef DEBUG_METHODS_ENABLED - if (type->property_setget.has(p_pinfo.name)) { - ERR_EXPLAIN("Object already has property: " + p_class); + ERR_EXPLAIN("Object " + p_class + " already has property: " + p_pinfo.name); ERR_FAIL(); } #endif diff --git a/core/dictionary.cpp b/core/dictionary.cpp index ccbdff3816..6a3ab82879 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -112,6 +112,15 @@ Variant Dictionary::get_valid(const Variant &p_key) const { return E.get(); } +Variant Dictionary::get(const Variant &p_key, const Variant &p_default) const { + const Variant *result = getptr(p_key); + if (!result) { + return p_default; + } + + return *result; +} + int Dictionary::size() const { return _p->variant_map.size(); diff --git a/core/dictionary.h b/core/dictionary.h index d3b98c2f63..b77cc55254 100644 --- a/core/dictionary.h +++ b/core/dictionary.h @@ -58,6 +58,7 @@ public: Variant *getptr(const Variant &p_key); Variant get_valid(const Variant &p_key) const; + Variant get(const Variant &p_key, const Variant &p_default) const; int size() const; bool empty() const; diff --git a/core/image.cpp b/core/image.cpp index 172f5e517a..698a0b0b98 100644 --- a/core/image.cpp +++ b/core/image.cpp @@ -1766,6 +1766,15 @@ int Image::get_image_required_mipmaps(int p_width, int p_height, Format p_format return mm; } +int Image::get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap) { + + if (p_mipmap <= 0) { + return 0; + } + int mm; + return _get_dst_image_size(p_width, p_height, p_format, mm, p_mipmap - 1); +} + bool Image::is_compressed() const { return format > FORMAT_RGBE9995; } diff --git a/core/image.h b/core/image.h index 11f9380c3c..0770eb953e 100644 --- a/core/image.h +++ b/core/image.h @@ -286,6 +286,7 @@ public: static int get_image_data_size(int p_width, int p_height, Format p_format, bool p_mipmaps = false); static int get_image_required_mipmaps(int p_width, int p_height, Format p_format); + static int get_image_mipmap_offset(int p_width, int p_height, Format p_format, int p_mipmap); enum CompressMode { COMPRESS_S3TC, diff --git a/core/io/image_loader.h b/core/io/image_loader.h index 561f275e0c..d95a483c0d 100644 --- a/core/io/image_loader.h +++ b/core/io/image_loader.h @@ -71,7 +71,7 @@ public: class ImageLoader { enum { - MAX_LOADERS = 8 + MAX_LOADERS = 32 }; friend class ResourceFormatLoaderImage; static ImageFormatLoader *loader[MAX_LOADERS]; diff --git a/core/io/ip_address.cpp b/core/io/ip_address.cpp index 6d979d10eb..194d1af6bf 100644 --- a/core/io/ip_address.cpp +++ b/core/io/ip_address.cpp @@ -184,7 +184,7 @@ bool IP_Address::is_ipv4() const { } const uint8_t *IP_Address::get_ipv4() const { - ERR_FAIL_COND_V(!is_ipv4(), 0); + ERR_FAIL_COND_V(!is_ipv4(), &(field8[12])); // Not the correct IPv4 (it's an IPv6), but we don't want to return a null pointer risking an engine crash. return &(field8[12]); } diff --git a/core/object.cpp b/core/object.cpp index 1eff56f026..ea77090a45 100644 --- a/core/object.cpp +++ b/core/object.cpp @@ -1941,30 +1941,30 @@ Object::~Object() { memdelete(script_instance); script_instance = NULL; - List<Connection> sconnections; const StringName *S = NULL; - while ((S = signal_map.next(S))) { + while ((S = signal_map.next(NULL))) { Signal *s = &signal_map[*S]; - ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it"); - ERR_CONTINUE(s->lock > 0); - - for (int i = 0; i < s->slot_map.size(); i++) { - - sconnections.push_back(s->slot_map.getv(i).conn); + if (s->lock) { + ERR_EXPLAIN("Attempt to delete an object in the middle of a signal emission from it"); + ERR_CONTINUE(s->lock > 0); } - } - for (List<Connection>::Element *E = sconnections.front(); E; E = E->next()) { + //brute force disconnect for performance + int slot_count = s->slot_map.size(); + const VMap<Signal::Target, Signal::Slot>::Pair *slot_list = s->slot_map.get_array(); - Connection &c = E->get(); - ERR_CONTINUE(c.source != this); //bug? + for (int i = 0; i < slot_count; i++) { + + slot_list[i].value.conn.target->connections.erase(slot_list[i].value.cE); + } - this->_disconnect(c.signal, c.target, c.method, true); + signal_map.erase(*S); } + //signals from nodes that connect to this node while (connections.size()) { Connection c = connections.front()->get(); diff --git a/core/os/input.cpp b/core/os/input.cpp index 1a24258a10..3b895b16b4 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -86,7 +86,7 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("set_mouse_mode", "mode"), &Input::set_mouse_mode); ClassDB::bind_method(D_METHOD("get_mouse_mode"), &Input::get_mouse_mode); ClassDB::bind_method(D_METHOD("warp_mouse_position", "to"), &Input::warp_mouse_position); - ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press); + ClassDB::bind_method(D_METHOD("action_press", "action", "strength"), &Input::action_press, DEFVAL(1.f)); ClassDB::bind_method(D_METHOD("action_release", "action"), &Input::action_release); ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW)); ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); diff --git a/core/undo_redo.cpp b/core/undo_redo.cpp index 7d67076df5..3d41c374ea 100644 --- a/core/undo_redo.cpp +++ b/core/undo_redo.cpp @@ -325,7 +325,7 @@ bool UndoRedo::undo() { return true; } -void UndoRedo::clear_history() { +void UndoRedo::clear_history(bool p_increase_version) { ERR_FAIL_COND(action_level > 0); _discard_redo(); @@ -333,7 +333,8 @@ void UndoRedo::clear_history() { while (actions.size()) _pop_history_tail(); - //version++; + if (p_increase_version) + version++; } String UndoRedo::get_current_action_name() const { @@ -493,7 +494,7 @@ void UndoRedo::_bind_methods() { ClassDB::bind_method(D_METHOD("add_undo_property", "object", "property", "value"), &UndoRedo::add_undo_property); ClassDB::bind_method(D_METHOD("add_do_reference", "object"), &UndoRedo::add_do_reference); ClassDB::bind_method(D_METHOD("add_undo_reference", "object"), &UndoRedo::add_undo_reference); - ClassDB::bind_method(D_METHOD("clear_history"), &UndoRedo::clear_history); + ClassDB::bind_method(D_METHOD("clear_history", "increase_version"), &UndoRedo::clear_history, DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_current_action_name"), &UndoRedo::get_current_action_name); ClassDB::bind_method(D_METHOD("get_version"), &UndoRedo::get_version); ClassDB::bind_method(D_METHOD("redo"), &UndoRedo::redo); diff --git a/core/undo_redo.h b/core/undo_redo.h index 22dcd60472..f09fca9a78 100644 --- a/core/undo_redo.h +++ b/core/undo_redo.h @@ -112,7 +112,7 @@ public: bool redo(); bool undo(); String get_current_action_name() const; - void clear_history(); + void clear_history(bool p_increase_version = true); uint64_t get_version() const; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 8693a584f2..0c6e43fe36 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -155,9 +155,7 @@ struct _VariantCall { funcdata.default_args = p_defaultarg; funcdata._const = p_const; funcdata.returns = p_has_return; -#ifdef DEBUG_ENABLED funcdata.return_type = p_return; -#endif if (p_argtype1.name) { funcdata.arg_types.push_back(p_argtype1.type); @@ -486,6 +484,7 @@ struct _VariantCall { VCALL_LOCALMEM0R(Dictionary, keys); VCALL_LOCALMEM0R(Dictionary, values); VCALL_LOCALMEM1R(Dictionary, duplicate); + VCALL_LOCALMEM2R(Dictionary, get); VCALL_LOCALMEM2(Array, set); VCALL_LOCALMEM1R(Array, get); @@ -1679,6 +1678,7 @@ void register_variant_methods() { ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, keys, varray()); ADDFUNC0R(DICTIONARY, ARRAY, Dictionary, values, varray()); ADDFUNC1R(DICTIONARY, DICTIONARY, Dictionary, duplicate, BOOL, "deep", varray(false)); + ADDFUNC2R(DICTIONARY, NIL, Dictionary, get, NIL, "key", NIL, "default", varray(Variant())); ADDFUNC0R(ARRAY, INT, Array, size, varray()); ADDFUNC0R(ARRAY, BOOL, Array, empty, varray()); diff --git a/core/vmap.h b/core/vmap.h index 9fc99e636d..5f6d8190c6 100644 --- a/core/vmap.h +++ b/core/vmap.h @@ -36,22 +36,23 @@ template <class T, class V> class VMap { - - struct _Pair { +public: + struct Pair { T key; V value; - _FORCE_INLINE_ _Pair() {} + _FORCE_INLINE_ Pair() {} - _FORCE_INLINE_ _Pair(const T &p_key, const V &p_value) { + _FORCE_INLINE_ Pair(const T &p_key, const V &p_value) { key = p_key; value = p_value; } }; - CowData<_Pair> _cowdata; +private: + CowData<Pair> _cowdata; _FORCE_INLINE_ int _find(const T &p_val, bool &r_exact) const { @@ -61,7 +62,7 @@ class VMap { int low = 0; int high = _cowdata.size() - 1; - const _Pair *a = _cowdata.ptr(); + const Pair *a = _cowdata.ptr(); int middle = 0; #if DEBUG_ENABLED @@ -95,7 +96,7 @@ class VMap { int low = 0; int high = _cowdata.size() - 1; int middle; - const _Pair *a = _cowdata.ptr(); + const Pair *a = _cowdata.ptr(); while (low <= high) { middle = (low + high) / 2; @@ -121,7 +122,7 @@ public: _cowdata.get_m(pos).value = p_val; return pos; } - _cowdata.insert(pos, _Pair(p_key, p_val)); + _cowdata.insert(pos, Pair(p_key, p_val)); return pos; } @@ -152,12 +153,12 @@ public: _FORCE_INLINE_ int size() const { return _cowdata.size(); } _FORCE_INLINE_ bool empty() const { return _cowdata.empty(); } - const _Pair *get_array() const { + const Pair *get_array() const { return _cowdata.ptr(); } - _Pair *get_array() { + Pair *get_array() { return _cowdata.ptrw(); } diff --git a/doc/classes/ConfigFile.xml b/doc/classes/ConfigFile.xml index a4709c1c86..703043294b 100644 --- a/doc/classes/ConfigFile.xml +++ b/doc/classes/ConfigFile.xml @@ -25,6 +25,7 @@ # Save the changes by overwriting the previous file config.save("user://settings.cfg") [/codeblock] + Keep in mind that section and property names can't contain spaces. Anything after a space will be ignored on save and on load. </description> <tutorials> </tutorials> diff --git a/doc/classes/Dictionary.xml b/doc/classes/Dictionary.xml index 06c996e13e..cc58c56404 100644 --- a/doc/classes/Dictionary.xml +++ b/doc/classes/Dictionary.xml @@ -87,6 +87,17 @@ Return the list of values in the [code]Dictionary[/code]. </description> </method> + <method name="get"> + <return type="Variant"> + </return> + <argument index="0" name="key" type="Variant"> + </argument> + <argument index="1" name="default" type="Variant" default="null"> + </argument> + <description> + Returns the current value for the specified key in the [code]Dictionary[/code]. If the key does not exist, the method returns the value of the optional default argument, or Null if it is omitted. + </description> + </method> </methods> <constants> </constants> diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index bf395ee513..724e6a078d 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -17,10 +17,11 @@ </return> <argument index="0" name="action" type="String"> </argument> - <argument index="1" name="strength" type="float"> + <argument index="1" name="strength" type="float" default="1.0"> </argument> <description> - This will simulate pressing the specified action. The strength can be used for non-boolean actions. + This will simulate pressing the specified action. + The strength can be used for non-boolean actions, it's ranged between 0 and 1 representing the intensity of the given action. </description> </method> <method name="action_release"> diff --git a/doc/classes/PHashTranslation.xml b/doc/classes/PHashTranslation.xml index 18c72a0576..e5745375b0 100644 --- a/doc/classes/PHashTranslation.xml +++ b/doc/classes/PHashTranslation.xml @@ -17,6 +17,7 @@ <argument index="0" name="from" type="Translation"> </argument> <description> + Generates and sets an optimized translation from the given [Translation] resource. </description> </method> </methods> diff --git a/doc/classes/Translation.xml b/doc/classes/Translation.xml index c4e9dbfb70..b57f8f3556 100644 --- a/doc/classes/Translation.xml +++ b/doc/classes/Translation.xml @@ -7,6 +7,8 @@ Translations are resources that can be loaded/unloaded on demand. They map a string to another string. </description> <tutorials> + <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link> + <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link> </tutorials> <demos> </demos> @@ -19,7 +21,7 @@ <argument index="1" name="xlated_message" type="String"> </argument> <description> - Add a message for translation. + Adds a message if nonexistent, followed by its translation. </description> </method> <method name="erase_message"> @@ -28,7 +30,7 @@ <argument index="0" name="src_message" type="String"> </argument> <description> - Erase a message. + Erases a message. </description> </method> <method name="get_message" qualifiers="const"> @@ -37,25 +39,27 @@ <argument index="0" name="src_message" type="String"> </argument> <description> - Return a message for translation. + Returns a message's translation. </description> </method> <method name="get_message_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of existing messages. </description> </method> <method name="get_message_list" qualifiers="const"> <return type="PoolStringArray"> </return> <description> - Return all the messages (keys). + Returns all the messages (keys). </description> </method> </methods> <members> <member name="locale" type="String" setter="set_locale" getter="get_locale"> + The locale of the translation. </member> </members> <constants> diff --git a/doc/classes/TranslationServer.xml b/doc/classes/TranslationServer.xml index 52d2b2cc47..c2c400ccd5 100644 --- a/doc/classes/TranslationServer.xml +++ b/doc/classes/TranslationServer.xml @@ -1,11 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="TranslationServer" inherits="Object" category="Core" version="3.1"> <brief_description> - Server that manages all translations. Translations can be set to it and removed from it. + Server that manages all translations. </brief_description> <description> + Server that manages all translations. Translations can be set to it and removed from it. </description> <tutorials> + <link>https://docs.godotengine.org/en/stable/tutorials/i18n/internationalizing_games.html</link> + <link>https://docs.godotengine.org/en/stable/tutorials/i18n/locales.html</link> </tutorials> <demos> </demos> @@ -16,18 +19,21 @@ <argument index="0" name="translation" type="Translation"> </argument> <description> + Adds a [Translation] resource. </description> </method> <method name="clear"> <return type="void"> </return> <description> + Clears the server from all translations. </description> </method> <method name="get_locale" qualifiers="const"> <return type="String"> </return> <description> + Returns the current locale of the game. </description> </method> <method name="get_locale_name" qualifiers="const"> @@ -36,6 +42,7 @@ <argument index="0" name="locale" type="String"> </argument> <description> + Returns a locale's language and its variant (e.g. "en_US" would return "English (United States)"). </description> </method> <method name="remove_translation"> @@ -44,6 +51,7 @@ <argument index="0" name="translation" type="Translation"> </argument> <description> + Removes the given translation from the server. </description> </method> <method name="set_locale"> @@ -52,6 +60,7 @@ <argument index="0" name="locale" type="String"> </argument> <description> + Sets the locale of the game. </description> </method> <method name="translate" qualifiers="const"> @@ -60,6 +69,7 @@ <argument index="0" name="message" type="String"> </argument> <description> + Returns the current locale's translation for the given message (key). </description> </method> </methods> diff --git a/doc/classes/UndoRedo.xml b/doc/classes/UndoRedo.xml index 0ea5c6e005..93806ac326 100644 --- a/doc/classes/UndoRedo.xml +++ b/doc/classes/UndoRedo.xml @@ -102,8 +102,11 @@ <method name="clear_history"> <return type="void"> </return> + <argument index="0" name="increase_version" type="bool" default="true"> + </argument> <description> Clear the undo/redo history and associated references. + Passing [code]false[/code] to [code]increase_version[/code] will prevent the version number to be increased from this. </description> </method> <method name="commit_action"> diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index bd3a36feef..7c095e3798 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -681,6 +681,8 @@ public: int particles_get_draw_passes(RID p_particles) const { return 0; } RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { return RID(); } + virtual bool particles_is_inactive(RID p_particles) const { return false; } + /* RENDER TARGET */ RID render_target_create() { return RID(); } diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 0c0bf56793..6eafdb0e1c 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -605,7 +605,6 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst size >>= 1; int mipmaps = 6; - int mm_level = mipmaps - 1; storage->shaders.cubemap_filter.set_conditional(CubemapFilterShaderGLES2::USE_SOURCE_PANORAMA, false); storage->shaders.cubemap_filter.bind(); @@ -628,8 +627,6 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst size >>= 1; - mm_level--; - lod++; } diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 060988fbea..3beb8eac33 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -1497,8 +1497,9 @@ Variant RasterizerStorageGLES2::material_get_param_default(RID p_material, const if (material->shader) { if (material->shader->uniforms.has(p_param)) { - Vector<ShaderLanguage::ConstantNode::Value> default_value = material->shader->uniforms[p_param].default_value; - return ShaderLanguage::constant_value_to_variant(default_value, material->shader->uniforms[p_param].type); + ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); } } return Variant(); @@ -3841,6 +3842,10 @@ RID RasterizerStorageGLES2::particles_get_draw_pass_mesh(RID p_particles, int p_ void RasterizerStorageGLES2::update_particles() { } +bool RasterizerStorageGLES2::particles_is_inactive(RID p_particles) const { + return true; +} + //////// void RasterizerStorageGLES2::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 59f911e880..5bdc65a0b5 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -1090,6 +1090,8 @@ public: virtual int particles_get_draw_passes(RID p_particles) const; virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const; + virtual bool particles_is_inactive(RID p_particles) const; + /* INSTANCE */ virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 28c0274afa..d52be09cac 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -86,10 +86,11 @@ static String _mkid(const String &p_id) { static String f2sp0(float p_float) { - if (int(p_float) == p_float) - return itos(p_float) + ".0"; - else - return rtoss(p_float); + String num = rtoss(p_float); + if (num.find(".") == -1 && num.find("e") == -1) { + num += ".0"; + } + return num; } static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) { diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index c76db83c0c..4166cb8361 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -1221,8 +1221,6 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons bool rebind_shader = true; - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); - glBindBuffer(GL_UNIFORM_BUFFER, state.canvas_item_ubo); glBufferData(GL_UNIFORM_BUFFER, sizeof(CanvasItemUBO), &state.canvas_item_ubo_data, GL_DYNAMIC_DRAW); glBindBuffer(GL_UNIFORM_BUFFER, 0); @@ -1340,7 +1338,7 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons last_blend_mode = last_blend_mode != RasterizerStorageGLES3::Shader::CanvasItem::BLEND_MODE_DISABLED ? last_blend_mode : -1; } - if (shader_ptr != shader_cache) { + if (shader_ptr != shader_cache || rebind_shader) { if (shader_ptr->canvas_item.uses_time) { VisualServerRaster::redraw_request(); @@ -1657,6 +1655,14 @@ void RasterizerCanvasGLES3::canvas_render_items(Item *p_item_list, int p_z, cons if (current_clip) { glDisable(GL_SCISSOR_TEST); } + //disable states that may have been used + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_DISTANCE_FIELD, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SKELETON, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_LIGHTING, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_SHADOWS, false); } void RasterizerCanvasGLES3::canvas_debug_viewport_shadows(Light *p_lights_with_shadow) { diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 0951b8f798..b707189d74 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -3599,7 +3599,7 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } - if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { + if (!env || storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT] || storage->frame.current_rt->width < 4 || storage->frame.current_rt->height < 4) { //no post process on small render targets //no environment or transparent render, simply return and convert to SRGB glBindFramebuffer(GL_FRAMEBUFFER, storage->frame.current_rt->fbo); glActiveTexture(GL_TEXTURE0); @@ -4297,8 +4297,10 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const glClearBufferfv(GL_COLOR, 0, clear_color.components); // specular } + VS::EnvironmentBG bg_mode = (!env || (probe && env->bg_mode == VS::ENV_BG_CANVAS)) ? VS::ENV_BG_CLEAR_COLOR : env->bg_mode; //if no environment, or canvas while rendering a probe (invalid use case), use color. + if (env) { - switch (env->bg_mode) { + switch (bg_mode) { case VS::ENV_BG_COLOR_SKY: case VS::ENV_BG_SKY: diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 7ca7d8a471..235c799a55 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -874,8 +874,6 @@ void RasterizerStorageGLES3::texture_set_data(RID p_texture, const Ref<Image> &p int size, ofs; img->get_mipmap_offset_and_size(i, ofs, size); - //print_line("mipmap: "+itos(i)+" size: "+itos(size)+" w: "+itos(mm_w)+", h: "+itos(mm_h)); - if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) { if (texture->compressed) { @@ -1062,8 +1060,6 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); - //print_line("GET FORMAT: " + Image::get_format_name(texture->format) + " mipmaps: " + itos(texture->mipmaps)); - for (int i = 0; i < texture->mipmaps; i++) { int ofs = 0; @@ -1142,8 +1138,6 @@ Ref<Image> RasterizerStorageGLES3::texture_get_data(RID p_texture, int p_layer) glBindTexture(GL_TEXTURE_2D, temp_color_texture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->alloc_width, texture->alloc_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - print_line(itos(texture->alloc_width) + " xx " + itos(texture->alloc_height) + " -> " + itos(real_format)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, temp_color_texture, 0); @@ -2253,8 +2247,9 @@ Variant RasterizerStorageGLES3::material_get_param_default(RID p_material, const if (material->shader) { if (material->shader->uniforms.has(p_param)) { - Vector<ShaderLanguage::ConstantNode::Value> default_value = material->shader->uniforms[p_param].default_value; - return ShaderLanguage::constant_value_to_variant(default_value, material->shader->uniforms[p_param].type); + ShaderLanguage::ShaderNode::Uniform uniform = material->shader->uniforms[p_param]; + Vector<ShaderLanguage::ConstantNode::Value> default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); } } return Variant(); @@ -2891,9 +2886,6 @@ void RasterizerStorageGLES3::_update_material(Material *material) { if (E->get().order < 0) continue; // texture, does not go here - //if (material->shader->mode == VS::SHADER_PARTICLES) { - // print_line("uniform " + String(E->key()) + " order " + itos(E->get().order) + " offset " + itos(material->shader->ubo_offsets[E->get().order])); - //} //regular uniform uint8_t *data = &local_ubo[material->shader->ubo_offsets[E->get().order]]; @@ -3786,12 +3778,14 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { Mesh *mesh = mesh_owner.get(p_mesh); ERR_FAIL_COND_V(!mesh, AABB()); - if (mesh->custom_aabb != AABB()) + if (mesh->custom_aabb != AABB()) { return mesh->custom_aabb; + } Skeleton *sk = NULL; - if (p_skeleton.is_valid()) + if (p_skeleton.is_valid()) { sk = skeleton_owner.get(p_skeleton); + } AABB aabb; @@ -3830,6 +3824,7 @@ AABB RasterizerStorageGLES3::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { mtx.origin.y = texture[base_ofs + 3]; AABB baabb = mtx.xform(skbones[j]); + if (first) { laabb = baabb; first = false; @@ -6449,6 +6444,13 @@ void RasterizerStorageGLES3::update_particles() { glDisable(GL_RASTERIZER_DISCARD); } +bool RasterizerStorageGLES3::particles_is_inactive(RID p_particles) const { + + const Particles *particles = particles_owner.getornull(p_particles); + ERR_FAIL_COND_V(!particles, false); + return !particles->emitting && particles->inactive; +} + //////// void RasterizerStorageGLES3::instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 8c843e4d96..398ffdeb82 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -1261,6 +1261,8 @@ public: virtual int particles_get_draw_passes(RID p_particles) const; virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const; + virtual bool particles_is_inactive(RID p_particles) const; + /* INSTANCE */ virtual void instance_add_skeleton(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index fb6e168327..6cc27bd77a 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -173,10 +173,11 @@ static String _mkid(const String &p_id) { static String f2sp0(float p_float) { - if (int(p_float) == p_float) - return itos(p_float) + ".0"; - else - return rtoss(p_float); + String num = rtoss(p_float); + if (num.find(".") == -1 && num.find("e") == -1) { + num += ".0"; + } + return num; } static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNode::Value> &p_values) { @@ -229,7 +230,7 @@ static String get_constant_text(SL::DataType p_type, const Vector<SL::ConstantNo text += ")"; return text; } break; - case SL::TYPE_FLOAT: return f2sp0(p_values[0].real) + "f"; + case SL::TYPE_FLOAT: return f2sp0(p_values[0].real); case SL::TYPE_VEC2: case SL::TYPE_VEC3: case SL::TYPE_VEC4: { diff --git a/drivers/gles3/shader_gles3.cpp b/drivers/gles3/shader_gles3.cpp index 799179e8d4..404a9107ab 100644 --- a/drivers/gles3/shader_gles3.cpp +++ b/drivers/gles3/shader_gles3.cpp @@ -219,20 +219,15 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { strings.push_back("#version 300 es\n"); #endif - int define_line_ofs = 1; - for (int i = 0; i < custom_defines.size(); i++) { strings.push_back(custom_defines[i].get_data()); - define_line_ofs++; } for (int j = 0; j < conditional_count; j++) { bool enable = ((1 << j) & conditional_version.version); strings.push_back(enable ? conditional_defines[j] : ""); - if (enable) - define_line_ofs++; if (enable) { DEBUG_PRINT(conditional_defines[j]); @@ -253,7 +248,6 @@ ShaderGLES3::Version *ShaderGLES3::get_current_version() { ERR_FAIL_COND_V(!custom_code_map.has(conditional_version.code_version), NULL); cc = &custom_code_map[conditional_version.code_version]; v.code_version = cc->version; - define_line_ofs += 2; } /* CREATE PROGRAM */ diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 294233d134..d4079c4b4f 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1103,9 +1103,9 @@ LIGHT_SHADER_CODE float Fr = mix(.04, 1.0, cLdotH5); float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - float specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; + specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; #endif } diff --git a/drivers/pulseaudio/audio_driver_pulseaudio.cpp b/drivers/pulseaudio/audio_driver_pulseaudio.cpp index d78316945f..010f7bdb0a 100644 --- a/drivers/pulseaudio/audio_driver_pulseaudio.cpp +++ b/drivers/pulseaudio/audio_driver_pulseaudio.cpp @@ -346,9 +346,9 @@ void AudioDriverPulseAudio::thread_func(void *p_udata) { for (int j = 0; j < ad->pa_map.channels - 1; j++) { ad->samples_out.write[out_idx++] = ad->samples_in[in_idx++] >> 16; } - uint32_t l = ad->samples_in[in_idx++]; - uint32_t r = ad->samples_in[in_idx++]; - ad->samples_out.write[out_idx++] = ((l >> 1) + (r >> 1)) >> 16; + uint32_t l = ad->samples_in[in_idx++] >> 16; + uint32_t r = ad->samples_in[in_idx++] >> 16; + ad->samples_out.write[out_idx++] = (l + r) / 2; } } } diff --git a/drivers/unix/net_socket_posix.cpp b/drivers/unix/net_socket_posix.cpp index f981be66ce..833b17f122 100644 --- a/drivers/unix/net_socket_posix.cpp +++ b/drivers/unix/net_socket_posix.cpp @@ -110,7 +110,7 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const } else { // IPv4 socket // IPv4 socket with IPv6 address - ERR_FAIL_COND_V(!p_ip.is_ipv4(), 0); + ERR_FAIL_COND_V(!p_ip.is_wildcard() && !p_ip.is_ipv4(), 0); struct sockaddr_in *addr4 = (struct sockaddr_in *)p_addr; addr4->sin_family = AF_INET; @@ -122,7 +122,6 @@ size_t NetSocketPosix::_set_addr_storage(struct sockaddr_storage *p_addr, const addr4->sin_addr.s_addr = INADDR_ANY; } - copymem(&addr4->sin_addr.s_addr, p_ip.get_ipv4(), 4); return sizeof(sockaddr_in); } } diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index c4516c1f17..926fa37040 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -118,8 +118,10 @@ void CreateDialog::popup_create(bool p_dont_clear, bool p_replace_mode) { if (enable_rl) { search_options->add_constant_override("draw_relationship_lines", 1); search_options->add_color_override("relationship_line_color", rl_color); + search_options->add_constant_override("draw_guides", 0); } else { search_options->add_constant_override("draw_relationship_lines", 0); + search_options->add_constant_override("draw_guides", 1); } is_replace_mode = p_replace_mode; diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 2f2840192a..14abaa835c 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -209,7 +209,6 @@ EditorAbout::EditorAbout() { TreeItem *tpl_ti_lc = _tpl_tree->create_item(root); tpl_ti_lc->set_text(0, TTR("Licenses")); tpl_ti_lc->set_selectable(0, false); - int read_idx = 0; String long_text = ""; for (int component_index = 0; component_index < COPYRIGHT_INFO_COUNT; component_index++) { @@ -234,7 +233,6 @@ EditorAbout::EditorAbout() { String license = "\n License: " + String(part.license) + "\n"; text += license; long_text += license + "\n"; - read_idx++; } ti->set_metadata(0, text); } diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 9420452da1..bd6ce797b5 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -946,16 +946,18 @@ void EditorData::script_class_save_icon_paths() { void EditorData::script_class_load_icon_paths() { script_class_clear_icon_paths(); - Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons"); - List<Variant> keys; - d.get_key_list(&keys); + if (ProjectSettings::get_singleton()->has_setting("_global_script_class_icons")) { + Dictionary d = ProjectSettings::get_singleton()->get("_global_script_class_icons"); + List<Variant> keys; + d.get_key_list(&keys); - for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { - String name = E->get().operator String(); - _script_class_icon_paths[name] = d[name]; + for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { + String name = E->get().operator String(); + _script_class_icon_paths[name] = d[name]; - String path = ScriptServer::get_global_class_path(name); - script_class_set_name(path, name); + String path = ScriptServer::get_global_class_path(name); + script_class_set_name(path, name); + } } } diff --git a/editor/editor_folding.cpp b/editor/editor_folding.cpp index eec4438f96..011fe20564 100644 --- a/editor/editor_folding.cpp +++ b/editor/editor_folding.cpp @@ -165,7 +165,7 @@ void EditorFolding::load_scene_folding(Node *p_scene, const String &p_path) { } bool EditorFolding::has_folding_data(const String &p_path) { - String path = EditorSettings::get_singleton()->get_project_settings_dir(); + String file = p_path.get_file() + "-folding-" + p_path.md5_text() + ".cfg"; file = EditorSettings::get_singleton()->get_project_settings_dir().plus_file(file); return FileAccess::exists(file); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 3ee8d9c6c5..de1f856608 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -399,8 +399,10 @@ void EditorHelpIndex::_notification(int p_what) { if (enable_rl) { class_list->add_constant_override("draw_relationship_lines", 1); class_list->add_color_override("relationship_line_color", rl_color); + class_list->add_constant_override("draw_guides", 0); } else { class_list->add_constant_override("draw_relationship_lines", 0); + class_list->add_constant_override("draw_guides", 1); } } } diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index d6f337cc20..a564a2a113 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1153,6 +1153,11 @@ void EditorInspectorSection::_gui_input(const Ref<InputEvent> &p_event) { Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { + Ref<Font> font = get_font("font", "Tree"); + if (mb->get_position().y > font->get_height()) { //clicked outside + return; + } + _test_unfold(); bool unfold = !object->editor_is_section_unfolded(section); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index dbbf5d08b8..d3ae5d6601 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2003,7 +2003,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (err != OK) ERR_PRINT("Failed to load scene"); editor_data.move_edited_scene_to_index(cur_idx); - get_undo_redo()->clear_history(); + get_undo_redo()->clear_history(false); scene_tabs->set_current_tab(cur_idx); } break; @@ -2613,7 +2613,7 @@ void EditorNode::_remove_edited_scene() { } _scene_tab_changed(new_index); editor_data.remove_scene(old_index); - editor_data.get_undo_redo().clear_history(); + editor_data.get_undo_redo().clear_history(false); _update_title(); _update_scene_tabs(); } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 9c1d22f6ec..3730807243 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -2145,7 +2145,8 @@ void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<T } } -void EditorPropertyResource::_update_menu() { +void EditorPropertyResource::_update_menu_items() { + //////////////////// UPDATE MENU ////////////////////////// RES res = get_edited_object()->get(get_edited_property()); @@ -2287,6 +2288,11 @@ void EditorPropertyResource::_update_menu() { menu->add_icon_item(icon, vformat(TTR("Convert To %s"), what), CONVERT_BASE_ID + i); } } +} + +void EditorPropertyResource::_update_menu() { + + _update_menu_items(); Rect2 gt = edit->get_global_rect(); menu->set_as_minsize(); @@ -2311,6 +2317,20 @@ void EditorPropertyResource::_sub_inspector_object_id_selected(int p_id) { emit_signal("object_id_selected", get_edited_property(), p_id); } +void EditorPropertyResource::_button_input(const Ref<InputEvent> &p_event) { + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid()) { + if (mb->is_pressed() && mb->get_button_index() == BUTTON_RIGHT) { + _update_menu_items(); + Vector2 pos = mb->get_global_position(); + //pos = assign->get_global_transform().xform(pos); + menu->set_as_minsize(); + menu->set_global_position(pos); + menu->popup(); + } + } +} + void EditorPropertyResource::_open_editor_pressed() { RES res = get_edited_object()->get(get_edited_property()); if (res.is_valid()) { @@ -2598,6 +2618,7 @@ void EditorPropertyResource::_bind_methods() { ClassDB::bind_method(D_METHOD("drop_data_fw"), &EditorPropertyResource::drop_data_fw); ClassDB::bind_method(D_METHOD("_button_draw"), &EditorPropertyResource::_button_draw); ClassDB::bind_method(D_METHOD("_open_editor_pressed"), &EditorPropertyResource::_open_editor_pressed); + ClassDB::bind_method(D_METHOD("_button_input"), &EditorPropertyResource::_button_input); } EditorPropertyResource::EditorPropertyResource() { @@ -2624,6 +2645,7 @@ EditorPropertyResource::EditorPropertyResource() { preview->set_margin(MARGIN_BOTTOM, -1); preview->set_margin(MARGIN_RIGHT, -1); assign->add_child(preview); + assign->connect("gui_input", this, "_button_input"); menu = memnew(PopupMenu); add_child(menu); @@ -2632,6 +2654,7 @@ EditorPropertyResource::EditorPropertyResource() { menu->connect("id_pressed", this, "_menu_option"); edit->connect("pressed", this, "_update_menu"); hbc->add_child(edit); + edit->connect("gui_input", this, "_button_input"); file = NULL; scene_tree = NULL; diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 35d8f4d306..541abb1f22 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -552,6 +552,8 @@ class EditorPropertyResource : public EditorProperty { void _resource_selected(); void _viewport_selected(const NodePath &p_path); + void _update_menu_items(); + void _update_menu(); void _sub_inspector_property_keyed(const String &p_property, const Variant &p_value, bool); @@ -564,6 +566,7 @@ class EditorPropertyResource : public EditorProperty { bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + void _button_input(const Ref<InputEvent> &p_event); void _open_editor_pressed(); protected: diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 34c273fbae..c0b441bbd5 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -433,7 +433,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { // navigation _initial_set("editors/3d/navigation/navigation_scheme", 0); - _initial_set("editors/3d/navigation/invert_y-axis", false); + _initial_set("editors/3d/navigation/invert_y_axis", false); hints["editors/3d/navigation/navigation_scheme"] = PropertyInfo(Variant::INT, "editors/3d/navigation/navigation_scheme", PROPERTY_HINT_ENUM, "Godot,Maya,Modo"); _initial_set("editors/3d/navigation/zoom_style", 0); hints["editors/3d/navigation/zoom_style"] = PropertyInfo(Variant::INT, "editors/3d/navigation/zoom_style", PROPERTY_HINT_ENUM, "Vertical, Horizontal"); diff --git a/editor/multi_node_edit.cpp b/editor/multi_node_edit.cpp index be4e752d55..420d8ad3cf 100644 --- a/editor/multi_node_edit.cpp +++ b/editor/multi_node_edit.cpp @@ -52,7 +52,7 @@ bool MultiNodeEdit::_set_impl(const StringName &p_name, const Variant &p_value, UndoRedo *ur = EditorNode::get_singleton()->get_undo_redo(); - ur->create_action(TTR("MultiNode Set") + " " + String(name)); + ur->create_action(TTR("MultiNode Set") + " " + String(name), UndoRedo::MERGE_ENDS); for (const List<NodePath>::Element *E = nodes.front(); E; E = E->next()) { if (!es->has_node(E->get())) diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 1add99bdcc..ee2283a035 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -5070,19 +5070,13 @@ void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String & editor_data->get_undo_redo().add_do_property(child, "polygon", list); } - // locate at preview position - Point2 pos = Point2(0, 0); - if (parent && parent->has_method("get_global_position")) { - pos = parent->call("get_global_position"); - } - Transform2D trans = canvas->get_canvas_transform(); - Point2 target_position = (p_point - trans.get_origin()) / trans.get_scale().x - pos; - if (default_type == "Polygon2D" || default_type == "TouchScreenButton" || default_type == "TextureRect" || default_type == "NinePatchRect") { - target_position -= texture_size / 2; - } + // Compute the global position + Transform2D xform = canvas_item_editor->get_canvas_transform(); + Point2 target_position = xform.affine_inverse().xform(p_point); + // there's nothing to be used as source position so snapping will work as absolute if enabled - target_position = canvas->snap_point(target_position); - editor_data->get_undo_redo().add_do_method(child, "set_position", target_position); + target_position = canvas_item_editor->snap_point(target_position); + editor_data->get_undo_redo().add_do_method(child, "set_global_position", target_position); } bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, const Point2 &p_point) { @@ -5117,8 +5111,8 @@ bool CanvasItemEditorViewport::_create_instance(Node *parent, String &path, cons CanvasItem *parent_ci = Object::cast_to<CanvasItem>(parent); if (parent_ci) { - Vector2 target_pos = canvas->get_canvas_transform().affine_inverse().xform(p_point); - target_pos = canvas->snap_point(target_pos); + Vector2 target_pos = canvas_item_editor->get_canvas_transform().affine_inverse().xform(p_point); + target_pos = canvas_item_editor->snap_point(target_pos); target_pos = parent_ci->get_global_transform_with_canvas().affine_inverse().xform(target_pos); editor_data->get_undo_redo().add_do_method(instanced_scene, "set_position", target_pos); } @@ -5238,7 +5232,7 @@ bool CanvasItemEditorViewport::can_drop_data(const Point2 &p_point, const Varian if (!preview_node->get_parent()) { // create preview only once _create_preview(files); } - Transform2D trans = canvas->get_canvas_transform(); + Transform2D trans = canvas_item_editor->get_canvas_transform(); preview_node->set_position((p_point - trans.get_origin()) / trans.get_scale().x); label->set_text(vformat(TTR("Adding %s..."), default_type)); } @@ -5333,7 +5327,7 @@ void CanvasItemEditorViewport::_bind_methods() { ClassDB::bind_method(D_METHOD("_on_mouse_exit"), &CanvasItemEditorViewport::_on_mouse_exit); } -CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas) { +CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor) { default_type = "Sprite"; // Node2D types.push_back("Sprite"); @@ -5348,7 +5342,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte target_node = NULL; editor = p_node; editor_data = editor->get_scene_tree_dock()->get_editor_data(); - canvas = p_canvas; + canvas_item_editor = p_canvas_item_editor; preview_node = memnew(Node2D); accept = memnew(AcceptDialog); diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index f71eb1b605..207e57dbe2 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -608,7 +608,7 @@ class CanvasItemEditorViewport : public Control { EditorNode *editor; EditorData *editor_data; - CanvasItemEditor *canvas; + CanvasItemEditor *canvas_item_editor; Node2D *preview_node; AcceptDialog *accept; WindowDialog *selector; @@ -642,7 +642,7 @@ public: virtual bool can_drop_data(const Point2 &p_point, const Variant &p_data) const; virtual void drop_data(const Point2 &p_point, const Variant &p_data); - CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas); + CanvasItemEditorViewport(EditorNode *p_node, CanvasItemEditor *p_canvas_item_editor); ~CanvasItemEditorViewport(); }; diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index 472b280d47..a5563c0497 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -1901,7 +1901,7 @@ void SpatialEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, con real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); - bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis"); + bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); if (invert_y_axis) { cursor.x_rot -= p_relative.y * radians_per_pixel; @@ -1926,7 +1926,7 @@ void SpatialEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, cons real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); - bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y-axis"); + bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". Transform prev_camera_transform = to_camera_transform(cursor); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 6614e24df7..95f0c4870e 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -980,8 +980,11 @@ void SceneTreeEditor::_editor_settings_changed() { if (enable_rl) { tree->add_constant_override("draw_relationship_lines", 1); tree->add_color_override("relationship_line_color", rl_color); - } else + tree->add_constant_override("draw_guides", 0); + } else { tree->add_constant_override("draw_relationship_lines", 0); + tree->add_constant_override("draw_guides", 1); + } } void SceneTreeEditor::_bind_methods() { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 089ffa285d..faa561ad54 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -1041,8 +1041,11 @@ void ScriptEditorDebugger::_notification(int p_what) { if (enable_rl) { inspect_scene_tree->add_constant_override("draw_relationship_lines", 1); inspect_scene_tree->add_color_override("relationship_line_color", rl_color); - } else + inspect_scene_tree->add_constant_override("draw_guides", 0); + } else { inspect_scene_tree->add_constant_override("draw_relationship_lines", 0); + inspect_scene_tree->add_constant_override("draw_guides", 1); + } } break; case NOTIFICATION_PROCESS: { diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 402a276f95..441fa7c8af 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -304,7 +304,11 @@ bool RigidCollisionObjectBullet::is_shape_disabled(int p_index) { } void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { - bulletdelete(shapes.write[p_shape_index].bt_shape); + ShapeWrapper &shp = shapes.write[p_shape_index]; + if (shp.bt_shape == mainShape) { + mainShape = NULL; + } + bulletdelete(shp.bt_shape); reload_shapes(); } @@ -366,5 +370,8 @@ void RigidCollisionObjectBullet::body_scale_changed() { void RigidCollisionObjectBullet::internal_shape_destroy(int p_index, bool p_permanentlyFromThisBody) { ShapeWrapper &shp = shapes.write[p_index]; shp.shape->remove_owner(this, p_permanentlyFromThisBody); + if (shp.bt_shape == mainShape) { + mainShape = NULL; + } bulletdelete(shp.bt_shape); } diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp index a36f1123bc..a94b88d566 100644 --- a/modules/bullet/generic_6dof_joint_bullet.cpp +++ b/modules/bullet/generic_6dof_joint_bullet.cpp @@ -135,6 +135,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value; break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis] = p_value; + break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis] = p_value; + break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis] = p_value; + break; case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: limits_lower[1][p_axis] = p_value; set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter @@ -143,6 +152,9 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO limits_upper[1][p_axis] = p_value; set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value; + break; case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value; break; @@ -152,6 +164,15 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value; break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness = p_value; + break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping = p_value; + break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint = p_value; + break; default: ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); WARN_DEPRECATED @@ -170,6 +191,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6 return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis]; case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis]; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + return sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis]; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + return sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis]; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + return sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis]; case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: return limits_lower[1][p_axis]; case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: @@ -182,6 +209,12 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6 return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity; case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint; default: ERR_EXPLAIN("This parameter " + itos(p_param) + " is deprecated"); WARN_DEPRECATED; @@ -215,6 +248,12 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag]; break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: + sixDOFConstraint->getTranslationalLimitMotor()->m_enableSpring[p_axis] = p_value; + break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: + sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableSpring = p_value; + break; default: ERR_EXPLAIN("This flag " + itos(p_flag) + " is deprecated"); WARN_DEPRECATED @@ -224,6 +263,5 @@ void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOF bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const { ERR_FAIL_INDEX_V(p_axis, 3, false); - return flags[p_axis][p_flag]; } diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 37e7718969..85659e1523 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -797,7 +797,10 @@ void RigidBodyBullet::reload_shapes() { const btScalar mass = invMass == 0 ? 0 : 1 / invMass; if (mainShape) { - btVector3 inertia; + // inertia initialised zero here because some of bullet's collision + // shapes incorrectly do not set the vector in calculateLocalIntertia. + // Arbitrary zero is preferable to undefined behaviour. + btVector3 inertia(0, 0, 0); mainShape->calculateLocalInertia(mass, inertia); btBody->setMassProps(mass, inertia); } diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 4eb798de11..23d879e1cd 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -159,6 +159,74 @@ CSGBrush *CSGShape::_get_brush() { return brush; } +int CSGShape::mikktGetNumFaces(const SMikkTSpaceContext *pContext) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + return surface.vertices.size() / 3; +} + +int CSGShape::mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace) { + // always 3 + return 3; +} + +void CSGShape::mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + Vector3 v = surface.verticesw[iFace * 3 + iVert]; + fvPosOut[0] = v.x; + fvPosOut[1] = v.y; + fvPosOut[2] = v.z; +} + +void CSGShape::mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + Vector3 n = surface.normalsw[iFace * 3 + iVert]; + fvNormOut[0] = n.x; + fvNormOut[1] = n.y; + fvNormOut[2] = n.z; +} + +void CSGShape::mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + Vector2 t = surface.uvsw[iFace * 3 + iVert]; + fvTexcOut[0] = t.x; + fvTexcOut[1] = t.y; +} + +void CSGShape::mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) { + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + int i = (iFace * 3 + iVert) * 4; + + // Godot seems to want the tangent flipped because our handedness is reversed.. + surface.tansw[i++] = -fvTangent[0]; + surface.tansw[i++] = -fvTangent[1]; + surface.tansw[i++] = -fvTangent[2]; + surface.tansw[i++] = fSign; +} + +void CSGShape::mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, + const tbool bIsOrientationPreserving, const int iFace, const int iVert) { + + ShapeUpdateSurface &surface = *((ShapeUpdateSurface *)pContext->m_pUserData); + + int i = iFace * 3 + iVert; + Vector3 normal = surface.normalsw[i]; + Vector3 tangent = Vector3(fvTangent[0], fvTangent[1], fvTangent[2]); + Vector3 bitangent = Vector3(fvBiTangent[0], fvBiTangent[1], fvBiTangent[2]); + float d = bitangent.dot(normal.cross(tangent)); + + // Godot seems to want the tangent flipped because our handedness is reversed.. + i *= 4; + surface.tansw[i++] = -tangent.x; + surface.tansw[i++] = -tangent.y; + surface.tansw[i++] = -tangent.z; + surface.tansw[i++] = d < 0 ? -1 : 1; +} + void CSGShape::_update_shape() { if (parent) @@ -211,6 +279,9 @@ void CSGShape::_update_shape() { surfaces.write[i].vertices.resize(face_count[i] * 3); surfaces.write[i].normals.resize(face_count[i] * 3); surfaces.write[i].uvs.resize(face_count[i] * 3); + if (calculate_tangents) { + surfaces.write[i].tans.resize(face_count[i] * 3 * 4); + } surfaces.write[i].last_added = 0; if (i != surfaces.size() - 1) { @@ -220,6 +291,9 @@ void CSGShape::_update_shape() { surfaces.write[i].verticesw = surfaces.write[i].vertices.write(); surfaces.write[i].normalsw = surfaces.write[i].normals.write(); surfaces.write[i].uvsw = surfaces.write[i].uvs.write(); + if (calculate_tangents) { + surfaces.write[i].tansw = surfaces.write[i].tans.write(); + } } //fill arrays @@ -274,9 +348,19 @@ void CSGShape::_update_shape() { normal = -normal; } - surfaces[idx].verticesw[last + order[j]] = v; - surfaces[idx].uvsw[last + order[j]] = n->faces[i].uvs[j]; - surfaces[idx].normalsw[last + order[j]] = normal; + int k = last + order[j]; + surfaces[idx].verticesw[k] = v; + surfaces[idx].uvsw[k] = n->faces[i].uvs[j]; + surfaces[idx].normalsw[k] = normal; + + if (calculate_tangents) { + // zero out our tangents for now + k *= 4; + surfaces[idx].tansw[k++] = 0.0; + surfaces[idx].tansw[k++] = 0.0; + surfaces[idx].tansw[k++] = 0.0; + surfaces[idx].tansw[k++] = 0.0; + } } surfaces.write[idx].last_added += 3; @@ -287,20 +371,43 @@ void CSGShape::_update_shape() { //create surfaces for (int i = 0; i < surfaces.size(); i++) { + // calculate tangents for this surface + bool have_tangents = calculate_tangents; + if (have_tangents) { + SMikkTSpaceInterface mkif; + mkif.m_getNormal = mikktGetNormal; + mkif.m_getNumFaces = mikktGetNumFaces; + mkif.m_getNumVerticesOfFace = mikktGetNumVerticesOfFace; + mkif.m_getPosition = mikktGetPosition; + mkif.m_getTexCoord = mikktGetTexCoord; + mkif.m_setTSpace = mikktSetTSpaceDefault; + mkif.m_setTSpaceBasic = NULL; + + SMikkTSpaceContext msc; + msc.m_pInterface = &mkif; + msc.m_pUserData = &surfaces.write[i]; + have_tangents = genTangSpaceDefault(&msc); + } + // unset write access surfaces.write[i].verticesw = PoolVector<Vector3>::Write(); surfaces.write[i].normalsw = PoolVector<Vector3>::Write(); surfaces.write[i].uvsw = PoolVector<Vector2>::Write(); + surfaces.write[i].tansw = PoolVector<float>::Write(); if (surfaces[i].last_added == 0) continue; + // and convert to surface array Array array; array.resize(Mesh::ARRAY_MAX); array[Mesh::ARRAY_VERTEX] = surfaces[i].vertices; array[Mesh::ARRAY_NORMAL] = surfaces[i].normals; array[Mesh::ARRAY_TEX_UV] = surfaces[i].uvs; + if (have_tangents) { + array[Mesh::ARRAY_TANGENT] = surfaces[i].tans; + } int idx = root_mesh->get_surface_count(); root_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_TRIANGLES, array); @@ -400,6 +507,15 @@ CSGShape::Operation CSGShape::get_operation() const { return operation; } +void CSGShape::set_calculate_tangents(bool p_calculate_tangents) { + calculate_tangents = p_calculate_tangents; + _make_dirty(); +} + +bool CSGShape::is_calculating_tangents() const { + return calculate_tangents; +} + void CSGShape::_validate_property(PropertyInfo &property) const { if (is_inside_tree() && property.name.begins_with("use_collision") && !is_root_shape()) { //hide collision if not root @@ -421,9 +537,13 @@ void CSGShape::_bind_methods() { ClassDB::bind_method(D_METHOD("set_snap", "snap"), &CSGShape::set_snap); ClassDB::bind_method(D_METHOD("get_snap"), &CSGShape::get_snap); + ClassDB::bind_method(D_METHOD("set_calculate_tangents", "enabled"), &CSGShape::set_calculate_tangents); + ClassDB::bind_method(D_METHOD("is_calculating_tangents"), &CSGShape::is_calculating_tangents); + ADD_PROPERTY(PropertyInfo(Variant::INT, "operation", PROPERTY_HINT_ENUM, "Union,Intersection,Subtraction"), "set_operation", "get_operation"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_collision"), "set_use_collision", "is_using_collision"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "snap", PROPERTY_HINT_RANGE, "0.0001,1,0.001"), "set_snap", "get_snap"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "calculate_tangents"), "set_calculate_tangents", "is_calculating_tangents"); BIND_ENUM_CONSTANT(OPERATION_UNION); BIND_ENUM_CONSTANT(OPERATION_INTERSECTION); @@ -438,6 +558,7 @@ CSGShape::CSGShape() { use_collision = false; operation = OPERATION_UNION; snap = 0.001; + calculate_tangents = true; } CSGShape::~CSGShape() { diff --git a/modules/csg/csg_shape.h b/modules/csg/csg_shape.h index 6898cdaf64..0a4bb5f665 100644 --- a/modules/csg/csg_shape.h +++ b/modules/csg/csg_shape.h @@ -36,6 +36,7 @@ #include "csg.h" #include "scene/3d/visual_instance.h" #include "scene/resources/concave_polygon_shape.h" +#include "thirdparty/misc/mikktspace.h" class CSGShape : public VisualInstance { GDCLASS(CSGShape, VisualInstance); @@ -63,6 +64,8 @@ private: Ref<ConcavePolygonShape> root_collision_shape; RID root_collision_instance; + bool calculate_tangents; + Ref<ArrayMesh> root_mesh; struct Vector3Hasher { @@ -78,14 +81,26 @@ private: PoolVector<Vector3> vertices; PoolVector<Vector3> normals; PoolVector<Vector2> uvs; + PoolVector<float> tans; Ref<Material> material; int last_added; PoolVector<Vector3>::Write verticesw; PoolVector<Vector3>::Write normalsw; PoolVector<Vector2>::Write uvsw; + PoolVector<float>::Write tansw; }; + //mikktspace callbacks + static int mikktGetNumFaces(const SMikkTSpaceContext *pContext); + static int mikktGetNumVerticesOfFace(const SMikkTSpaceContext *pContext, const int iFace); + static void mikktGetPosition(const SMikkTSpaceContext *pContext, float fvPosOut[], const int iFace, const int iVert); + static void mikktGetNormal(const SMikkTSpaceContext *pContext, float fvNormOut[], const int iFace, const int iVert); + static void mikktGetTexCoord(const SMikkTSpaceContext *pContext, float fvTexcOut[], const int iFace, const int iVert); + static void mikktSetTSpaceBasic(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert); + static void mikktSetTSpaceDefault(const SMikkTSpaceContext *pContext, const float fvTangent[], const float fvBiTangent[], const float fMagS, const float fMagT, + const tbool bIsOrientationPreserving, const int iFace, const int iVert); + void _update_shape(); protected: @@ -115,6 +130,9 @@ public: void set_snap(float p_snap); float get_snap() const; + void set_calculate_tangents(bool p_calculate_tangents); + bool is_calculating_tangents() const; + bool is_root_shape() const; CSGShape(); ~CSGShape(); diff --git a/modules/csg/doc_classes/CSGShape.xml b/modules/csg/doc_classes/CSGShape.xml index 90621b94f4..ac3c2342fc 100644 --- a/modules/csg/doc_classes/CSGShape.xml +++ b/modules/csg/doc_classes/CSGShape.xml @@ -20,6 +20,9 @@ </method> </methods> <members> + <member name="calculate_tangents" type="bool" setter="set_calculate_tangents" getter="is_calculating_tangents"> + Calculate tangents for the CSG shape which allows the use of normal maps. This is only applied on the root shape, this setting is ignored on any child. + </member> <member name="operation" type="int" setter="set_operation" getter="get_operation" enum="CSGShape.Operation"> The operation that is performed on this shape. This is ignored for the first CSG child node as the operation is between this node and the previous child of this nodes parent. </member> diff --git a/modules/gdscript/gdscript_function.cpp b/modules/gdscript/gdscript_function.cpp index 31115a4bd9..c67cf124c0 100644 --- a/modules/gdscript/gdscript_function.cpp +++ b/modules/gdscript/gdscript_function.cpp @@ -477,56 +477,53 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GET_VARIANT_PTR(dst, 3); #ifdef DEBUG_ENABLED - if (a->get_type() != Variant::OBJECT || a->operator Object *() == NULL) { - - err_text = "Left operand of 'is' is not an instance of anything."; - OPCODE_BREAK; - } if (b->get_type() != Variant::OBJECT || b->operator Object *() == NULL) { err_text = "Right operand of 'is' is not a class."; OPCODE_BREAK; } #endif - Object *obj_A = *a; - Object *obj_B = *b; - - GDScript *scr_B = Object::cast_to<GDScript>(obj_B); bool extends_ok = false; + if (a->get_type() == Variant::OBJECT && a->operator Object *() != NULL) { + Object *obj_A = *a; + Object *obj_B = *b; - if (scr_B) { - //if B is a script, the only valid condition is that A has an instance which inherits from the script - //in other situation, this shoul return false. + GDScript *scr_B = Object::cast_to<GDScript>(obj_B); - if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) { + if (scr_B) { + //if B is a script, the only valid condition is that A has an instance which inherits from the script + //in other situation, this shoul return false. - GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr()); - //bool found=false; - while (cmp) { + if (obj_A->get_script_instance() && obj_A->get_script_instance()->get_language() == GDScriptLanguage::get_singleton()) { - if (cmp == scr_B) { - //inherits from script, all ok - extends_ok = true; - break; - } + GDScript *cmp = static_cast<GDScript *>(obj_A->get_script_instance()->get_script().ptr()); + //bool found=false; + while (cmp) { - cmp = cmp->_base; + if (cmp == scr_B) { + //inherits from script, all ok + extends_ok = true; + break; + } + + cmp = cmp->_base; + } } - } - } else { + } else { - GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B); + GDScriptNativeClass *nc = Object::cast_to<GDScriptNativeClass>(obj_B); #ifdef DEBUG_ENABLED - if (!nc) { + if (!nc) { - err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "')."; - OPCODE_BREAK; - } + err_text = "Right operand of 'is' is not a class (type: '" + obj_B->get_class() + "')."; + OPCODE_BREAK; + } #endif - extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name()); + extends_ok = ClassDB::is_parent_class(obj_A->get_class_name(), nc->get_name()); + } } *dst = extends_ok; diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 09b3a5631f..a4bda42b16 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -6432,6 +6432,10 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String StringName native; if (p_base_type.kind == DataType::GDSCRIPT) { base_gdscript = p_base_type.script_type; + if (base_gdscript.is_null() || !base_gdscript->is_valid()) { + // GDScript wasn't properly compÃled, don't bother trying + return false; + } } else if (p_base_type.kind == DataType::SCRIPT) { base_script = p_base_type.script_type; } else if (p_base_type.kind == DataType::NATIVE) { @@ -6472,6 +6476,12 @@ bool GDScriptParser::_get_function_signature(DataType &p_base_type, const String base_script = base_script->get_base_script(); } + if (native == StringName()) { + // Empty native class, might happen in some Script implementations + // Just ignore it + return false; + } + #ifdef DEBUG_METHODS_ENABLED // Only native remains @@ -6914,6 +6924,10 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN Ref<GDScript> gds; if (base_type.kind == DataType::GDSCRIPT) { gds = base_type.script_type; + if (gds.is_null() || !gds->is_valid()) { + // GDScript wasn't properly compÃled, don't bother trying + return false; + } } Ref<Script> scr; @@ -6976,6 +6990,12 @@ bool GDScriptParser::_get_member_type(const DataType &p_base_type, const StringN scr = scr->get_base_script(); } + if (native == StringName()) { + // Empty native class, might happen in some Script implementations + // Just ignore it + return false; + } + // Check ClassDB if (!ClassDB::class_exists(native)) { native = "_" + native.operator String(); diff --git a/modules/mono/glue/Managed/Files/Basis.cs b/modules/mono/glue/Managed/Files/Basis.cs index a5618cb28d..54d2813abf 100644 --- a/modules/mono/glue/Managed/Files/Basis.cs +++ b/modules/mono/glue/Managed/Files/Basis.cs @@ -410,10 +410,12 @@ namespace Godot ); } - public Quat Quat() { + public Quat Quat() + { real_t trace = _x[0] + _y[1] + _z[2]; - if (trace > 0.0f) { + if (trace > 0.0f) + { real_t s = Mathf.Sqrt(trace + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -424,7 +426,8 @@ namespace Godot ); } - if (_x[0] > _y[1] && _x[0] > _z[2]) { + if (_x[0] > _y[1] && _x[0] > _z[2]) + { real_t s = Mathf.Sqrt(_x[0] - _y[1] - _z[2] + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -435,7 +438,8 @@ namespace Godot ); } - if (_y[1] > _z[2]) { + if (_y[1] > _z[2]) + { real_t s = Mathf.Sqrt(-_x[0] + _y[1] - _z[2] + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -444,7 +448,9 @@ namespace Godot (_y[2] + _z[1]) * inv_s, (_x[2] - _z[0]) * inv_s ); - } else { + } + else + { real_t s = Mathf.Sqrt(-_x[0] - _y[1] + _z[2] + 1.0f) * 2f; real_t inv_s = 1f / s; return new Quat( @@ -502,8 +508,8 @@ namespace Godot { var axis_sq = new Vector3(axis.x * axis.x, axis.y * axis.y, axis.z * axis.z); - real_t cosine = Mathf.Cos( phi); - real_t sine = Mathf.Sin( phi); + real_t cosine = Mathf.Cos(phi); + real_t sine = Mathf.Sin(phi); _x = new Vector3 ( @@ -529,9 +535,9 @@ namespace Godot public Basis(Vector3 xAxis, Vector3 yAxis, Vector3 zAxis) { - _x = xAxis; - _y = yAxis; - _z = zAxis; + x = xAxis; + y = yAxis; + z = zAxis; } public Basis(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz) diff --git a/modules/squish/image_compress_squish.cpp b/modules/squish/image_compress_squish.cpp index 26cb76011c..a08ac7bd28 100644 --- a/modules/squish/image_compress_squish.cpp +++ b/modules/squish/image_compress_squish.cpp @@ -64,12 +64,13 @@ void image_decompress_squish(Image *p_image) { return; } - int dst_ofs = 0; - for (int i = 0; i <= mm_count; i++) { int src_ofs = 0, mipmap_size = 0, mipmap_w = 0, mipmap_h = 0; p_image->get_mipmap_offset_size_and_dimensions(i, src_ofs, mipmap_size, mipmap_w, mipmap_h); - squish::DecompressImage(&wb[dst_ofs], mipmap_w, mipmap_h, &rb[src_ofs], squish_flags); + int dst_ofs = Image::get_image_mipmap_offset(p_image->get_width(), p_image->get_height(), target_format, i); + squish::DecompressImage(&wb[dst_ofs], w, h, &rb[src_ofs], squish_flags); + w >>= 1; + h >>= 1; } p_image->create(p_image->get_width(), p_image->get_height(), p_image->has_mipmaps(), target_format, data); diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 81dc861f3f..8123aaa427 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -1237,7 +1237,9 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a ERR_FAIL_COND_V(window_object == nil, ERR_UNAVAILABLE); window_view = [[GodotContentView alloc] init]; - [window_view setWantsLayer:TRUE]; + if (@available(macOS 10.14, *)) { + [window_view setWantsLayer:TRUE]; + } float displayScale = 1.0; if (is_hidpi_allowed()) { diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 2ab7b835b6..04854e93b6 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -369,7 +369,7 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a } // disable resizable window - if (!current_videomode.resizable) { + if (!current_videomode.resizable && !current_videomode.fullscreen) { XSizeHints *xsh; xsh = XAllocSizeHints(); xsh->flags = PMinSize | PMaxSize; diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index a092ef826f..c2af725919 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -323,6 +323,7 @@ void AudioStreamPlayer2D::play(float p_from_pos) { } if (stream_playback.is_valid()) { + active = true; setplay = p_from_pos; output_ready = false; set_physics_process_internal(true); diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp index 6056a7f76f..0ea2e85dfa 100644 --- a/scene/2d/canvas_item.cpp +++ b/scene/2d/canvas_item.cpp @@ -376,6 +376,9 @@ bool CanvasItem::is_visible_in_tree() const { void CanvasItem::_propagate_visibility_changed(bool p_visible) { + if (p_visible && first_draw) { //avoid propagating it twice + first_draw = false; + } notification(NOTIFICATION_VISIBILITY_CHANGED); if (p_visible) diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index a1b624a246..4fc2282ae7 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -1313,7 +1313,7 @@ void CPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); ADD_GROUP("Hue Variation", "hue_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION); ADD_GROUP("Animation", "anim_"); diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 2c362f1b31..1c504d00fc 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -298,6 +298,7 @@ Skeleton2D::Skeleton2D() { transform_dirty = true; skeleton = VS::get_singleton()->skeleton_create(); + set_notify_transform(true); } Skeleton2D::~Skeleton2D() { diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp index 7d7c47619a..d656ba0f64 100644 --- a/scene/2d/visibility_notifier_2d.cpp +++ b/scene/2d/visibility_notifier_2d.cpp @@ -190,7 +190,7 @@ void VisibilityEnabler2D::_find_nodes(Node *p_node) { if (enabler[ENABLER_FREEZE_BODIES]) { RigidBody2D *rb2d = Object::cast_to<RigidBody2D>(p_node); - if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_CHARACTER || (rb2d->get_mode() == RigidBody2D::MODE_RIGID && !rb2d->is_able_to_sleep())))) { + if (rb2d && ((rb2d->get_mode() == RigidBody2D::MODE_CHARACTER || rb2d->get_mode() == RigidBody2D::MODE_RIGID))) { add = true; meta = rb2d->get_mode(); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 401a1971c6..afd87deca6 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -641,6 +641,7 @@ float AudioStreamPlayer3D::get_pitch_scale() const { void AudioStreamPlayer3D::play(float p_from_pos) { if (stream_playback.is_valid()) { + active = true; setplay = p_from_pos; output_ready = false; set_physics_process_internal(true); diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index a22708ac99..69839a0087 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -1369,7 +1369,7 @@ void CPUParticles::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); ADD_GROUP("Hue Variation", "hue_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "Curve"), "set_param_curve", "get_param_curve", PARAM_HUE_VARIATION); ADD_GROUP("Animation", "anim_"); diff --git a/scene/3d/physics_joint.cpp b/scene/3d/physics_joint.cpp index a30fc0ac3e..02c6b1d969 100644 --- a/scene/3d/physics_joint.cpp +++ b/scene/3d/physics_joint.cpp @@ -716,6 +716,11 @@ void Generic6DOFJoint::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/damping"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_LIMIT); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_x", "_get_angular_hi_limit_x"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_x/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_x", "_get_angular_lo_limit_x"); @@ -727,6 +732,10 @@ void Generic6DOFJoint::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_x/target_velocity"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_x/force_limit"), "set_param_x", "get_param_x", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_x/enabled"), "set_flag_x", "get_flag_x", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/stiffness"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/damping"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_x/equilibrium_point"), "set_param_x", "get_param_x", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_LIMIT); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_y/upper_distance"), "set_param_y", "get_param_y", PARAM_LINEAR_UPPER_LIMIT); @@ -737,6 +746,10 @@ void Generic6DOFJoint::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/damping"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_LIMIT); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_y", "_get_angular_hi_limit_y"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_y/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_y", "_get_angular_lo_limit_y"); @@ -748,6 +761,10 @@ void Generic6DOFJoint::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_y/target_velocity"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_y/force_limit"), "set_param_y", "get_param_y", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_y/enabled"), "set_flag_y", "get_flag_y", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/stiffness"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/damping"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_y/equilibrium_point"), "set_param_y", "get_param_y", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_LIMIT); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_limit_z/upper_distance"), "set_param_z", "get_param_z", PARAM_LINEAR_UPPER_LIMIT); @@ -758,6 +775,10 @@ void Generic6DOFJoint::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_LINEAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "linear_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_LINEAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/damping"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "linear_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_limit_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_LIMIT); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/upper_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_hi_limit_z", "_get_angular_hi_limit_z"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "angular_limit_z/lower_angle", PROPERTY_HINT_RANGE, "-180,180,0.01"), "_set_angular_lo_limit_z", "_get_angular_lo_limit_z"); @@ -769,6 +790,10 @@ void Generic6DOFJoint::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_motor_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_MOTOR); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_z/target_velocity"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_TARGET_VELOCITY); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_motor_z/force_limit"), "set_param_z", "get_param_z", PARAM_ANGULAR_MOTOR_FORCE_LIMIT); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "angular_spring_z/enabled"), "set_flag_z", "get_flag_z", FLAG_ENABLE_ANGULAR_SPRING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/stiffness"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_STIFFNESS); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/damping"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_DAMPING); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "angular_spring_z/equilibrium_point"), "set_param_z", "get_param_z", PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT); BIND_ENUM_CONSTANT(PARAM_LINEAR_LOWER_LIMIT); BIND_ENUM_CONSTANT(PARAM_LINEAR_UPPER_LIMIT); @@ -790,6 +815,8 @@ void Generic6DOFJoint::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_LIMIT); BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_LIMIT); + BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_SPRING); + BIND_ENUM_CONSTANT(FLAG_ENABLE_ANGULAR_SPRING); BIND_ENUM_CONSTANT(FLAG_ENABLE_MOTOR); BIND_ENUM_CONSTANT(FLAG_ENABLE_LINEAR_MOTOR); BIND_ENUM_CONSTANT(FLAG_MAX); @@ -923,6 +950,9 @@ Generic6DOFJoint::Generic6DOFJoint() { set_param_x(PARAM_LINEAR_DAMPING, 1.0); set_param_x(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); set_param_x(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); + set_param_x(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); + set_param_x(PARAM_LINEAR_SPRING_DAMPING, 0.01); + set_param_x(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); set_param_x(PARAM_ANGULAR_LOWER_LIMIT, 0); set_param_x(PARAM_ANGULAR_UPPER_LIMIT, 0); set_param_x(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); @@ -932,9 +962,14 @@ Generic6DOFJoint::Generic6DOFJoint() { set_param_x(PARAM_ANGULAR_ERP, 0.5); set_param_x(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); set_param_x(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); + set_param_x(PARAM_ANGULAR_SPRING_STIFFNESS, 0); + set_param_x(PARAM_ANGULAR_SPRING_DAMPING, 0); + set_param_x(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); set_flag_x(FLAG_ENABLE_ANGULAR_LIMIT, true); set_flag_x(FLAG_ENABLE_LINEAR_LIMIT, true); + set_flag_x(FLAG_ENABLE_ANGULAR_SPRING, false); + set_flag_x(FLAG_ENABLE_LINEAR_SPRING, false); set_flag_x(FLAG_ENABLE_MOTOR, false); set_flag_x(FLAG_ENABLE_LINEAR_MOTOR, false); @@ -945,6 +980,9 @@ Generic6DOFJoint::Generic6DOFJoint() { set_param_y(PARAM_LINEAR_DAMPING, 1.0); set_param_y(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); set_param_y(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); + set_param_y(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); + set_param_y(PARAM_LINEAR_SPRING_DAMPING, 0.01); + set_param_y(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); set_param_y(PARAM_ANGULAR_LOWER_LIMIT, 0); set_param_y(PARAM_ANGULAR_UPPER_LIMIT, 0); set_param_y(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); @@ -954,9 +992,14 @@ Generic6DOFJoint::Generic6DOFJoint() { set_param_y(PARAM_ANGULAR_ERP, 0.5); set_param_y(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); set_param_y(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); + set_param_y(PARAM_ANGULAR_SPRING_STIFFNESS, 0); + set_param_y(PARAM_ANGULAR_SPRING_DAMPING, 0); + set_param_y(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); set_flag_y(FLAG_ENABLE_ANGULAR_LIMIT, true); set_flag_y(FLAG_ENABLE_LINEAR_LIMIT, true); + set_flag_y(FLAG_ENABLE_ANGULAR_SPRING, false); + set_flag_y(FLAG_ENABLE_LINEAR_SPRING, false); set_flag_y(FLAG_ENABLE_MOTOR, false); set_flag_y(FLAG_ENABLE_LINEAR_MOTOR, false); @@ -967,6 +1010,9 @@ Generic6DOFJoint::Generic6DOFJoint() { set_param_z(PARAM_LINEAR_DAMPING, 1.0); set_param_z(PARAM_LINEAR_MOTOR_TARGET_VELOCITY, 0); set_param_z(PARAM_LINEAR_MOTOR_FORCE_LIMIT, 0); + set_param_z(PARAM_LINEAR_SPRING_STIFFNESS, 0.01); + set_param_z(PARAM_LINEAR_SPRING_DAMPING, 0.01); + set_param_z(PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT, 0.0); set_param_z(PARAM_ANGULAR_LOWER_LIMIT, 0); set_param_z(PARAM_ANGULAR_UPPER_LIMIT, 0); set_param_z(PARAM_ANGULAR_LIMIT_SOFTNESS, 0.5f); @@ -976,9 +1022,14 @@ Generic6DOFJoint::Generic6DOFJoint() { set_param_z(PARAM_ANGULAR_ERP, 0.5); set_param_z(PARAM_ANGULAR_MOTOR_TARGET_VELOCITY, 0); set_param_z(PARAM_ANGULAR_MOTOR_FORCE_LIMIT, 300); + set_param_z(PARAM_ANGULAR_SPRING_STIFFNESS, 0); + set_param_z(PARAM_ANGULAR_SPRING_DAMPING, 0); + set_param_z(PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT, 0); set_flag_z(FLAG_ENABLE_ANGULAR_LIMIT, true); set_flag_z(FLAG_ENABLE_LINEAR_LIMIT, true); + set_flag_z(FLAG_ENABLE_ANGULAR_SPRING, false); + set_flag_z(FLAG_ENABLE_LINEAR_SPRING, false); set_flag_z(FLAG_ENABLE_MOTOR, false); set_flag_z(FLAG_ENABLE_LINEAR_MOTOR, false); } diff --git a/scene/3d/physics_joint.h b/scene/3d/physics_joint.h index 37870d6f30..ee4ca28658 100644 --- a/scene/3d/physics_joint.h +++ b/scene/3d/physics_joint.h @@ -251,6 +251,9 @@ public: PARAM_LINEAR_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, + PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, + PARAM_LINEAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, + PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, @@ -260,12 +263,17 @@ public: PARAM_ANGULAR_ERP = PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, + PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, + PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, + PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, PARAM_MAX = PhysicsServer::G6DOF_JOINT_MAX, }; enum Flag { FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, + FLAG_ENABLE_LINEAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, + FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, FLAG_ENABLE_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR, FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, FLAG_MAX = PhysicsServer::G6DOF_JOINT_FLAG_MAX diff --git a/scene/3d/visibility_notifier.cpp b/scene/3d/visibility_notifier.cpp index c69387d082..9a0832b27a 100644 --- a/scene/3d/visibility_notifier.cpp +++ b/scene/3d/visibility_notifier.cpp @@ -153,7 +153,7 @@ void VisibilityEnabler::_find_nodes(Node *p_node) { if (enabler[ENABLER_FREEZE_BODIES]) { RigidBody *rb = Object::cast_to<RigidBody>(p_node); - if (rb && ((rb->get_mode() == RigidBody::MODE_CHARACTER || (rb->get_mode() == RigidBody::MODE_RIGID && !rb->is_able_to_sleep())))) { + if (rb && ((rb->get_mode() == RigidBody::MODE_CHARACTER || rb->get_mode() == RigidBody::MODE_RIGID))) { add = true; meta = rb->get_mode(); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 102f05a146..64202ba0e3 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1348,6 +1348,9 @@ void AnimationPlayer::_animation_changed() { clear_caches(); emit_signal("caches_cleared"); + if (is_playing()) { + playback.seeked = true; //need to restart stuff, like audio + } } void AnimationPlayer::_stop_playing_caches() { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 31f7a21114..c083e727d1 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -901,6 +901,7 @@ void Tree::update_cache() { cache.item_margin = get_constant("item_margin"); cache.button_margin = get_constant("button_margin"); cache.guide_width = get_constant("guide_width"); + cache.draw_guides = get_constant("draw_guides"); cache.draw_relationship_lines = get_constant("draw_relationship_lines"); cache.relationship_line_color = get_color("relationship_line_color"); cache.scroll_border = get_constant("scroll_border"); @@ -1132,7 +1133,9 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 cell_rect.size.x += cache.hseparation; } - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1); + if (cache.draw_guides) { + VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1); + } if (i == 0) { diff --git a/scene/gui/tree.h b/scene/gui/tree.h index 34138acb85..886ce66e2c 100644 --- a/scene/gui/tree.h +++ b/scene/gui/tree.h @@ -434,6 +434,7 @@ private: int button_margin; Point2 offset; int draw_relationship_lines; + int draw_guides; int scroll_border; int scroll_speed; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 3242068bf7..ae2ab2af80 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -157,7 +157,7 @@ void Node::_notification(int p_notification) { // kill children as cleanly as possible while (data.children.size()) { - Node *child = data.children[0]; + Node *child = data.children[data.children.size() - 1]; //begin from the end because its faster and more consistent with creation remove_child(child); memdelete(child); } @@ -1182,13 +1182,24 @@ void Node::remove_child(Node *p_child) { ERR_FAIL_COND(data.blocked > 0); } + int child_count = data.children.size(); + Node **children = data.children.ptrw(); int idx = -1; - for (int i = 0; i < data.children.size(); i++) { - if (data.children[i] == p_child) { + if (p_child->data.pos >= 0 && p_child->data.pos < child_count) { + if (children[p_child->data.pos] == p_child) { + idx = p_child->data.pos; + } + } + + if (idx == -1) { //maybe removed while unparenting or something and index was not updated, so just in case the above fails, try this. + for (int i = 0; i < child_count; i++) { - idx = i; - break; + if (children[i] == p_child) { + + idx = i; + break; + } } } @@ -1205,10 +1216,14 @@ void Node::remove_child(Node *p_child) { data.children.remove(idx); - for (int i = idx; i < data.children.size(); i++) { + //update pointer and size + child_count = data.children.size(); + children = data.children.ptrw(); - data.children[i]->data.pos = i; - data.children[i]->notification(NOTIFICATION_MOVED_IN_PARENT); + for (int i = idx; i < child_count; i++) { + + children[i]->data.pos = i; + children[i]->notification(NOTIFICATION_MOVED_IN_PARENT); } p_child->data.parent = NULL; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 82645aa17a..8545efb966 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1510,12 +1510,17 @@ void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_inpu Control *control = Object::cast_to<Control>(ci); if (control) { - control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it) + if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) { + control->emit_signal(SceneStringNames::get_singleton()->gui_input, ev); //signal should be first, so it's possible to override an event (and then accept it) + } if (gui.key_event_accepted) break; if (!control->is_inside_tree()) break; - control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev); + + if (control->data.mouse_filter != Control::MOUSE_FILTER_IGNORE) { + control->call_multilevel(SceneStringNames::get_singleton()->_gui_input, ev); + } if (!control->is_inside_tree() || control->is_set_as_toplevel()) break; @@ -1895,7 +1900,13 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (gui.drag_data.get_type() != Variant::NIL) { gui.mouse_focus = NULL; + break; } else { + if (gui.drag_preview != NULL) { + ERR_PRINT("Don't set a drag preview and return null data. Preview was deleted and drag request ignored."); + memdelete(gui.drag_preview); + gui.drag_preview = NULL; + } gui.dragging = false; } diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 4de47b2cb0..fff136cdc3 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -653,6 +653,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const theme->set_constant("item_margin", "Tree", 12 * scale); theme->set_constant("button_margin", "Tree", 4 * scale); theme->set_constant("draw_relationship_lines", "Tree", 0); + theme->set_constant("draw_guides", "Tree", 1); theme->set_constant("scroll_border", "Tree", 4); theme->set_constant("scroll_speed", "Tree", 12); diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 838d73edb3..80191367ce 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -706,6 +706,7 @@ bool ArrayMesh::_get(const StringName &p_name, Variant &r_ret) const { Vector<AABB> skel_aabb = VS::get_singleton()->mesh_surface_get_skeleton_aabb(mesh, idx); Array arr; + arr.resize(skel_aabb.size()); for (int i = 0; i < skel_aabb.size(); i++) { arr[i] = skel_aabb[i]; } diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index b3fc13b79e..dae01e8d96 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -1154,7 +1154,7 @@ void ParticlesMaterial::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "color_ramp", PROPERTY_HINT_RESOURCE_TYPE, "GradientTexture"), "set_color_ramp", "get_color_ramp"); ADD_GROUP("Hue Variation", "hue_"); - ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.1"), "set_param", "get_param", PARAM_HUE_VARIATION); + ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation", PROPERTY_HINT_RANGE, "-1,1,0.01"), "set_param", "get_param", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::REAL, "hue_variation_random", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_param_randomness", "get_param_randomness", PARAM_HUE_VARIATION); ADD_PROPERTYI(PropertyInfo(Variant::OBJECT, "hue_variation_curve", PROPERTY_HINT_RESOURCE_TYPE, "CurveTexture"), "set_param_texture", "get_param_texture", PARAM_HUE_VARIATION); ADD_GROUP("Animation", "anim_"); diff --git a/scene/resources/sky_box.cpp b/scene/resources/sky_box.cpp index a6a52c7bba..347bca4400 100644 --- a/scene/resources/sky_box.cpp +++ b/scene/resources/sky_box.cpp @@ -190,9 +190,15 @@ Ref<Image> ProceduralSky::_generate_sky() { float c = (v_angle - (Math_PI * 0.5)) / (Math_PI * 0.5); color = ground_horizon_linear.linear_interpolate(ground_bottom_linear, Math::ease(c, ground_curve)); + color.r *= ground_energy; + color.g *= ground_energy; + color.b *= ground_energy; } else { float c = v_angle / (Math_PI * 0.5); color = sky_horizon_linear.linear_interpolate(sky_top_linear, Math::ease(1.0 - c, sky_curve)); + color.r *= sky_energy; + color.g *= sky_energy; + color.b *= sky_energy; float sun_angle = Math::rad2deg(Math::acos(CLAMP(sun.dot(normal), -1.0, 1.0))); diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp index 60505c08c5..3a965ff800 100644 --- a/servers/physics/joints/generic_6dof_joint_sw.cpp +++ b/servers/physics/joints/generic_6dof_joint_sw.cpp @@ -503,6 +503,24 @@ void Generic6DOFJointSW::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJoi case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: { // Not implemented in GodotPhysics backend } break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning } } @@ -585,6 +603,24 @@ real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJ case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: { // Not implemented in GodotPhysics backend } break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning } return 0; @@ -610,6 +646,12 @@ void Generic6DOFJointSW::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: { // Not implemented in GodotPhysics backend } break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning } } @@ -632,6 +674,12 @@ bool Generic6DOFJointSW::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJoin case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: { // Not implemented in GodotPhysics backend } break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning } diff --git a/servers/physics_server.h b/servers/physics_server.h index cbb325dea3..15b353f768 100644 --- a/servers/physics_server.h +++ b/servers/physics_server.h @@ -697,6 +697,9 @@ public: G6DOF_JOINT_LINEAR_DAMPING, G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, + G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, + G6DOF_JOINT_LINEAR_SPRING_DAMPING, + G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, G6DOF_JOINT_ANGULAR_LOWER_LIMIT, G6DOF_JOINT_ANGULAR_UPPER_LIMIT, G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, @@ -706,6 +709,9 @@ public: G6DOF_JOINT_ANGULAR_ERP, G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, + G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, + G6DOF_JOINT_ANGULAR_SPRING_DAMPING, + G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, G6DOF_JOINT_MAX }; @@ -713,6 +719,8 @@ public: G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, + G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, + G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, G6DOF_JOINT_FLAG_ENABLE_MOTOR, G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, G6DOF_JOINT_FLAG_MAX diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h index f9beeb226c..4329203ccb 100644 --- a/servers/visual/rasterizer.h +++ b/servers/visual/rasterizer.h @@ -518,6 +518,8 @@ public: virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; virtual void particles_restart(RID p_particles) = 0; + virtual bool particles_is_inactive(RID p_particles) const = 0; + virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) = 0; virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp index 0783d91a59..358ed8ca54 100644 --- a/servers/visual/shader_language.cpp +++ b/servers/visual/shader_language.cpp @@ -2353,7 +2353,7 @@ bool ShaderLanguage::is_sampler_type(DataType p_type) { p_type == TYPE_SAMPLERCUBE; } -Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type) { +Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) { if (p_value.size() > 0) { Variant value; switch (p_type) { @@ -2397,7 +2397,11 @@ Variant ShaderLanguage::constant_value_to_variant(const Vector<ShaderLanguage::C value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real)); break; case ShaderLanguage::TYPE_VEC4: - value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); + if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); + } else { + value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); + } break; case ShaderLanguage::TYPE_MAT2: value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0)); diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h index 9277dfa2cf..b51106fad7 100644 --- a/servers/visual/shader_language.h +++ b/servers/visual/shader_language.h @@ -550,7 +550,7 @@ public: static int get_cardinality(DataType p_type); static bool is_scalar_type(DataType p_type); static bool is_sampler_type(DataType p_type); - static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type); + static Variant constant_value_to_variant(const Vector<ShaderLanguage::ConstantNode::Value> &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE); static void get_keyword_list(List<String> *r_keywords); static void get_builtin_funcs(List<String> *r_keywords); diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp index 13de92f226..1deca7bc66 100644 --- a/servers/visual/visual_server_scene.cpp +++ b/servers/visual/visual_server_scene.cpp @@ -1912,9 +1912,14 @@ void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const Ca if (ins->base_type == VS::INSTANCE_PARTICLES) { //particles visible? process them - VSG::storage->particles_request_process(ins->base); - //particles visible? request redraw - VisualServerRaster::redraw_request(); + if (VSG::storage->particles_is_inactive(ins->base)) { + //but if nothing is going on, don't do it. + keep = false; + } else { + VSG::storage->particles_request_process(ins->base); + //particles visible? request redraw + VisualServerRaster::redraw_request(); + } } if (geom->lighting_dirty) { diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index ca5271190c..e1db123f58 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -343,7 +343,7 @@ RID VisualServer::get_white_texture() { #define SMALL_VEC2 Vector2(0.00001, 0.00001) #define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001) -Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb) { +Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb) { PoolVector<uint8_t>::Write vw = r_vertex_array.write(); diff --git a/servers/visual_server.h b/servers/visual_server.h index 59eb43da97..743e010034 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -61,7 +61,7 @@ protected: RID white_texture; RID test_material; - Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> r_bone_aabb); + Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, PoolVector<uint8_t> &r_vertex_array, int p_vertex_array_len, PoolVector<uint8_t> &r_index_array, int p_index_array_len, AABB &r_aabb, Vector<AABB> &r_bone_aabb); static VisualServer *(*create_func)(); static void _bind_methods(); |