diff options
27 files changed, 172 insertions, 74 deletions
diff --git a/core/global_constants.cpp b/core/global_constants.cpp index 8bddeae69a..7854f342b0 100644 --- a/core/global_constants.cpp +++ b/core/global_constants.cpp @@ -435,6 +435,8 @@ void register_global_constants() { BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_5); BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_6); BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_7); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_8); + BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_9); BIND_GLOBAL_ENUM_CONSTANT(JOY_AXIS_MAX); BIND_GLOBAL_ENUM_CONSTANT(JOY_ANALOG_LX); diff --git a/core/os/input_event.h b/core/os/input_event.h index f2c8cc802d..de3c0232ff 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -122,7 +122,9 @@ enum JoystickList { JOY_AXIS_5 = 5, JOY_AXIS_6 = 6, JOY_AXIS_7 = 7, - JOY_AXIS_MAX = 8, + JOY_AXIS_8 = 8, + JOY_AXIS_9 = 9, + JOY_AXIS_MAX = 10, JOY_ANALOG_LX = JOY_AXIS_0, JOY_ANALOG_LY = JOY_AXIS_1, diff --git a/core/translation.cpp b/core/translation.cpp index 058db956e5..7e4d4feb89 100644 --- a/core/translation.cpp +++ b/core/translation.cpp @@ -966,7 +966,7 @@ Vector<String> TranslationServer::get_all_locale_names() { const char **ptr = locale_names; while (*ptr) { - locales.push_back(*ptr); + locales.push_back(String::utf8(*ptr)); ptr++; } @@ -1168,6 +1168,6 @@ TranslationServer::TranslationServer() for (int i = 0; locale_list[i]; ++i) { - locale_name_map.insert(locale_list[i], locale_names[i]); + locale_name_map.insert(locale_list[i], String::utf8(locale_names[i])); } } diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 2629e6740d..9fd4328402 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -376,7 +376,7 @@ <return type="String"> </return> <description> - Returns a unique string. + Returns a string that is unique to the device. Currently only works on Android and iOS. Returns empty string on other platforms. </description> </method> <method name="get_unix_time" qualifiers="const"> diff --git a/doc/classes/Object.xml b/doc/classes/Object.xml index d30ebfaef8..5ba5299a77 100644 --- a/doc/classes/Object.xml +++ b/doc/classes/Object.xml @@ -21,20 +21,21 @@ <argument index="0" name="property" type="String"> </argument> <description> - Return a property, return null if the property does not exist. + Returns the given property. Returns [code]null[/code] if the [code]property[/code] does not exist. </description> </method> <method name="_get_property_list" qualifiers="virtual"> <return type="Array"> </return> <description> - Return the property list, array of dictionaries, dictionaries must contain: name:String, type:int (see TYPE_* enum in [@Global Scope]) and optionally: hint:int (see PROPERTY_HINT_* in [@Global Scope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@Global Scope]). + Returns the object's property list as an [Array] of dictionaries. Dictionaries must contain: name:String, type:int (see TYPE_* enum in [@Global Scope]) and optionally: hint:int (see PROPERTY_HINT_* in [@Global Scope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@Global Scope]). </description> </method> <method name="_init" qualifiers="virtual"> <return type="void"> </return> <description> + The virtual method called upon initialization. </description> </method> <method name="_notification" qualifiers="virtual"> @@ -43,7 +44,7 @@ <argument index="0" name="what" type="int"> </argument> <description> - Notification request, the notification id is received. + Notify the object internally using an ID. </description> </method> <method name="_set" qualifiers="virtual"> @@ -54,7 +55,7 @@ <argument index="1" name="value" type="Variant"> </argument> <description> - Set a property. Return true if the property was found. + Sets a property. Returns [code]true[/code] if the [code]property[/code] exists. </description> </method> <method name="add_user_signal"> @@ -65,7 +66,7 @@ <argument index="1" name="arguments" type="Array" default="[ ]"> </argument> <description> - Add a user signal (can be added anytime). Arguments are optional, but can be added as an array of dictionaries, each containing "name" and "type" (from [@Global Scope] TYPE_*). + Adds a user-defined [code]signal[/code]. Arguments are optional, but can be added as an [Array] of dictionaries, each containing "name" and "type" (from [@Global Scope] TYPE_*). </description> </method> <method name="call" qualifiers="vararg"> @@ -74,6 +75,7 @@ <argument index="0" name="method" type="String"> </argument> <description> + Calls the [code]method[/code] on the object and returns a result. Pass parameters as a comma separated list. </description> </method> <method name="call_deferred" qualifiers="vararg"> @@ -82,6 +84,7 @@ <argument index="0" name="method" type="String"> </argument> <description> + Calls the [code]method[/code] on the object during idle time and returns a result. Pass parameters as a comma separated list. </description> </method> <method name="callv"> @@ -92,13 +95,14 @@ <argument index="1" name="arg_array" type="Array"> </argument> <description> + Calls the [code]method[/code] on the object and returns a result. Pass parameters as an [Array]. </description> </method> <method name="can_translate_messages" qualifiers="const"> <return type="bool"> </return> <description> - Return true if this object can translate strings. + Returns [code]true[/code] if the object can translate strings. </description> </method> <method name="connect"> @@ -115,7 +119,7 @@ <argument index="4" name="flags" type="int" default="0"> </argument> <description> - Connect a signal to a method at a target (member function). Binds are optional and are passed as extra arguments to the call. Flags specify optional deferred or one shot connections, see enum CONNECT_*. A signal can only be connected once to a method, and it will throw an error if already connected. If you want to avoid this, use [method is_connected] to check. + Connects a [code]signal[/code] to a [code]method[/code] on a [code]target[/code] object. Pass optional [code]binds[/code] to the call. Use [code]flags[/code] to set deferred or one shot connections. See [code]CONNECT_*[/code] constants. A [code]signal[/code] can only be connected once to a [code]method[/code]. It will throw an error if already connected. To avoid this, first use [method is_connected] to check for existing connections. </description> </method> <method name="disconnect"> @@ -128,7 +132,7 @@ <argument index="2" name="method" type="String"> </argument> <description> - Disconnect a signal from a method. + Disconnects a [code]signal[/code] from a [code]method[/code] on the given [code]target[/code]. </description> </method> <method name="emit_signal" qualifiers="vararg"> @@ -137,12 +141,14 @@ <argument index="0" name="signal" type="String"> </argument> <description> + Emits the given [code]signal[/code]. </description> </method> <method name="free"> <return type="void"> </return> <description> + Deletes the object from memory. </description> </method> <method name="get" qualifiers="const"> @@ -151,21 +157,21 @@ <argument index="0" name="property" type="String"> </argument> <description> - Get a property from the object. + Returns a [Variant] for a [code]property[/code]. </description> </method> <method name="get_class" qualifiers="const"> <return type="String"> </return> <description> - Return the class of the object as a string. + Returns the object's class as a [String]. </description> </method> <method name="get_incoming_connections" qualifiers="const"> <return type="Array"> </return> <description> - Returns an [Array] of dictionaries with information about signals that are connected to this object. + Returns an [Array] of dictionaries with information about signals that are connected to the object. Inside each [Dictionary] there are 3 fields: - "source" is a reference to signal emitter. - "signal_name" is name of connected signal. @@ -176,7 +182,7 @@ <return type="int"> </return> <description> - Return the instance ID. All objects have a unique instance ID. + Returns the object's unique instance ID. </description> </method> <method name="get_meta" qualifiers="const"> @@ -185,34 +191,35 @@ <argument index="0" name="name" type="String"> </argument> <description> - Return a metadata from the object. + Returns the object's metadata for the given [code]name[/code]. </description> </method> <method name="get_meta_list" qualifiers="const"> <return type="PoolStringArray"> </return> <description> - Return the list of metadata in the object. + Returns the object's metadata as a [PoolStringArray]. </description> </method> <method name="get_method_list" qualifiers="const"> <return type="Array"> </return> <description> + Returns the object's methods and their signatures as an [Array]. </description> </method> <method name="get_property_list" qualifiers="const"> <return type="Array"> </return> <description> - Return the list of properties as an array of dictionaries, dictionaries contain: name:String, type:int (see TYPE_* enum in [@Global Scope]) and optionally: hint:int (see PROPERTY_HINT_* in [@Global Scope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@Global Scope]). + Returns the list of properties as an [Array] of dictionaries. Dictionaries contain: name:String, type:int (see TYPE_* enum in [@Global Scope]) and optionally: hint:int (see PROPERTY_HINT_* in [@Global Scope]), hint_string:String, usage:int (see PROPERTY_USAGE_* in [@Global Scope]). </description> </method> <method name="get_script" qualifiers="const"> <return type="Reference"> </return> <description> - Return the object script (or null if it doesn't have one). + Returns the object's [Script] or [code]null[/code] if one doesn't exist. </description> </method> <method name="get_signal_connection_list" qualifiers="const"> @@ -221,13 +228,14 @@ <argument index="0" name="signal" type="String"> </argument> <description> + Returns an [Array] of connections for the given [code]signal[/code]. </description> </method> <method name="get_signal_list" qualifiers="const"> <return type="Array"> </return> <description> - Return the list of signals as an array of dictionaries. + Returns the list of signals as an [Array] of dictionaries. </description> </method> <method name="has_meta" qualifiers="const"> @@ -236,7 +244,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Return true if a metadata is found with the requested name. + Returns [code]true[/code] if a metadata is found with the given [code]name[/code]. </description> </method> <method name="has_method" qualifiers="const"> @@ -245,6 +253,7 @@ <argument index="0" name="method" type="String"> </argument> <description> + Returns [code]true[/code] if the object contains the given [code]method[/code]. </description> </method> <method name="has_user_signal" qualifiers="const"> @@ -253,13 +262,14 @@ <argument index="0" name="signal" type="String"> </argument> <description> + Returns [code]true[/code] if the given user-defined [code]signal[/code] exists. </description> </method> <method name="is_blocking_signals" qualifiers="const"> <return type="bool"> </return> <description> - Return true if signal emission blocking is enabled. + Returns [code]true[/code] if signal emission blocking is enabled. </description> </method> <method name="is_class" qualifiers="const"> @@ -268,7 +278,7 @@ <argument index="0" name="type" type="String"> </argument> <description> - Check the class of the object against a string (including inheritance). + Returns [code]true[/code] if the object inherits from the given [code]type[/code]. </description> </method> <method name="is_connected" qualifiers="const"> @@ -281,13 +291,14 @@ <argument index="2" name="method" type="String"> </argument> <description> - Return true if a connection exists for a given signal and target/method. + Returns [code]true[/code] if a connection exists for a given [code]signal[/code], [code]target[/code], and [code]method[/code]. </description> </method> <method name="is_queued_for_deletion" qualifiers="const"> <return type="bool"> </return> <description> + Returns [code]true[/code] if the [code]queue_free[/code] method was called for the object. </description> </method> <method name="notification"> @@ -333,7 +344,7 @@ <argument index="0" name="enable" type="bool"> </argument> <description> - Define whether this object can translate strings (with calls to [method tr]). Default is true. + Define whether the object can translate strings (with calls to [method tr]). Default is true. </description> </method> <method name="set_meta"> diff --git a/editor/SCsub b/editor/SCsub index 2b6494608b..c531d2c7a6 100644 --- a/editor/SCsub +++ b/editor/SCsub @@ -39,6 +39,8 @@ def make_doc_header(target, source, env): docend = "" for s in source: src = s.srcnode().abspath + if not src.endswith(".xml"): + continue f = open_utf8(src, "r") content = f.read() buf+=content diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index a48e6c9057..290cb1be42 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -117,7 +117,7 @@ EditorAbout::EditorAbout() { Label *about_text = memnew(Label); about_text->set_v_size_flags(Control::SIZE_SHRINK_CENTER); - about_text->set_text(VERSION_FULL_NAME + hash + String::utf8("\n\u00A9 2007-2017 Juan Linietsky, Ariel Manzur.\n\u00A9 2014-2017 ") + + about_text->set_text(VERSION_FULL_NAME + hash + String::utf8("\n\xc2\xa9 2007-2017 Juan Linietsky, Ariel Manzur.\n\xc2\xa9 2014-2017 ") + TTR("Godot Engine contributors") + "\n"); hbc->add_child(about_text); @@ -201,7 +201,7 @@ EditorAbout::EditorAbout() { for (int j = 0; j < about_tp_copyright_count[i]; j++) { text += "\n Files:\n " + String(about_tp_file[read_idx]).replace("\n", "\n ") + "\n"; - String copyright = String::utf8(" \u00A9 ") + String::utf8(about_tp_copyright[read_idx]).replace("\n", String::utf8("\n \u00A9 ")); + String copyright = String::utf8(" \xc2\xa9 ") + String::utf8(about_tp_copyright[read_idx]).replace("\n", String::utf8("\n \xc2\xa9 ")); text += copyright; long_text += copyright; String license = "\n License: " + String(about_tp_license[read_idx]) + "\n"; diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index 02ead3aee8..7f956b01ff 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -427,7 +427,9 @@ void ThemeEditor::_dialog_cbk() { void ThemeEditor::_theme_menu_cbk(int p_option) { - if (p_option == POPUP_CREATE_EMPTY || p_option == POPUP_CREATE_EDITOR_EMPTY) { + if (p_option == POPUP_CREATE_EMPTY || p_option == POPUP_CREATE_EDITOR_EMPTY || p_option == POPUP_IMPORT_EDITOR_THEME) { + + bool import = (p_option == POPUP_IMPORT_EDITOR_THEME); Ref<Theme> base_theme; @@ -449,21 +451,21 @@ void ThemeEditor::_theme_menu_cbk(int p_option) { base_theme->get_icon_list(type, &icons); for (List<StringName>::Element *E = icons.front(); E; E = E->next()) { - theme->set_icon(E->get(), type, Ref<Texture>()); + theme->set_icon(E->get(), type, import ? base_theme->get_icon(E->get(), type) : Ref<Texture>()); } List<StringName> shaders; base_theme->get_shader_list(type, &shaders); for (List<StringName>::Element *E = shaders.front(); E; E = E->next()) { - theme->set_shader(E->get(), type, Ref<Shader>()); + theme->set_shader(E->get(), type, import ? base_theme->get_shader(E->get(), type) : Ref<Shader>()); } List<StringName> styleboxs; base_theme->get_stylebox_list(type, &styleboxs); for (List<StringName>::Element *E = styleboxs.front(); E; E = E->next()) { - theme->set_stylebox(E->get(), type, Ref<StyleBox>()); + theme->set_stylebox(E->get(), type, import ? base_theme->get_stylebox(E->get(), type) : Ref<StyleBox>()); } List<StringName> fonts; @@ -477,14 +479,14 @@ void ThemeEditor::_theme_menu_cbk(int p_option) { base_theme->get_color_list(type, &colors); for (List<StringName>::Element *E = colors.front(); E; E = E->next()) { - theme->set_color(E->get(), type, Color()); + theme->set_color(E->get(), type, import ? base_theme->get_color(E->get(), type) : Color()); } List<StringName> constants; base_theme->get_constant_list(type, &constants); for (List<StringName>::Element *E = constants.front(); E; E = E->next()) { - theme->set_constant(E->get(), type, base_theme->get_constant(type, E->get())); + theme->set_constant(E->get(), type, base_theme->get_constant(E->get(), type)); } } } @@ -639,7 +641,7 @@ ThemeEditor::ThemeEditor() { theme_menu->get_popup()->add_separator(); theme_menu->get_popup()->add_item(TTR("Create Empty Template"), POPUP_CREATE_EMPTY); theme_menu->get_popup()->add_item(TTR("Create Empty Editor Template"), POPUP_CREATE_EDITOR_EMPTY); - + theme_menu->get_popup()->add_item(TTR("Create From Current Editor Theme"), POPUP_IMPORT_EDITOR_THEME); add_child(theme_menu); theme_menu->set_position(Vector2(3, 3) * EDSCALE); theme_menu->get_popup()->connect("id_pressed", this, "_theme_menu_cbk"); diff --git a/editor/plugins/theme_editor_plugin.h b/editor/plugins/theme_editor_plugin.h index 16b2da94d1..4d46282ba1 100644 --- a/editor/plugins/theme_editor_plugin.h +++ b/editor/plugins/theme_editor_plugin.h @@ -69,7 +69,8 @@ class ThemeEditor : public Control { POPUP_REMOVE, POPUP_CLASS_REMOVE, POPUP_CREATE_EMPTY, - POPUP_CREATE_EDITOR_EMPTY + POPUP_CREATE_EDITOR_EMPTY, + POPUP_IMPORT_EDITOR_THEME }; int popup_mode; diff --git a/editor/plugins/tile_map_editor_plugin.cpp b/editor/plugins/tile_map_editor_plugin.cpp index 9235dafaa6..0ee0eed3a2 100644 --- a/editor/plugins/tile_map_editor_plugin.cpp +++ b/editor/plugins/tile_map_editor_plugin.cpp @@ -973,7 +973,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Point2i pos = points[i]; - if (!paint_undo.has(over_tile)) { + if (!paint_undo.has(pos)) { paint_undo[pos] = _get_op_from_cell(pos); } @@ -993,7 +993,7 @@ bool TileMapEditor::forward_gui_input(const Ref<InputEvent> &p_event) { Point2i pos = points[i]; - if (!paint_undo.has(over_tile)) { + if (!paint_undo.has(pos)) { paint_undo[pos] = _get_op_from_cell(pos); } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 7438c7671e..58f70ce11e 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -533,10 +533,6 @@ void SceneTreeDock::_tool_selected(int p_tool, bool p_confirm_override) { if (p_confirm_override) { _delete_confirm(); - // hack, force 2d editor viewport to refresh after deletion - if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton()) - editor->get_viewport_control()->update(); - } else { delete_dialog->set_text(TTR("Delete Node(s)?")); delete_dialog->popup_centered_minsize(); @@ -1345,6 +1341,12 @@ void SceneTreeDock::_delete_confirm() { } } editor_data->get_undo_redo().commit_action(); + + // hack, force 2d editor viewport to refresh after deletion + if (CanvasItemEditor *editor = CanvasItemEditor::get_singleton()) + editor->get_viewport_control()->update(); + + editor->push_item(NULL); } void SceneTreeDock::_selection_changed() { diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 5739568d91..769e2c943e 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -93,11 +93,15 @@ void CollisionObjectBullet::setupBulletCollisionObject(btCollisionObject *p_coll void CollisionObjectBullet::add_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) { exceptions.insert(p_ignoreCollisionObject->get_self()); bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, true); + if (space) + space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher()); } void CollisionObjectBullet::remove_collision_exception(const CollisionObjectBullet *p_ignoreCollisionObject) { exceptions.erase(p_ignoreCollisionObject->get_self()); bt_collision_object->setIgnoreCollisionCheck(p_ignoreCollisionObject->bt_collision_object, false); + if (space) + space->get_broadphase()->getOverlappingPairCache()->cleanProxyFromPairs(bt_collision_object->getBroadphaseHandle(), space->get_dispatcher()); } bool CollisionObjectBullet::has_collision_exception(const CollisionObjectBullet *p_otherCollisionObject) const { diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index cbbfdac1d7..b36896650b 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -109,6 +109,7 @@ public: void flush_queries(); void step(real_t p_delta_time); + _FORCE_INLINE_ btBroadphaseInterface *get_broadphase() { return broadphase; } _FORCE_INLINE_ btCollisionDispatcher *get_dispatcher() { return dispatcher; } _FORCE_INLINE_ btSoftBodyWorldInfo *get_soft_body_world_info() { return soft_body_world_info; } _FORCE_INLINE_ bool is_using_soft_world() { return soft_body_world_info; } diff --git a/modules/gdnative/gdnative/array.cpp b/modules/gdnative/gdnative/array.cpp index 51c023981f..90bc4dc031 100644 --- a/modules/gdnative/gdnative/array.cpp +++ b/modules/gdnative/gdnative/array.cpp @@ -158,6 +158,11 @@ godot_variant GDAPI *godot_array_operator_index(godot_array *p_self, const godot return (godot_variant *)&self->operator[](p_idx); } +const godot_variant GDAPI *godot_array_operator_index_const(const godot_array *p_self, const godot_int p_idx) { + const Array *self = (const Array *)p_self; + return (const godot_variant *)&self->operator[](p_idx); +} + void GDAPI godot_array_append(godot_array *p_self, const godot_variant *p_value) { Array *self = (Array *)p_self; Variant *val = (Variant *)p_value; diff --git a/modules/gdnative/gdnative/dictionary.cpp b/modules/gdnative/gdnative/dictionary.cpp index ed98cdbb00..7f8320622d 100644 --- a/modules/gdnative/gdnative/dictionary.cpp +++ b/modules/gdnative/gdnative/dictionary.cpp @@ -130,6 +130,12 @@ godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_self, c return (godot_variant *)&self->operator[](*key); } +const godot_variant GDAPI *godot_dictionary_operator_index_const(const godot_dictionary *p_self, const godot_variant *p_key) { + const Dictionary *self = (const Dictionary *)p_self; + const Variant *key = (const Variant *)p_key; + return (const godot_variant *)&self->operator[](*key); +} + godot_variant GDAPI *godot_dictionary_next(const godot_dictionary *p_self, const godot_variant *p_key) { Dictionary *self = (Dictionary *)p_self; const Variant *key = (const Variant *)p_key; diff --git a/modules/gdnative/gdnative_api.json b/modules/gdnative/gdnative_api.json index ac0293172d..0bd9dbceb4 100644 --- a/modules/gdnative/gdnative_api.json +++ b/modules/gdnative/gdnative_api.json @@ -2489,6 +2489,14 @@ ] }, { + "name": "godot_array_operator_index_const", + "return_type": "const godot_variant *", + "arguments": [ + ["const godot_array *", "p_self"], + ["const godot_int", "p_idx"] + ] + }, + { "name": "godot_array_append", "return_type": "void", "arguments": [ @@ -2787,6 +2795,14 @@ ] }, { + "name": "godot_dictionary_operator_index_const", + "return_type": "const godot_variant *", + "arguments": [ + ["const godot_dictionary *", "p_self"], + ["const godot_variant *", "p_key"] + ] + }, + { "name": "godot_dictionary_next", "return_type": "godot_variant *", "arguments": [ @@ -5645,6 +5661,13 @@ ] }, { + "name": "godot_pluginscript_register_language", + "return_type": "void", + "arguments": [ + ["const godot_pluginscript_language_desc *", "language_desc"] + ] + }, + { "name": "godot_arvr_register_interface", "return_type": "void", "arguments": [ diff --git a/modules/gdnative/include/gdnative/array.h b/modules/gdnative/include/gdnative/array.h index d0639589b7..01ae61e280 100644 --- a/modules/gdnative/include/gdnative/array.h +++ b/modules/gdnative/include/gdnative/array.h @@ -76,6 +76,8 @@ godot_variant GDAPI godot_array_get(const godot_array *p_self, const godot_int p godot_variant GDAPI *godot_array_operator_index(godot_array *p_self, const godot_int p_idx); +const godot_variant GDAPI *godot_array_operator_index_const(const godot_array *p_self, const godot_int p_idx); + void GDAPI godot_array_append(godot_array *p_self, const godot_variant *p_value); void GDAPI godot_array_clear(godot_array *p_self); diff --git a/modules/gdnative/include/gdnative/dictionary.h b/modules/gdnative/include/gdnative/dictionary.h index e68d0fdc29..6d1f436921 100644 --- a/modules/gdnative/include/gdnative/dictionary.h +++ b/modules/gdnative/include/gdnative/dictionary.h @@ -85,6 +85,8 @@ void GDAPI godot_dictionary_set(godot_dictionary *p_self, const godot_variant *p godot_variant GDAPI *godot_dictionary_operator_index(godot_dictionary *p_self, const godot_variant *p_key); +const godot_variant GDAPI *godot_dictionary_operator_index_const(const godot_dictionary *p_self, const godot_variant *p_key); + godot_variant GDAPI *godot_dictionary_next(const godot_dictionary *p_self, const godot_variant *p_key); godot_bool GDAPI godot_dictionary_operator_equal(const godot_dictionary *p_self, const godot_dictionary *p_b); diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index d9b10ff3fa..de8e35c406 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -1060,7 +1060,7 @@ static bool _guess_identifier_type_in_block(GDCompletionContext &context, int p_ } //use the last assignment, (then backwards?) - if (last_assign) { + if (last_assign && last_assign_line != p_line) { return _guess_expression_type(context, last_assign, last_assign_line, r_type); } @@ -1194,6 +1194,8 @@ static bool _guess_identifier_type(GDCompletionContext &context, int p_line, con r_type = _get_type_from_pinfo(context._class->variables[i]._export); return true; } else if (context._class->variables[i].expression) { + if (p_line <= context._class->variables[i].line) + return false; bool rtype = _guess_expression_type(context, context._class->variables[i].expression, context._class->variables[i].line, r_type); if (rtype && r_type.type != Variant::NIL) diff --git a/modules/mobile_vr/mobile_interface.cpp b/modules/mobile_vr/mobile_interface.cpp index eb87bb2cf0..93d5c22ef8 100644 --- a/modules/mobile_vr/mobile_interface.cpp +++ b/modules/mobile_vr/mobile_interface.cpp @@ -122,6 +122,7 @@ void MobileVRInterface::set_position_from_sensors() { Vector3 north(0.0, 0.0, 1.0); // North is Z positive // make copies of our inputs + bool has_grav = false; Vector3 acc = input->get_accelerometer(); Vector3 gyro = input->get_gyroscope(); Vector3 grav = input->get_gravity(); @@ -143,14 +144,17 @@ void MobileVRInterface::set_position_from_sensors() { // what a stable gravity vector is grav = acc; if (grav.length() > 0.1) { - has_gyro = true; + has_grav = true; }; } else { - has_gyro = true; + has_grav = true; }; bool has_magneto = magneto.length() > 0.1; - bool has_grav = grav.length() > 0.1; + if (gyro.length() > 0.1) { + /* this can return to 0.0 if the user doesn't move the phone, so once on, it's on */ + has_gyro = true; + }; #ifdef ANDROID_ENABLED ///@TODO needs testing, i don't have a gyro, potentially can be removed depending on what comes out of issue #8101 diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 8d73de9889..a5dc6ffc13 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -858,6 +858,8 @@ public: if (call_mode == VisualScriptFunctionCall::CALL_MODE_INSTANCE) { if (returns >= 2) { *p_outputs[1] = v.call(function, p_inputs + 1, input_args, r_error); + } else if (returns == 1) { + v.call(function, p_inputs + 1, input_args, r_error); } else { r_error.error = Variant::CallError::CALL_ERROR_INVALID_METHOD; r_error_str = "Invalid returns count for call_mode == CALL_MODE_INSTANCE"; diff --git a/platform/android/detect.py b/platform/android/detect.py index 4d5e586faf..2666034ef7 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -25,7 +25,7 @@ def get_opts(): ('ndk_platform', 'Target platform (android-<api>, e.g. "android-18")', "android-18"), EnumVariable('android_arch', 'Target architecture', "armv7", ('armv7', 'armv6', 'arm64v8', 'x86')), BoolVariable('android_neon', 'Enable NEON support (armv7 only)', True), - BoolVariable('android_stl', 'Enable Android STL support (for modules)', False), + BoolVariable('android_stl', 'Enable Android STL support (for modules)', True), BoolVariable('ndk_unified_headers', 'Enable NDK unified headers', True) ] diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp index 4e19214c59..040266843d 100644 --- a/scene/3d/particles.cpp +++ b/scene/3d/particles.cpp @@ -642,7 +642,7 @@ void ParticlesMaterial::_update_shader() { code += " float angle1 = (rand_from_seed(alt_seed)*2.0-1.0)*spread/180.0*3.1416;\n"; code += " vec3 rot = vec3( cos(angle1), sin(angle1),0.0 );\n"; - code += " VELOCITY = (rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n"; + code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } else { //initiate velocity spread in 3D @@ -650,7 +650,7 @@ void ParticlesMaterial::_update_shader() { code += " float angle2 = rand_from_seed(alt_seed)*20.0*3.1416; // make it more random like\n"; code += " vec3 rot_xz = vec3( sin(angle1), 0.0, cos(angle1) );\n"; code += " vec3 rot = vec3( cos(angle2)*rot_xz.x,sin(angle2)*rot_xz.x, rot_xz.z);\n"; - code += " VELOCITY = (rot*initial_linear_velocity+rot*initial_linear_velocity_random*rand_from_seed(alt_seed));\n"; + code += " VELOCITY = rot*initial_linear_velocity*mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; } code += " float base_angle = (initial_angle+tex_angle)*mix(1.0,angle_rand,initial_angle_random);\n"; diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp index a289b4b0ca..ef54eb58cf 100644 --- a/servers/physics/body_pair_sw.cpp +++ b/servers/physics/body_pair_sw.cpp @@ -46,6 +46,7 @@ //#define ALLOWED_PENETRATION 0.01 #define RELAXATION_TIMESTEPS 3 #define MIN_VELOCITY 0.0001 +#define MAX_BIAS_ROTATION (Math_PI / 8) void BodyPairSW::_contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { @@ -71,6 +72,7 @@ void BodyPairSW::contact_added_callback(const Vector3 &p_point_A, const Vector3 contact.acc_normal_impulse = 0; contact.acc_bias_impulse = 0; + contact.acc_bias_impulse_center_of_mass = 0; contact.acc_tangent_impulse = Vector3(); contact.local_A = local_A; contact.local_B = local_B; @@ -82,12 +84,12 @@ void BodyPairSW::contact_added_callback(const Vector3 &p_point_A, const Vector3 for (int i = 0; i < contact_count; i++) { Contact &c = contacts[i]; - if ( - c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) && + if (c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) && c.local_B.distance_squared_to(local_B) < (contact_recycle_radius * contact_recycle_radius)) { contact.acc_normal_impulse = c.acc_normal_impulse; contact.acc_bias_impulse = c.acc_bias_impulse; + contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass; contact.acc_tangent_impulse = c.acc_tangent_impulse; new_index = i; break; @@ -325,9 +327,7 @@ bool BodyPairSW::setup(real_t p_step) { A->apply_impulse(c.rA + A->get_center_of_mass(), -j_vec); B->apply_impulse(c.rB + B->get_center_of_mass(), j_vec); c.acc_bias_impulse = 0; - Vector3 jb_vec = c.normal * c.acc_bias_impulse; - A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb_vec); - B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb_vec); + c.acc_bias_impulse_center_of_mass = 0; c.bounce = MAX(A->get_bounce(), B->get_bounce()); if (c.bounce) { @@ -356,7 +356,7 @@ void BodyPairSW::solve(real_t p_step) { c.active = false; //try to deactivate, will activate itself if still needed - //bias impule + //bias impulse Vector3 crbA = A->get_biased_angular_velocity().cross(c.rA); Vector3 crbB = B->get_biased_angular_velocity().cross(c.rB); @@ -372,8 +372,26 @@ void BodyPairSW::solve(real_t p_step) { Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld); - A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb); - B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb); + A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb, MAX_BIAS_ROTATION / p_step); + B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb, MAX_BIAS_ROTATION / p_step); + + crbA = A->get_biased_angular_velocity().cross(c.rA); + crbB = B->get_biased_angular_velocity().cross(c.rB); + dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA; + + vbn = dbv.dot(c.normal); + + if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { + + real_t jbn_com = (-vbn + c.bias) / (A->get_inv_mass() + B->get_inv_mass()); + real_t jbnOld_com = c.acc_bias_impulse_center_of_mass; + c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f); + + Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com); + + A->apply_bias_impulse(A->get_center_of_mass(), -jb_com, 0.0f); + B->apply_bias_impulse(B->get_center_of_mass(), jb_com, 0.0f); + } c.active = true; } @@ -382,7 +400,7 @@ void BodyPairSW::solve(real_t p_step) { Vector3 crB = B->get_angular_velocity().cross(c.rB); Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; - //normal impule + //normal impulse real_t vn = dv.dot(c.normal); if (Math::abs(vn) > MIN_VELOCITY) { @@ -399,7 +417,7 @@ void BodyPairSW::solve(real_t p_step) { c.active = true; } - //friction impule + //friction impulse real_t friction = A->get_friction() * B->get_friction(); diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h index f09c977950..74fda60998 100644 --- a/servers/physics/body_pair_sw.h +++ b/servers/physics/body_pair_sw.h @@ -59,6 +59,7 @@ class BodyPairSW : public ConstraintSW { real_t acc_normal_impulse; // accumulated normal impulse (Pn) Vector3 acc_tangent_impulse; // accumulated tangent impulse (Pt) real_t acc_bias_impulse; // accumulated normal impulse for position bias (Pnb) + real_t acc_bias_impulse_center_of_mass; // accumulated normal impulse for position bias applied to com real_t mass_normal; real_t bias; real_t bounce; diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h index 782bf14a4b..98095fd3c6 100644 --- a/servers/physics/body_sw.h +++ b/servers/physics/body_sw.h @@ -223,10 +223,16 @@ public: angular_velocity += _inv_inertia_tensor.xform(p_j); } - _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_pos, const Vector3 &p_j) { + _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_pos, const Vector3 &p_j, real_t p_max_delta_av = -1.0) { biased_linear_velocity += p_j * _inv_mass; - biased_angular_velocity += _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); + if (p_max_delta_av != 0.0) { + Vector3 delta_av = _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); + if (p_max_delta_av > 0 && delta_av.length() > p_max_delta_av) { + delta_av = delta_av.normalized() * p_max_delta_av; + } + biased_angular_velocity += delta_av; + } } _FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3 &p_j) { diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 6eaaaa777b..f9febd1093 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -626,13 +626,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co int amount = _cull_aabb_for_body(p_body, motion_aabb); - for (int j = 0; j < p_body->get_shape_count(); j++) { + for (int body_shape_idx = 0; body_shape_idx < p_body->get_shape_count(); body_shape_idx++) { - if (p_body->is_shape_set_as_disabled(j)) + if (p_body->is_shape_set_as_disabled(body_shape_idx)) continue; - Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); - Shape2DSW *body_shape = p_body->get_shape(j); + Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(body_shape_idx); + Shape2DSW *body_shape = p_body->get_shape(body_shape_idx); bool stuck = false; @@ -642,14 +642,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co for (int i = 0; i < amount; i++) { const CollisionObject2DSW *col_obj = intersection_query_results[i]; - int shape_idx = intersection_query_subindex_results[i]; - Shape2DSW *against_shape = col_obj->get_shape(shape_idx); + int col_shape_idx = intersection_query_subindex_results[i]; + Shape2DSW *against_shape = col_obj->get_shape(col_shape_idx); bool excluded = false; for (int k = 0; k < excluded_shape_pair_count; k++) { - if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == shape_idx) { + if (excluded_shape_pairs[k].local_shape == body_shape && excluded_shape_pairs[k].against_object == col_obj && excluded_shape_pairs[k].against_shape_index == col_shape_idx) { excluded = true; break; } @@ -660,7 +660,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co continue; } - Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(col_shape_idx); //test initial overlap, does it collide if going all the way? if (!CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion, against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) { continue; @@ -669,7 +669,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co //test initial overlap if (CollisionSolver2DSW::solve(body_shape, body_shape_xform, Vector2(), against_shape, col_obj_xform, Vector2(), NULL, NULL, NULL, 0)) { - if (col_obj->is_shape_set_as_one_way_collision(j)) { + if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) { continue; } @@ -698,7 +698,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co } } - if (col_obj->is_shape_set_as_one_way_collision(j)) { + if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) { Vector2 cd[2]; Physics2DServerSW::CollCbkData cbk; @@ -710,7 +710,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.valid_depth = 10e20; Vector2 sep = mnormal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0); + bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0); if (!collided || cbk.amount == 0) { continue; } @@ -726,7 +726,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co safe = 0; unsafe = 0; - best_shape = j; //sadly it's the best + best_shape = body_shape_idx; //sadly it's the best break; } if (best_safe == 1.0) { @@ -736,7 +736,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co safe = best_safe; unsafe = best_unsafe; - best_shape = j; + best_shape = body_shape_idx; } } } |