diff options
30 files changed, 497 insertions, 148 deletions
diff --git a/core/io/resource_loader.cpp b/core/io/resource_loader.cpp index 285cc6e3c2..9b89fa3399 100644 --- a/core/io/resource_loader.cpp +++ b/core/io/resource_loader.cpp @@ -430,6 +430,9 @@ void ResourceLoader::reload_translation_remaps() { void ResourceLoader::load_translation_remaps() { + if (!ProjectSettings::get_singleton()->has("locale/translation_remaps")) + return; + Dictionary remaps = ProjectSettings::get_singleton()->get("locale/translation_remaps"); List<Variant> keys; remaps.get_key_list(&keys); diff --git a/core/os/file_access.cpp b/core/os/file_access.cpp index 2bb676381f..7f5a84843c 100644 --- a/core/os/file_access.cpp +++ b/core/os/file_access.cpp @@ -300,6 +300,8 @@ Vector<String> FileAccess::get_csv_line(String delim) const { String l; int qc = 0; do { + ERR_FAIL_COND_V(eof_reached(), Vector<String>()); + l += get_line() + "\n"; qc = 0; for (int i = 0; i < l.length(); i++) { diff --git a/core/os/os.cpp b/core/os/os.cpp index 5a9766891d..8e4c357195 100644 --- a/core/os/os.cpp +++ b/core/os/os.cpp @@ -512,7 +512,13 @@ bool OS::check_feature_support(const String &p_feature) { return false; } +void *OS::get_stack_bottom() const { + return _stack_bottom; +} + OS::OS() { + void *volatile stack_bottom; + last_error = NULL; singleton = this; _keep_screen_on = true; // set default value to true, because this had been true before godot 2.0. @@ -525,6 +531,7 @@ OS::OS() { _render_thread_mode = RENDER_THREAD_SAFE; _allow_hidpi = true; + _stack_bottom = (void *)(&stack_bottom); } OS::~OS() { diff --git a/core/os/os.h b/core/os/os.h index 362fec8a9e..957c1d0ba7 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -60,6 +60,8 @@ class OS { char *last_error; + void *_stack_bottom; + public: enum RenderThreadMode { @@ -411,6 +413,13 @@ public: bool check_feature_support(const String &p_feature); + /** + * Returns the stack bottom of the main thread of the application. + * This may be of use when integrating languages with garbage collectors that + * need to check whether a pointer is on the stack. + */ + virtual void *get_stack_bottom() const; + bool is_hidpi_allowed() const { return _allow_hidpi; } OS(); virtual ~OS(); diff --git a/core/project_settings.cpp b/core/project_settings.cpp index 1a0a50a10f..0426af3fa0 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -602,7 +602,8 @@ Error ProjectSettings::_save_settings_text(const String &p_file, const Map<Strin file->store_string("config_version=" + itos(FORMAT_VERSION) + "\n"); if (p_custom_features != String()) - file->store_string("_custom_featores=\"" + p_custom_features + "\"\n"); + file->store_string("custom_features=\"" + p_custom_features + "\"\n"); + file->store_string("\n"); for (Map<String, List<String> >::Element *E = props.front(); E; E = E->next()) { diff --git a/core/reference.cpp b/core/reference.cpp index c55f8a7fe3..060608eacb 100644 --- a/core/reference.cpp +++ b/core/reference.cpp @@ -74,7 +74,8 @@ bool Reference::unreference() { bool die = refcount.unref(); if (get_script_instance()) { - die = die && get_script_instance()->refcount_decremented(); + bool script_ret = get_script_instance()->refcount_decremented(); + die = die && script_ret; } return die; diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index a7b6f25590..dec41e7976 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -74,7 +74,7 @@ Error ScriptDebuggerRemote::connect_to_host(const String &p_host, uint16_t p_por } else { OS::get_singleton()->delay_usec(1000000); - print_line("Remote Debugger: Connection failed with status: " + String::num(tcp_client->get_status()) + "'', retrying in 1 sec."); + print_line("Remote Debugger: Connection failed with status: '" + String::num(tcp_client->get_status()) + "', retrying in 1 sec."); }; }; diff --git a/core/variant_parser.cpp b/core/variant_parser.cpp index 26a6a05a30..398f20caf3 100644 --- a/core/variant_parser.cpp +++ b/core/variant_parser.cpp @@ -1099,7 +1099,7 @@ Error VariantParser::parse_value(Token &token, Variant &value, Stream *p_stream, return OK; - } else if (id == "PoolFloatArray" || id == "FloatArray") { + } else if (id == "PoolRealArray" || id == "FloatArray") { Vector<float> args; Error err = _parse_construct<float>(p_stream, args, line, r_err_str); @@ -1855,7 +1855,7 @@ Error VariantWriter::write(const Variant &p_variant, StoreStringFunc p_store_str } break; case Variant::POOL_REAL_ARRAY: { - p_store_string_func(p_store_string_ud, "PoolFloatArray( "); + p_store_string_func(p_store_string_ud, "PoolRealArray( "); PoolVector<real_t> data = p_variant; int len = data.size(); PoolVector<real_t>::Read r = data.read(); diff --git a/doc/base/classes.xml b/doc/base/classes.xml index e345238fc4..4b2f3336cd 100644 --- a/doc/base/classes.xml +++ b/doc/base/classes.xml @@ -39,7 +39,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Remove sign (works for integer and float). + Returns the absolute value of parameter s (i.e. unsigned value, works for integer and float). </description> </method> <method name="acos"> @@ -48,7 +48,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Arc-cosine. + Returns the principal value of the arc cosine of s, expressed in radians. In trigonometrics, arc cosine is the inverse operation of cosine. </description> </method> <method name="asin"> @@ -57,7 +57,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Arc-sine. + Returns the principal value of the arc sine of s, expressed in radians. In trigonometrics, arc sine is the inverse operation of sine. </description> </method> <method name="assert"> @@ -75,7 +75,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Arc-tangent. + Returns the principal value of the arc tangent of s, expressed in radians. In trigonometrics, arc tangent is the inverse operation of tangent. Notice that because of the sign ambiguity, the function cannot determine with certainty in which quadrant the angle falls only by its tangent value. See [method atan2] for an alternative that takes a fractional argument instead. </description> </method> <method name="atan2"> @@ -86,7 +86,7 @@ <argument index="1" name="y" type="float"> </argument> <description> - Arc-tangent that takes a 2D vector as argument, returns the full -pi to +pi range. + Returns the principal value of the arc tangent of y/x, expressed in radians. To compute the value, the function takes into account the sign of both arguments in order to determine the quadrant. </description> </method> <method name="bytes2var"> @@ -104,7 +104,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Ceiling (rounds up to nearest integer). + Rounds s upward, returning the smallest integral value that is not less than s. </description> </method> <method name="char"> @@ -125,7 +125,7 @@ <argument index="2" name="max" type="float"> </argument> <description> - Clamp both values to a range. + Clamps a value between a minimum and maximum value. </description> </method> <method name="convert"> @@ -145,7 +145,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Standard cosine function. + Returns the cosine of an angle of s radians. </description> </method> <method name="cosh"> @@ -154,7 +154,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Hyperbolic cosine. + Returns the hyperbolic cosine of s. </description> </method> <method name="db2linear"> @@ -223,7 +223,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Exponential logarithm. + Returns the base-e exponential function of s, which is e raised to the power s: e^s. </description> </method> <method name="floor"> @@ -232,7 +232,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Floor (rounds down to nearest integer). + Rounds s downward, returning the largest integral value that is not greater than s. </description> </method> <method name="fmod"> @@ -243,7 +243,11 @@ <argument index="1" name="y" type="float"> </argument> <description> - Module (remainder of x/y). + Returns the floating-point remainder of x/y (rounded towards zero): + [codeblock] + fmod = x - tquot * y + [/codeblock] + Where tquot is the truncated (i.e., rounded towards zero) result of: x/y. </description> </method> <method name="fposmod"> @@ -301,6 +305,7 @@ <argument index="0" name="s" type="float"> </argument> <description> + Returns whether s is an infinity value (either positive infinity or negative infinity). </description> </method> <method name="is_nan"> @@ -309,6 +314,7 @@ <argument index="0" name="s" type="float"> </argument> <description> + Returns whether s is a NaN (Not-A-Number) value. </description> </method> <method name="lerp"> @@ -539,7 +545,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Round to nearest integer. + Returns the integral value that is nearest to s, with halfway cases rounded away from zero. </description> </method> <method name="seed"> @@ -566,7 +572,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Standard sine function. + Returns the sine of an angle of s radians. </description> </method> <method name="sinh"> @@ -575,7 +581,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Hyperbolic sine. + Returns the hyperbolic sine of s. </description> </method> <method name="sqrt"> @@ -584,7 +590,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Square root. + Returns the square root of s. </description> </method> <method name="stepify"> @@ -606,7 +612,7 @@ <argument index="1" name="..." type="Variant"> </argument> <description> - Convert one or more arguments to strings in the best way possible. + Convert one or more arguments to string in the best way possible. </description> </method> <method name="str2var"> @@ -624,7 +630,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Standard tangent function. + Returns the tangent of an angle of s radians. </description> </method> <method name="tanh"> @@ -633,7 +639,7 @@ <argument index="0" name="s" type="float"> </argument> <description> - Hyperbolic tangent. + Returns the hyperbolic tangent of s. </description> </method> <method name="to_json"> @@ -668,6 +674,7 @@ <argument index="0" name="json" type="String"> </argument> <description> + This method is used to validate the structure and data types of a piece of JSON, similar to XML Schema for XML. </description> </method> <method name="var2bytes"> @@ -695,6 +702,7 @@ </argument> <description> Return a weak reference to an object. + A weak reference to an object is not enough to keep the object alive: when the only remaining references to a referent are weak references, garbage collection is free to destroy the referent and reuse its memory for something else. However, until the object is actually destroyed the weak reference may return the object even if there are no strong references to it. </description> </method> <method name="yield"> @@ -715,8 +723,11 @@ Constant that represents how many times the diameter of a circumference fits around its perimeter. </constant> <constant name="INF" value="inf"> + A positive infinity. (For negative infinity, use -INF). </constant> <constant name="NAN" value="nan"> + Macro constant that expands to an expression of type float that represents a NaN. + The NaN values are used to identify undefined or non-representable values for floating-point elements, such as the square root of negative numbers or the result of 0/0. </constant> </constants> </class> @@ -1960,8 +1971,11 @@ </class> <class name="AStar" inherits="Reference" category="Core"> <brief_description> + AStar class representation that uses vectors as edges. </brief_description> <description> + A* (A star) is a computer algorithm that is widely used in pathfinding and graph traversal, the process of plotting an efficiently directed path between multiple points. It enjoys widespread use due to its performance and accuracy. Godot's A* implementation make use of vectors as points. + You must add points manually with [method AStar.add_point] and create segments manually with [method AStar.connect_points]. So you can test if there is a path between two points with the [method AStar.are_points_connected] function, get the list of existing ids in the found path with [method AStar.get_id_path], or the points list with [method AStar.get_point_path]. </description> <methods> <method name="_compute_cost" qualifiers="virtual"> @@ -1988,7 +2002,7 @@ <argument index="2" name="weight_scale" type="float" default="1"> </argument> <description> - Add a new point at the given position. The [code]weight_scale[/code] has to be 1 or larger. + Add a new point at the given position [code]pos[/code] with the given identifier [code]id[/code]. The [code]weight_scale[/code] has to be 1 or larger. </description> </method> <method name="are_points_connected" qualifiers="const"> @@ -1999,10 +2013,12 @@ <argument index="1" name="to_id" type="int"> </argument> <description> + Returns if there is a connection/segment between points [code]id[/code] and [code]from_id[/code] </description> </method> <method name="clear"> <description> + Clear all the points and segments from AStar instance. </description> </method> <method name="connect_points"> @@ -2013,6 +2029,7 @@ <argument index="2" name="bidirectional" type="bool" default="true"> </argument> <description> + Create a segment between points [code]id[/code] and [code]to_id[/code]. </description> </method> <method name="disconnect_points"> @@ -2021,6 +2038,7 @@ <argument index="1" name="to_id" type="int"> </argument> <description> + Deletes a segment between points [code]id[/code] and [code]to_id[/code]. </description> </method> <method name="get_available_point_id" qualifiers="const"> @@ -2035,6 +2053,7 @@ <argument index="0" name="to_pos" type="Vector3"> </argument> <description> + Returns the id of closest point of given point. -1 is returned if there are no points on AStar. </description> </method> <method name="get_closest_pos_in_segment" qualifiers="const"> @@ -2043,6 +2062,7 @@ <argument index="0" name="to_pos" type="Vector3"> </argument> <description> + Returns the position of closest point that has segments. </description> </method> <method name="get_id_path"> @@ -2053,6 +2073,7 @@ <argument index="1" name="to_id" type="int"> </argument> <description> + Returns an array with the point ids of path found by AStar between two given points. </description> </method> <method name="get_point_path"> @@ -2063,6 +2084,7 @@ <argument index="1" name="to_id" type="int"> </argument> <description> + Returns an array with the points of path found by AStar between two given points. </description> </method> <method name="get_point_pos" qualifiers="const"> @@ -2071,6 +2093,7 @@ <argument index="0" name="id" type="int"> </argument> <description> + Returns the position of point with given id. </description> </method> <method name="get_point_weight_scale" qualifiers="const"> @@ -2079,6 +2102,7 @@ <argument index="0" name="id" type="int"> </argument> <description> + Returns the weight scale of point with given id. </description> </method> <method name="has_point" qualifiers="const"> @@ -2087,12 +2111,14 @@ <argument index="0" name="id" type="int"> </argument> <description> + Returns if the point with given id exists on AStar; </description> </method> <method name="remove_point"> <argument index="0" name="id" type="int"> </argument> <description> + Removes the point with given id. </description> </method> </methods> @@ -10743,17 +10769,17 @@ </theme_item> <theme_item name="color_sample" type="Texture"> </theme_item> - <theme_item name="color_width" type="int"> - </theme_item> - <theme_item name="hseparator" type="int"> + <theme_item name="h_width" type="int"> </theme_item> <theme_item name="label_width" type="int"> </theme_item> + <theme_item name="margin" type="int"> + </theme_item> <theme_item name="screen_picker" type="Texture"> </theme_item> - <theme_item name="value_height" type="int"> + <theme_item name="sv_height" type="int"> </theme_item> - <theme_item name="value_width" type="int"> + <theme_item name="sv_width" type="int"> </theme_item> </theme_items> </class> @@ -14036,7 +14062,7 @@ <description> Add a custom type, which will appear in the list of nodes or resources. An icon can be optionally passed. When given node or resource is selected, the base type will be instanced (ie, "Spatial", "Control", "Resource"), then the script will be loaded and set to this object. - You can use the [method EditorPlugin.handles] to check if your custom object is being edited by checking the script or using 'extends' keyword. + You can use the [method EditorPlugin.handles] to check if your custom object is being edited by checking the script or using 'is' keyword. During run-time, this will be a simple object with a script so this function does not need to be called then. </description> </method> @@ -16307,6 +16333,8 @@ <constant name="COMPRESSION_ZSTD" value="2"> Use the Zstd compression method. </constant> + <constant name="COMPRESSION_GZIP" value="3"> + </constant> </constants> </class> <class name="FileDialog" inherits="ConfirmationDialog" category="Core"> @@ -16815,6 +16843,12 @@ <description> </description> </method> + <method name="get_normal_bias" qualifiers="const"> + <return type="float"> + </return> + <description> + </description> + </method> <method name="get_probe_data" qualifiers="const"> <return type="Object"> </return> @@ -16881,6 +16915,12 @@ <description> </description> </method> + <method name="set_normal_bias"> + <argument index="0" name="max" type="float"> + </argument> + <description> + </description> + </method> <method name="set_probe_data"> <argument index="0" name="data" type="Object"> </argument> @@ -16915,6 +16955,8 @@ </member> <member name="interior" type="bool" setter="set_interior" getter="is_interior" brief=""> </member> + <member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" brief=""> + </member> <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" brief=""> </member> <member name="subdiv" type="int" setter="set_subdiv" getter="get_subdiv" brief=""> @@ -16973,6 +17015,12 @@ <description> </description> </method> + <method name="get_normal_bias" qualifiers="const"> + <return type="float"> + </return> + <description> + </description> + </method> <method name="get_propagation" qualifiers="const"> <return type="float"> </return> @@ -17045,6 +17093,12 @@ <description> </description> </method> + <method name="set_normal_bias"> + <argument index="0" name="bias" type="float"> + </argument> + <description> + </description> + </method> <method name="set_propagation"> <argument index="0" name="propagation" type="float"> </argument> @@ -17075,6 +17129,8 @@ </member> <member name="interior" type="bool" setter="set_interior" getter="is_interior" brief=""> </member> + <member name="normal_bias" type="float" setter="set_normal_bias" getter="get_normal_bias" brief=""> + </member> <member name="propagation" type="float" setter="set_propagation" getter="get_propagation" brief=""> </member> <member name="to_cell_xform" type="Transform" setter="set_to_cell_xform" getter="get_to_cell_xform" brief=""> @@ -24714,7 +24770,7 @@ <description> </description> </method> - <method name="create_debug_tagents"> + <method name="create_debug_tangents"> <description> </description> </method> @@ -27962,6 +28018,8 @@ </description> </method> <method name="get_meta" qualifiers="const"> + <return type="Variant"> + </return> <argument index="0" name="name" type="String"> </argument> <description> diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 21bdb217fc..cd74c450f5 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -3516,7 +3516,6 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p _copy_screen(); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, false); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_FAR_BLUR, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_LOW, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_MEDIUM, false); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES3::DOF_QUALITY_HIGH, false); @@ -3611,6 +3610,16 @@ void RasterizerSceneGLES3::_post_process(Environment *env, const CameraMatrix &p composite_from = storage->frame.current_rt->effects.mip_maps[0].color; } + if (env->dof_blur_near_enabled || env->dof_blur_far_enabled) { + //these needed to disable filtering, reenamble + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, storage->frame.current_rt->effects.mip_maps[0].color); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + if (env->auto_exposure) { //compute auto exposure diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index 76df57d410..2a9f078d8c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -6189,6 +6189,8 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { glBindTexture(GL_TEXTURE_2D, rt->effects.mip_maps[i].color); int level = 0; + int fb_w = w; + int fb_h = h; while (true) { @@ -6206,13 +6208,15 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { level++; } - glTexStorage2DCustom(GL_TEXTURE_2D, level + 1, color_internal_format, rt->width, rt->height, color_format, color_type); + glTexStorage2DCustom(GL_TEXTURE_2D, level + 1, color_internal_format, fb_w, fb_h, color_format, color_type); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level); glDisable(GL_SCISSOR_TEST); glColorMask(1, 1, 1, 1); - glDepthMask(GL_TRUE); + if (rt->buffers.active == false) { + glDepthMask(GL_TRUE); + } for (int j = 0; j < rt->effects.mip_maps[i].sizes.size(); j++) { @@ -6235,7 +6239,6 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { float zero[4] = { 1, 0, 1, 0 }; glViewport(0, 0, rt->effects.mip_maps[i].sizes[j].width, rt->effects.mip_maps[i].sizes[j].height); - glClearBufferfv(GL_COLOR, 0, zero); if (used_depth) { glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); @@ -6912,7 +6915,7 @@ void RasterizerStorageGLES3::initialize() { config.use_anisotropic_filter = config.extensions.has("GL_EXT_texture_filter_anisotropic"); if (config.use_anisotropic_filter) { glGetFloatv(_GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &config.anisotropic_level); - config.anisotropic_level = MIN(int(ProjectSettings::get_singleton()->get("rendering/quality/anisotropic_filter_level")), config.anisotropic_level); + config.anisotropic_level = MIN(int(ProjectSettings::get_singleton()->get("rendering/quality/filters/anisotropic_filter_level")), config.anisotropic_level); } frame.clear_request = false; diff --git a/drivers/gles3/rasterizer_storage_gles3.h b/drivers/gles3/rasterizer_storage_gles3.h index 7d0f3e5745..b536c9841c 100644 --- a/drivers/gles3/rasterizer_storage_gles3.h +++ b/drivers/gles3/rasterizer_storage_gles3.h @@ -1285,12 +1285,11 @@ public: buffers.fbo = 0; used_in_frame = false; - flags[RENDER_TARGET_VFLIP] = false; - flags[RENDER_TARGET_TRANSPARENT] = false; - flags[RENDER_TARGET_NO_3D_EFFECTS] = false; - flags[RENDER_TARGET_NO_3D] = false; - flags[RENDER_TARGET_NO_SAMPLING] = false; + for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { + flags[i] = false; + } flags[RENDER_TARGET_HDR] = true; + buffers.active = false; buffers.effects_active = false; diff --git a/drivers/gles3/shaders/tonemap.glsl b/drivers/gles3/shaders/tonemap.glsl index c6dfc6917d..988e31d1ea 100644 --- a/drivers/gles3/shaders/tonemap.glsl +++ b/drivers/gles3/shaders/tonemap.glsl @@ -144,6 +144,38 @@ vec4 texture2D_bicubic(sampler2D tex, vec2 uv,int p_lod) #endif +vec3 tonemap_filmic(vec3 color,float white) { + + float A = 0.15; + float B = 0.50; + float C = 0.10; + float D = 0.20; + float E = 0.02; + float F = 0.30; + float W = 11.2; + + vec3 coltn = ((color*(A*color+C*B)+D*E)/(color*(A*color+B)+D*F))-E/F; + float whitetn = ((white*(A*white+C*B)+D*E)/(white*(A*white+B)+D*F))-E/F; + + return coltn/whitetn; + +} + +vec3 tonemap_aces(vec3 color) { + float a = 2.51f; + float b = 0.03f; + float c = 2.43f; + float d = 0.59f; + float e = 0.14f; + return color = clamp((color*(a*color+b))/(color*(c*color+d)+e),vec3(0.0),vec3(1.0)); +} + +vec3 tonemap_reindhart(vec3 color,vec3 white) { + + return ( color * ( 1.0 + ( color / ( white) ) ) ) / ( 1.0 + color ); +} + + void main() { ivec2 coord = ivec2(gl_FragCoord.xy); @@ -157,8 +189,11 @@ void main() { color*=exposure; - #if defined(USE_GLOW_LEVEL1) || defined(USE_GLOW_LEVEL2) || defined(USE_GLOW_LEVEL3) || defined(USE_GLOW_LEVEL4) || defined(USE_GLOW_LEVEL5) || defined(USE_GLOW_LEVEL6) || defined(USE_GLOW_LEVEL7) +#define USING_GLOW +#endif + +#if defined(USING_GLOW) vec3 glow = vec3(0.0); #ifdef USE_GLOW_LEVEL1 @@ -193,85 +228,83 @@ void main() { glow *= glow_intensity; +#endif -#ifdef USE_GLOW_REPLACE +#ifdef USE_REINDHART_TONEMAPPER - color.rgb = glow; + color.rgb = tonemap_reindhart(color.rgb,white); + +# if defined(USING_GLOW) + glow = tonemap_reindhart(glow,white); +# endif #endif -#ifdef USE_GLOW_SCREEN +#ifdef USE_FILMIC_TONEMAPPER - color.rgb = clamp((color.rgb + glow) - (color.rgb * glow), 0.0, 1.0); + color.rgb = tonemap_filmic(color.rgb,white); + +# if defined(USING_GLOW) + glow = tonemap_filmic(glow,white); +# endif #endif -#ifdef USE_GLOW_SOFTLIGHT +#ifdef USE_ACES_TONEMAPPER - { + color.rgb = tonemap_aces(color.rgb); - glow = (glow * 0.5) + 0.5; - color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); - color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); - color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); - } +# if defined(USING_GLOW) + glow = tonemap_aces(glow); +# endif #endif -#if !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) - color.rgb+=glow; -#endif - + //regular Linear -> SRGB conversion + vec3 a = vec3(0.055); + color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308))); +#if defined(USING_GLOW) + glow = mix( (vec3(1.0)+a)*pow(glow,vec3(1.0/2.4))-a , 12.92*glow , lessThan(glow,vec3(0.0031308))); #endif +//glow needs to be added in SRGB space (together with image space effects) -#ifdef USE_REINDHART_TONEMAPPER + color.rgb = clamp(color.rgb,0.0,1.0); - { - color.rgb = ( color.rgb * ( 1.0 + ( color.rgb / ( white) ) ) ) / ( 1.0 + color.rgb ); - - } +#if defined(USING_GLOW) + glow = clamp(glow,0.0,1.0); #endif -#ifdef USE_FILMIC_TONEMAPPER +#ifdef USE_GLOW_REPLACE - { + color.rgb = glow; - float A = 0.15; - float B = 0.50; - float C = 0.10; - float D = 0.20; - float E = 0.02; - float F = 0.30; - float W = 11.2; +#endif - vec3 coltn = ((color.rgb*(A*color.rgb+C*B)+D*E)/(color.rgb*(A*color.rgb+B)+D*F))-E/F; - float whitetn = ((white*(A*white+C*B)+D*E)/(white*(A*white+B)+D*F))-E/F; +#ifdef USE_GLOW_SCREEN - color.rgb=coltn/whitetn; + color.rgb = max((color.rgb + glow) - (color.rgb * glow), vec3(0.0)); - } #endif -#ifdef USE_ACES_TONEMAPPER +#ifdef USE_GLOW_SOFTLIGHT { - float a = 2.51f; - float b = 0.03f; - float c = 2.43f; - float d = 0.59f; - float e = 0.14f; - color.rgb = clamp((color.rgb*(a*color.rgb+b))/(color.rgb*(c*color.rgb+d)+e),vec3(0.0),vec3(1.0)); + + glow = (glow * 0.5) + 0.5; + color.r = (glow.r <= 0.5) ? (color.r - (1.0 - 2.0 * glow.r) * color.r * (1.0 - color.r)) : (((glow.r > 0.5) && (color.r <= 0.25)) ? (color.r + (2.0 * glow.r - 1.0) * (4.0 * color.r * (4.0 * color.r + 1.0) * (color.r - 1.0) + 7.0 * color.r)) : (color.r + (2.0 * glow.r - 1.0) * (sqrt(color.r) - color.r))); + color.g = (glow.g <= 0.5) ? (color.g - (1.0 - 2.0 * glow.g) * color.g * (1.0 - color.g)) : (((glow.g > 0.5) && (color.g <= 0.25)) ? (color.g + (2.0 * glow.g - 1.0) * (4.0 * color.g * (4.0 * color.g + 1.0) * (color.g - 1.0) + 7.0 * color.g)) : (color.g + (2.0 * glow.g - 1.0) * (sqrt(color.g) - color.g))); + color.b = (glow.b <= 0.5) ? (color.b - (1.0 - 2.0 * glow.b) * color.b * (1.0 - color.b)) : (((glow.b > 0.5) && (color.b <= 0.25)) ? (color.b + (2.0 * glow.b - 1.0) * (4.0 * color.b * (4.0 * color.b + 1.0) * (color.b - 1.0) + 7.0 * color.b)) : (color.b + (2.0 * glow.b - 1.0) * (sqrt(color.b) - color.b))); } #endif - //regular Linear -> SRGB conversion - vec3 a = vec3(0.055); - color.rgb = mix( (vec3(1.0)+a)*pow(color.rgb,vec3(1.0/2.4))-a , 12.92*color.rgb , lessThan(color.rgb,vec3(0.0031308))); - +#if defined(USING_GLOW) && !defined(USE_GLOW_SCREEN) && !defined(USE_GLOW_SOFTLIGHT) && !defined(USE_GLOW_REPLACE) + //additive + color.rgb+=glow; +#endif #ifdef USE_BCS diff --git a/editor/asset_library_editor_plugin.cpp b/editor/asset_library_editor_plugin.cpp index 74e21b31ea..f92b70d0c0 100644 --- a/editor/asset_library_editor_plugin.cpp +++ b/editor/asset_library_editor_plugin.cpp @@ -1334,10 +1334,13 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) { search_hb2->add_child(memnew(Label(TTR("Site:") + " "))); repository = memnew(OptionButton); + // FIXME: Reenable me once GH-7147 is fixed. + /* repository->add_item("godotengine.org"); repository->set_item_metadata(0, "https://godotengine.org/asset-library/api"); - repository->add_item("localhost"); // TODO: Maybe remove? - repository->set_item_metadata(1, "http://127.0.0.1/asset-library/api"); + */ + repository->add_item("localhost"); + repository->set_item_metadata(/*1*/ 0, "http://127.0.0.1/asset-library/api"); repository->connect("item_selected", this, "_repository_changed"); search_hb2->add_child(repository); diff --git a/editor/plugins/spatial_editor_plugin.cpp b/editor/plugins/spatial_editor_plugin.cpp index ef7ed5f7f6..c31e11cc38 100644 --- a/editor/plugins/spatial_editor_plugin.cpp +++ b/editor/plugins/spatial_editor_plugin.cpp @@ -1563,13 +1563,13 @@ void SpatialEditorViewport::_update_freelook(real_t delta) { Vector3 right = camera->get_transform().basis.xform(Vector3(1, 0, 0)); Vector3 up = camera->get_transform().basis.xform(Vector3(0, 1, 0)); - int key_left = ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), KEY_A)->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); - int key_right = ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D)->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); - int key_forward = ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W)->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); - int key_backwards = ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S)->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); - int key_up = ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q)->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); - int key_down = ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E)->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); - int key_speed_modifier = ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT)->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); + int key_left = ED_GET_SHORTCUT("spatial_editor/freelook_left")->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); + int key_right = ED_GET_SHORTCUT("spatial_editor/freelook_right")->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); + int key_forward = ED_GET_SHORTCUT("spatial_editor/freelook_forward")->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); + int key_backwards = ED_GET_SHORTCUT("spatial_editor/freelook_backwards")->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); + int key_up = ED_GET_SHORTCUT("spatial_editor/freelook_up")->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); + int key_down = ED_GET_SHORTCUT("spatial_editor/freelook_down")->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); + int key_speed_modifier = ED_GET_SHORTCUT("spatial_editor/freelook_speed_modifier")->get_shortcut()->cast_to<InputEventKey>()->get_scancode(); Vector3 velocity; bool pressed = false; @@ -2424,6 +2424,14 @@ SpatialEditorViewport::SpatialEditorViewport(SpatialEditor *p_spatial_editor, Ed view_menu->get_popup()->add_shortcut(ED_GET_SHORTCUT("spatial_editor/align_selection_with_view"), VIEW_ALIGN_SELECTION_WITH_VIEW); view_menu->get_popup()->connect("id_pressed", this, "_menu_option"); + ED_SHORTCUT("spatial_editor/freelook_left", TTR("Freelook Left"), KEY_A); + ED_SHORTCUT("spatial_editor/freelook_right", TTR("Freelook Right"), KEY_D); + ED_SHORTCUT("spatial_editor/freelook_forward", TTR("Freelook Forward"), KEY_W); + ED_SHORTCUT("spatial_editor/freelook_backwards", TTR("Freelook Backwards"), KEY_S); + ED_SHORTCUT("spatial_editor/freelook_up", TTR("Freelook Up"), KEY_Q); + ED_SHORTCUT("spatial_editor/freelook_down", TTR("Freelook Down"), KEY_E); + ED_SHORTCUT("spatial_editor/freelook_speed_modifier", TTR("Freelook Speed Modifier"), KEY_SHIFT); + preview_camera = memnew(Button); preview_camera->set_toggle_mode(true); preview_camera->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, 90); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index c2af2445cc..71afa8ac79 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -2199,6 +2199,7 @@ void PropertyEditor::set_item_text(TreeItem *p_item, int p_type, const String &p case Variant::BOOL: { p_item->set_checked(1, obj->get(p_name)); + p_item->set_text(1, obj->get(p_name) ? TTR("On") : TTR("Off")); } break; case Variant::REAL: case Variant::INT: { @@ -3141,7 +3142,7 @@ void PropertyEditor::update_tree() { case Variant::BOOL: { item->set_cell_mode(1, TreeItem::CELL_MODE_CHECK); - item->set_text(1, TTR("On")); + item->set_text(1, obj->get(p.name) ? TTR("On") : TTR("Off")); item->set_tooltip(1, obj->get(p.name) ? "True" : "False"); item->set_checked(1, obj->get(p.name)); if (show_type_icons) diff --git a/modules/gdnative/godot/gdnative.cpp b/modules/gdnative/godot/gdnative.cpp index 7b94b75a52..29b499ebab 100644 --- a/modules/gdnative/godot/gdnative.cpp +++ b/modules/gdnative/godot/gdnative.cpp @@ -33,6 +33,7 @@ #include "error_macros.h" #include "gdnative.h" #include "global_constants.h" +#include "os/os.h" #include "project_settings.h" #include "variant.h" @@ -89,6 +90,10 @@ godot_object GDAPI *godot_global_get_singleton(char *p_name) { return (godot_object *)ProjectSettings::get_singleton()->get_singleton_object(String(p_name)); } // result shouldn't be freed +void GDAPI *godot_get_stack_bottom() { + return OS::get_singleton()->get_stack_bottom(); +} + // MethodBind API godot_method_bind GDAPI *godot_method_bind_get_method(const char *p_classname, const char *p_methodname) { diff --git a/modules/gdnative/godot/gdnative.h b/modules/gdnative/godot/gdnative.h index 4b79706b52..510bf36cd4 100644 --- a/modules/gdnative/godot/gdnative.h +++ b/modules/gdnative/godot/gdnative.h @@ -245,6 +245,10 @@ void GDAPI godot_object_destroy(godot_object *p_o); godot_object GDAPI *godot_global_get_singleton(char *p_name); // result shouldn't be freed +////// OS API + +void GDAPI *godot_get_stack_bottom(); // returns stack bottom of the main thread + ////// MethodBind API typedef struct { diff --git a/modules/gdscript/gd_editor.cpp b/modules/gdscript/gd_editor.cpp index 1e1327d72f..c88889767c 100644 --- a/modules/gdscript/gd_editor.cpp +++ b/modules/gdscript/gd_editor.cpp @@ -1334,8 +1334,8 @@ static void _find_identifiers(GDCompletionContext &context, int p_line, bool p_o static const char *_type_names[Variant::VARIANT_MAX] = { "null", "bool", "int", "float", "String", "Vector2", "Rect2", "Vector3", "Transform2D", "Plane", "Quat", "AABB", "Basis", "Transform", - "Color", "NodePath", "RID", "Object", "Dictionary", "Array", "RawArray", "IntArray", "FloatArray", "StringArray", - "Vector2Array", "Vector3Array", "ColorArray" + "Color", "NodePath", "RID", "Object", "Dictionary", "Array", "PoolByteArray", "PoolIntArray", "PoolRealArray", "PoolStringArray", + "PoolVector2Array", "PoolVector3Array", "PoolColorArray" }; for (int i = 0; i < Variant::VARIANT_MAX; i++) { diff --git a/modules/gdscript/gd_parser.cpp b/modules/gdscript/gd_parser.cpp index ba0413a5a9..36aa249398 100644 --- a/modules/gdscript/gd_parser.cpp +++ b/modules/gdscript/gd_parser.cpp @@ -314,9 +314,10 @@ GDParser::Node *GDParser::_parse_expression(Node *p_parent, bool p_static, bool path += String(tokenizer->get_token_literal()); tokenizer->advance(); need_identifier = false; + } else { + done = true; } - done = true; break; } } diff --git a/modules/gdscript/gd_tokenizer.cpp b/modules/gdscript/gd_tokenizer.cpp index 01e3835494..5803046185 100644 --- a/modules/gdscript/gd_tokenizer.cpp +++ b/modules/gdscript/gd_tokenizer.cpp @@ -159,7 +159,7 @@ static const _bit _type_list[] = { { Variant::ARRAY, "Array" }, { Variant::POOL_BYTE_ARRAY, "PoolByteArray" }, { Variant::POOL_INT_ARRAY, "PoolIntArray" }, - { Variant::POOL_REAL_ARRAY, "PoolFloatArray" }, + { Variant::POOL_REAL_ARRAY, "PoolRealArray" }, { Variant::POOL_STRING_ARRAY, "PoolStringArray" }, { Variant::POOL_VECTOR2_ARRAY, "PoolVector2Array" }, { Variant::POOL_VECTOR3_ARRAY, "PoolVector3Array" }, diff --git a/modules/nativescript/nativescript.cpp b/modules/nativescript/nativescript.cpp index 541fe951e4..271f5bde1c 100644 --- a/modules/nativescript/nativescript.cpp +++ b/modules/nativescript/nativescript.cpp @@ -40,6 +40,10 @@ #include "scene/main/scene_tree.h" #include "scene/resources/scene_format_text.h" +#ifndef NO_THREADS +#include "os/thread.h" +#endif + #if defined(TOOLS_ENABLED) && defined(DEBUG_METHODS_ENABLED) #include "api_generator.h" #endif @@ -106,42 +110,16 @@ void NativeScript::set_library(Ref<GDNativeLibrary> p_library) { return; } library = p_library; - - // See if this library was "registered" already. - lib_path = library->get_active_library_path(); - Map<String, Ref<GDNative> >::Element *E = NSL->library_gdnatives.find(lib_path); - - if (!E) { - Ref<GDNative> gdn; - gdn.instance(); - gdn->set_library(library); - - // TODO(karroffel): check the return value? - gdn->initialize(); - - NSL->library_gdnatives.insert(lib_path, gdn); - - NSL->library_classes.insert(lib_path, Map<StringName, NativeScriptDesc>()); - if (!NSL->library_script_users.has(lib_path)) - NSL->library_script_users.insert(lib_path, Set<NativeScript *>()); - - NSL->library_script_users[lib_path].insert(this); - - void *args[1] = { - (void *)&lib_path - }; - - // here the library registers all the classes and stuff. - gdn->call_native_raw(NSL->_init_call_type, - NSL->_init_call_name, - NULL, - 1, - args, - NULL); - } else { - // already initialized. Nice. +#ifndef NO_THREADS + if (Thread::get_caller_ID() != Thread::get_main_ID()) { + NSL->defer_init_library(p_library, this); + } else +#endif + { + NSL->init_library(p_library); + NSL->register_script(this); } } @@ -445,7 +423,7 @@ NativeScript::NativeScript() { // TODO(karroffel): implement this NativeScript::~NativeScript() { - NSL->library_script_users[lib_path].erase(this); + NSL->unregister_script(this); } ////// ScriptInstance stuff @@ -502,7 +480,7 @@ bool NativeScriptInstance::get(const StringName &p_name, Variant &r_ret) const { if (P) { godot_variant value; value = P->get().getter.get_func((godot_object *)owner, - P->get().setter.method_data, + P->get().getter.method_data, userdata); r_ret = *(Variant *)&value; godot_variant_destroy(&value); @@ -650,6 +628,28 @@ void NativeScriptInstance::notification(int p_notification) { call_multilevel("_notification", args, 1); } +void NativeScriptInstance::refcount_incremented() { + Variant::CallError err; + call("_refcount_incremented", NULL, 0, err); + if (err.error != Variant::CallError::CALL_OK && err.error != Variant::CallError::CALL_ERROR_INVALID_METHOD) { + ERR_PRINT("Failed to invoke _refcount_incremented - should not happen"); + } +} + +bool NativeScriptInstance::refcount_decremented() { + Variant::CallError err; + Variant ret = call("_refcount_decremented", NULL, 0, err); + if (err.error != Variant::CallError::CALL_OK && err.error != Variant::CallError::CALL_ERROR_INVALID_METHOD) { + ERR_PRINT("Failed to invoke _refcount_decremented - should not happen"); + return true; // assume we can destroy the object + } + if (err.error == Variant::CallError::CALL_ERROR_INVALID_METHOD) { + // the method does not exist, default is true + return true; + } + return ret; +} + Ref<Script> NativeScriptInstance::get_script() const { return script; } @@ -798,6 +798,9 @@ void NativeScriptLanguage::_unload_stuff() { NativeScriptLanguage::NativeScriptLanguage() { NativeScriptLanguage::singleton = this; +#ifndef NO_THREADS + mutex = Mutex::create(); +#endif } // TODO(karroffel): implement this @@ -811,6 +814,10 @@ NativeScriptLanguage::~NativeScriptLanguage() { NSL->library_gdnatives.clear(); NSL->library_script_users.clear(); } + +#ifndef NO_THREADS + memdelete(mutex); +#endif } String NativeScriptLanguage::get_name() const { @@ -948,6 +955,134 @@ int NativeScriptLanguage::profiling_get_frame_data(ProfilingInfo *p_info_arr, in return -1; } +#ifndef NO_THREADS +void NativeScriptLanguage::defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script) { + MutexLock lock(mutex); + libs_to_init.insert(lib); + scripts_to_register.insert(script); + has_objects_to_register = true; +} +#endif + +void NativeScriptLanguage::init_library(const Ref<GDNativeLibrary> &lib) { +#ifndef NO_THREADS + MutexLock lock(mutex); +#endif + // See if this library was "registered" already. + const String &lib_path = lib->get_active_library_path(); + Map<String, Ref<GDNative> >::Element *E = library_gdnatives.find(lib_path); + + if (!E) { + Ref<GDNative> gdn; + gdn.instance(); + gdn->set_library(lib); + + // TODO(karroffel): check the return value? + gdn->initialize(); + + library_gdnatives.insert(lib_path, gdn); + + library_classes.insert(lib_path, Map<StringName, NativeScriptDesc>()); + + if (!library_script_users.has(lib_path)) + library_script_users.insert(lib_path, Set<NativeScript *>()); + + void *args[1] = { + (void *)&lib_path + }; + + // here the library registers all the classes and stuff. + gdn->call_native_raw(_init_call_type, + _init_call_name, + NULL, + 1, + args, + NULL); + } else { + // already initialized. Nice. + } +} + +void NativeScriptLanguage::register_script(NativeScript *script) { +#ifndef NO_THREADS + MutexLock lock(mutex); +#endif + library_script_users[script->lib_path].insert(script); +} + +void NativeScriptLanguage::unregister_script(NativeScript *script) { +#ifndef NO_THREADS + MutexLock lock(mutex); +#endif + Map<String, Set<NativeScript *> >::Element *S = library_script_users.find(script->lib_path); + if (S) { + S->get().erase(script); + if (S->get().size() == 0) { + library_script_users.erase(S); + } + } +#ifndef NO_THREADS + scripts_to_register.erase(script); +#endif +} + +#ifndef NO_THREADS + +void NativeScriptLanguage::frame() { + if (has_objects_to_register) { + MutexLock lock(mutex); + for (Set<Ref<GDNativeLibrary> >::Element *L = libs_to_init.front(); L; L = L->next()) { + init_library(L->get()); + } + libs_to_init.clear(); + for (Set<NativeScript *>::Element *S = scripts_to_register.front(); S; S = S->next()) { + register_script(S->get()); + } + scripts_to_register.clear(); + has_objects_to_register = false; + } +} + +void NativeScriptLanguage::thread_enter() { + Vector<Ref<GDNative> > libs; + { + MutexLock lock(mutex); + for (Map<String, Ref<GDNative> >::Element *L = library_gdnatives.front(); L; L = L->next()) { + libs.push_back(L->get()); + } + } + for (int i = 0; i < libs.size(); ++i) { + libs[i]->call_native_raw( + _thread_cb_call_type, + _thread_enter_call_name, + NULL, + 0, + NULL, + NULL); + } +} + +void NativeScriptLanguage::thread_exit() { + Vector<Ref<GDNative> > libs; + { + MutexLock lock(mutex); + for (Map<String, Ref<GDNative> >::Element *L = library_gdnatives.front(); L; L = L->next()) { + libs.push_back(L->get()); + } + } + for (int i = 0; i < libs.size(); ++i) { + libs[i]->call_native_raw( + _thread_cb_call_type, + _thread_exit_call_name, + NULL, + 0, + NULL, + NULL); + } +} + +#endif // NO_THREADS + void NativeReloadNode::_bind_methods() { ClassDB::bind_method(D_METHOD("_notification"), &NativeReloadNode::_notification); } @@ -960,7 +1095,9 @@ void NativeReloadNode::_notification(int p_what) { if (unloaded) break; - +#ifndef NO_THREADS + MutexLock lock(NSL->mutex); +#endif NSL->_unload_stuff(); for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { @@ -976,9 +1113,10 @@ void NativeReloadNode::_notification(int p_what) { if (!unloaded) break; - +#ifndef NO_THREADS + MutexLock lock(NSL->mutex); +#endif Set<StringName> libs_to_remove; - for (Map<String, Ref<GDNative> >::Element *L = NSL->library_gdnatives.front(); L; L = L->next()) { if (!L->get()->initialize()) { diff --git a/modules/nativescript/nativescript.h b/modules/nativescript/nativescript.h index bc7a6e3ed6..05e2d361d3 100644 --- a/modules/nativescript/nativescript.h +++ b/modules/nativescript/nativescript.h @@ -41,6 +41,10 @@ #include "godot_nativescript.h" #include "modules/gdnative/gdnative.h" +#ifndef NO_THREADS +#include "os/mutex.h" +#endif + struct NativeScriptDesc { struct Method { @@ -181,6 +185,9 @@ public: virtual void call_multilevel(const StringName &p_method, const Variant **p_args, int p_argcount); virtual void call_multilevel_reversed(const StringName &p_method, const Variant **p_args, int p_argcount); + virtual void refcount_incremented(); + virtual bool refcount_decremented(); + ~NativeScriptInstance(); }; @@ -197,6 +204,19 @@ private: void _unload_stuff(); +#ifndef NO_THREADS + Mutex *mutex; + + Set<Ref<GDNativeLibrary> > libs_to_init; + Set<NativeScript *> scripts_to_register; + volatile bool has_objects_to_register; // so that we don't lock mutex every frame - it's rarely needed + void defer_init_library(Ref<GDNativeLibrary> lib, NativeScript *script); +#endif + + void init_library(const Ref<GDNativeLibrary> &lib); + void register_script(NativeScript *script); + void unregister_script(NativeScript *script); + public: Map<String, Map<StringName, NativeScriptDesc> > library_classes; Map<String, Ref<GDNative> > library_gdnatives; @@ -206,6 +226,10 @@ public: const StringName _init_call_type = "nativescript_init"; const StringName _init_call_name = "godot_nativescript_init"; + const StringName _thread_cb_call_type = "godot_nativescript_thread_cb"; + const StringName _thread_enter_call_name = "godot_nativescript_thread_enter"; + const StringName _thread_exit_call_name = "godot_nativescript_thread_exit"; + NativeScriptLanguage(); ~NativeScriptLanguage(); @@ -215,6 +239,13 @@ public: void _hacky_api_anchor(); +#ifndef NO_THREADS + virtual void thread_enter(); + virtual void thread_exit(); + + virtual void frame(); +#endif + virtual String get_name() const; virtual void init(); virtual String get_type() const; diff --git a/modules/nativescript/register_types.cpp b/modules/nativescript/register_types.cpp index 6c88b04a56..a8a931343b 100644 --- a/modules/nativescript/register_types.cpp +++ b/modules/nativescript/register_types.cpp @@ -61,6 +61,32 @@ void init_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p fn(args[0]); } +#ifndef NO_THREADS + +typedef void (*native_script_empty_callback)(); + +void thread_call_cb(void *p_handle, godot_string *p_proc_name, void *p_data, int p_num_args, void **args, void *r_ret) { + if (p_handle == NULL) { + ERR_PRINT("No valid library handle, can't call nativescript thread enter/exit callback"); + return; + } + + void *library_proc; + Error err = OS::get_singleton()->get_dynamic_library_symbol_handle( + p_handle, + *(String *)p_proc_name, + library_proc); + if (err != OK) { + // it's fine if thread callbacks are not present in the library. + return; + } + + native_script_empty_callback fn = (native_script_empty_callback)library_proc; + fn(); +} + +#endif // NO_THREADS + ResourceFormatLoaderNativeScript *resource_loader_gdns = NULL; ResourceFormatSaverNativeScript *resource_saver_gdns = NULL; @@ -72,6 +98,9 @@ void register_nativescript_types() { ScriptServer::register_language(native_script_language); GDNativeCallRegistry::singleton->register_native_raw_call_type(native_script_language->_init_call_type, init_call_cb); +#ifndef NO_THREADS + GDNativeCallRegistry::singleton->register_native_raw_call_type(native_script_language->_thread_cb_call_type, thread_call_cb); +#endif resource_saver_gdns = memnew(ResourceFormatSaverNativeScript); ResourceSaver::add_resource_format_saver(resource_saver_gdns); diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 1329c94198..cb5c022764 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -109,7 +109,6 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_ RasterizerGLES3::register_config(); RasterizerGLES3::make_current(); - RasterizerStorageGLES3::system_fbo = gl_view_base_fb; visual_server = memnew(VisualServerRaster()); /* @@ -122,6 +121,9 @@ void OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p_ visual_server->init(); visual_server->cursor_set_visible(false, 0); + // reset this to what it should be, it will have been set to 0 after visual_server->init() is called + RasterizerStorageGLES3::system_fbo = gl_view_base_fb; + audio_driver = memnew(AudioDriverIphone); audio_driver->set_singleton(); audio_driver->init(); @@ -434,7 +436,8 @@ bool OSIPhone::can_draw() const { int OSIPhone::set_base_framebuffer(int p_fb) { - RasterizerStorageGLES3::system_fbo = gl_view_base_fb; + // gl_view_base_fb has not been updated yet + RasterizerStorageGLES3::system_fbo = p_fb; return 0; }; diff --git a/scene/3d/mesh_instance.cpp b/scene/3d/mesh_instance.cpp index 558932ceb9..51237c0bc3 100644 --- a/scene/3d/mesh_instance.cpp +++ b/scene/3d/mesh_instance.cpp @@ -275,7 +275,7 @@ void MeshInstance::_mesh_changed() { materials.resize(mesh->get_surface_count()); } -void MeshInstance::create_debug_tagents() { +void MeshInstance::create_debug_tangents() { Vector<Vector3> lines; Vector<Color> colors; @@ -366,8 +366,8 @@ void MeshInstance::_bind_methods() { ClassDB::set_method_flags("MeshInstance", "create_convex_collision", METHOD_FLAGS_DEFAULT); ClassDB::bind_method(D_METHOD("_mesh_changed"), &MeshInstance::_mesh_changed); - ClassDB::bind_method(D_METHOD("create_debug_tagents"), &MeshInstance::create_debug_tagents); - ClassDB::set_method_flags("MeshInstance", "create_debug_tagents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); + ClassDB::bind_method(D_METHOD("create_debug_tangents"), &MeshInstance::create_debug_tangents); + ClassDB::set_method_flags("MeshInstance", "create_debug_tangents", METHOD_FLAGS_DEFAULT | METHOD_FLAG_EDITOR); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "mesh", PROPERTY_HINT_RESOURCE_TYPE, "Mesh"), "set_mesh", "get_mesh"); ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "skeleton"), "set_skeleton_path", "get_skeleton_path"); diff --git a/scene/3d/mesh_instance.h b/scene/3d/mesh_instance.h index be328084af..1bb2c97d10 100644 --- a/scene/3d/mesh_instance.h +++ b/scene/3d/mesh_instance.h @@ -83,7 +83,7 @@ public: Node *create_convex_collision_node(); void create_convex_collision(); - void create_debug_tagents(); + void create_debug_tangents(); virtual Rect3 get_aabb() const; virtual PoolVector<Face3> get_faces(uint32_t p_usage_flags) const; diff --git a/scene/gui/texture_button.cpp b/scene/gui/texture_button.cpp index 33d9b76b70..2912aa82fc 100644 --- a/scene/gui/texture_button.cpp +++ b/scene/gui/texture_button.cpp @@ -206,7 +206,7 @@ void TextureButton::_bind_methods() { ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_focused", PROPERTY_HINT_RESOURCE_TYPE, "Texture"), "set_focused_texture", "get_focused_texture"); ADD_PROPERTYNZ(PropertyInfo(Variant::OBJECT, "texture_click_mask", PROPERTY_HINT_RESOURCE_TYPE, "BitMap"), "set_click_mask", "get_click_mask"); ADD_PROPERTYNZ(PropertyInfo(Variant::BOOL, "expand", PROPERTY_HINT_RESOURCE_TYPE, "bool"), "set_expand", "get_expand"); - ADD_PROPERTYNO(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); + ADD_PROPERTYNZ(PropertyInfo(Variant::INT, "stretch_mode", PROPERTY_HINT_ENUM, "Scale,Tile,Keep,Keep Centered,Keep Aspect,Keep Aspect Centered,Keep Aspect Covered"), "set_stretch_mode", "get_stretch_mode"); BIND_CONSTANT(STRETCH_SCALE); BIND_CONSTANT(STRETCH_TILE); diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index ae89d8ed94..accced404b 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -167,6 +167,7 @@ void Environment::set_tonemap_auto_exposure(bool p_enabled) { tonemap_auto_exposure = p_enabled; VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + _change_notify(); } bool Environment::get_tonemap_auto_exposure() const { diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index 080e538cbf..307f4107eb 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -1576,7 +1576,7 @@ VisualServer::VisualServer() { GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048); GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096); GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384")); GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_0_subdiv", 1); GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_1_subdiv", 2); GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_2_subdiv", 3); |