diff options
82 files changed, 823 insertions, 338 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 68ec20a525..2ea2ed6bba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -70,11 +70,15 @@ Similar rules can be applied when contributing bug fixes - it's always best to discuss the implementation in the bug report first if you are not 100% about what would be the best fix. +In addition to the following tips, also take a look at the +[Engine development guide](http://docs.godotengine.org/en/latest/development/cpp/) +for an introduction to developing on Godot. + #### Be nice to the git history -Try to make simple PRs with that handle one specific topic. Just like for -reporting issues, it's better to open 3 different PRs that each address a -different issue than one big PR with three commits. +Try to make simple PRs that handle one specific topic. Just like for reporting +issues, it's better to open 3 different PRs that each address a different issue +than one big PR with three commits. When updating your fork with upstream changes, please use ``git pull --rebase`` to avoid creating "merge commits". Those commits unnecessarily pollute the git @@ -40,7 +40,7 @@ Official binaries for the Godot editor and the export templates can be found [See the official docs](http://docs.godotengine.org/en/latest/development/compiling/) for compilation instructions for every supported platform. -### Community +### Community and contributing Godot is not only an engine but an ever-growing community of users and engine developers. The main community channels are listed [on the homepage](https://godotengine.org/community). @@ -49,6 +49,8 @@ To get in touch with the developers, the best way is to join the [#godotengine IRC channel](https://webchat.freenode.net/?channels=godotengine) on Freenode. +To get started contributing to the project, see the [contributing guide](CONTRIBUTING.md). + ### Documentation and demos The official documentation is hosted on [ReadTheDocs](http://docs.godotengine.org). diff --git a/core/array.cpp b/core/array.cpp index 9f09ddbe15..9708452850 100644 --- a/core/array.cpp +++ b/core/array.cpp @@ -258,7 +258,6 @@ struct _ArrayVariantSortCustom { Array &Array::sort_custom(Object *p_obj, const StringName &p_function) { ERR_FAIL_NULL_V(p_obj, *this); - ERR_FAIL_COND_V(!p_obj->has_method(p_function), *this); SortArray<Variant, _ArrayVariantSortCustom, true> avs; avs.compare.obj = p_obj; diff --git a/core/io/marshalls.cpp b/core/io/marshalls.cpp index ec430d41a9..6338cee39d 100644 --- a/core/io/marshalls.cpp +++ b/core/io/marshalls.cpp @@ -850,17 +850,16 @@ Error encode_variant(const Variant &p_variant, uint8_t *r_buffer, int &r_len, bo } break; case Variant::INT: { - int64_t val = p_variant; if (flags & ENCODE_FLAG_64) { //64 bits if (buf) { - encode_uint64(val, buf); + encode_uint64(p_variant.operator int64_t(), buf); } r_len += 8; } else { if (buf) { - encode_uint32(int32_t(val), buf); + encode_uint32(p_variant.operator int32_t(), buf); } r_len += 4; diff --git a/core/oa_hash_map.h b/core/oa_hash_map.h index 3705762d6c..9840442519 100644 --- a/core/oa_hash_map.h +++ b/core/oa_hash_map.h @@ -125,7 +125,7 @@ private: while (42) { if (hashes[pos] == EMPTY_HASH) { - _construct(pos, hash, p_key, p_value); + _construct(pos, hash, key, value); return; } @@ -136,7 +136,7 @@ private: if (hashes[pos] & DELETED_HASH_BIT) { // we found a place where we can fit in! - _construct(pos, hash, p_key, p_value); + _construct(pos, hash, key, value); return; } diff --git a/core/os/rw_lock.h b/core/os/rw_lock.h index 8d1029723b..4333d9a016 100644 --- a/core/os/rw_lock.h +++ b/core/os/rw_lock.h @@ -57,9 +57,7 @@ class RWLockRead { public: RWLockRead(const RWLock *p_lock) { - if (p_lock) { - lock = const_cast<RWLock *>(p_lock); - } + lock = const_cast<RWLock *>(p_lock); if (lock) lock->read_lock(); } ~RWLockRead() { diff --git a/core/ustring.cpp b/core/ustring.cpp index 3f073b181f..b55607946d 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -586,6 +586,8 @@ String String::camelcase_to_underscore(bool lowercase) const { bool is_upper = cstr[i] >= A && cstr[i] <= Z; bool is_number = cstr[i] >= '0' && cstr[i] <= '9'; bool are_next_2_lower = false; + bool is_next_lower = false; + bool is_next_number = false; bool was_precedent_upper = cstr[i - 1] >= A && cstr[i - 1] <= Z; bool was_precedent_number = cstr[i - 1] >= '0' && cstr[i - 1] <= '9'; @@ -593,7 +595,18 @@ String String::camelcase_to_underscore(bool lowercase) const { are_next_2_lower = cstr[i + 1] >= a && cstr[i + 1] <= z && cstr[i + 2] >= a && cstr[i + 2] <= z; } - bool should_split = ((is_upper && !was_precedent_upper && !was_precedent_number) || (was_precedent_upper && is_upper && are_next_2_lower) || (is_number && !was_precedent_number)); + if (i + 1 < this->size()) { + is_next_lower = cstr[i + 1] >= a && cstr[i + 1] <= z; + is_next_number = cstr[i + 1] >= '0' && cstr[i + 1] <= '9'; + } + + const bool a = is_upper && !was_precedent_upper && !was_precedent_number; + const bool b = was_precedent_upper && is_upper && are_next_2_lower; + const bool c = is_number && !was_precedent_number; + const bool can_break_number_letter = is_number && !was_precedent_number && is_next_lower; + const bool can_break_letter_number = !is_number && was_precedent_number && (is_next_lower || is_next_number); + + bool should_split = a || b || c || can_break_number_letter || can_break_letter_number; if (should_split) { new_string += this->substr(start_index, i - start_index) + "_"; start_index = i; @@ -3092,7 +3105,7 @@ String String::simplify_path() const { } else if (s.begins_with("user://")) { drive = "user://"; - s = s.substr(6, s.length()); + s = s.substr(7, s.length()); } else if (s.begins_with("/") || s.begins_with("\\")) { drive = s.substr(0, 1); diff --git a/core/variant_call.cpp b/core/variant_call.cpp index f7fa2ebc70..8693a584f2 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -1895,6 +1895,7 @@ void register_variant_methods() { _VariantCall::add_constant(Variant::VECTOR3, "AXIS_Z", Vector3::AXIS_Z); _VariantCall::add_variant_constant(Variant::VECTOR3, "ZERO", Vector3(0, 0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR3, "ONE", Vector3(1, 1, 1)); _VariantCall::add_variant_constant(Variant::VECTOR3, "INF", Vector3(Math_INF, Math_INF, Math_INF)); _VariantCall::add_variant_constant(Variant::VECTOR3, "LEFT", Vector3(-1, 0, 0)); _VariantCall::add_variant_constant(Variant::VECTOR3, "RIGHT", Vector3(1, 0, 0)); @@ -1904,6 +1905,7 @@ void register_variant_methods() { _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1)); _VariantCall::add_variant_constant(Variant::VECTOR2, "ZERO", Vector2(0, 0)); + _VariantCall::add_variant_constant(Variant::VECTOR2, "ONE", Vector2(1, 1)); _VariantCall::add_variant_constant(Variant::VECTOR2, "INF", Vector2(Math_INF, Math_INF)); _VariantCall::add_variant_constant(Variant::VECTOR2, "LEFT", Vector2(-1, 0)); _VariantCall::add_variant_constant(Variant::VECTOR2, "RIGHT", Vector2(1, 0)); diff --git a/core/variant_op.cpp b/core/variant_op.cpp index f230f12b5d..d193858966 100644 --- a/core/variant_op.cpp +++ b/core/variant_op.cpp @@ -3521,7 +3521,7 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & //not as efficient but.. real_t va = a; real_t vb = b; - r_dst = (1.0 - c) * va + vb * c; + r_dst = va + (vb - va) * c; } else { r_dst = a; @@ -3542,16 +3542,13 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & case INT: { int64_t va = a._data._int; int64_t vb = b._data._int; - if (va != vb) - r_dst = int((1.0 - c) * va + vb * c); - else //avoid int casting issues - r_dst = a; + r_dst = int(va + (vb - va) * c); } return; case REAL: { real_t va = a._data._real; real_t vb = b._data._real; - r_dst = (1.0 - c) * va + vb * c; + r_dst = va + (vb - va) * c; } return; case STRING: { @@ -3559,7 +3556,9 @@ void Variant::interpolate(const Variant &a, const Variant &b, float c, Variant & String sa = *reinterpret_cast<const String *>(a._data._mem); String sb = *reinterpret_cast<const String *>(b._data._mem); String dst; - int csize = sb.length() * c + sa.length() * (1.0 - c); + int sa_len = sa.length(); + int sb_len = sb.length(); + int csize = sa_len + (sb_len - sa_len) * c; if (csize == 0) { r_dst = ""; return; diff --git a/doc/classes/BaseButton.xml b/doc/classes/BaseButton.xml index 3ff8634010..3364770280 100644 --- a/doc/classes/BaseButton.xml +++ b/doc/classes/BaseButton.xml @@ -106,6 +106,8 @@ <constant name="DRAW_DISABLED" value="3" enum="DrawMode"> The state of buttons are disabled. </constant> + <constant name="DRAW_HOVER_PRESSED" value="4" enum="DrawMode"> + </constant> <constant name="ACTION_MODE_BUTTON_PRESS" value="0" enum="ActionMode"> Require just a press to consider the button clicked. </constant> diff --git a/doc/classes/CheckBox.xml b/doc/classes/CheckBox.xml index fb2cf64d98..a2a7cf85e8 100644 --- a/doc/classes/CheckBox.xml +++ b/doc/classes/CheckBox.xml @@ -31,10 +31,14 @@ </theme_item> <theme_item name="font_color_hover" type="Color"> </theme_item> + <theme_item name="font_color_hover_pressed" type="Color"> + </theme_item> <theme_item name="font_color_pressed" type="Color"> </theme_item> <theme_item name="hover" type="StyleBox"> </theme_item> + <theme_item name="hover_pressed" type="StyleBox"> + </theme_item> <theme_item name="hseparation" type="int"> </theme_item> <theme_item name="normal" type="StyleBox"> diff --git a/doc/classes/CheckButton.xml b/doc/classes/CheckButton.xml index deba9a17b6..24875017fe 100644 --- a/doc/classes/CheckButton.xml +++ b/doc/classes/CheckButton.xml @@ -29,10 +29,14 @@ </theme_item> <theme_item name="font_color_hover" type="Color"> </theme_item> + <theme_item name="font_color_hover_pressed" type="Color"> + </theme_item> <theme_item name="font_color_pressed" type="Color"> </theme_item> <theme_item name="hover" type="StyleBox"> </theme_item> + <theme_item name="hover_pressed" type="StyleBox"> + </theme_item> <theme_item name="hseparation" type="int"> </theme_item> <theme_item name="normal" type="StyleBox"> diff --git a/doc/classes/FileDialog.xml b/doc/classes/FileDialog.xml index 247228d265..29aa26b67f 100644 --- a/doc/classes/FileDialog.xml +++ b/doc/classes/FileDialog.xml @@ -17,7 +17,7 @@ <argument index="0" name="filter" type="String"> </argument> <description> - Add a custom filter. Filter format is: "mask ; description", example (C++): dialog->add_filter("*.png ; PNG Images"); + Add a custom filter. Example: [code]add_filter("*.png ; PNG Images")[/code] </description> </method> <method name="clear_filters"> @@ -31,12 +31,14 @@ <return type="void"> </return> <description> + Clear currently selected items in the dialog. </description> </method> <method name="get_line_edit"> <return type="LineEdit"> </return> <description> + Returns the LineEdit for the selected file. </description> </method> <method name="get_vbox"> @@ -56,6 +58,7 @@ </methods> <members> <member name="access" type="int" setter="set_access" getter="get_access" enum="FileDialog.Access"> + The file system access scope. See enum [code]Access[/code] constants. </member> <member name="current_dir" type="String" setter="set_current_dir" getter="get_current_dir"> The current working directory of the file dialog. @@ -67,13 +70,16 @@ The currently selected file path of the file dialog. </member> <member name="filters" type="PoolStringArray" setter="set_filters" getter="get_filters"> + Set file type filters. This example shows only .png and .gd files [code]set_filters(PoolStringArray(["*.png ; PNG Images","*.gd ; GD Script"]))[/code]. </member> <member name="mode" type="int" setter="set_mode" getter="get_mode" enum="FileDialog.Mode"> + Set dialog to open or save mode, changes selection behavior. See enum [code]Mode[/code] constants. </member> <member name="mode_overrides_title" type="bool" setter="set_mode_overrides_title" getter="is_mode_overriding_title"> - If [code]true[/code], changing the [code]mode[/code] property will set the window title accordingly (e. g. setting mode to [code]MODE_OPEN_FILE[/code] will change the window title to "Open a File"). + If [code]true[/code], changing the [code]Mode[/code] property will set the window title accordingly (e. g. setting mode to [code]MODE_OPEN_FILE[/code] will change the window title to "Open a File"). </member> <member name="show_hidden_files" type="bool" setter="set_show_hidden_files" getter="is_showing_hidden_files"> + If [code]true[/code], the dialog will show hidden files. </member> </members> <signals> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index c244b8b7a7..f842dd8311 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -89,6 +89,7 @@ The cursor's position inside the [code]LineEdit[/code]. When set, the text may scroll to accommodate it. </member> <member name="clear_button_enabled" type="bool" setter="set_clear_button_enabled" getter="is_clear_button_enabled"> + If [code]true[/code] the [code]LineEdit[/code] will show a clear button if [code]text[/code] is not empty. </member> <member name="context_menu_enabled" type="bool" setter="set_context_menu_enabled" getter="is_context_menu_enabled"> If [code]true[/code] the context menu will appear when right clicked. @@ -169,6 +170,7 @@ Undoes the previous action. </constant> <constant name="MENU_REDO" value="6" enum="MenuItems"> + Reverse the last undo action. </constant> <constant name="MENU_MAX" value="7" enum="MenuItems"> </constant> diff --git a/doc/classes/MeshDataTool.xml b/doc/classes/MeshDataTool.xml index 43d94004a8..5c3af3e2e1 100644 --- a/doc/classes/MeshDataTool.xml +++ b/doc/classes/MeshDataTool.xml @@ -1,8 +1,22 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="MeshDataTool" inherits="Reference" category="Core" version="3.1"> <brief_description> + Helper tool to access and edit [Mesh] data. </brief_description> <description> + The MeshDataTool provides access to individual vertices in a [Mesh]. It allows users to read and edit vertex data of meshes. It also creates an array of faces and edges. + To use the MeshDataTool, load a mesh with [method create_from_surface]. When you are finished editing the data commit the data to a mesh with [method commit_to_surface]. + Below is an example of how the MeshDataTool may be used. + [codeblock] + var mdt = MeshDataTool.new() + mdt.create_from_surface(mesh, 0) + for i in range(mdt.get_vertex_count()): + var vertex = mdt.get_vertex(i) + ... + mdt.set_vertex(i, vertex) + mesh.surface_remove(0) + mdt.commit_to_surface(mesh) + [/codeblock] </description> <tutorials> </tutorials> @@ -13,6 +27,7 @@ <return type="void"> </return> <description> + Clears all data currently in MeshDataTool. </description> </method> <method name="commit_to_surface"> @@ -21,6 +36,7 @@ <argument index="0" name="mesh" type="ArrayMesh"> </argument> <description> + Adds a new surface to specified [Mesh] with edited data. </description> </method> <method name="create_from_surface"> @@ -31,12 +47,15 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Uses specified surface of given [Mesh] to populate data for MeshDataTool. + Requires [Mesh] with primitive type [code]PRIMITIVE_TRIANGLES[/code]. </description> </method> <method name="get_edge_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of edges in this [Mesh]. </description> </method> <method name="get_edge_faces" qualifiers="const"> @@ -45,6 +64,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns array of faces that touch given edge. </description> </method> <method name="get_edge_meta" qualifiers="const"> @@ -53,6 +73,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns meta information assigned to given edge. </description> </method> <method name="get_edge_vertex" qualifiers="const"> @@ -63,12 +84,15 @@ <argument index="1" name="vertex" type="int"> </argument> <description> + Returns index of specified vertex connected to given edge. + Vertex argument can only be 0 or 1 because edges are comprised of two vertices. </description> </method> <method name="get_face_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of faces in this [Mesh]. </description> </method> <method name="get_face_edge" qualifiers="const"> @@ -79,6 +103,8 @@ <argument index="1" name="edge" type="int"> </argument> <description> + Returns specified edge associated with given face. + Edge argument must 2 or less becuase a face only has three edges. </description> </method> <method name="get_face_meta" qualifiers="const"> @@ -87,6 +113,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns meta data associated with given face. </description> </method> <method name="get_face_normal" qualifiers="const"> @@ -95,6 +122,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Calculates and returns face normal of given face. </description> </method> <method name="get_face_vertex" qualifiers="const"> @@ -105,18 +133,23 @@ <argument index="1" name="vertex" type="int"> </argument> <description> + Returns specified vertex of given face. + Vertex argument must be 2 or less becuase faces contain three vertices. </description> </method> <method name="get_format" qualifiers="const"> <return type="int"> </return> <description> + Returns format of [Mesh]. Format is an integer made up of [Mesh] format flags combined together. For example, a mesh containing both vertices and normals would return a format of [code]3[/code] becuase [code]ARRAY_FORMAT_VERTEX[/code] is [code]1[/code] and [code]ARRAY_FORMAT_NORMAL[/code] is [code]2[/code]. + For list of format flags see [ArrayMesh]. </description> </method> <method name="get_material" qualifiers="const"> <return type="Material"> </return> <description> + Returns material assigned to the [Mesh]. </description> </method> <method name="get_vertex" qualifiers="const"> @@ -125,6 +158,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns the vertex at given index. </description> </method> <method name="get_vertex_bones" qualifiers="const"> @@ -133,6 +167,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns the bones of the given vertex. </description> </method> <method name="get_vertex_color" qualifiers="const"> @@ -141,12 +176,14 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns the color of the given vertex. </description> </method> <method name="get_vertex_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the total number of vertices in [Mesh]. </description> </method> <method name="get_vertex_edges" qualifiers="const"> @@ -155,6 +192,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns array of edges that share given vertex. </description> </method> <method name="get_vertex_faces" qualifiers="const"> @@ -163,6 +201,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns array of faces that share given vertex. </description> </method> <method name="get_vertex_meta" qualifiers="const"> @@ -171,6 +210,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns meta data associated with given vertex. </description> </method> <method name="get_vertex_normal" qualifiers="const"> @@ -179,6 +219,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns normal of given vertex. </description> </method> <method name="get_vertex_tangent" qualifiers="const"> @@ -187,6 +228,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns tangent of given vertex. </description> </method> <method name="get_vertex_uv" qualifiers="const"> @@ -195,6 +237,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns UV of given vertex. </description> </method> <method name="get_vertex_uv2" qualifiers="const"> @@ -203,6 +246,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns UV2 of given vertex. </description> </method> <method name="get_vertex_weights" qualifiers="const"> @@ -211,6 +255,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Returns bone weights of given vertex. </description> </method> <method name="set_edge_meta"> @@ -221,6 +266,7 @@ <argument index="1" name="meta" type="Variant"> </argument> <description> + Sets the meta data of given edge. </description> </method> <method name="set_face_meta"> @@ -231,6 +277,7 @@ <argument index="1" name="meta" type="Variant"> </argument> <description> + Sets the meta data of given face. </description> </method> <method name="set_material"> @@ -239,6 +286,7 @@ <argument index="0" name="material" type="Material"> </argument> <description> + Sets the material to be used by newly constructed [Mesh]. </description> </method> <method name="set_vertex"> @@ -249,6 +297,7 @@ <argument index="1" name="vertex" type="Vector3"> </argument> <description> + Sets the position of given vertex. </description> </method> <method name="set_vertex_bones"> @@ -259,6 +308,7 @@ <argument index="1" name="bones" type="PoolIntArray"> </argument> <description> + Sets the bones of given vertex. </description> </method> <method name="set_vertex_color"> @@ -269,6 +319,7 @@ <argument index="1" name="color" type="Color"> </argument> <description> + Sets the color of given vertex. </description> </method> <method name="set_vertex_meta"> @@ -279,6 +330,7 @@ <argument index="1" name="meta" type="Variant"> </argument> <description> + Sets the meta data associated with given vertex. </description> </method> <method name="set_vertex_normal"> @@ -289,6 +341,7 @@ <argument index="1" name="normal" type="Vector3"> </argument> <description> + Sets the normal of given vertex. </description> </method> <method name="set_vertex_tangent"> @@ -299,6 +352,7 @@ <argument index="1" name="tangent" type="Plane"> </argument> <description> + Sets the tangent of given vertex. </description> </method> <method name="set_vertex_uv"> @@ -309,6 +363,7 @@ <argument index="1" name="uv" type="Vector2"> </argument> <description> + Sets the UV of given vertex. </description> </method> <method name="set_vertex_uv2"> @@ -319,6 +374,7 @@ <argument index="1" name="uv2" type="Vector2"> </argument> <description> + Sets the UV2 of given vertex. </description> </method> <method name="set_vertex_weights"> @@ -329,6 +385,7 @@ <argument index="1" name="weights" type="PoolRealArray"> </argument> <description> + Sets the bone weights of given vertex. </description> </method> </methods> diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index 0b7c0a63ad..4516fc522a 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -102,7 +102,7 @@ <argument index="0" name="name" type="String"> </argument> <description> - Returns true if the specified property exists and its initial value differs from the current value. + Returns true if the specified property exists and its initial value differs from the current value. </description> </method> <method name="property_get_revert"> @@ -111,14 +111,14 @@ <argument index="0" name="name" type="String"> </argument> <description> - Returns the initial value of the specified property. Returns null if the property does not exist. + Returns the initial value of the specified property. Returns null if the property does not exist. </description> </method> <method name="save"> <return type="int" enum="Error"> </return> <description> - Saves the configuration to the project.godot file. + Saves the configuration to the project.godot file. </description> </method> <method name="save_custom"> @@ -127,7 +127,7 @@ <argument index="0" name="file" type="String"> </argument> <description> - Saves the configuration to a custom file. + Saves the configuration to a custom file. </description> </method> <method name="set_initial_value"> @@ -213,8 +213,6 @@ <member name="audio/mix_rate" type="int" setter="" getter=""> Mix rate used for audio. In general, it's better to not touch this and leave it to the host operating system. </member> - <member name="audio/output_latency" type="int" setter="" getter=""> - </member> <member name="audio/video_delay_compensation_ms" type="int" setter="" getter=""> Setting to hardcode audio delay when playing video. Best to leave this untouched unless you know what you are doing. </member> @@ -697,6 +695,14 @@ </member> <member name="rendering/quality/reflections/texture_array_reflections.mobile" type="bool" setter="" getter=""> </member> + <member name="rendering/quality/shading/force_blinn_over_ggx" type="bool" setter="" getter=""> + </member> + <member name="rendering/quality/shading/force_blinn_over_ggx.mobile" type="bool" setter="" getter=""> + </member> + <member name="rendering/quality/shading/force_lambert_over_burley" type="bool" setter="" getter=""> + </member> + <member name="rendering/quality/shading/force_lambert_over_burley.mobile" type="bool" setter="" getter=""> + </member> <member name="rendering/quality/shading/force_vertex_shading" type="bool" setter="" getter=""> Force vertex shading for all rendering. This can increase performance a lot, but also reduces quality inmensely. Can work to optimize on very low end mobile. </member> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index 618f2f42b2..357d2e7a15 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -166,6 +166,12 @@ Adds a meta tag to the tag stack. Similar to the bbcode [code][url=something]{text}[/url][/code], but supports non-[String] metadata types. </description> </method> + <method name="push_strikethrough"> + <return type="void"> + </return> + <description> + </description> + </method> <method name="push_table"> <return type="void"> </return> @@ -304,15 +310,17 @@ </constant> <constant name="ITEM_UNDERLINE" value="6" enum="ItemType"> </constant> - <constant name="ITEM_ALIGN" value="7" enum="ItemType"> + <constant name="ITEM_STRIKETHROUGH" value="7" enum="ItemType"> + </constant> + <constant name="ITEM_ALIGN" value="8" enum="ItemType"> </constant> - <constant name="ITEM_INDENT" value="8" enum="ItemType"> + <constant name="ITEM_INDENT" value="9" enum="ItemType"> </constant> - <constant name="ITEM_LIST" value="9" enum="ItemType"> + <constant name="ITEM_LIST" value="10" enum="ItemType"> </constant> - <constant name="ITEM_TABLE" value="10" enum="ItemType"> + <constant name="ITEM_TABLE" value="11" enum="ItemType"> </constant> - <constant name="ITEM_META" value="11" enum="ItemType"> + <constant name="ITEM_META" value="12" enum="ItemType"> </constant> </constants> <theme_items> diff --git a/doc/classes/ScriptCreateDialog.xml b/doc/classes/ScriptCreateDialog.xml index 3de068dbcb..67ce9a8e87 100644 --- a/doc/classes/ScriptCreateDialog.xml +++ b/doc/classes/ScriptCreateDialog.xml @@ -24,6 +24,8 @@ </argument> <argument index="1" name="path" type="String"> </argument> + <argument index="2" name="built_in_enabled" type="bool" default="true"> + </argument> <description> Prefills required fields to configure the ScriptCreateDialog for use. </description> diff --git a/doc/classes/SpinBox.xml b/doc/classes/SpinBox.xml index 0fcd5bbaf5..5087cf355a 100644 --- a/doc/classes/SpinBox.xml +++ b/doc/classes/SpinBox.xml @@ -19,6 +19,8 @@ </method> </methods> <members> + <member name="align" type="int" setter="set_align" getter="get_align" enum="LineEdit.Align"> + </member> <member name="editable" type="bool" setter="set_editable" getter="is_editable"> </member> <member name="prefix" type="String" setter="set_prefix" getter="get_prefix"> diff --git a/doc/classes/StreamPeerSSL.xml b/doc/classes/StreamPeerSSL.xml index cf8769d22b..33948df509 100644 --- a/doc/classes/StreamPeerSSL.xml +++ b/doc/classes/StreamPeerSSL.xml @@ -63,6 +63,8 @@ <constant name="STATUS_DISCONNECTED" value="0" enum="Status"> A status representing a [code]StreamPeerSSL[/code] that is disconnected. </constant> + <constant name="STATUS_HANDSHAKING" value="1" enum="Status"> + </constant> <constant name="STATUS_CONNECTED" value="2" enum="Status"> A status representing a [code]StreamPeerSSL[/code] that is connected to a host. </constant> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index d404c32b38..536165487d 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -671,6 +671,7 @@ <return type="PoolByteArray"> </return> <description> + Returns the SHA-256 hash of the string as an array of bytes. </description> </method> <method name="sha256_text"> diff --git a/doc/classes/SurfaceTool.xml b/doc/classes/SurfaceTool.xml index deda7bc292..4f9ac68e47 100644 --- a/doc/classes/SurfaceTool.xml +++ b/doc/classes/SurfaceTool.xml @@ -14,6 +14,7 @@ [/codeblock] The [code]SurfaceTool[/code] now contains one vertex of a triangle which has a UV coordinate and a specified [Color]. If another vertex were added without calls to [method add_uv] or [method add_color] then the last values would be used. It is very important that vertex attributes are passed [b]before[/b] the call to [method add_vertex], failure to do this will result in an error when committing the vertex information to a mesh. + Additionally, the attributes used before the first vertex is added determine the format of the mesh. For example if you only add UVs to the first vertex, you cannot add color to any of the subsequent vertices. </description> <tutorials> </tutorials> @@ -26,7 +27,7 @@ <argument index="0" name="bones" type="PoolIntArray"> </argument> <description> - Add an array of bones for the next Vertex to use. + Add an array of bones for the next Vertex to use. Array must contain 4 integers. </description> </method> <method name="add_color"> @@ -99,6 +100,7 @@ </argument> <description> Insert a triangle fan made of array data into [Mesh] being constructed. + Requires primitive type be set to [code]PRIMITIVE_TRIANGLES[/code]. </description> </method> <method name="add_uv"> @@ -134,7 +136,7 @@ <argument index="0" name="weights" type="PoolRealArray"> </argument> <description> - Specify weight value for next Vertex to use. + Specify weight values for next Vertex to use. Array must contain 4 values. </description> </method> <method name="append_from"> @@ -147,6 +149,7 @@ <argument index="2" name="transform" type="Transform"> </argument> <description> + Append vertices from a given [Mesh] surface onto the current vertex array with specified [Transform]. </description> </method> <method name="begin"> @@ -184,6 +187,7 @@ <argument index="1" name="surface" type="int"> </argument> <description> + Creates a vertex array from an existing [Mesh]. </description> </method> <method name="deindex"> @@ -201,12 +205,15 @@ <description> Generates normals from Vertices so you do not have to do it manually. Setting "flip" [code]true[/code] inverts resulting normals. + Requires primitive type to be set to [code]PRIMITIVE_TRIANGLES[/code]. </description> </method> <method name="generate_tangents"> <return type="void"> </return> <description> + Generates a tangent vector for each vertex. + Requires that each vertex have UVs and normals set already. </description> </method> <method name="index"> diff --git a/doc/classes/TabContainer.xml b/doc/classes/TabContainer.xml index 5acfd6194e..f17c10b31e 100644 --- a/doc/classes/TabContainer.xml +++ b/doc/classes/TabContainer.xml @@ -82,6 +82,7 @@ <return type="int"> </return> <description> + Returns the [code]TabContainer[/code] rearrange group id. </description> </method> <method name="set_popup"> @@ -132,6 +133,7 @@ <argument index="0" name="group_id" type="int"> </argument> <description> + Defines rearrange group id, choose for each [code]TabContainer[/code] the same value to enable tab drag between [code]TabContainer[/code]. Enable drag with [code]set_drag_to_rearrange_enabled(true)[/code]. </description> </method> </methods> @@ -140,6 +142,7 @@ The current tab index. When set, this index's [Control] node's [code]visible[/code] property is set to [code]true[/code] and all others are set to [code]false[/code]. </member> <member name="drag_to_rearrange_enabled" type="bool" setter="set_drag_to_rearrange_enabled" getter="get_drag_to_rearrange_enabled"> + If [code]true[/code], tabs can be rearranged with mouse drag. </member> <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="TabContainer.TabAlign"> The alignment of all tabs in the tab container. See the [code]ALIGN_*[/code] constants for details. @@ -171,10 +174,13 @@ </signals> <constants> <constant name="ALIGN_LEFT" value="0" enum="TabAlign"> + Align the tabs to the left. </constant> <constant name="ALIGN_CENTER" value="1" enum="TabAlign"> + Align the tabs to the center. </constant> <constant name="ALIGN_RIGHT" value="2" enum="TabAlign"> + Align the tabs to the right. </constant> </constants> <theme_items> diff --git a/doc/classes/Tabs.xml b/doc/classes/Tabs.xml index fc1d0476ed..350b49513d 100644 --- a/doc/classes/Tabs.xml +++ b/doc/classes/Tabs.xml @@ -19,6 +19,7 @@ <argument index="1" name="icon" type="Texture" default="null"> </argument> <description> + Adds a new tab. </description> </method> <method name="ensure_tab_visible"> @@ -27,6 +28,7 @@ <argument index="0" name="idx" type="int"> </argument> <description> + Moves the Scroll view to make the tab visible. </description> </method> <method name="get_offset_buttons_visible" qualifiers="const"> @@ -39,12 +41,14 @@ <return type="bool"> </return> <description> + Returns [code]true[/code] if select with right mouse button is enabled. </description> </method> <method name="get_tab_count" qualifiers="const"> <return type="int"> </return> <description> + Returns the number of tabs. </description> </method> <method name="get_tab_disabled" qualifiers="const"> @@ -53,6 +57,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns [code]true[/code] if the tab at index [code]tab_idx[/code] is disabled. </description> </method> <method name="get_tab_icon" qualifiers="const"> @@ -61,6 +66,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns the [Texture] for the tab at index [code]tab_idx[/code] or null if the tab has no [Texture]. </description> </method> <method name="get_tab_offset" qualifiers="const"> @@ -84,12 +90,14 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Returns the title of the tab at index [code]tab_idx[/code]. Tab titles default to the name of the indexed child node, but this can be overridden with [method set_tab_title]. </description> </method> <method name="get_tabs_rearrange_group" qualifiers="const"> <return type="int"> </return> <description> + Returns the [code]Tabs[/code] rearrange group id. </description> </method> <method name="move_tab"> @@ -109,6 +117,7 @@ <argument index="0" name="tab_idx" type="int"> </argument> <description> + Removes tab at index [code]tab_idx[/code] </description> </method> <method name="set_select_with_rmb"> @@ -117,6 +126,7 @@ <argument index="0" name="enabled" type="bool"> </argument> <description> + If [code]true[/code] enables selecting a tab with right mouse button. </description> </method> <method name="set_tab_disabled"> @@ -127,6 +137,7 @@ <argument index="1" name="disabled" type="bool"> </argument> <description> + If [code]disabled[/code] is false, hides the tab at index [code]tab_idx[/code]. Note that its title text will remain, unless also removed with [method set_tab_title]. </description> </method> <method name="set_tab_icon"> @@ -137,6 +148,7 @@ <argument index="1" name="icon" type="Texture"> </argument> <description> + Sets an icon for the tab at index [code]tab_idx[/code]. </description> </method> <method name="set_tab_title"> @@ -147,6 +159,7 @@ <argument index="1" name="title" type="String"> </argument> <description> + Sets a title for the tab at index [code]tab_idx[/code]. </description> </method> <method name="set_tabs_rearrange_group"> @@ -155,17 +168,21 @@ <argument index="0" name="group_id" type="int"> </argument> <description> + Defines rearrange group id, choose for each [code]Tabs[/code] the same value to enable tab drag between [code]Tabs[/code]. Enable drag with [code]set_drag_to_rearrange_enabled(true)[/code]. </description> </method> </methods> <members> <member name="current_tab" type="int" setter="set_current_tab" getter="get_current_tab"> + Select tab at index [code]tab_idx[/code]. </member> <member name="drag_to_rearrange_enabled" type="bool" setter="set_drag_to_rearrange_enabled" getter="get_drag_to_rearrange_enabled"> + If [code]true[/code], tabs can be rearranged with mouse drag. </member> <member name="scrolling_enabled" type="bool" setter="set_scrolling_enabled" getter="get_scrolling_enabled"> </member> <member name="tab_align" type="int" setter="set_tab_align" getter="get_tab_align" enum="Tabs.TabAlign"> + The alignment of all tabs. See enum [code]TabAlign[/code] constants for details. </member> <member name="tab_close_display_policy" type="int" setter="set_tab_close_display_policy" getter="get_tab_close_display_policy" enum="Tabs.CloseButtonDisplayPolicy"> </member> @@ -210,10 +227,13 @@ </signals> <constants> <constant name="ALIGN_LEFT" value="0" enum="TabAlign"> + Align the tabs to the left. </constant> <constant name="ALIGN_CENTER" value="1" enum="TabAlign"> + Align the tabs to the center. </constant> <constant name="ALIGN_RIGHT" value="2" enum="TabAlign"> + Align the tabs to the right. </constant> <constant name="ALIGN_MAX" value="3" enum="TabAlign"> </constant> diff --git a/doc/classes/TileSet.xml b/doc/classes/TileSet.xml index 3f0d6317a6..ffd15e8d8b 100644 --- a/doc/classes/TileSet.xml +++ b/doc/classes/TileSet.xml @@ -268,7 +268,7 @@ <argument index="1" name="shape_id" type="int"> </argument> <description> - Returns the [Transform2D] of a tile's sahpe. + Returns the [Transform2D] of a tile's shape. </description> </method> <method name="tile_get_shapes" qualifiers="const"> diff --git a/doc/classes/TreeItem.xml b/doc/classes/TreeItem.xml index c5a63b1acb..b4227b34be 100644 --- a/doc/classes/TreeItem.xml +++ b/doc/classes/TreeItem.xml @@ -25,7 +25,7 @@ <argument index="4" name="tooltip" type="String" default=""""> </argument> <description> - Adds a button with [Texture] [code]button[/code] at column [code]column[/code]. The [code]button_idx[/code] index is used to identify the button when calling other methods. If not specified, the next available index is used, which may be retrieved by calling [code]get_buton_count()[/code] immediately after this method. Optionally, the button can be [code]disabled[/code] and have a [code]tooltip[/code]. + Adds a button with [Texture] [code]button[/code] at column [code]column[/code]. The [code]button_idx[/code] index is used to identify the button when calling other methods. If not specified, the next available index is used, which may be retrieved by calling [method get_button_count] immediately after this method. Optionally, the button can be [code]disabled[/code] and have a [code]tooltip[/code]. </description> </method> <method name="clear_custom_bg_color"> @@ -559,13 +559,10 @@ <constant name="CELL_MODE_RANGE" value="2" enum="TreeCellMode"> Cell contains a range. </constant> - <constant name="CELL_MODE_RANGE_EXPRESSION" value="3" enum="TreeCellMode"> - Cell contains a range expression. - </constant> - <constant name="CELL_MODE_ICON" value="4" enum="TreeCellMode"> + <constant name="CELL_MODE_ICON" value="3" enum="TreeCellMode"> Cell contains an icon. </constant> - <constant name="CELL_MODE_CUSTOM" value="5" enum="TreeCellMode"> + <constant name="CELL_MODE_CUSTOM" value="4" enum="TreeCellMode"> </constant> <constant name="ALIGN_LEFT" value="0" enum="TextAlign"> Align text to the left. See [code]set_text_align()[/code]. diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 7e03e7f0fe..c323cf6992 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -267,7 +267,10 @@ </members> <constants> <constant name="ZERO" value="Vector2( 0, 0 )"> - Null vector. + Zero vector. + </constant> + <constant name="ONE" value="Vector2( 1, 1 )"> + One vector. </constant> <constant name="INF" value="Vector2( inf, inf )"> Infinite vector. diff --git a/doc/classes/Vector3.xml b/doc/classes/Vector3.xml index 4211c34d8e..8c4e08778d 100644 --- a/doc/classes/Vector3.xml +++ b/doc/classes/Vector3.xml @@ -280,7 +280,10 @@ Enumerated value for the Z axis. </constant> <constant name="ZERO" value="Vector3( 0, 0, 0 )"> - Null vector. + Zero vector. + </constant> + <constant name="ONE" value="Vector3( 1, 1, 1 )"> + One vector. </constant> <constant name="INF" value="Vector3( inf, inf, inf )"> Infinite vector. diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index 58b3d33cdb..225a1f2bba 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -4380,7 +4380,7 @@ </constant> <constant name="ENV_TONE_MAPPER_LINEAR" value="0" enum="EnvironmentToneMapper"> </constant> - <constant name="ENV_TONE_MAPPER_REINHARDT" value="1" enum="EnvironmentToneMapper"> + <constant name="ENV_TONE_MAPPER_REINHARD" value="1" enum="EnvironmentToneMapper"> </constant> <constant name="ENV_TONE_MAPPER_FILMIC" value="2" enum="EnvironmentToneMapper"> </constant> diff --git a/drivers/coreaudio/audio_driver_coreaudio.cpp b/drivers/coreaudio/audio_driver_coreaudio.cpp index cf8fb08f76..aaec63d7ff 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.cpp +++ b/drivers/coreaudio/audio_driver_coreaudio.cpp @@ -95,11 +95,6 @@ Error AudioDriverCoreAudio::init() { result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &output_device_address_cb, this); ERR_FAIL_COND_V(result != noErr, FAILED); - - prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; - - result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); - ERR_FAIL_COND_V(result != noErr, FAILED); #endif AudioStreamBasicDescription strdesc; @@ -123,26 +118,6 @@ Error AudioDriverCoreAudio::init() { break; } - zeromem(&strdesc, sizeof(strdesc)); - size = sizeof(strdesc); - result = AudioUnitGetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size); - ERR_FAIL_COND_V(result != noErr, FAILED); - - switch (strdesc.mChannelsPerFrame) { - case 1: // Mono - capture_channels = 1; - break; - - case 2: // Stereo - capture_channels = 2; - break; - - default: - // Unknown number of channels, default to stereo - capture_channels = 2; - break; - } - mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); zeromem(&strdesc, sizeof(strdesc)); @@ -158,11 +133,6 @@ Error AudioDriverCoreAudio::init() { result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &strdesc, sizeof(strdesc)); ERR_FAIL_COND_V(result != noErr, FAILED); - strdesc.mChannelsPerFrame = capture_channels; - - result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); - ERR_FAIL_COND_V(result != noErr, FAILED); - int latency = GLOBAL_DEF_RST("audio/output_latency", DEFAULT_OUTPUT_LATENCY); // Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels) buffer_frames = closest_power_of_2(latency * mix_rate / 1000); @@ -189,16 +159,10 @@ Error AudioDriverCoreAudio::init() { result = AudioUnitSetProperty(audio_unit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, kOutputBus, &callback, sizeof(callback)); ERR_FAIL_COND_V(result != noErr, FAILED); - zeromem(&callback, sizeof(AURenderCallbackStruct)); - callback.inputProc = &AudioDriverCoreAudio::input_callback; - callback.inputProcRefCon = this; - result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback)); - ERR_FAIL_COND_V(result != noErr, FAILED); - result = AudioUnitInitialize(audio_unit); ERR_FAIL_COND_V(result != noErr, FAILED); - return OK; + return capture_init(); } OSStatus AudioDriverCoreAudio::output_callback(void *inRefCon, @@ -265,7 +229,7 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon, bufferList.mBuffers[0].mNumberChannels = ad->capture_channels; bufferList.mBuffers[0].mDataByteSize = ad->input_buf.size() * sizeof(int16_t); - OSStatus result = AudioUnitRender(ad->audio_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); + OSStatus result = AudioUnitRender(ad->input_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList); if (result == noErr) { for (int i = 0; i < inNumberFrames * ad->capture_channels; i++) { int32_t sample = ad->input_buf[i] << 16; @@ -332,6 +296,8 @@ bool AudioDriverCoreAudio::try_lock() { } void AudioDriverCoreAudio::finish() { + capture_finish(); + if (audio_unit) { OSStatus result; @@ -375,6 +341,7 @@ void AudioDriverCoreAudio::finish() { ERR_PRINT("AudioComponentInstanceDispose failed"); } + audio_unit = NULL; unlock(); } @@ -384,20 +351,158 @@ void AudioDriverCoreAudio::finish() { } } -Error AudioDriverCoreAudio::capture_start() { +Error AudioDriverCoreAudio::capture_init() { + AudioComponentDescription desc; + zeromem(&desc, sizeof(desc)); + desc.componentType = kAudioUnitType_Output; +#ifdef OSX_ENABLED + desc.componentSubType = kAudioUnitSubType_HALOutput; +#else + desc.componentSubType = kAudioUnitSubType_RemoteIO; +#endif + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + + AudioComponent comp = AudioComponentFindNext(NULL, &desc); + ERR_FAIL_COND_V(comp == NULL, FAILED); + + OSStatus result = AudioComponentInstanceNew(comp, &input_unit); + ERR_FAIL_COND_V(result != noErr, FAILED); + +#ifdef OSX_ENABLED + AudioObjectPropertyAddress prop; + prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; + prop.mScope = kAudioObjectPropertyScopeGlobal; + prop.mElement = kAudioObjectPropertyElementMaster; + + result = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); + ERR_FAIL_COND_V(result != noErr, FAILED); +#endif UInt32 flag = 1; - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); + ERR_FAIL_COND_V(result != noErr, FAILED); + flag = 0; + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + UInt32 size; +#ifdef OSX_ENABLED + AudioDeviceID deviceId; + size = sizeof(AudioDeviceID); + AudioObjectPropertyAddress property = { kAudioHardwarePropertyDefaultInputDevice, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster }; + + result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &property, 0, NULL, &size, &deviceId); + ERR_FAIL_COND_V(result != noErr, FAILED); + + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); + ERR_FAIL_COND_V(result != noErr, FAILED); +#endif + + AudioStreamBasicDescription strdesc; + zeromem(&strdesc, sizeof(strdesc)); + size = sizeof(strdesc); + result = AudioUnitGetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, &size); + ERR_FAIL_COND_V(result != noErr, FAILED); + + switch (strdesc.mChannelsPerFrame) { + case 1: // Mono + capture_channels = 1; + break; + + case 2: // Stereo + capture_channels = 2; + break; + + default: + // Unknown number of channels, default to stereo + capture_channels = 2; + break; + } + + mix_rate = GLOBAL_DEF_RST("audio/mix_rate", DEFAULT_MIX_RATE); + + zeromem(&strdesc, sizeof(strdesc)); + strdesc.mFormatID = kAudioFormatLinearPCM; + strdesc.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked; + strdesc.mChannelsPerFrame = capture_channels; + strdesc.mSampleRate = mix_rate; + strdesc.mFramesPerPacket = 1; + strdesc.mBitsPerChannel = 16; + strdesc.mBytesPerFrame = strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8; + strdesc.mBytesPerPacket = strdesc.mBytesPerFrame * strdesc.mFramesPerPacket; + + result = AudioUnitSetProperty(input_unit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, &strdesc, sizeof(strdesc)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + AURenderCallbackStruct callback; + zeromem(&callback, sizeof(AURenderCallbackStruct)); + callback.inputProc = &AudioDriverCoreAudio::input_callback; + callback.inputProcRefCon = this; + result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, kInputBus, &callback, sizeof(callback)); + ERR_FAIL_COND_V(result != noErr, FAILED); + + result = AudioUnitInitialize(input_unit); ERR_FAIL_COND_V(result != noErr, FAILED); return OK; } +void AudioDriverCoreAudio::capture_finish() { + if (input_unit) { + lock(); + + AURenderCallbackStruct callback; + zeromem(&callback, sizeof(AURenderCallbackStruct)); + OSStatus result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &callback, sizeof(callback)); + if (result != noErr) { + ERR_PRINT("AudioUnitSetProperty failed"); + } + + result = AudioUnitUninitialize(input_unit); + if (result != noErr) { + ERR_PRINT("AudioUnitUninitialize failed"); + } + +#ifdef OSX_ENABLED + AudioObjectPropertyAddress prop; + prop.mSelector = kAudioHardwarePropertyDefaultInputDevice; + prop.mScope = kAudioObjectPropertyScopeGlobal; + prop.mElement = kAudioObjectPropertyElementMaster; + + result = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &prop, &input_device_address_cb, this); + if (result != noErr) { + ERR_PRINT("AudioObjectRemovePropertyListener failed"); + } +#endif + + result = AudioComponentInstanceDispose(input_unit); + if (result != noErr) { + ERR_PRINT("AudioComponentInstanceDispose failed"); + } + + input_unit = NULL; + unlock(); + } +} + +Error AudioDriverCoreAudio::capture_start() { + + OSStatus result = AudioOutputUnitStart(input_unit); + if (result != noErr) { + ERR_PRINTS("AudioOutputUnitStart failed, code: " + itos(result)); + } + + return OK; +} + Error AudioDriverCoreAudio::capture_stop() { - UInt32 flag = 0; - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag)); - ERR_FAIL_COND_V(result != noErr, FAILED); + if (input_unit) { + OSStatus result = AudioOutputUnitStop(input_unit); + if (result != noErr) { + ERR_PRINTS("AudioOutputUnitStop failed, code: " + itos(result)); + } + } return OK; } @@ -531,12 +636,14 @@ void AudioDriverCoreAudio::_set_device(const String &device, bool capture) { } if (found) { - OSStatus result = AudioUnitSetProperty(audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, capture ? kInputBus : kOutputBus, &deviceId, sizeof(AudioDeviceID)); + OSStatus result = AudioUnitSetProperty(capture ? input_unit : audio_unit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &deviceId, sizeof(AudioDeviceID)); ERR_FAIL_COND(result != noErr); - // Reset audio input to keep synchronisation. - input_position = 0; - input_size = 0; + if (capture) { + // Reset audio input to keep synchronisation. + input_position = 0; + input_size = 0; + } } } @@ -580,6 +687,7 @@ String AudioDriverCoreAudio::capture_get_device() { AudioDriverCoreAudio::AudioDriverCoreAudio() { audio_unit = NULL; + input_unit = NULL; active = false; mutex = NULL; diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h index d3f7c8d596..474a9e43ae 100644 --- a/drivers/coreaudio/audio_driver_coreaudio.h +++ b/drivers/coreaudio/audio_driver_coreaudio.h @@ -43,6 +43,7 @@ class AudioDriverCoreAudio : public AudioDriver { AudioComponentInstance audio_unit; + AudioComponentInstance input_unit; bool active; Mutex *mutex; @@ -83,6 +84,9 @@ class AudioDriverCoreAudio : public AudioDriver { UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData); + Error capture_init(); + void capture_finish(); + public: const char *get_name() const { return "CoreAudio"; diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index b42e2dfb1f..c928f753b1 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -43,7 +43,6 @@ /* #include "shaders/blend_shape.glsl.gen.h" #include "shaders/canvas.glsl.gen.h" -#include "shaders/copy.glsl.gen.h" #include "shaders/particles.glsl.gen.h" */ diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 2803f3371b..ed2b39a17d 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -2519,7 +2519,7 @@ void RasterizerSceneGLES3::_draw_sky(RasterizerStorageGLES3::Sky *p_sky, const C storage->shaders.copy.set_conditional(CopyShaderGLES3::USE_PANORAMA, false); } -void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform) { +void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog) { //store camera into ubo store_camera(p_cam_projection, state.ubo_data.projection_matrix); @@ -2570,7 +2570,7 @@ void RasterizerSceneGLES3::_setup_environment(Environment *env, const CameraMatr state.ubo_data.fog_color_enabled[0] = linear_fog.r; state.ubo_data.fog_color_enabled[1] = linear_fog.g; state.ubo_data.fog_color_enabled[2] = linear_fog.b; - state.ubo_data.fog_color_enabled[3] = env->fog_enabled ? 1.0 : 0.0; + state.ubo_data.fog_color_enabled[3] = (!p_no_fog && env->fog_enabled) ? 1.0 : 0.0; Color linear_sun = env->fog_sun_color.to_linear(); state.ubo_data.fog_sun_color_amount[0] = linear_sun.r; @@ -4083,7 +4083,7 @@ void RasterizerSceneGLES3::render_scene(const Transform &p_cam_transform, const state.ubo_data.screen_pixel_size[1] = 1.0 / storage->frame.current_rt->height; } - _setup_environment(env, p_cam_projection, p_cam_transform); + _setup_environment(env, p_cam_projection, p_cam_transform, p_reflection_probe.is_valid()); bool fb_cleared = false; diff --git a/drivers/gles3/rasterizer_scene_gles3.h b/drivers/gles3/rasterizer_scene_gles3.h index b4c4a0558f..4b4a0b9303 100644 --- a/drivers/gles3/rasterizer_scene_gles3.h +++ b/drivers/gles3/rasterizer_scene_gles3.h @@ -831,7 +831,7 @@ public: void _draw_sky(RasterizerStorageGLES3::Sky *p_sky, const CameraMatrix &p_projection, const Transform &p_transform, bool p_vflip, float p_custom_fov, float p_energy); - void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform); + void _setup_environment(Environment *env, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, bool p_no_fog = false); void _setup_directional_light(int p_index, const Transform &p_camera_inverse_transform, bool p_use_shadows); void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_shadow_atlas); void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, const CameraMatrix &p_camera_projection, RID p_reflection_atlas, Environment *p_env); diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 9faf07c2f9..a9aa152f10 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -4066,35 +4066,37 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances multimesh->data.resize(format_floats * p_instances); + float *dataptr = multimesh->data.ptrw(); + for (int i = 0; i < p_instances * format_floats; i += format_floats) { int color_from = 0; int custom_data_from = 0; if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { - multimesh->data.write[i + 0] = 1.0; - multimesh->data.write[i + 1] = 0.0; - multimesh->data.write[i + 2] = 0.0; - multimesh->data.write[i + 3] = 0.0; - multimesh->data.write[i + 4] = 0.0; - multimesh->data.write[i + 5] = 1.0; - multimesh->data.write[i + 6] = 0.0; - multimesh->data.write[i + 7] = 0.0; + dataptr[i + 0] = 1.0; + dataptr[i + 1] = 0.0; + dataptr[i + 2] = 0.0; + dataptr[i + 3] = 0.0; + dataptr[i + 4] = 0.0; + dataptr[i + 5] = 1.0; + dataptr[i + 6] = 0.0; + dataptr[i + 7] = 0.0; color_from = 8; custom_data_from = 8; } else { - multimesh->data.write[i + 0] = 1.0; - multimesh->data.write[i + 1] = 0.0; - multimesh->data.write[i + 2] = 0.0; - multimesh->data.write[i + 3] = 0.0; - multimesh->data.write[i + 4] = 0.0; - multimesh->data.write[i + 5] = 1.0; - multimesh->data.write[i + 6] = 0.0; - multimesh->data.write[i + 7] = 0.0; - multimesh->data.write[i + 8] = 0.0; - multimesh->data.write[i + 9] = 0.0; - multimesh->data.write[i + 10] = 1.0; - multimesh->data.write[i + 11] = 0.0; + dataptr[i + 0] = 1.0; + dataptr[i + 1] = 0.0; + dataptr[i + 2] = 0.0; + dataptr[i + 3] = 0.0; + dataptr[i + 4] = 0.0; + dataptr[i + 5] = 1.0; + dataptr[i + 6] = 0.0; + dataptr[i + 7] = 0.0; + dataptr[i + 8] = 0.0; + dataptr[i + 9] = 0.0; + dataptr[i + 10] = 1.0; + dataptr[i + 11] = 0.0; color_from = 12; custom_data_from = 12; } @@ -4109,14 +4111,14 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances } cu; cu.colu = 0xFFFFFFFF; - multimesh->data.write[i + color_from + 0] = cu.colf; + dataptr[i + color_from + 0] = cu.colf; custom_data_from = color_from + 1; } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { - multimesh->data.write[i + color_from + 0] = 1.0; - multimesh->data.write[i + color_from + 1] = 1.0; - multimesh->data.write[i + color_from + 2] = 1.0; - multimesh->data.write[i + color_from + 3] = 1.0; + dataptr[i + color_from + 0] = 1.0; + dataptr[i + color_from + 1] = 1.0; + dataptr[i + color_from + 2] = 1.0; + dataptr[i + color_from + 3] = 1.0; custom_data_from = color_from + 4; } @@ -4130,13 +4132,13 @@ void RasterizerStorageGLES3::multimesh_allocate(RID p_multimesh, int p_instances } cu; cu.colu = 0; - multimesh->data.write[i + custom_data_from + 0] = cu.colf; + dataptr[i + custom_data_from + 0] = cu.colf; } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { - multimesh->data.write[i + custom_data_from + 0] = 0.0; - multimesh->data.write[i + custom_data_from + 1] = 0.0; - multimesh->data.write[i + custom_data_from + 2] = 0.0; - multimesh->data.write[i + custom_data_from + 3] = 0.0; + dataptr[i + custom_data_from + 0] = 0.0; + dataptr[i + custom_data_from + 1] = 0.0; + dataptr[i + custom_data_from + 2] = 0.0; + dataptr[i + custom_data_from + 3] = 0.0; } } diff --git a/drivers/gles3/shader_compiler_gles3.cpp b/drivers/gles3/shader_compiler_gles3.cpp index dbc8507951..be36b41417 100644 --- a/drivers/gles3/shader_compiler_gles3.cpp +++ b/drivers/gles3/shader_compiler_gles3.cpp @@ -872,6 +872,7 @@ ShaderCompilerGLES3::ShaderCompilerGLES3() { actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; + actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl index 598bd3465e..8388b15edb 100644 --- a/drivers/gles3/shaders/scene.glsl +++ b/drivers/gles3/shaders/scene.glsl @@ -1340,7 +1340,7 @@ void reflection_process(int idx, vec3 vertex, vec3 normal, vec3 binormal, vec3 t reflection_accum += reflection; } -#ifndef USE_LIGHTMAP +#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) if (reflections[idx].ambient.a > 0.0) { //compute ambient using skybox vec3 local_amb_vec = (reflections[idx].local_matrix * vec4(normal, 0.0)).xyz; @@ -1957,7 +1957,7 @@ FRAGMENT_SHADER_CODE } else { specular_light += env_reflection_light; } -#ifndef USE_LIGHTMAP +#if !defined(USE_LIGHTMAP) && !defined(USE_LIGHTMAP_CAPTURE) if (ambient_accum.a > 0.0) { ambient_light = ambient_accum.rgb / ambient_accum.a; } diff --git a/drivers/unix/dir_access_unix.cpp b/drivers/unix/dir_access_unix.cpp index 48b4369b7e..929e67faa9 100644 --- a/drivers/unix/dir_access_unix.cpp +++ b/drivers/unix/dir_access_unix.cpp @@ -309,7 +309,7 @@ Error DirAccessUnix::change_dir(String p_dir) { // prev_dir is the directory we are changing out of String prev_dir; char real_current_dir_name[2048]; - getcwd(real_current_dir_name, 2048); + ERR_FAIL_COND_V(getcwd(real_current_dir_name, 2048) == NULL, ERR_BUG); if (prev_dir.parse_utf8(real_current_dir_name)) prev_dir = real_current_dir_name; //no utf8, maybe latin? @@ -330,7 +330,7 @@ Error DirAccessUnix::change_dir(String p_dir) { // the directory exists, so set current_dir to try_dir current_dir = try_dir; - chdir(prev_dir.utf8().get_data()); + ERR_FAIL_COND_V(chdir(prev_dir.utf8().get_data()) != 0, ERR_BUG); return OK; } @@ -405,7 +405,7 @@ DirAccessUnix::DirAccessUnix() { // set current directory to an absolute path of the current directory char real_current_dir_name[2048]; - getcwd(real_current_dir_name, 2048); + ERR_FAIL_COND(getcwd(real_current_dir_name, 2048) == NULL); if (current_dir.parse_utf8(real_current_dir_name)) current_dir = real_current_dir_name; diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 6c70934bc6..7ff27be501 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -487,9 +487,11 @@ String OS_Unix::get_executable_path() const { //fix for running from a symlink char buf[256]; memset(buf, 0, 256); - readlink("/proc/self/exe", buf, sizeof(buf)); + ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf)); String b; - b.parse_utf8(buf); + if (len > 0) { + b.parse_utf8(buf, len); + } if (b == "") { WARN_PRINT("Couldn't get executable path from /proc/self/exe, using argv[0]"); return OS::get_executable_path(); diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 79c22f667a..aeb304d3b9 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1039,6 +1039,8 @@ void CodeTextEditor::delete_lines() { int to_line = text_editor->get_selection_to_line(); int from_line = text_editor->get_selection_from_line(); int count = Math::abs(to_line - from_line) + 1; + + text_editor->cursor_set_line(to_line, false); while (count) { text_editor->set_line(text_editor->cursor_get_line(), ""); text_editor->backspace_at_cursor(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index c5c78b2590..96d482f47e 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -477,33 +477,16 @@ EditorPropertyCheck::EditorPropertyCheck() { void EditorPropertyEnum::_option_selected(int p_which) { - String text = options->get_item_text(p_which); - Vector<String> text_split = text.split(":"); - if (text_split.size() == 1) { - emit_signal("property_changed", get_edited_property(), p_which); - return; - } - String name = text_split[1]; - emit_signal("property_changed", get_edited_property(), name.to_int()); + int val = options->get_item_metadata(p_which); + emit_signal("property_changed", get_edited_property(), val); } void EditorPropertyEnum::update_property() { int which = get_edited_object()->get(get_edited_property()); - if (which == 0) { - options->select(which); - return; - } for (int i = 0; i < options->get_item_count(); i++) { - String text = options->get_item_text(i); - Vector<String> text_split = text.split(":"); - if (text_split.size() == 1) { - options->select(which); - return; - } - String name = text_split[1]; - if (itos(which) == name) { + if (which == (int)options->get_item_metadata(i)) { options->select(i); return; } @@ -511,8 +494,15 @@ void EditorPropertyEnum::update_property() { } void EditorPropertyEnum::setup(const Vector<String> &p_options) { + + int current_val = 0; for (int i = 0; i < p_options.size(); i++) { - options->add_item(p_options[i], i); + Vector<String> text_split = p_options[i].split(":"); + if (text_split.size() != 1) + current_val = text_split[1].to_int(); + options->add_item(text_split[0]); + options->set_item_metadata(i, current_val); + current_val += 1; } } @@ -1779,7 +1769,7 @@ void EditorPropertyColor::_color_changed(const Color &p_color) { void EditorPropertyColor::_popup_closed() { - emit_signal("property_changed", get_edited_property(), picker->get_pick_color(), true); + emit_signal("property_changed", get_edited_property(), picker->get_pick_color(), false); } void EditorPropertyColor::_bind_methods() { @@ -2102,12 +2092,18 @@ void EditorPropertyResource::_menu_option(int p_which) { } } -void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<Texture> &p_preview, ObjectID p_obj) { +void EditorPropertyResource::_resource_preview(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, ObjectID p_obj) { RES p = get_edited_object()->get(get_edited_property()); if (p.is_valid() && p->get_instance_id() == p_obj) { + String type = p->get_class_name(); + + if (ClassDB::is_parent_class(type, "Script")) { + assign->set_text(p->get_path().get_file()); + return; + } + if (p_preview.is_valid()) { - String type = p->get_class_name(); preview->set_margin(MARGIN_LEFT, assign->get_icon()->get_width() + assign->get_stylebox("normal")->get_default_margin(MARGIN_LEFT) + get_constant("hseparation", "Button")); if (type == "GradientTexture") { preview->set_stretch_mode(TextureRect::STRETCH_SCALE); @@ -2374,7 +2370,7 @@ void EditorPropertyResource::update_property() { if (res->get_name() != String()) { assign->set_text(res->get_name()); } else if (res->get_path().is_resource_file()) { - assign->set_text(res->get_name()); + assign->set_text(res->get_path().get_file()); assign->set_tooltip(res->get_path()); } else { assign->set_text(res->get_class()); diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 18e70345aa..35d8f4d306 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -548,7 +548,7 @@ class EditorPropertyResource : public EditorProperty { void _file_selected(const String &p_path); void _menu_option(int p_which); - void _resource_preview(const String &p_path, const Ref<Texture> &p_preview, ObjectID p_obj); + void _resource_preview(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, ObjectID p_obj); void _resource_selected(); void _viewport_selected(const NodePath &p_path); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index f88d1b24a6..0ccaa95fb7 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -336,12 +336,10 @@ FindInFilesDialog::FindInFilesDialog() { _whole_words_checkbox = memnew(CheckBox); _whole_words_checkbox->set_text(TTR("Whole Words")); - _whole_words_checkbox->set_pressed(true); hbc->add_child(_whole_words_checkbox); _match_case_checkbox = memnew(CheckBox); _match_case_checkbox->set_text(TTR("Match Case")); - _match_case_checkbox->set_pressed(true); hbc->add_child(_match_case_checkbox); gc->add_child(hbc); @@ -563,7 +561,7 @@ FindInFilesPanel::FindInFilesPanel() { _cancel_button = memnew(Button); _cancel_button->set_text(TTR("Cancel")); _cancel_button->connect("pressed", this, "_on_cancel_button_clicked"); - _cancel_button->set_disabled(true); + _cancel_button->hide(); hbc->add_child(_cancel_button); vbc->add_child(hbc); @@ -642,7 +640,7 @@ void FindInFilesPanel::start_search() { _finder->start(); update_replace_buttons(); - _cancel_button->set_disabled(false); + _cancel_button->show(); } void FindInFilesPanel::stop_search() { @@ -652,7 +650,7 @@ void FindInFilesPanel::stop_search() { _status_label->set_text(""); update_replace_buttons(); set_progress_visible(false); - _cancel_button->set_disabled(true); + _cancel_button->hide(); } void FindInFilesPanel::_notification(int p_what) { @@ -688,7 +686,7 @@ void FindInFilesPanel::_on_result_found(String fpath, int line_number, int begin // Do this first because it resets properties of the cell... item->set_cell_mode(text_index, TreeItem::CELL_MODE_CUSTOM); - String item_text = String::num_int64(line_number) + ": " + text.replace("\t", " "); + String item_text = vformat("%3s: %s", line_number, text.replace("\t", " ")); item->set_text(text_index, item_text); item->set_custom_draw(text_index, this, "_draw_result_text"); @@ -754,7 +752,7 @@ void FindInFilesPanel::_on_finished() { _status_label->set_text(TTR("Search complete")); update_replace_buttons(); set_progress_visible(false); - _cancel_button->set_disabled(true); + _cancel_button->hide(); } void FindInFilesPanel::_on_cancel_button_clicked() { diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 60ca66e464..e8bb772a64 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -321,7 +321,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { } else { //mesh since nothing else node = memnew(MeshInstance); - Object::cast_to<MeshInstance>(node)->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); + //Object::cast_to<MeshInstance>(node)->set_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT, true); } } break; case Collada::Node::TYPE_SKELETON: { diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 6d72cb4909..c5a5980fc1 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -365,29 +365,37 @@ Node *ResourceImporterScene::_fix_node(Node *p_node, Node *p_root, Map<Ref<Array return p_node; MeshInstance *mi = Object::cast_to<MeshInstance>(p_node); if (mi) { - Node *col; + Node *col = NULL; if (_teststr(name, "colonly")) { col = mi->create_trimesh_collision_node(); - ERR_FAIL_COND_V(!col, NULL); + if (col == NULL) { + ERR_PRINTS("Error generating collision for mesh: " + name); + } else { - col->set_name(_fixstr(name, "colonly")); + col->set_name(_fixstr(name, "colonly")); + } } else { col = mi->create_convex_collision_node(); - ERR_FAIL_COND_V(!col, NULL); + if (col == NULL) { + ERR_PRINTS("Error generating collision for mesh: " + name); + } else { - col->set_name(_fixstr(name, "convcolonly")); + col->set_name(_fixstr(name, "convcolonly")); + } } - Object::cast_to<Spatial>(col)->set_transform(mi->get_transform()); - p_node->replace_by(col); - memdelete(p_node); - p_node = col; + if (col) { + Object::cast_to<Spatial>(col)->set_transform(mi->get_transform()); + p_node->replace_by(col); + memdelete(p_node); + p_node = col; - StaticBody *sb = Object::cast_to<StaticBody>(col); - CollisionShape *colshape = Object::cast_to<CollisionShape>(sb->get_child(0)); - colshape->set_name("shape"); - colshape->set_owner(p_node->get_owner()); + StaticBody *sb = Object::cast_to<StaticBody>(col); + CollisionShape *colshape = Object::cast_to<CollisionShape>(sb->get_child(0)); + colshape->set_name("shape"); + colshape->set_owner(p_node->get_owner()); + } } else if (p_node->has_meta("empty_draw_type")) { String empty_draw_type = String(p_node->get_meta("empty_draw_type")); StaticBody *sb = memnew(StaticBody); diff --git a/editor/import/resource_importer_scene.h b/editor/import/resource_importer_scene.h index b046e2e975..b81a52ab70 100644 --- a/editor/import/resource_importer_scene.h +++ b/editor/import/resource_importer_scene.h @@ -116,7 +116,7 @@ class ResourceImporterScene : public ResourceImporter { enum LightBakeMode { LIGHT_BAKE_DISABLED, LIGHT_BAKE_ENABLE, - //LIGHT_BAKE_LIGHTMAPS + LIGHT_BAKE_LIGHTMAPS }; void _replace_owner(Node *p_node, Node *p_scene, Node *p_new_owner); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 9b968c3523..362b8543d4 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -817,6 +817,9 @@ void ScriptTextEditor::_edit_option(int p_op) { if (tx->get_selection_to_column() == 0) end -= 1; + int col_to = tx->get_selection_to_column(); + int cursor_pos = tx->cursor_get_column(); + // Check if all lines in the selected block are commented bool is_commented = true; for (int i = begin; i <= end; i++) { @@ -839,19 +842,42 @@ void ScriptTextEditor::_edit_option(int p_op) { } tx->set_line(i, line_text); } + + // Adjust selection & cursor position. + int offset = is_commented ? -1 : 1; + int col_from = tx->get_selection_from_column() > 0 ? tx->get_selection_from_column() + offset : 0; + + if (is_commented && tx->cursor_get_column() == tx->get_line(tx->cursor_get_line()).length() + 1) + cursor_pos += 1; + + if (tx->get_selection_to_column() != 0 && col_to != tx->get_line(tx->get_selection_to_line()).length() + 1) + col_to += offset; + + if (tx->cursor_get_column() != 0) + cursor_pos += offset; + + tx->select(begin, col_from, tx->get_selection_to_line(), col_to); + tx->cursor_set_column(cursor_pos); + } else { int begin = tx->cursor_get_line(); String line_text = tx->get_line(begin); - if (line_text.begins_with(delimiter)) + int col = tx->cursor_get_column(); + if (line_text.begins_with(delimiter)) { line_text = line_text.substr(delimiter.length(), line_text.length()); - else + col -= 1; + } else { line_text = delimiter + line_text; + col += 1; + } + tx->set_line(begin, line_text); + tx->cursor_set_column(col); } tx->end_complex_operation(); tx->update(); - //tx->deselect(); + } break; case EDIT_COMPLETE: { diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index 3de2284cea..9988d82fb8 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -569,6 +569,10 @@ void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { int invalid_count = 0; for (int i = 0; i < p_paths.size(); i++) { Ref<Texture> t = Ref<Texture>(ResourceLoader::load(p_paths[i])); + + ERR_EXPLAIN("'" + p_paths[i] + "' is not a valid texture."); + ERR_CONTINUE(!t.is_valid()); + if (texture_map.has(t->get_rid())) { invalid_count++; } else { @@ -577,9 +581,13 @@ void TileSetEditor::_on_textures_added(const PoolStringArray &p_paths) { texture_list->set_item_metadata(texture_list->get_item_count() - 1, t->get_rid()); } } - update_texture_list_icon(); - texture_list->select(texture_list->get_item_count() - 1); - _on_texture_list_selected(texture_list->get_item_count() - 1); + + if (texture_list->get_item_count() > 0) { + update_texture_list_icon(); + texture_list->select(texture_list->get_item_count() - 1); + _on_texture_list_selected(texture_list->get_item_count() - 1); + } + if (invalid_count > 0) { err_dialog->set_text(vformat(TTR("%s file(s) were not added because was already on the list."), String::num(invalid_count, 0))); err_dialog->popup_centered(Size2(300, 60)); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index c611327a31..9ef6e4332c 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -132,7 +132,7 @@ void CustomPropertyEditor::_menu_option(int p_which) { emit_signal("variant_changed"); } else if (hint == PROPERTY_HINT_ENUM) { - v = p_which; + v = menu->get_item_metadata(p_which); emit_signal("variant_changed"); } } break; @@ -427,12 +427,14 @@ bool CustomPropertyEditor::edit(Object *p_owner, const String &p_name, Variant:: } else if (hint == PROPERTY_HINT_ENUM) { Vector<String> options = hint_text.split(","); + int current_val = 0; for (int i = 0; i < options.size(); i++) { - if (options[i].find(":") != -1) { - menu->add_item(options[i].get_slicec(':', 0), options[i].get_slicec(':', 1).to_int()); - } else { - menu->add_item(options[i], i); - } + Vector<String> text_split = options[i].split(":"); + if (text_split.size() != 1) + current_val = text_split[1].to_int(); + menu->add_item(text_split[0]); + menu->set_item_metadata(i, current_val); + current_val += 1; } menu->set_position(get_position()); menu->popup(); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 07670bb420..848e4def6d 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -73,7 +73,7 @@ void SceneTreeEditor::_cell_button_pressed(Object *p_item, int p_column, int p_i undo_redo->create_action(TTR("Toggle Visible")); _toggle_visible(n); List<Node *> selection = editor_selection->get_selected_node_list(); - if (selection.size() > 1) { + if (selection.size() > 1 && selection.find(n) != NULL) { for (List<Node *>::Element *E = selection.front(); E; E = E->next()) { Node *nv = E->get(); ERR_FAIL_COND(!nv); diff --git a/main/tests/test_oa_hash_map.cpp b/main/tests/test_oa_hash_map.cpp index 26e728d3aa..deaba285cf 100644 --- a/main/tests/test_oa_hash_map.cpp +++ b/main/tests/test_oa_hash_map.cpp @@ -92,6 +92,35 @@ MainLoop *test() { } } + // stress test / test for issue #22928 + { + OAHashMap<int, int> map; + int dummy; + const int N = 1000; + uint32_t *keys = new uint32_t[N]; + + Math::seed(0); + + // insert a couple of random keys (with a dummy value, which is ignored) + for (int i = 0; i < N; i++) { + keys[i] = Math::rand(); + map.set(keys[i], dummy); + + if (!map.lookup(keys[i], dummy)) + OS::get_singleton()->print("could not find 0x%X despite it was just inserted!\n", unsigned(keys[i])); + } + + // check whether the keys are still present + for (int i = 0; i < N; i++) { + if (!map.lookup(keys[i], dummy)) { + OS::get_singleton()->print("could not find 0x%X despite it has been inserted previously! (not checking the other keys, breaking...)\n", unsigned(keys[i])); + break; + } + } + + delete[] keys; + } + return NULL; } } // namespace TestOAHashMap diff --git a/main/tests/test_string.cpp b/main/tests/test_string.cpp index 74157d63c9..7e19c7bf3e 100644 --- a/main/tests/test_string.cpp +++ b/main/tests/test_string.cpp @@ -480,7 +480,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish % frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; //////// INTS @@ -491,7 +491,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int left padded with zeroes. format = "fish %05d frog"; @@ -500,7 +500,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 00005 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int left padded with spaces. format = "fish %5d frog"; @@ -509,7 +509,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int right padded with spaces. format = "fish %-5d frog"; @@ -518,7 +518,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int with sign (positive). format = "fish %+d frog"; @@ -527,7 +527,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish +5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Negative int. format = "fish %d frog"; @@ -536,7 +536,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish -5 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Hex (lower) format = "fish %x frog"; @@ -545,7 +545,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 2d frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Hex (upper) format = "fish %X frog"; @@ -554,7 +554,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 2D frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Octal format = "fish %o frog"; @@ -563,7 +563,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 143 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ////// REALS @@ -574,7 +574,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real left-padded format = "fish %11f frog"; @@ -583,7 +583,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real right-padded format = "fish %-11f frog"; @@ -592,7 +592,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real given int. format = "fish %f frog"; @@ -601,7 +601,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.000000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with sign (positive). format = "fish %+f frog"; @@ -610,7 +610,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish +99.990000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with 1 decimals. format = "fish %.1f frog"; @@ -619,7 +619,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 100.0 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with 12 decimals. format = "fish %.12f frog"; @@ -628,7 +628,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990000000000 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Real with no decimals. format = "fish %.f frog"; @@ -637,7 +637,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 100 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; /////// Strings. @@ -648,7 +648,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // String left-padded format = "fish %10s frog"; @@ -657,7 +657,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // String right-padded format = "fish %-10s frog"; @@ -666,7 +666,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Characters @@ -677,7 +677,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish A frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character as int. format = "fish %c frog"; @@ -686,7 +686,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish A frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Dynamic width @@ -698,7 +698,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish cheese frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Int dynamic width format = "fish %*d frog"; @@ -708,7 +708,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Float dynamic width format = "fish %*.*f frog"; @@ -719,7 +719,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == String("fish 99.990 frog") && !error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ///// Errors @@ -730,7 +730,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "not enough arguments for format string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // More arguments than formats. format = "fish %s frog"; @@ -740,7 +740,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "not all arguments converted during string formatting" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Incomplete format. format = "fish %10"; @@ -749,7 +749,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "incomplete format" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Bad character in format string format = "fish %&f frog"; @@ -758,7 +758,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "unsupported format character" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Too many decimals. format = "fish %2.2.2f frog"; @@ -767,7 +767,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "too many decimal points in format" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // * not a number format = "fish %*f frog"; @@ -777,7 +777,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "* wants number" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character too long. format = "fish %c frog"; @@ -786,7 +786,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "%c requires number or single-character string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; // Character bad type. format = "fish %c frog"; @@ -795,7 +795,7 @@ bool test_28() { output = format.sprintf(args, &error); success = (output == "%c requires number or single-character string" && error); OS::get_singleton()->print(output_format, format.c_str(), output.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; return state; } @@ -819,37 +819,127 @@ bool test_29() { String ip4 = "192.168.0.1"; bool success = ip4.is_valid_ip_address(); OS::get_singleton()->print("Is valid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip4 = "192.368.0.1"; success = (!ip4.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv4: %ls, %s\n", ip4.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; String ip6 = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"; success = ip6.is_valid_ip_address(); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8:85j3:0000:0000:8a2e:0370:7334"; success = (!ip6.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8:85f345:0000:0000:8a2e:0370:7334"; success = (!ip6.is_valid_ip_address()); OS::get_singleton()->print("Is invalid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "2001:0db8::0:8a2e:370:7334"; success = (ip6.is_valid_ip_address()); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; ip6 = "::ffff:192.168.0.1"; success = (ip6.is_valid_ip_address()); OS::get_singleton()->print("Is valid ipv6: %ls, %s\n", ip6.c_str(), success ? "OK" : "FAIL"); - if (!success) state = false; + state = state && success; + + return state; +}; + +bool test_30() { + bool state = true; + bool success = true; + String input = "bytes2var"; + String output = "Bytes 2 Var"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "linear2db"; + output = "Linear 2 Db"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "vector3"; + output = "Vector 3"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "sha256"; + output = "Sha 256"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "2db"; + output = "2 Db"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "PascalCase"; + output = "Pascal Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "PascalPascalCase"; + output = "Pascal Pascal Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case"; + output = "Snake Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_snake_case"; + output = "Snake Snake Case"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "sha256sum"; + output = "Sha 256 Sum"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "cat2dog"; + output = "Cat 2 Dog"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "function(name)"; + output = "Function(name)"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls (existing incorrect behavior): %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case_function(snake_case_arg)"; + output = "Snake Case Function(snake Case Arg)"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls (existing incorrect behavior): %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); + + input = "snake_case_function( snake_case_arg )"; + output = "Snake Case Function( Snake Case Arg )"; + success = (input.capitalize() == output); + state = state && success; + OS::get_singleton()->print("Capitalize %ls: %ls, %s\n", input.c_str(), output.c_str(), success ? "OK" : "FAIL"); return state; }; @@ -887,6 +977,7 @@ TestFunc test_funcs[] = { test_27, test_28, test_29, + test_30, 0 }; diff --git a/modules/bullet/bullet_utilities.h b/modules/bullet/bullet_utilities.h index 029eb6691a..553c1d0384 100644 --- a/modules/bullet/bullet_utilities.h +++ b/modules/bullet/bullet_utilities.h @@ -39,7 +39,8 @@ new cl #define bulletdelete(cl) \ - delete cl; \ - cl = NULL; - + { \ + delete cl; \ + cl = NULL; \ + } #endif diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index a3944b4f99..402a276f95 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -310,9 +310,10 @@ void RigidCollisionObjectBullet::shape_changed(int p_shape_index) { void RigidCollisionObjectBullet::reload_shapes() { - if (mainShape && mainShape->isCompound()) + if (mainShape && mainShape->isCompound()) { // Destroy compound bulletdelete(mainShape); + } mainShape = NULL; diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index c199667270..e4aee842ba 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -72,6 +72,7 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ bool in_word = false; bool in_function_name = false; bool in_variable_declaration = false; + bool in_function_args = false; bool in_member_variable = false; bool in_node_path = false; bool is_hex_notation = false; @@ -220,17 +221,24 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } if (is_symbol) { - in_function_name = false; - in_member_variable = false; - if (expect_type && str[j] != ' ' && str[j] != '\t' && str[j] != ':') { + if (in_function_name) { + in_function_args = true; + } + + if (in_function_args && str[j] == ')') { + in_function_args = false; + } + + if (expect_type && prev_is_char) { expect_type = false; } + if (j > 0 && str[j] == '>' && str[j - 1] == '-') { expect_type = true; } - if (in_variable_declaration || previous_text == "(" || previous_text == ",") { + if (in_variable_declaration || in_function_args) { int k = j; // Skip space while (k < str.length() && (str[k] == '\t' || str[k] == ' ')) { @@ -244,6 +252,8 @@ Map<int, TextEdit::HighlighterInfo> GDScriptSyntaxHighlighter::_get_line_syntax_ } in_variable_declaration = false; + in_function_name = false; + in_member_variable = false; } if (!in_node_path && in_region == -1 && str[j] == '$') { diff --git a/modules/gdscript/gdscript_tokenizer.cpp b/modules/gdscript/gdscript_tokenizer.cpp index 77e1b7290e..c37142b3c1 100644 --- a/modules/gdscript/gdscript_tokenizer.cpp +++ b/modules/gdscript/gdscript_tokenizer.cpp @@ -128,8 +128,8 @@ const char *GDScriptTokenizer::token_names[TK_MAX] = { "'.'", "'?'", "':'", - "'->'", "'$'", + "'->'", "'\\n'", "PI", "TAU", diff --git a/modules/mono/doc_classes/GodotSharp.xml b/modules/mono/doc_classes/GodotSharp.xml index 985c66464b..921c1ca825 100644 --- a/modules/mono/doc_classes/GodotSharp.xml +++ b/modules/mono/doc_classes/GodotSharp.xml @@ -23,18 +23,44 @@ Detaches the current thread from the mono runtime. </description> </method> - <method name="is_domain_loaded"> + <method name="get_domain_id"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="get_scripts_domain_id"> + <return type="int"> + </return> + <description> + </description> + </method> + <method name="is_domain_finalizing_for_unload"> + <return type="bool"> + </return> + <argument index="0" name="domain_id" type="int"> + </argument> + <description> + Returns whether the domain is being finalized. + </description> + </method> + <method name="is_runtime_initialized"> + <return type="bool"> + </return> + <description> + </description> + </method> + <method name="is_runtime_shutting_down"> <return type="bool"> </return> <description> - Returns whether the scripts domain is loaded. </description> </method> - <method name="is_finalizing_domain"> + <method name="is_scripts_domain_loaded"> <return type="bool"> </return> <description> - Returns whether the scripts domain is being finalized. + Returns whether the scripts domain is loaded. </description> </method> </methods> diff --git a/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs index 9f0d562ef7..5fd708d539 100644 --- a/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs +++ b/modules/mono/editor/GodotSharpTools/Editor/GodotSharpExport.cs @@ -41,9 +41,11 @@ namespace GodotSharpTools.Editor string outputDataDir = Path.Combine(outputDir, GetDataDirName()); - Directory.Delete(outputDataDir, recursive: true); // Clean first + if (Directory.Exists(outputDataDir)) + Directory.Delete(outputDataDir, recursive: true); // Clean first + Directory.CreateDirectory(outputDataDir); - + foreach (string dir in Directory.GetDirectories(templateDirPath, "*", SearchOption.AllDirectories)) { Directory.CreateDirectory(Path.Combine(outputDataDir, dir.Substring(templateDirPath.Length + 1))); diff --git a/modules/opensimplex/doc_classes/NoiseTexture.xml b/modules/opensimplex/doc_classes/NoiseTexture.xml index 9642865c43..d88abb3180 100644 --- a/modules/opensimplex/doc_classes/NoiseTexture.xml +++ b/modules/opensimplex/doc_classes/NoiseTexture.xml @@ -12,24 +12,6 @@ <demos> </demos> <methods> - <method name="set_height"> - <return type="void"> - </return> - <argument index="0" name="height" type="int"> - </argument> - <description> - Set texture height. - </description> - </method> - <method name="set_width"> - <return type="void"> - </return> - <argument index="0" name="width" type="int"> - </argument> - <description> - Set texture width. - </description> - </method> </methods> <members> <member name="as_normalmap" type="bool" setter="set_as_normalmap" getter="is_normalmap"> diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index ff97c21fd9..52a30baaec 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -48,20 +48,22 @@ bool VisualScriptNode::is_breakpoint() const { void VisualScriptNode::_notification(int p_what) { if (p_what == NOTIFICATION_POSTINITIALIZE) { - - int dvc = get_input_value_port_count(); - for (int i = 0; i < dvc; i++) { - Variant::Type expected = get_input_value_port_info(i).type; - Variant::CallError ce; - default_input_values.push_back(Variant::construct(expected, NULL, 0, ce, false)); - } + _update_input_ports(); } } -void VisualScriptNode::ports_changed_notify() { - +void VisualScriptNode::_update_input_ports() { default_input_values.resize(MAX(default_input_values.size(), get_input_value_port_count())); //let it grow as big as possible, we don't want to lose values on resize + int port_count = get_input_value_port_count(); + for (int i = 0; i < port_count; i++) { + Variant::Type expected = get_input_value_port_info(i).type; + Variant::CallError ce; + set_default_input_value(i, Variant::construct(expected, NULL, 0, ce, false)); + } +} +void VisualScriptNode::ports_changed_notify() { + _update_input_ports(); emit_signal("ports_changed"); } diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index ea99ce4970..bd666447a3 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -52,6 +52,7 @@ class VisualScriptNode : public Resource { Array _get_default_input_values() const; void validate_input_default_values(); + void _update_input_ports(); protected: void _notification(int p_what); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index 25cd4ab54e..7fdd7fe446 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -1940,7 +1940,7 @@ void VisualScriptEditor::_draw_color_over_button(Object *obj, Color p_color) { button->draw_rect(Rect2(normal->get_offset(), button->get_size() - normal->get_minimum_size()), p_color); } -void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud) { +void VisualScriptEditor::_button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud) { Array ud = p_ud; ERR_FAIL_COND(ud.size() != 2); diff --git a/modules/visual_script/visual_script_editor.h b/modules/visual_script/visual_script_editor.h index fb90e346a4..97c75dae94 100644 --- a/modules/visual_script/visual_script_editor.h +++ b/modules/visual_script/visual_script_editor.h @@ -237,7 +237,7 @@ class VisualScriptEditor : public ScriptEditorBase { void _selected_method(const String &p_method, const String &p_type); void _draw_color_over_button(Object *obj, Color p_color); - void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, Variant p_ud); + void _button_resource_previewed(const String &p_path, const Ref<Texture> &p_preview, const Ref<Texture> &p_small_preview, Variant p_ud); VisualScriptNode::TypeGuess _guess_output_type(int p_port_action_node, int p_port_action_output, Set<int> &visited_nodes); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index 865f93a148..99748af8a1 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -3708,18 +3708,18 @@ void register_visual_script_nodes() { for (List<MethodInfo>::Element *E = constructors.front(); E; E = E->next()) { if (E->get().arguments.size() > 0) { - - String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + " ( "; + String name = "functions/constructors/" + Variant::get_type_name(Variant::Type(i)) + "("; for (int j = 0; j < E->get().arguments.size(); j++) { - if (j > 0) + if (j > 0) { name += ", "; - if (E->get().arguments.size() == 1) + } + if (E->get().arguments.size() == 1) { name += Variant::get_type_name(E->get().arguments[j].type); - else + } else { name += E->get().arguments[j].name; + } } - name += ") "; - + name += ")"; VisualScriptLanguage::singleton->add_register_func(name, create_constructor_node); Pair<Variant::Type, MethodInfo> pair; pair.first = Variant::Type(i); diff --git a/modules/visual_script/visual_script_property_selector.cpp b/modules/visual_script/visual_script_property_selector.cpp index d3637939c9..e5d12cb495 100644 --- a/modules/visual_script/visual_script_property_selector.cpp +++ b/modules/visual_script/visual_script_property_selector.cpp @@ -304,31 +304,36 @@ void VisualScriptPropertySelector::_update_search() { continue; MethodInfo mi = E->get(); - String desc = mi.name.capitalize() + " ("; + String desc_arguments; + if (mi.arguments.size() > 0) { + desc_arguments = "("; + for (int i = 0; i < mi.arguments.size(); i++) { + + if (i > 0) { + desc_arguments += ", "; + } + if (mi.arguments[i].type == Variant::NIL) { + desc_arguments += "var"; + } else if (mi.arguments[i].name.find(":") != -1) { + desc_arguments += mi.arguments[i].name.get_slice(":", 1); + mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); + } else { + desc_arguments += Variant::get_type_name(mi.arguments[i].type); + } + } + desc_arguments += ")"; + } + String desc_raw = mi.name + desc_arguments; + String desc = desc_raw.capitalize().replace("( ", "("); if (search_box->get_text() != String() && name.findn(search_box->get_text()) == -1 && - desc.findn(search_box->get_text()) == -1) + desc.findn(search_box->get_text()) == -1 && + desc_raw.findn(search_box->get_text()) == -1) { continue; - - TreeItem *item = search_options->create_item(category ? category : root); - - for (int i = 0; i < mi.arguments.size(); i++) { - - if (i > 0) - desc += ", "; - - if (mi.arguments[i].type == Variant::NIL) - desc += "var"; - else if (mi.arguments[i].name.find(":") != -1) { - desc += mi.arguments[i].name.get_slice(":", 1); - mi.arguments[i].name = mi.arguments[i].name.get_slice(":", 0); - } else - desc += Variant::get_type_name(mi.arguments[i].type); } - desc += ")"; - + TreeItem *item = search_options->create_item(category ? category : root); item->set_text(0, desc); item->set_icon(0, get_icon("MemberMethod", "EditorIcons")); item->set_metadata(0, name); @@ -414,11 +419,16 @@ void VisualScriptPropertySelector::get_visual_node_names(const String &root_filt String basic_type = Variant::get_type_name(vnode_function_call->get_basic_type()); type_name = basic_type.capitalize() + " "; } - VisualScriptBuiltinFunc *vnode_builtin_function_call = Object::cast_to<VisualScriptBuiltinFunc>(*VisualScriptLanguage::singleton->create_node_from_name(E->get())); - if (vnode_builtin_function_call != NULL) { - type_name = "Builtin "; + + Vector<String> desc = path[path.size() - 1].replace("(", "( ").replace(")", " )").replace(",", ", ").split(" "); + for (size_t i = 0; i < desc.size(); i++) { + desc.write[i] = desc[i].capitalize(); + if (desc[i].ends_with(",")) { + desc.write[i] = desc[i].replace(",", ", "); + } } - item->set_text(0, type_name + path[path.size() - 1].capitalize()); + + item->set_text(0, type_name + String("").join(desc)); item->set_icon(0, get_icon("VisualScript", "EditorIcons")); item->set_selectable(0, true); item->set_metadata(0, E->get()); diff --git a/modules/websocket/lws_client.cpp b/modules/websocket/lws_client.cpp index cd814760e6..b3e5f6ffab 100644 --- a/modules/websocket/lws_client.cpp +++ b/modules/websocket/lws_client.cpp @@ -80,9 +80,12 @@ Error LWSClient::connect_to_host(String p_host, String p_path, uint16_t p_port, char hbuf[1024]; char pbuf[2048]; String addr_str = (String)addr; - strncpy(abuf, addr_str.ascii().get_data(), 1024); - strncpy(hbuf, p_host.utf8().get_data(), 1024); - strncpy(pbuf, p_path.utf8().get_data(), 2048); + strncpy(abuf, addr_str.ascii().get_data(), 1023); + abuf[1023] = '\0'; + strncpy(hbuf, p_host.utf8().get_data(), 1023); + hbuf[1023] = '\0'; + strncpy(pbuf, p_path.utf8().get_data(), 2047); + pbuf[2047] = '\0'; i.context = context; if (p_protocols.size() > 0) diff --git a/platform/android/build.gradle.template b/platform/android/build.gradle.template index cc45fee95f..1603ea70d9 100644 --- a/platform/android/build.gradle.template +++ b/platform/android/build.gradle.template @@ -1,10 +1,11 @@ buildscript { repositories { + google() jcenter() $$GRADLE_REPOSITORY_URLS$$ } dependencies { - classpath 'com.android.tools.build:gradle:2.3.3' + classpath 'com.android.tools.build:gradle:3.2.0' $$GRADLE_CLASSPATH$$ } } @@ -32,7 +33,7 @@ android { } compileSdkVersion 27 - buildToolsVersion "27.0.3" + buildToolsVersion "28.0.3" useLibrary 'org.apache.http.legacy' packagingOptions { @@ -75,9 +76,11 @@ android { $$GRADLE_JNI_DIRS$$ ] } + applicationVariants.all { variant -> - // ApplicationVariant is undocumented, but this method is widely used; may break with another version of the Android Gradle plugin - variant.outputs.get(0).setOutputFile(new File("${projectDir}/../../../bin", "android_${variant.name}.apk")) + variant.outputs.all { output -> + output.outputFileName = "../../../../../../../bin/android_${variant.name}.apk" + } } } diff --git a/platform/android/java/gradle/wrapper/gradle-wrapper.properties b/platform/android/java/gradle/wrapper/gradle-wrapper.properties index fe37fa74a9..6fb3a79546 100644 --- a/platform/android/java/gradle/wrapper/gradle-wrapper.properties +++ b/platform/android/java/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip diff --git a/platform/android/java_glue.cpp b/platform/android/java_glue.cpp index ad8f21785d..07e4048c12 100644 --- a/platform/android/java_glue.cpp +++ b/platform/android/java_glue.cpp @@ -883,6 +883,8 @@ static void _initialize_java_modules() { ERR_EXPLAIN("Couldn't find proper initialize function 'public static Godot.SingletonBase Class::initialize(Activity p_activity)' initializer for singleton class: " + m); ERR_CONTINUE(!initialize); } + jobject obj = env->CallStaticObjectMethod(singletonClass, initialize, _godot_instance); + env->NewGlobalRef(obj); } } } diff --git a/platform/x11/godot_x11.cpp b/platform/x11/godot_x11.cpp index 3241cbcbf9..21148f8e86 100644 --- a/platform/x11/godot_x11.cpp +++ b/platform/x11/godot_x11.cpp @@ -43,7 +43,7 @@ int main(int argc, char *argv[]) { setlocale(LC_CTYPE, ""); char *cwd = (char *)malloc(PATH_MAX); - getcwd(cwd, PATH_MAX); + char *ret = getcwd(cwd, PATH_MAX); Error err = Main::setup(argv[0], argc - 1, &argv[1]); if (err != OK) { @@ -55,7 +55,8 @@ int main(int argc, char *argv[]) { os.run(); // it is actually the OS that decides how to run Main::cleanup(); - chdir(cwd); + if (ret) + chdir(cwd); free(cwd); return os.get_exit_code(); diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index a1ae05d971..9de72a4fcd 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -179,7 +179,7 @@ void AudioStreamPlayer2D::_notification(int p_what) { Physics2DDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; - int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask); + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, false, true); for (int i = 0; i < areas; i++) { diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index d29c6b37d5..e6dcd643be 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -985,7 +985,7 @@ void CPUParticles2D::_notification(int p_what) { if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - if (particles.size() == 0) + if (particles.size() == 0 || !is_visible_in_tree()) return; float delta = get_process_delta_time(); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index abf022ecb3..7ad43b722d 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -290,7 +290,7 @@ void AudioStreamPlayer3D::_notification(int p_what) { PhysicsDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; - int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask); + int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set<RID>(), area_mask, false, true); Area *area = NULL; for (int i = 0; i < areas; i++) { diff --git a/scene/3d/cpu_particles.cpp b/scene/3d/cpu_particles.cpp index ec51c31674..35a2049bda 100644 --- a/scene/3d/cpu_particles.cpp +++ b/scene/3d/cpu_particles.cpp @@ -592,7 +592,7 @@ void CPUParticles::_particles_process(float p_delta) { Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad)); Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad)); - direction_yz.z = direction_yz.z / Math::sqrt(direction_yz.z); //better uniform distribution + direction_yz.z = direction_yz.z / MAX(0.0001, Math::sqrt(ABS(direction_yz.z))); //better uniform distribution Vector3 direction = Vector3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z); direction.normalize(); p.velocity = direction * parameters[PARAM_INITIAL_LINEAR_VELOCITY] * Math::lerp(1.0f, float(Math::randf()), randomness[PARAM_INITIAL_LINEAR_VELOCITY]); @@ -977,6 +977,8 @@ void CPUParticles::_update_particle_data_buffer() { ptr += 17; } + + can_update = true; } #ifndef NO_THREADS @@ -989,8 +991,10 @@ void CPUParticles::_update_render_thread() { #ifndef NO_THREADS update_mutex->lock(); #endif - - VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data); + if (can_update) { + VS::get_singleton()->multimesh_set_as_bulk_array(multimesh, particle_data); + can_update = false; //wait for next time + } #ifndef NO_THREADS update_mutex->unlock(); @@ -1032,7 +1036,7 @@ void CPUParticles::_notification(int p_what) { if (p_what == NOTIFICATION_INTERNAL_PROCESS) { - if (particles.size() == 0) + if (particles.size() == 0 || !is_visible_in_tree()) return; float delta = get_process_delta_time(); @@ -1061,6 +1065,8 @@ void CPUParticles::_notification(int p_what) { } } + bool processed = false; + if (time == 0 && pre_process_time > 0.0) { float frame_time; @@ -1073,6 +1079,7 @@ void CPUParticles::_notification(int p_what) { while (todo >= 0) { _particles_process(frame_time); + processed = true; todo -= frame_time; } } @@ -1091,6 +1098,7 @@ void CPUParticles::_notification(int p_what) { while (todo >= frame_time) { _particles_process(frame_time); + processed = true; todo -= decr; } @@ -1098,9 +1106,12 @@ void CPUParticles::_notification(int p_what) { } else { _particles_process(delta); + processed = true; } - _update_particle_data_buffer(); + if (processed) { + _update_particle_data_buffer(); + } } } @@ -1424,6 +1435,8 @@ CPUParticles::CPUParticles() { flags[i] = false; } + can_update = false; + set_color(Color(1, 1, 1, 1)); #ifndef NO_THREADS diff --git a/scene/3d/cpu_particles.h b/scene/3d/cpu_particles.h index 4e29d8d4ce..77a144b70b 100644 --- a/scene/3d/cpu_particles.h +++ b/scene/3d/cpu_particles.h @@ -142,6 +142,8 @@ private: int fixed_fps; bool fractional_delta; + volatile bool can_update; + DrawOrder draw_order; Ref<Mesh> mesh; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index effcd0abee..e155d0ef86 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -769,7 +769,7 @@ void Control::force_drag(const Variant &p_data, Control *p_control) { void Control::set_drag_preview(Control *p_control) { ERR_FAIL_COND(!is_inside_tree()); - ERR_FAIL_COND(get_viewport()->gui_is_dragging()); + ERR_FAIL_COND(!get_viewport()->gui_is_dragging()); get_viewport()->_gui_set_drag_preview(this, p_control); } diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 32580a5ae6..f8a5c4cea3 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -2331,9 +2331,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) { // no need to indent if we are going upwards. if (auto_indent && !(k->get_command() && k->get_shift())) { - // indent once again if previous line will end with ':' or '{' + // indent once again if previous line will end with ':' or '{' and the line is not a comment // (i.e. colon/brace precedes current cursor position) - if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{')) { + if (cursor.column > 0 && (text[cursor.line][cursor.column - 1] == ':' || text[cursor.line][cursor.column - 1] == '{') && !is_line_comment(cursor.line)) { if (indent_using_spaces) { ins += space_indent; } else { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 3a540d187b..0c11181f98 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -2183,6 +2183,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { Ref<InputEventKey> k = p_event; + bool is_command = k.is_valid() && k->get_command(); if (p_event->is_action("ui_right") && p_event->is_pressed()) { if (!cursor_can_exit_tree) accept_event(); @@ -2219,13 +2220,13 @@ void Tree::_gui_input(Ref<InputEvent> p_event) { _go_left(); } - } else if (p_event->is_action("ui_up") && p_event->is_pressed() && !k->get_command()) { + } else if (p_event->is_action("ui_up") && p_event->is_pressed() && !is_command) { if (!cursor_can_exit_tree) accept_event(); _go_up(); - } else if (p_event->is_action("ui_down") && p_event->is_pressed() && !k->get_command()) { + } else if (p_event->is_action("ui_down") && p_event->is_pressed() && !is_command) { if (!cursor_can_exit_tree) accept_event(); @@ -2933,7 +2934,7 @@ void Tree::_notification(int p_what) { if (show_column_titles) { - //title butons + //title buttons int ofs = cache.bg->get_margin(MARGIN_LEFT); for (int i = 0; i < columns.size(); i++) { diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index 6f67ba8af1..ba48982fda 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -308,7 +308,7 @@ void ParticlesMaterial::_update_shader() { code += " float angle2_rad = rand_from_seed_m1_p1(alt_seed) * spread_rad * (1.0 - flatness);\n"; code += " vec3 direction_xz = vec3(sin(angle1_rad), 0, cos(angle1_rad));\n"; code += " vec3 direction_yz = vec3(0, sin(angle2_rad), cos(angle2_rad));\n"; - code += " direction_yz.z = direction_yz.z / sqrt(direction_yz.z); // better uniform distribution\n"; + code += " direction_yz.z = direction_yz.z / max(0.0001,sqrt(abs(direction_yz.z))); // better uniform distribution\n"; code += " vec3 direction = vec3(direction_xz.x * direction_yz.z, direction_yz.y, direction_xz.z * direction_yz.z);\n"; code += " direction = normalize(direction);\n"; code += " VELOCITY = direction * initial_linear_velocity * mix(1.0, rand_from_seed(alt_seed), initial_linear_velocity_random);\n"; diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index fead2f54da..d36057b465 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -1297,6 +1297,7 @@ void AudioServer::_bind_methods() { ADD_SIGNAL(MethodInfo("bus_layout_changed")); BIND_ENUM_CONSTANT(SPEAKER_MODE_STEREO); + BIND_ENUM_CONSTANT(SPEAKER_SURROUND_31); BIND_ENUM_CONSTANT(SPEAKER_SURROUND_51); BIND_ENUM_CONSTANT(SPEAKER_SURROUND_71); } diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp index 2f2f6d2908..86ef719f6f 100644 --- a/servers/physics/collision_solver_sw.cpp +++ b/servers/physics/collision_solver_sw.cpp @@ -31,7 +31,6 @@ #include "collision_solver_sw.h" #include "collision_solver_sat.h" -#include "collision_solver_sat.h" #include "gjk_epa.h" #define collision_solver sat_calculate_penetration diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp index 57e8d86468..69acf52e17 100644 --- a/servers/visual/shader_types.cpp +++ b/servers/visual/shader_types.cpp @@ -109,6 +109,7 @@ ShaderTypes::ShaderTypes() { shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA_SCISSOR"] = ShaderLanguage::TYPE_FLOAT; |