diff options
175 files changed, 3107 insertions, 883 deletions
diff --git a/.gitignore b/.gitignore index 35fadafbda..6db75f2324 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ platform/android/java/build.gradle platform/android/java/AndroidManifest.xml platform/android/java/libs/* platform/android/java/assets +platform/android/java/.idea/* +platform/android/java/*.iml # General c++ generated files *.lib @@ -44,6 +46,7 @@ gmon.out # QT project files *.config *.creator +*.creator.* *.files *.includes diff --git a/core/dictionary.cpp b/core/dictionary.cpp index ba0de95861..d68411a572 100644 --- a/core/dictionary.cpp +++ b/core/dictionary.cpp @@ -50,6 +50,32 @@ void Dictionary::get_key_list(List<Variant> *p_keys) const { } } +Variant Dictionary::get_key_at_index(int p_index) const { + + int index = 0; + for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { + if (index == p_index) { + return E.key(); + } + index++; + } + + return Variant(); +} + +Variant Dictionary::get_value_at_index(int p_index) const { + + int index = 0; + for (OrderedHashMap<Variant, Variant, VariantHasher, VariantComparator>::Element E = _p->variant_map.front(); E; E = E.next()) { + if (index == p_index) { + return E.value(); + } + index++; + } + + return Variant(); +} + Variant &Dictionary::operator[](const Variant &p_key) { return _p->variant_map[p_key]; diff --git a/core/dictionary.h b/core/dictionary.h index 9eef265d5b..84a5cafe1d 100644 --- a/core/dictionary.h +++ b/core/dictionary.h @@ -47,6 +47,8 @@ class Dictionary { public: void get_key_list(List<Variant> *p_keys) const; + Variant get_key_at_index(int p_index) const; + Variant get_value_at_index(int p_index) const; Variant &operator[](const Variant &p_key); const Variant &operator[](const Variant &p_key) const; diff --git a/core/io/http_client.cpp b/core/io/http_client.cpp index 9e301ccac5..8d85e78226 100644 --- a/core/io/http_client.cpp +++ b/core/io/http_client.cpp @@ -248,6 +248,7 @@ void HTTPClient::close() { body_size = 0; body_left = 0; chunk_left = 0; + read_until_eof = false; response_num = 0; } @@ -352,10 +353,17 @@ Error HTTPClient::poll() { chunked = false; body_left = 0; chunk_left = 0; + read_until_eof = false; response_str.clear(); response_headers.clear(); response_num = RESPONSE_OK; + // Per the HTTP 1.1 spec, keep-alive is the default, but in practice + // it's safe to assume it only if the explicit header is found, allowing + // to handle body-up-to-EOF responses on naive servers; that's what Curl + // and browsers do + bool keep_alive = false; + for (int i = 0; i < responses.size(); i++) { String header = responses[i].strip_edges(); @@ -365,13 +373,14 @@ Error HTTPClient::poll() { if (s.begins_with("content-length:")) { body_size = s.substr(s.find(":") + 1, s.length()).strip_edges().to_int(); body_left = body_size; - } - if (s.begins_with("transfer-encoding:")) { + } else if (s.begins_with("transfer-encoding:")) { String encoding = header.substr(header.find(":") + 1, header.length()).strip_edges(); if (encoding == "chunked") { chunked = true; } + } else if (s.begins_with("connection: keep-alive")) { + keep_alive = true; } if (i == 0 && responses[i].begins_with("HTTP")) { @@ -384,11 +393,16 @@ Error HTTPClient::poll() { } } - if (body_size == 0 && !chunked) { + if (body_size || chunked) { - status = STATUS_CONNECTED; // Ready for new requests - } else { status = STATUS_BODY; + } else if (!keep_alive) { + + read_until_eof = true; + status = STATUS_BODY; + } else { + + status = STATUS_CONNECTED; } return OK; } @@ -515,34 +529,53 @@ PoolByteArray HTTPClient::read_response_body_chunk() { } else { - int to_read = MIN(body_left, read_chunk_size); + int to_read = !read_until_eof ? MIN(body_left, read_chunk_size) : read_chunk_size; PoolByteArray ret; ret.resize(to_read); int _offset = 0; - while (to_read > 0) { + while (read_until_eof || to_read > 0) { int rec = 0; { PoolByteArray::Write w = ret.write(); err = _get_http_data(w.ptr() + _offset, to_read, rec); } - if (rec > 0) { - body_left -= rec; - to_read -= rec; - _offset += rec; - } else { + if (rec < 0) { if (to_read > 0) // Ended up reading less ret.resize(_offset); break; + } else { + _offset += rec; + if (!read_until_eof) { + body_left -= rec; + to_read -= rec; + } else { + if (rec < to_read) { + ret.resize(_offset); + err = ERR_FILE_EOF; + break; + } + ret.resize(_offset + to_read); + } } } - if (body_left == 0) { - status = STATUS_CONNECTED; + if (!read_until_eof) { + if (body_left == 0) { + status = STATUS_CONNECTED; + } + return ret; + } else { + if (err == ERR_FILE_EOF) { + err = OK; // EOF is expected here + close(); + return ret; + } } - return ret; } if (err != OK) { + close(); + if (err == ERR_FILE_EOF) { status = STATUS_DISCONNECTED; // Server disconnected @@ -602,6 +635,7 @@ HTTPClient::HTTPClient() { body_size = 0; chunked = false; body_left = 0; + read_until_eof = false; chunk_left = 0; response_num = 0; ssl = false; diff --git a/core/io/http_client.h b/core/io/http_client.h index 839012e701..38ec82ce8c 100644 --- a/core/io/http_client.h +++ b/core/io/http_client.h @@ -173,6 +173,7 @@ private: int chunk_left; int body_size; int body_left; + bool read_until_eof; Ref<StreamPeerTCP> tcp_connection; Ref<StreamPeer> connection; diff --git a/core/project_settings.cpp b/core/project_settings.cpp index ac4a4b7d15..ef485cb3b2 100644 --- a/core/project_settings.cpp +++ b/core/project_settings.cpp @@ -1071,6 +1071,7 @@ ProjectSettings::ProjectSettings() { GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_mode", 2); GLOBAL_DEF("debug/settings/profiler/max_functions", 16384); + GLOBAL_DEF("debug/settings/performance/update_frequency_msec", 250); //assigning here, because using GLOBAL_GET on every block for compressing can be slow Compression::zstd_long_distance_matching = GLOBAL_DEF("compression/formats/zstd/long_distance_matching", false); diff --git a/core/script_debugger_remote.cpp b/core/script_debugger_remote.cpp index 75bcedbbc8..7a30a33c67 100644 --- a/core/script_debugger_remote.cpp +++ b/core/script_debugger_remote.cpp @@ -854,7 +854,7 @@ void ScriptDebuggerRemote::idle_poll() { if (performance) { uint64_t pt = OS::get_singleton()->get_ticks_msec(); - if (pt - last_perf_time > 1000) { + if (pt - last_perf_time > update_frequency) { last_perf_time = pt; int max = performance->get("MONITOR_MAX"); @@ -1081,7 +1081,7 @@ ScriptDebuggerRemote::ScriptDebuggerRemote() : eh.userdata = this; add_error_handler(&eh); - profile_info.resize(CLAMP(int(ProjectSettings::get_singleton()->get("debug/settings/profiler/max_functions")), 128, 65535)); + profile_info.resize(CLAMP(int(GLOBAL_GET("debug/settings/profiler/max_functions")), 128, 65535)); profile_info_ptrs.resize(profile_info.size()); } diff --git a/core/script_language.cpp b/core/script_language.cpp index 1dab58e29e..ce9b138bb2 100644 --- a/core/script_language.cpp +++ b/core/script_language.cpp @@ -29,6 +29,7 @@ /*************************************************************************/ #include "script_language.h" +#include "project_settings.h" ScriptLanguage *ScriptServer::_languages[MAX_LANGUAGES]; int ScriptServer::_language_count = 0; @@ -283,6 +284,7 @@ ScriptDebugger::ScriptDebugger() { lines_left = -1; depth = -1; break_lang = NULL; + update_frequency = GLOBAL_GET("debug/settings/performance/update_frequency_msec"); } bool PlaceHolderScriptInstance::set(const StringName &p_name, const Variant &p_value) { diff --git a/core/script_language.h b/core/script_language.h index b4c55cac9e..64c6f2eb81 100644 --- a/core/script_language.h +++ b/core/script_language.h @@ -352,6 +352,8 @@ class ScriptDebugger { public: typedef void (*RequestSceneTreeMessageFunc)(void *); + int update_frequency; + struct LiveEditFuncs { void *udata; diff --git a/core/ustring.cpp b/core/ustring.cpp index 85b7a16e6a..51f05468e2 100644 --- a/core/ustring.cpp +++ b/core/ustring.cpp @@ -753,6 +753,46 @@ Vector<String> String::split(const String &p_splitter, bool p_allow_empty, int p return ret; } +Vector<String> String::rsplit(const String &p_splitter, bool p_allow_empty, int p_maxsplit) const { + + Vector<String> ret; + const int len = length(); + int from = len; + + while (true) { + + int end = rfind(p_splitter, from); + if (end < 0) + end = 0; + + if (p_allow_empty || (end < from)) { + const String str = substr(end > 0 ? end + p_splitter.length() : end, end > 0 ? from - end : from + 2); + + if (p_maxsplit <= 0) { + ret.push_back(str); + } else if (p_maxsplit > 0) { + + // Put rest of the string and leave cycle. + if (p_maxsplit == ret.size()) { + ret.push_back(substr(0, from + 2)); + break; + } + + // Otherwise, push items until positive limit is reached. + ret.push_back(str); + } + } + + if (end == 0) + break; + + from = end - p_splitter.length(); + } + + ret.invert(); + return ret; +} + Vector<float> String::split_floats(const String &p_splitter, bool p_allow_empty) const { Vector<float> ret; diff --git a/core/ustring.h b/core/ustring.h index 1ed694bb80..b57e9629d9 100644 --- a/core/ustring.h +++ b/core/ustring.h @@ -172,6 +172,7 @@ public: String get_slicec(CharType p_splitter, int p_slice) const; Vector<String> split(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; + Vector<String> rsplit(const String &p_splitter, bool p_allow_empty = true, int p_maxsplit = 0) const; Vector<String> split_spaces() const; Vector<float> split_floats(const String &p_splitter, bool p_allow_empty = true) const; Vector<float> split_floats_mk(const Vector<String> &p_splitters, bool p_allow_empty = true) const; diff --git a/core/variant_call.cpp b/core/variant_call.cpp index 4e883d496f..4158c2a60e 100644 --- a/core/variant_call.cpp +++ b/core/variant_call.cpp @@ -257,6 +257,7 @@ struct _VariantCall { VCALL_LOCALMEM2R(String, insert); VCALL_LOCALMEM0R(String, capitalize); VCALL_LOCALMEM3R(String, split); + VCALL_LOCALMEM3R(String, rsplit); VCALL_LOCALMEM2R(String, split_floats); VCALL_LOCALMEM0R(String, to_upper); VCALL_LOCALMEM0R(String, to_lower); @@ -1469,6 +1470,7 @@ void register_variant_methods() { ADDFUNC2R(STRING, STRING, String, insert, INT, "position", STRING, "what", varray()); ADDFUNC0R(STRING, STRING, String, capitalize, varray()); ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, split, STRING, "divisor", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); + ADDFUNC3R(STRING, POOL_STRING_ARRAY, String, rsplit, STRING, "divisor", BOOL, "allow_empty", INT, "maxsplit", varray(true, 0)); ADDFUNC2R(STRING, POOL_REAL_ARRAY, String, split_floats, STRING, "divisor", BOOL, "allow_empty", varray(true)); ADDFUNC0R(STRING, STRING, String, to_upper, varray()); diff --git a/doc/classes/Array.xml b/doc/classes/Array.xml index 5f85751c13..35c120cd6a 100644 --- a/doc/classes/Array.xml +++ b/doc/classes/Array.xml @@ -282,7 +282,7 @@ </method> <method name="sort"> <description> - Sort the array using natural order and return reference to the array. + Sort the array using natural order. </description> </method> <method name="sort_custom"> @@ -291,7 +291,7 @@ <argument index="1" name="func" type="String"> </argument> <description> - Sort the array using a custom method and return reference to the array. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior. + Sort the array using a custom method. The arguments are an object that holds the method and the name of such method. The custom method receives two arguments (a pair of elements from the array) and must return true if the first argument is less than the second, and return false otherwise. Note: you cannot randomize the return value as the heapsort algorithm expects a deterministic result. Doing so will result in unexpected behavior. [codeblock] class MyCustomSorter: static func sort(a, b): diff --git a/doc/classes/AudioStreamSample.xml b/doc/classes/AudioStreamSample.xml index 8b6651abe7..b6abda1a6f 100644 --- a/doc/classes/AudioStreamSample.xml +++ b/doc/classes/AudioStreamSample.xml @@ -13,6 +13,9 @@ <methods> </methods> <members> + <member name="data" type="PoolByteArray" setter="set_data" getter="get_data"> + Contains the audio data in bytes. + </member> <member name="format" type="int" setter="set_format" getter="get_format" enum="AudioStreamSample.Format"> Audio format. See FORMAT_* constants for values. </member> diff --git a/doc/classes/Curve2D.xml b/doc/classes/Curve2D.xml index 71bdaff688..26de8be42c 100644 --- a/doc/classes/Curve2D.xml +++ b/doc/classes/Curve2D.xml @@ -55,6 +55,8 @@ <argument index="0" name="to_point" type="Vector2"> </argument> <description> + Returns the closest offset to [code]to_point[/code]. This offset is meant to be used in [method interpolate_baked]. + [code]to_point[/code] must be in this curve's local space. </description> </method> <method name="get_closest_point" qualifiers="const"> @@ -63,6 +65,8 @@ <argument index="0" name="to_point" type="Vector2"> </argument> <description> + Returns the closest point (in curve's local space) to [code]to_point[/code]. + [code]to_point[/code] must be in this curve's local space. </description> </method> <method name="get_point_count" qualifiers="const"> diff --git a/doc/classes/Curve3D.xml b/doc/classes/Curve3D.xml index c012e2794e..1355c74faf 100644 --- a/doc/classes/Curve3D.xml +++ b/doc/classes/Curve3D.xml @@ -56,12 +56,22 @@ Returns the cache of tilts as a [RealArray]. </description> </method> + <method name="get_baked_up_vectors" qualifiers="const"> + <return type="PoolVector3Array"> + </return> + <description> + Returns the cache of up vectors as a [PoolVector3Array]. + If [member up_vector_enabled] is [code]false[/code], the cache will be empty. + </description> + </method> <method name="get_closest_offset" qualifiers="const"> <return type="float"> </return> <argument index="0" name="to_point" type="Vector3"> </argument> <description> + Returns the closest offset to [code]to_point[/code]. This offset is meant to be used in one of the interpolate_baked* methods. + [code]to_point[/code] must be in this curve's local space. </description> </method> <method name="get_closest_point" qualifiers="const"> @@ -70,6 +80,8 @@ <argument index="0" name="to_point" type="Vector3"> </argument> <description> + Returns the closest point (in curve's local space) to [code]to_point[/code]. + [code]to_point[/code] must be in this curve's local space. </description> </method> <method name="get_point_count" qualifiers="const"> @@ -140,6 +152,19 @@ Cubic interpolation tends to follow the curves better, but linear is faster (and often, precise enough). </description> </method> + <method name="interpolate_baked_up_vector" qualifiers="const"> + <return type="Vector3"> + </return> + <argument index="0" name="offset" type="float"> + </argument> + <argument index="1" name="apply_tilt" type="bool" default="false"> + </argument> + <description> + Returns an up vector within the curve at position [code]offset[/code], where [code]offset[/code] is measured as a distance in 3D units along the curve. + To do that, it finds the two cached up vectors where the [code]offset[/code] lies between, then interpolates the values. If [code]apply_tilt[/code] is [code]true[/code], an interpolated tilt is applied to the interpolated up vector. + If the curve has no up vectors, the function sends an error to the console, and returns (0, 1, 0). + </description> + </method> <method name="interpolatef" qualifiers="const"> <return type="Vector3"> </return> @@ -200,7 +225,7 @@ </argument> <description> Sets the tilt angle in radians for the point "idx". If the index is out of bounds, the function sends an error to the console. - The tilt controls the rotation along the look-at axis an object traveling the path would have. In the case of a curve controlling a [PathFollow], this tilt is an offset over the natural tilt the PathFollow calculates. + The tilt controls the rotation along the look-at axis an object traveling the path would have. In the case of a curve controlling a [PathFollow] or [OrientedPathFollow], this tilt is an offset over the natural tilt the [PathFollow] or [OrientedPathFollow] calculates. </description> </method> <method name="tessellate" qualifiers="const"> @@ -222,6 +247,9 @@ <member name="bake_interval" type="float" setter="set_bake_interval" getter="get_bake_interval"> The distance in meters between two adjacent cached points. Changing it forces the cache to be recomputed the next time the [method get_baked_points] or [method get_baked_length] function is called. The smaller the distance, the more points in the cache and the more memory it will consume, so use with care. </member> + <member name="up_vector_enabled" type="bool" setter="set_up_vector_enabled" getter="is_up_vector_enabled"> + If [code]true[/code], the curve will bake up vectors used for orientation. See [OrientedPathFollow]. Changing it forces the cache to be recomputed. + </member> </members> <constants> </constants> diff --git a/doc/classes/OrientedPathFollow.xml b/doc/classes/OrientedPathFollow.xml new file mode 100644 index 0000000000..c32e545ff5 --- /dev/null +++ b/doc/classes/OrientedPathFollow.xml @@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="OrientedPathFollow" inherits="Spatial" category="Core" version="3.1"> + <brief_description> + Oriented point sampler for a [Path]. + </brief_description> + <description> + This node behaves like [PathFollow], except it uses its parent [Path] up vector information to enforce orientation. + Make sure to check if the curve of this node's parent [Path] has up vectors enabled. See [PathFollow] and [Curve3D] for further information. + </description> + <tutorials> + </tutorials> + <demos> + </demos> + <methods> + </methods> + <members> + <member name="cubic_interp" type="bool" setter="set_cubic_interpolation" getter="get_cubic_interpolation"> + If [code]true[/code] the position between two cached points is interpolated cubically, and linearly otherwise. + The points along the [Curve3D] of the [Path] are precomputed before use, for faster calculations. The point at the requested offset is then calculated interpolating between two adjacent cached points. This may present a problem if the curve makes sharp turns, as the cached points may not follow the curve closely enough. + There are two answers to this problem: Either increase the number of cached points and increase memory consumption, or make a cubic interpolation between two points at the cost of (slightly) slower calculations. + </member> + <member name="h_offset" type="float" setter="set_h_offset" getter="get_h_offset"> + The node's offset along the curve. + </member> + <member name="loop" type="bool" setter="set_loop" getter="has_loop"> + If [code]true[/code], any offset outside the path's length will wrap around, instead of stopping at the ends. Use it for cyclic paths. + </member> + <member name="offset" type="float" setter="set_offset" getter="get_offset"> + The distance from the first vertex, measured in 3D units along the path. This sets this node's position to a point within the path. + </member> + <member name="unit_offset" type="float" setter="set_unit_offset" getter="get_unit_offset"> + The distance from the first vertex, considering 0.0 as the first vertex and 1.0 as the last. This is just another way of expressing the offset within the path, as the offset supplied is multiplied internally by the path's length. + </member> + <member name="v_offset" type="float" setter="set_v_offset" getter="get_v_offset"> + The node's offset perpendicular to the curve. + </member> + </members> + <constants> + </constants> +</class> diff --git a/doc/classes/Plane.xml b/doc/classes/Plane.xml index 157bf42239..ca035ad383 100644 --- a/doc/classes/Plane.xml +++ b/doc/classes/Plane.xml @@ -24,7 +24,7 @@ <argument index="3" name="d" type="float"> </argument> <description> - Creates a plane from the three parameters "a", "b", "c" and "d". + Creates a plane from the four parameters "a", "b", "c" and "d". </description> </method> <method name="Plane"> diff --git a/doc/classes/Shader.xml b/doc/classes/Shader.xml index 732881c777..7c07778a05 100644 --- a/doc/classes/Shader.xml +++ b/doc/classes/Shader.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="Shader" inherits="Resource" category="Core" version="3.1"> <brief_description> - To be changed, ignore. + A custom shader program. </brief_description> <description> - To be changed, ignore. + This class allows you to define a custom shader program that can be used for various materials to render objects. </description> <tutorials> http://docs.godotengine.org/en/3.0/tutorials/shading/index.html @@ -24,6 +24,7 @@ <return type="int" enum="Shader.Mode"> </return> <description> + Returns the shader mode for the shader, eiter [code]MODE_CANVAS_ITEM[/code], [code]MODE_SPATIAL[/code] or [code]MODE_PARTICLES[/code] </description> </method> <method name="has_param" qualifiers="const"> diff --git a/doc/classes/ShaderMaterial.xml b/doc/classes/ShaderMaterial.xml index 4767686a8f..058e00e46c 100644 --- a/doc/classes/ShaderMaterial.xml +++ b/doc/classes/ShaderMaterial.xml @@ -1,8 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="ShaderMaterial" inherits="Material" category="Core" version="3.1"> <brief_description> + A material that uses a custom [Shader] program </brief_description> <description> + A material that uses a custom [Shader] program to render either items to screen or process particles. You can create multiple materials for the same shader but configure different values for the uniforms defined in the shader. </description> <tutorials> </tutorials> @@ -15,6 +17,7 @@ <argument index="0" name="param" type="String"> </argument> <description> + Returns the current value set for this material of a uniform in the shader </description> </method> <method name="set_shader_param"> @@ -25,11 +28,13 @@ <argument index="1" name="value" type="Variant"> </argument> <description> + Changes the value set for this material of a uniform in the shader </description> </method> </methods> <members> <member name="shader" type="Shader" setter="set_shader" getter="get_shader"> + The [Shader] program used to render this material </member> </members> <constants> diff --git a/doc/classes/String.xml b/doc/classes/String.xml index 83fb76f287..a55e184474 100644 --- a/doc/classes/String.xml +++ b/doc/classes/String.xml @@ -688,6 +688,20 @@ If [code]maxsplit[/code] is given, at most maxsplit number of splits occur, and the remainder of the string is returned as the final element of the list (thus, the list will have at most maxsplit+1 elements) </description> </method> + <method name="rsplit"> + <return type="PoolStringArray"> + </return> + <argument index="0" name="divisor" type="String"> + </argument> + <argument index="1" name="allow_empty" type="bool" default="True"> + </argument> + <argument index="2" name="maxsplit" type="int" default="0"> + </argument> + <description> + Splits the string by a [code]divisor[/code] string and returns an array of the substrings, starting from right. Example "One,Two,Three" will return ["One","Two","Three"] if split by ",". + If [code]maxsplit[/code] is specified, then it is number of splits to do, default is 0 which splits all the items. + </description> + </method> <method name="split_floats"> <return type="PoolRealArray"> </return> diff --git a/doc/classes/TextureRect.xml b/doc/classes/TextureRect.xml index 7a4208ccea..95afc5d281 100644 --- a/doc/classes/TextureRect.xml +++ b/doc/classes/TextureRect.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="TextureRect" inherits="Control" category="Core" version="3.1"> <brief_description> - Draws a sprite or a texture inside a User Interface. The texture can tile or not. + Control for drawing textures. </brief_description> <description> - Use TextureRect to draw icons and sprites in your User Interfaces. To create panels and menu boxes, take a look at [NinePatchFrame]. Its Stretch Mode property controls the texture's scale and placement. It can scale, tile and stay centered inside its bounding rectangle. TextureRect is one of the 5 most common nodes to create game UI. + Used to draw icons and sprites in a user interface. The texture's placement can be controlled with the [member stretch_mode] property. It can scale, tile, or stay centered inside its bounding rectangle. </description> <tutorials> </tutorials> @@ -14,10 +14,10 @@ </methods> <members> <member name="expand" type="bool" setter="set_expand" getter="has_expand"> - If [code]true[/code], the texture scales to fit its bounding rectangle. Default value: [code]false[/code]. + If [code]true[/code] the texture scales to fit its bounding rectangle. Default value: [code]false[/code]. </member> <member name="stretch_mode" type="int" setter="set_stretch_mode" getter="get_stretch_mode" enum="TextureRect.StretchMode"> - Controls the texture's behavior when you resize the node's bounding rectangle. Set it to one of the [code]STRETCH_*[/code] constants. See the constants to learn more. + Controls the texture's behavior when resizing the node's bounding rectangle. See [enum StretchMode]. </member> <member name="texture" type="Texture" setter="set_texture" getter="get_texture"> The node's [Texture] resource. diff --git a/doc/classes/VideoPlayer.xml b/doc/classes/VideoPlayer.xml index d2639590a1..9ffa3aa52b 100644 --- a/doc/classes/VideoPlayer.xml +++ b/doc/classes/VideoPlayer.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="VideoPlayer" inherits="Control" category="Core" version="3.1"> <brief_description> - Control to play video files. + Control for playing video streams. </brief_description> <description> - This control has the ability to play video streams. The only format accepted is the OGV Theora, so any other format must be converted before using in a project. + Control node for playing video streams. Supported formats are WebM and OGV Theora. </description> <tutorials> </tutorials> @@ -15,51 +15,56 @@ <return type="String"> </return> <description> - Get the name of the video stream. + Returns the video stream's name. </description> </method> <method name="get_video_texture"> <return type="Texture"> </return> <description> - Get the current frame of the video as a [Texture]. + Returns the current frame as a [Texture]. </description> </method> <method name="is_playing" qualifiers="const"> <return type="bool"> </return> <description> - Get whether or not the video is playing. + Returns [code]true[/code] if the video is playing. </description> </method> <method name="play"> <return type="void"> </return> <description> - Start the video playback. + Starts the video playback. </description> </method> <method name="stop"> <return type="void"> </return> <description> - Stop the video playback. + Stops the video playback. </description> </method> </methods> <members> <member name="audio_track" type="int" setter="set_audio_track" getter="get_audio_track"> + The embedded audio track to play. </member> <member name="autoplay" type="bool" setter="set_autoplay" getter="has_autoplay"> + If [code]true[/code] playback starts when the scene loads. Default value: [code]false[/code]. </member> <member name="buffering_msec" type="int" setter="set_buffering_msec" getter="get_buffering_msec"> - The amount of milliseconds to store in buffer while playing. + Amount of time in milliseconds to store in buffer while playing. </member> <member name="bus" type="String" setter="set_bus" getter="get_bus"> + Audio bus to use for sound playback. </member> <member name="expand" type="bool" setter="set_expand" getter="has_expand"> + If [code]true[/code] the video scales to the control size. Default value: [code]true[/code]. </member> <member name="paused" type="bool" setter="set_paused" getter="is_paused"> + If [code]true[/code] the video is paused. </member> <member name="stream" type="VideoStream" setter="set_stream" getter="get_stream"> </member> @@ -67,14 +72,16 @@ The current position of the stream, in seconds. </member> <member name="volume" type="float" setter="set_volume" getter="get_volume"> - The volume of the audio track as a linear value. + Audio volume as a linear value. </member> <member name="volume_db" type="float" setter="set_volume_db" getter="get_volume_db"> + Audio volume in dB. </member> </members> <signals> <signal name="finished"> <description> + Emitted when playback is finished. </description> </signal> </signals> diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index ff423bf0d0..bb4c8ab4d7 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -193,11 +193,11 @@ void RasterizerCanvasGLES3::canvas_end() { state.using_ninepatch = false; } -RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map) { +RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force) { RasterizerStorageGLES3::Texture *tex_return = NULL; - if (p_texture == state.current_tex) { + if (p_texture == state.current_tex && !p_force) { tex_return = state.current_tex_ptr; } else if (p_texture.is_valid()) { @@ -232,7 +232,7 @@ RasterizerStorageGLES3::Texture *RasterizerCanvasGLES3::_bind_canvas_texture(con state.current_tex_ptr = NULL; } - if (p_normal_map == state.current_normal) { + if (p_normal_map == state.current_normal && !p_force) { //do none state.canvas_shader.set_uniform(CanvasShaderGLES3::USE_DEFAULT_NORMAL, state.current_normal.is_valid()); @@ -1086,7 +1086,7 @@ void RasterizerCanvasGLES3::_copy_texscreen(const Rect2 &p_rect) { state.using_texture_rect = true; _set_texture_rect_mode(false); - _bind_canvas_texture(state.current_tex, state.current_normal); + _bind_canvas_texture(state.current_tex, state.current_normal, true); glEnable(GL_BLEND); } diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index bfaf1fdb4b..c7f2e54efb 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -123,7 +123,7 @@ public: virtual void canvas_end(); _FORCE_INLINE_ void _set_texture_rect_mode(bool p_enable, bool p_ninepatch = false); - _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map); + _FORCE_INLINE_ RasterizerStorageGLES3::Texture *_bind_canvas_texture(const RID &p_texture, const RID &p_normal_map, bool p_force = false); _FORCE_INLINE_ void _draw_gui_primitive(int p_points, const Vector2 *p_vertices, const Color *p_colors, const Vector2 *p_uvs); _FORCE_INLINE_ void _draw_polygon(const int *p_indices, int p_index_count, int p_vertex_count, const Vector2 *p_vertices, const Vector2 *p_uvs, const Color *p_colors, bool p_singlecolor, const int *p_bones, const float *p_weights); diff --git a/drivers/unix/stream_peer_tcp_posix.cpp b/drivers/unix/stream_peer_tcp_posix.cpp index 6d798f32f9..44b9ef1d7c 100644 --- a/drivers/unix/stream_peer_tcp_posix.cpp +++ b/drivers/unix/stream_peer_tcp_posix.cpp @@ -297,6 +297,7 @@ Error StreamPeerTCPPosix::read(uint8_t *p_buffer, int p_bytes, int &r_received, status = STATUS_NONE; peer_port = 0; peer_host = IP_Address(); + r_received = total_read; return ERR_FILE_EOF; } else { diff --git a/drivers/windows/stream_peer_tcp_winsock.cpp b/drivers/windows/stream_peer_tcp_winsock.cpp index cb501ce35d..19c937170b 100644 --- a/drivers/windows/stream_peer_tcp_winsock.cpp +++ b/drivers/windows/stream_peer_tcp_winsock.cpp @@ -212,6 +212,7 @@ Error StreamPeerTCPWinsock::read(uint8_t *p_buffer, int p_bytes, int &r_received _block(sockfd, true, false); } else if (read == 0) { disconnect_from_host(); + r_received = total_read; return ERR_FILE_EOF; } else { diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 708bff252a..de9203232c 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -52,6 +52,13 @@ void EditorAutoloadSettings::_notification(int p_what) { file_dialog->add_filter("*." + E->get()); } + + for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) { + AutoLoadInfo &info = E->get(); + if (info.node && info.in_editor) { + get_tree()->get_root()->call_deferred("add_child", info.node); + } + } } } @@ -291,6 +298,36 @@ void EditorAutoloadSettings::_autoload_file_callback(const String &p_path) { autoload_add_name->set_text(p_path.get_file().get_basename()); } +Node *EditorAutoloadSettings::_create_autoload(const String &p_path) { + RES res = ResourceLoader::load(p_path); + ERR_EXPLAIN("Can't autoload: " + p_path); + ERR_FAIL_COND_V(res.is_null(), NULL); + Node *n = NULL; + if (res->is_class("PackedScene")) { + Ref<PackedScene> ps = res; + n = ps->instance(); + } else if (res->is_class("Script")) { + Ref<Script> s = res; + StringName ibt = s->get_instance_base_type(); + bool valid_type = ClassDB::is_parent_class(ibt, "Node"); + ERR_EXPLAIN("Script does not inherit a Node: " + p_path); + ERR_FAIL_COND_V(!valid_type, NULL); + + Object *obj = ClassDB::instance(ibt); + + ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt)); + ERR_FAIL_COND_V(obj == NULL, NULL); + + n = Object::cast_to<Node>(obj); + n->set_script(s.get_ref_ptr()); + } + + ERR_EXPLAIN("Path in autoload not a node or script: " + p_path); + ERR_FAIL_COND_V(!n, NULL); + + return n; +} + void EditorAutoloadSettings::update_autoload() { if (updating_autoload) @@ -299,15 +336,11 @@ void EditorAutoloadSettings::update_autoload() { updating_autoload = true; Map<String, AutoLoadInfo> to_remove; - Map<String, AutoLoadInfo> to_remove_singleton; - List<AutoLoadInfo> to_add; - List<String> to_add_singleton; // Only for when the node is still the same + List<AutoLoadInfo *> to_add; for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) { - to_remove.insert(E->get().name, E->get()); - if (E->get().is_singleton) { - to_remove_singleton.insert(E->get().name, E->get()); - } + AutoLoadInfo &info = E->get(); + to_remove.insert(info.name, info); } autoload_cache.clear(); @@ -331,11 +364,6 @@ void EditorAutoloadSettings::update_autoload() { if (name.empty()) continue; - AutoLoadInfo old_info; - if (to_remove.has(name)) { - old_info = to_remove[name]; - } - AutoLoadInfo info; info.is_singleton = path.begins_with("*"); @@ -347,28 +375,31 @@ void EditorAutoloadSettings::update_autoload() { info.path = path; info.order = ProjectSettings::get_singleton()->get_order(pi.name); - if (old_info.name == info.name) { + bool need_to_add = true; + if (to_remove.has(name)) { + AutoLoadInfo &old_info = to_remove[name]; if (old_info.path == info.path) { - // Still the same resource, check singleton status - to_remove.erase(name); - if (info.is_singleton) { - if (old_info.is_singleton) { - to_remove_singleton.erase(name); + // Still the same resource, check status + info.node = old_info.node; + if (info.node) { + Ref<Script> scr = info.node->get_script(); + info.in_editor = scr.is_valid() && scr->is_tool(); + if (info.is_singleton == old_info.is_singleton && info.in_editor == old_info.in_editor) { + to_remove.erase(name); + need_to_add = false; } else { - to_add_singleton.push_back(name); + info.node = NULL; } } - } else { - // Resource changed - to_add.push_back(info); } - } else { - // New autoload - to_add.push_back(info); } autoload_cache.push_back(info); + if (need_to_add) { + to_add.push_back(&(autoload_cache.back()->get())); + } + TreeItem *item = tree->create_item(root); item->set_text(0, name); item->set_editable(0, true); @@ -387,71 +418,54 @@ void EditorAutoloadSettings::update_autoload() { item->set_selectable(3, false); } - // Remove autoload constants - for (Map<String, AutoLoadInfo>::Element *E = to_remove_singleton.front(); E; E = E->next()) { - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptServer::get_language(i)->remove_named_global_constant(E->get().name); - } - } - - // Remove obsolete nodes from the tree + // Remove deleted/changed autoloads for (Map<String, AutoLoadInfo>::Element *E = to_remove.front(); E; E = E->next()) { AutoLoadInfo &info = E->get(); - Node *al = get_node("/root/" + info.name); - ERR_CONTINUE(!al); - get_tree()->get_root()->remove_child(al); - memdelete(al); - } + if (info.is_singleton) { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptServer::get_language(i)->remove_named_global_constant(info.name); + } + } + if (info.in_editor) { + ERR_CONTINUE(!info.node); + get_tree()->get_root()->remove_child(info.node); + } - // Register new singletons already in the tree - for (List<String>::Element *E = to_add_singleton.front(); E; E = E->next()) { - Node *al = get_node("/root/" + E->get()); - ERR_CONTINUE(!al); - for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptServer::get_language(i)->add_named_global_constant(E->get(), al); + if (info.node) { + memdelete(info.node); + info.node = NULL; } } - // Add new nodes to the tree + // Load new/changed autoloads List<Node *> nodes_to_add; - for (List<AutoLoadInfo>::Element *E = to_add.front(); E; E = E->next()) { - AutoLoadInfo &info = E->get(); + for (List<AutoLoadInfo *>::Element *E = to_add.front(); E; E = E->next()) { + AutoLoadInfo *info = E->get(); - RES res = ResourceLoader::load(info.path); - ERR_EXPLAIN("Can't autoload: " + info.path); - ERR_CONTINUE(res.is_null()); - Node *n = NULL; - if (res->is_class("PackedScene")) { - Ref<PackedScene> ps = res; - n = ps->instance(); - } else if (res->is_class("Script")) { - Ref<Script> s = res; - StringName ibt = s->get_instance_base_type(); - bool valid_type = ClassDB::is_parent_class(ibt, "Node"); - ERR_EXPLAIN("Script does not inherit a Node: " + info.path); - ERR_CONTINUE(!valid_type); - - Object *obj = ClassDB::instance(ibt); - - ERR_EXPLAIN("Cannot instance script for autoload, expected 'Node' inheritance, got: " + String(ibt)); - ERR_CONTINUE(obj == NULL); - - n = Object::cast_to<Node>(obj); - n->set_script(s.get_ref_ptr()); - } + info->node = _create_autoload(info->path); - ERR_EXPLAIN("Path in autoload not a node or script: " + info.path); - ERR_CONTINUE(!n); - n->set_name(info.name); + ERR_CONTINUE(!info->node); + info->node->set_name(info->name); - //defer so references are all valid on _ready() - nodes_to_add.push_back(n); + Ref<Script> scr = info->node->get_script(); + info->in_editor = scr.is_valid() && scr->is_tool(); - if (info.is_singleton) { + if (info->in_editor) { + //defer so references are all valid on _ready() + nodes_to_add.push_back(info->node); + } + + if (info->is_singleton) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { - ScriptServer::get_language(i)->add_named_global_constant(info.name, n); + ScriptServer::get_language(i)->add_named_global_constant(info->name, info->node); } } + + if (!info->in_editor && !info->is_singleton) { + // No reason to keep this node + memdelete(info->node); + info->node = NULL; + } } for (List<Node *>::Element *E = nodes_to_add.front(); E; E = E->next()) { @@ -728,6 +742,24 @@ EditorAutoloadSettings::EditorAutoloadSettings() { info.name = name; info.path = path; info.order = ProjectSettings::get_singleton()->get_order(pi.name); + info.node = _create_autoload(path); + + if (info.node) { + Ref<Script> scr = info.node->get_script(); + info.in_editor = scr.is_valid() && scr->is_tool(); + info.node->set_name(info.name); + } + + if (info.is_singleton) { + for (int i = 0; i < ScriptServer::get_language_count(); i++) { + ScriptServer::get_language(i)->add_named_global_constant(info.name, info.node); + } + } + + if (!info.is_singleton && !info.in_editor) { + memdelete(info.node); + info.node = NULL; + } autoload_cache.push_back(info); } @@ -796,3 +828,12 @@ EditorAutoloadSettings::EditorAutoloadSettings() { add_child(tree, true); } + +EditorAutoloadSettings::~EditorAutoloadSettings() { + for (List<AutoLoadInfo>::Element *E = autoload_cache.front(); E; E = E->next()) { + AutoLoadInfo &info = E->get(); + if (info.node && !info.in_editor) { + memdelete(info.node); + } + } +} diff --git a/editor/editor_autoload_settings.h b/editor/editor_autoload_settings.h index 1797c10e61..0b75faa009 100644 --- a/editor/editor_autoload_settings.h +++ b/editor/editor_autoload_settings.h @@ -52,11 +52,19 @@ class EditorAutoloadSettings : public VBoxContainer { String name; String path; bool is_singleton; + bool in_editor; int order; + Node *node; bool operator==(const AutoLoadInfo &p_info) { return order == p_info.order; } + + AutoLoadInfo() { + is_singleton = false; + in_editor = false; + node = NULL; + } }; List<AutoLoadInfo> autoload_cache; @@ -78,6 +86,7 @@ class EditorAutoloadSettings : public VBoxContainer { void _autoload_activated(); void _autoload_open(const String &fpath); void _autoload_file_callback(const String &p_path); + Node *_create_autoload(const String &p_path); Variant get_drag_data_fw(const Point2 &p_point, Control *p_control); bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_control) const; @@ -93,6 +102,7 @@ public: void autoload_remove(const String &p_name); EditorAutoloadSettings(); + ~EditorAutoloadSettings(); }; #endif diff --git a/editor/editor_data.cpp b/editor/editor_data.cpp index 4ac3e33cb9..d41d5c929a 100644 --- a/editor/editor_data.cpp +++ b/editor/editor_data.cpp @@ -420,6 +420,18 @@ void EditorData::paste_object_params(Object *p_object) { } } +bool EditorData::call_build() { + + bool result = true; + + for (int i = 0; i < editor_plugins.size() && result; i++) { + + result &= editor_plugins[i]->build(); + } + + return result; +} + UndoRedo &EditorData::get_undo_redo() { return undo_redo; diff --git a/editor/editor_data.h b/editor/editor_data.h index f020d07ea7..0452867bf4 100644 --- a/editor/editor_data.h +++ b/editor/editor_data.h @@ -197,6 +197,7 @@ public: NodePath get_edited_scene_live_edit_root(); bool check_and_update_scene(int p_idx); void move_edited_scene_to_index(int p_idx); + bool call_build(); void set_plugin_window_layout(Ref<ConfigFile> p_layout); void get_plugin_window_layout(Ref<ConfigFile> p_layout); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index f9b104cdae..b49c2d26d0 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -1978,8 +1978,27 @@ FindBar::FindBar() { } void FindBar::popup_search() { + show(); - search_text->grab_focus(); + bool grabbed_focus = false; + if (!search_text->has_focus()) { + search_text->grab_focus(); + grabbed_focus = true; + } + + if (!search_text->get_text().empty()) { + search_text->select_all(); + search_text->set_cursor_position(search_text->get_text().length()); + if (grabbed_focus) { + _search(); + } + } + + call_deferred("_update_size"); +} + +void FindBar::_update_size() { + container->set_custom_minimum_size(Size2(0, hbc->get_size().height)); } @@ -2016,6 +2035,7 @@ void FindBar::_bind_methods() { ClassDB::bind_method("_search_next", &FindBar::search_next); ClassDB::bind_method("_search_prev", &FindBar::search_prev); ClassDB::bind_method("_hide_pressed", &FindBar::_hide_bar); + ClassDB::bind_method("_update_size", &FindBar::_update_size); ADD_SIGNAL(MethodInfo("search")); } diff --git a/editor/editor_help.h b/editor/editor_help.h index 35d98d274c..514169dc19 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -148,6 +148,8 @@ class FindBar : public HBoxContainer { void _search_text_changed(const String &p_text); void _search_text_entered(const String &p_text); + void _update_size(); + protected: void _notification(int p_what); void _unhandled_input(const Ref<InputEvent> &p_event); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index c2d2f7ddcc..f94b7cd6ee 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -520,6 +520,8 @@ bool EditorProperty::is_draw_red() const { void EditorProperty::_focusable_focused(int p_index) { + if (!selectable) + return; bool already_selected = selected; selected = true; selected_focusable = p_index; @@ -596,7 +598,7 @@ void EditorProperty::_gui_input(const Ref<InputEvent> &p_event) { if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) { - if (!selected) { + if (!selected && selectable) { selected = true; emit_signal("selected", property, -1); update(); @@ -681,6 +683,19 @@ void EditorProperty::expand_all_folding() { void EditorProperty::collapse_all_folding() { } +void EditorProperty::set_selectable(bool p_selectable) { + selectable = p_selectable; +} + +bool EditorProperty::is_selectable() const { + return selectable; +} + +void EditorProperty::set_object_and_property(Object *p_object, const StringName &p_property) { + object = p_object; + property = p_property; +} + void EditorProperty::_bind_methods() { ClassDB::bind_method(D_METHOD("set_label", "text"), &EditorProperty::set_label); @@ -729,6 +744,7 @@ void EditorProperty::_bind_methods() { EditorProperty::EditorProperty() { + selectable = true; text_size = 0; read_only = false; checkable = false; diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 14387c46df..a6b183799f 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -72,6 +72,7 @@ private: bool _get_instanced_node_original_property(const StringName &p_prop, Variant &value); void _focusable_focused(int p_index); + bool selectable; bool selected; int selected_focusable; @@ -130,6 +131,10 @@ public: virtual Variant get_drag_data(const Point2 &p_point); + void set_selectable(bool p_selectable); + bool is_selectable() const; + + void set_object_and_property(Object *p_object, const StringName &p_property); EditorProperty(); }; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index dd3b6c2c4c..4b068f1000 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4271,12 +4271,21 @@ EditorBuildCallback EditorNode::build_callbacks[EditorNode::MAX_BUILD_CALLBACKS] bool EditorNode::call_build() { - for (int i = 0; i < build_callback_count; i++) { - if (!build_callbacks[i]()) - return false; + bool builds_successful = true; + + for (int i = 0; i < build_callback_count && builds_successful; i++) { + if (!build_callbacks[i]()) { + ERR_PRINT("A Godot Engine build callback failed."); + builds_successful = false; + } } - return true; + if (builds_successful && !editor_data.call_build()) { + ERR_PRINT("An EditorPlugin build callback failed."); + builds_successful = false; + } + + return builds_successful; } void EditorNode::_inherit_imported(const String &p_action) { @@ -5379,6 +5388,7 @@ EditorNode::EditorNode() { //resource_preview->add_preview_generator( Ref<EditorSamplePreviewPlugin>( memnew(EditorSamplePreviewPlugin ))); resource_preview->add_preview_generator(Ref<EditorMeshPreviewPlugin>(memnew(EditorMeshPreviewPlugin))); resource_preview->add_preview_generator(Ref<EditorBitmapPreviewPlugin>(memnew(EditorBitmapPreviewPlugin))); + resource_preview->add_preview_generator(Ref<EditorFontPreviewPlugin>(memnew(EditorFontPreviewPlugin))); { Ref<SpatialMaterialConversionPlugin> spatial_mat_convert; diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 24d0592ee7..cc44938c25 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -689,6 +689,15 @@ void EditorPlugin::get_window_layout(Ref<ConfigFile> p_layout) { } } +bool EditorPlugin::build() { + + if (get_script_instance() && get_script_instance()->has_method("build")) { + return get_script_instance()->call("build"); + } + + return true; +} + void EditorPlugin::queue_save_layout() const { EditorNode::get_singleton()->save_layout(); @@ -767,6 +776,7 @@ void EditorPlugin::_bind_methods() { ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::POOL_STRING_ARRAY, "get_breakpoints")); ClassDB::add_virtual_method(get_class_static(), MethodInfo("set_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile"))); ClassDB::add_virtual_method(get_class_static(), MethodInfo("get_window_layout", PropertyInfo(Variant::OBJECT, "layout", PROPERTY_HINT_RESOURCE_TYPE, "ConfigFile"))); + ClassDB::add_virtual_method(get_class_static(), MethodInfo(Variant::BOOL, "build")); ADD_SIGNAL(MethodInfo("scene_changed", PropertyInfo(Variant::OBJECT, "scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node"))); ADD_SIGNAL(MethodInfo("scene_closed", PropertyInfo(Variant::STRING, "filepath"))); diff --git a/editor/editor_plugin.h b/editor/editor_plugin.h index 8af7f83771..fcc74cb1e9 100644 --- a/editor/editor_plugin.h +++ b/editor/editor_plugin.h @@ -192,6 +192,7 @@ public: virtual void set_window_layout(Ref<ConfigFile> p_layout); virtual void get_window_layout(Ref<ConfigFile> p_layout); virtual void edited_scene_changed() {} // if changes are pending in editor, apply them + virtual bool build(); // builds with external tools. Returns true if safe to continue running scene. EditorInterface *get_editor_interface(); diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 812e461a14..c6d3a43f4e 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -31,7 +31,20 @@ #include "editor_properties.h" #include "editor/editor_resource_preview.h" #include "editor_node.h" +#include "editor_properties_array_dict.h" #include "scene/main/viewport.h" + +///////////////////// NULL ///////////////////////// + +void EditorPropertyNil::update_property() { +} + +EditorPropertyNil::EditorPropertyNil() { + Label *label = memnew(Label); + label->set_text("[null]"); + add_child(label); +} + ///////////////////// TEXT ///////////////////////// void EditorPropertyText::_text_changed(const String &p_string) { if (updating) @@ -487,7 +500,7 @@ public: virtual String get_tooltip(const Point2 &p_pos) const { for (int i = 0; i < flag_rects.size(); i++) { - if (flag_rects[i].has_point(p_pos) && i < names.size()) { + if (i < names.size() && flag_rects[i].has_point(p_pos)) { return names[i]; } } @@ -1509,7 +1522,8 @@ EditorPropertyColor::EditorPropertyColor() { void EditorPropertyNodePath::_node_selected(const NodePath &p_path) { - emit_signal("property_changed", get_edited_property(), p_path); + Node *base_node = Object::cast_to<Node>(get_edited_object()); + emit_signal("property_changed", get_edited_property(), base_node->get_path().rel_path_to(p_path)); update_property(); } @@ -2273,6 +2287,10 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ switch (p_type) { // atomic types + case Variant::NIL: { + EditorPropertyNil *editor = memnew(EditorPropertyNil); + add_property_editor(p_path, editor); + } break; case Variant::BOOL: { EditorPropertyCheck *editor = memnew(EditorPropertyCheck); add_property_editor(p_path, editor); @@ -2631,24 +2649,40 @@ bool EditorInspectorDefaultPlugin::parse_property(Object *p_object, Variant::Typ } break; case Variant::DICTIONARY: { + EditorPropertyDictionary *editor = memnew(EditorPropertyDictionary); + add_property_editor(p_path, editor); } break; case Variant::ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; - - // arrays case Variant::POOL_BYTE_ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; // 20 case Variant::POOL_INT_ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; case Variant::POOL_REAL_ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; case Variant::POOL_STRING_ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; case Variant::POOL_VECTOR2_ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; case Variant::POOL_VECTOR3_ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; // 25 case Variant::POOL_COLOR_ARRAY: { + EditorPropertyArray *editor = memnew(EditorPropertyArray); + add_property_editor(p_path, editor); } break; default: {} } diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 19884cc9dc..03e72b4ec2 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -39,6 +39,15 @@ #include "editor/scene_tree_editor.h" #include "scene/gui/color_picker.h" +class EditorPropertyNil : public EditorProperty { + GDCLASS(EditorPropertyNil, EditorProperty) + LineEdit *text; + +public: + virtual void update_property(); + EditorPropertyNil(); +}; + class EditorPropertyText : public EditorProperty { GDCLASS(EditorPropertyText, EditorProperty) LineEdit *text; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp new file mode 100644 index 0000000000..90f8d0e157 --- /dev/null +++ b/editor/editor_properties_array_dict.cpp @@ -0,0 +1,999 @@ +#include "editor_properties_array_dict.h" +#include "editor/editor_scale.h" +#include "editor_properties.h" + +bool EditorPropertyArrayObject::_set(const StringName &p_name, const Variant &p_value) { + + String pn = p_name; + + if (pn.begins_with("indices")) { + int idx = pn.get_slicec('/', 1).to_int(); + array.set(idx, p_value); + return true; + } + + return false; +} + +bool EditorPropertyArrayObject::_get(const StringName &p_name, Variant &r_ret) const { + + String pn = p_name; + + if (pn.begins_with("indices")) { + + int idx = pn.get_slicec('/', 1).to_int(); + bool valid; + r_ret = array.get(idx, &valid); + return valid; + } + + return false; +} + +void EditorPropertyArrayObject::set_array(const Variant &p_array) { + array = p_array; +} + +Variant EditorPropertyArrayObject::get_array() { + return array; +} + +EditorPropertyArrayObject::EditorPropertyArrayObject() { +} + +/////////////////// + +bool EditorPropertyDictionaryObject::_set(const StringName &p_name, const Variant &p_value) { + + String pn = p_name; + + if (pn == "new_item_key") { + + new_item_key = p_value; + return true; + } + + if (pn == "new_item_value") { + + new_item_value = p_value; + return true; + } + + if (pn.begins_with("indices")) { + int idx = pn.get_slicec('/', 1).to_int(); + Variant key = dict.get_key_at_index(idx); + dict[key] = p_value; + return true; + } + + return false; +} + +bool EditorPropertyDictionaryObject::_get(const StringName &p_name, Variant &r_ret) const { + + String pn = p_name; + + if (pn == "new_item_key") { + + r_ret = new_item_key; + return true; + } + + if (pn == "new_item_value") { + + r_ret = new_item_value; + return true; + } + + if (pn.begins_with("indices")) { + + int idx = pn.get_slicec('/', 1).to_int(); + Variant key = dict.get_key_at_index(idx); + r_ret = dict[key]; + return true; + } + + return false; +} + +void EditorPropertyDictionaryObject::set_dict(const Dictionary &p_dict) { + dict = p_dict; +} + +Dictionary EditorPropertyDictionaryObject::get_dict() { + return dict; +} + +void EditorPropertyDictionaryObject::set_new_item_key(const Variant &p_new_item) { + new_item_key = p_new_item; +} + +Variant EditorPropertyDictionaryObject::get_new_item_key() { + return new_item_key; +} + +void EditorPropertyDictionaryObject::set_new_item_value(const Variant &p_new_item) { + new_item_value = p_new_item; +} + +Variant EditorPropertyDictionaryObject::get_new_item_value() { + return new_item_value; +} + +EditorPropertyDictionaryObject::EditorPropertyDictionaryObject() { +} + +///////////////////// ARRAY /////////////////////////// + +void EditorPropertyArray::_property_changed(const String &p_prop, Variant p_value) { + + if (p_prop.begins_with("indices")) { + int idx = p_prop.get_slice("/", 1).to_int(); + Variant array = object->get_array(); + array.set(idx, p_value); + emit_signal("property_changed", get_edited_property(), array); + + if (array.get_type() == Variant::ARRAY) { + array = array.call("duplicate"); //dupe, so undo/redo works better + } + object->set_array(array); + } +} + +void EditorPropertyArray::_change_type(Object *p_button, int p_index) { + + Button *button = Object::cast_to<Button>(p_button); + + Rect2 rect = button->get_global_rect(); + change_type->set_as_minsize(); + change_type->set_global_position(rect.position + rect.size - Vector2(change_type->get_combined_minimum_size().x, 0)); + change_type->popup(); + changing_type_idx = p_index; +} + +void EditorPropertyArray::_change_type_menu(int p_index) { + + Variant value; + Variant::CallError ce; + value = Variant::construct(Variant::Type(p_index), NULL, 0, ce); + Variant array = object->get_array(); + array.set(changing_type_idx, value); + + emit_signal("property_changed", get_edited_property(), array); + + if (array.get_type() == Variant::ARRAY) { + array = array.call("duplicate"); //dupe, so undo/redo works better + } + object->set_array(array); + update_property(); +} + +void EditorPropertyArray::update_property() { + + Variant array = get_edited_object()->get(get_edited_property()); + + if ((!array.is_array()) != edit->is_disabled()) { + + if (array.is_array()) { + edit->set_disabled(false); + edit->set_pressed(false); + + } else { + edit->set_disabled(true); + if (vbox) { + memdelete(vbox); + } + } + } + + if (!array.is_array()) { + return; + } + + String arrtype; + switch (array.get_type()) { + case Variant::ARRAY: { + + arrtype = "Array"; + + } break; + + // arrays + case Variant::POOL_BYTE_ARRAY: { + arrtype = "ByteArray"; + + } break; + case Variant::POOL_INT_ARRAY: { + arrtype = "IntArray"; + + } break; + case Variant::POOL_REAL_ARRAY: { + + arrtype = "FltArray"; + } break; + case Variant::POOL_STRING_ARRAY: { + + arrtype = "StrArray"; + } break; + case Variant::POOL_VECTOR2_ARRAY: { + + arrtype = "Vec2Array"; + } break; + case Variant::POOL_VECTOR3_ARRAY: { + arrtype = "Vec3Array"; + + } break; + case Variant::POOL_COLOR_ARRAY: { + arrtype = "ColArray"; + } break; + default: {} + } + + edit->set_text(arrtype + "[" + itos(array.call("size")) + "]"); + +#ifdef TOOLS_ENABLED + + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); + if (edit->is_pressed() != unfolded) { + edit->set_pressed(unfolded); + } + + if (unfolded) { + + updating = true; + + if (!vbox) { + + vbox = memnew(VBoxContainer); + add_child(vbox); + set_bottom_editor(vbox); + HBoxContainer *hbc = memnew(HBoxContainer); + vbox->add_child(hbc); + Label *label = memnew(Label(TTR("Size: "))); + label->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(label); + length = memnew(EditorSpinSlider); + length->set_step(1); + length->set_max(1000000); + length->set_h_size_flags(SIZE_EXPAND_FILL); + hbc->add_child(length); + length->connect("value_changed", this, "_length_changed"); + + page_hb = memnew(HBoxContainer); + vbox->add_child(page_hb); + label = memnew(Label(TTR("Page: "))); + label->set_h_size_flags(SIZE_EXPAND_FILL); + page_hb->add_child(label); + page = memnew(EditorSpinSlider); + page->set_step(1); + page_hb->add_child(page); + page->set_h_size_flags(SIZE_EXPAND_FILL); + page->connect("value_changed", this, "_page_changed"); + } else { + //bye bye children of the box + while (vbox->get_child_count() > 2) { + memdelete(vbox->get_child(2)); + } + } + + int len = array.call("size"); + + length->set_value(len); + + int pages = MAX(0, len - 1) / page_len + 1; + + page->set_max(pages); + page_idx = MIN(page_idx, pages - 1); + page->set_value(page_idx); + page_hb->set_visible(pages > 1); + + int offset = page_idx * page_len; + + int amount = MIN(len - offset, page_len); + + if (array.get_type() == Variant::ARRAY) { + array = array.call("duplicate"); + } + + object->set_array(array); + + for (int i = 0; i < amount; i++) { + String prop_name = "indices/" + itos(i + offset); + + EditorProperty *prop = NULL; + Variant value = array.get(i + offset); + + switch (value.get_type()) { + case Variant::NIL: { + prop = memnew(EditorPropertyNil); + + } break; + + // atomic types + case Variant::BOOL: { + + prop = memnew(EditorPropertyCheck); + + } break; + case Variant::INT: { + EditorPropertyInteger *ed = memnew(EditorPropertyInteger); + ed->setup(-100000, 100000, true, true); + prop = ed; + + } break; + case Variant::REAL: { + + EditorPropertyFloat *ed = memnew(EditorPropertyFloat); + ed->setup(-100000, 100000, 0.001, true, false, true, true); + prop = ed; + } break; + case Variant::STRING: { + + prop = memnew(EditorPropertyText); + + } break; + + // math types + + case Variant::VECTOR2: { + + EditorPropertyVector2 *ed = memnew(EditorPropertyVector2); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::RECT2: { + + EditorPropertyRect2 *ed = memnew(EditorPropertyRect2); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::VECTOR3: { + + EditorPropertyVector3 *ed = memnew(EditorPropertyVector3); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::TRANSFORM2D: { + + EditorPropertyTransform2D *ed = memnew(EditorPropertyTransform2D); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::PLANE: { + + EditorPropertyPlane *ed = memnew(EditorPropertyPlane); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::QUAT: { + + EditorPropertyQuat *ed = memnew(EditorPropertyQuat); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::AABB: { + + EditorPropertyAABB *ed = memnew(EditorPropertyAABB); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::BASIS: { + EditorPropertyBasis *ed = memnew(EditorPropertyBasis); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::TRANSFORM: { + EditorPropertyTransform *ed = memnew(EditorPropertyTransform); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + + // misc types + case Variant::COLOR: { + prop = memnew(EditorPropertyColor); + + } break; + case Variant::NODE_PATH: { + prop = memnew(EditorPropertyNodePath); + + } break; + case Variant::_RID: { + prop = memnew(EditorPropertyNil); + + } break; + case Variant::OBJECT: { + + prop = memnew(EditorPropertyResource); + + } break; + case Variant::DICTIONARY: { + prop = memnew(EditorPropertyDictionary); + + } break; + case Variant::ARRAY: { + + prop = memnew(EditorPropertyArray); + + } break; + + // arrays + case Variant::POOL_BYTE_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + case Variant::POOL_INT_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + case Variant::POOL_REAL_ARRAY: { + + prop = memnew(EditorPropertyArray); + } break; + case Variant::POOL_STRING_ARRAY: { + + prop = memnew(EditorPropertyArray); + } break; + case Variant::POOL_VECTOR2_ARRAY: { + + prop = memnew(EditorPropertyArray); + } break; + case Variant::POOL_VECTOR3_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + case Variant::POOL_COLOR_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + default: {} + } + + prop->set_object_and_property(object.ptr(), prop_name); + prop->set_label(itos(i + offset)); + prop->set_selectable(false); + prop->connect("property_changed", this, "_property_changed"); + if (array.get_type() == Variant::ARRAY) { + HBoxContainer *hb = memnew(HBoxContainer); + vbox->add_child(hb); + hb->add_child(prop); + prop->set_h_size_flags(SIZE_EXPAND_FILL); + Button *edit = memnew(Button); + edit->set_icon(get_icon("Edit", "EditorIcons")); + hb->add_child(edit); + edit->connect("pressed", this, "_change_type", varray(edit, i + offset)); + } else { + vbox->add_child(prop); + } + + prop->update_property(); + } + + updating = false; + + } else { + if (vbox) { + set_bottom_editor(NULL); + memdelete(vbox); + vbox = NULL; + } + } +#endif +} + +void EditorPropertyArray::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + } +} +void EditorPropertyArray::_edit_pressed() { + + get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed()); + update_property(); +} + +void EditorPropertyArray::_page_changed(double p_page) { + if (updating) + return; + page_idx = p_page; + update_property(); +} + +void EditorPropertyArray::_length_changed(double p_page) { + if (updating) + return; + + Variant array = object->get_array(); + array.call("resize", int(p_page)); + emit_signal("property_changed", get_edited_property(), array); + + if (array.get_type() == Variant::ARRAY) { + array = array.call("duplicate"); //dupe, so undo/redo works better + } + object->set_array(array); + update_property(); +} + +void EditorPropertyArray::_bind_methods() { + ClassDB::bind_method("_edit_pressed", &EditorPropertyArray::_edit_pressed); + ClassDB::bind_method("_page_changed", &EditorPropertyArray::_page_changed); + ClassDB::bind_method("_length_changed", &EditorPropertyArray::_length_changed); + ClassDB::bind_method("_property_changed", &EditorPropertyArray::_property_changed); + ClassDB::bind_method("_change_type", &EditorPropertyArray::_change_type); + ClassDB::bind_method("_change_type_menu", &EditorPropertyArray::_change_type_menu); +} + +EditorPropertyArray::EditorPropertyArray() { + + object.instance(); + page_idx = 0; + page_len = 10; + edit = memnew(Button); + edit->set_flat(true); + edit->set_h_size_flags(SIZE_EXPAND_FILL); + edit->set_clip_text(true); + edit->connect("pressed", this, "_edit_pressed"); + edit->set_toggle_mode(true); + add_child(edit); + add_focusable(edit); + vbox = NULL; + page = NULL; + length = NULL; + updating = false; + change_type = memnew(PopupMenu); + add_child(change_type); + change_type->connect("id_pressed", this, "_change_type_menu"); + changing_type_idx = -1; + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + String type = Variant::get_type_name(Variant::Type(i)); + change_type->add_item(type, i); + } + changing_type_idx = -1; +} + +///////////////////// DICTIONARY /////////////////////////// + +void EditorPropertyDictionary::_property_changed(const String &p_prop, Variant p_value) { + + if (p_prop == "new_item_key") { + + object->set_new_item_key(p_value); + } else if (p_prop == "new_item_value") { + + object->set_new_item_value(p_value); + } else if (p_prop.begins_with("indices")) { + int idx = p_prop.get_slice("/", 1).to_int(); + Dictionary dict = object->get_dict(); + Variant key = dict.get_key_at_index(idx); + dict[key] = p_value; + + emit_signal("property_changed", get_edited_property(), dict); + + dict = dict.duplicate(); //dupe, so undo/redo works better + object->set_dict(dict); + } +} + +void EditorPropertyDictionary::_change_type(Object *p_button, int p_index) { + + Button *button = Object::cast_to<Button>(p_button); + + Rect2 rect = button->get_global_rect(); + change_type->set_as_minsize(); + change_type->set_global_position(rect.position + rect.size - Vector2(change_type->get_combined_minimum_size().x, 0)); + change_type->popup(); + changing_type_idx = p_index; +} + +void EditorPropertyDictionary::_add_key_value() { + + Dictionary dict = object->get_dict(); + dict[object->get_new_item_key()] = object->get_new_item_value(); + object->set_new_item_key(Variant()); + object->set_new_item_value(Variant()); + + emit_signal("property_changed", get_edited_property(), dict); + + dict = dict.duplicate(); //dupe, so undo/redo works better + object->set_dict(dict); + update_property(); +} + +void EditorPropertyDictionary::_change_type_menu(int p_index) { + + if (changing_type_idx < 0) { + Variant value; + Variant::CallError ce; + value = Variant::construct(Variant::Type(p_index), NULL, 0, ce); + if (changing_type_idx == -1) { + object->set_new_item_key(value); + } else { + object->set_new_item_value(value); + } + update_property(); + return; + } + + Dictionary dict = object->get_dict(); + + if (p_index < Variant::VARIANT_MAX) { + + Variant value; + Variant::CallError ce; + value = Variant::construct(Variant::Type(p_index), NULL, 0, ce); + Variant key = dict.get_key_at_index(changing_type_idx); + dict[key] = value; + } else { + Variant key = dict.get_key_at_index(changing_type_idx); + dict.erase(key); + } + + emit_signal("property_changed", get_edited_property(), dict); + + dict = dict.duplicate(); //dupe, so undo/redo works better + object->set_dict(dict); + update_property(); +} + +void EditorPropertyDictionary::update_property() { + + Dictionary dict = get_edited_object()->get(get_edited_property()); + + edit->set_text("Dict[" + itos(dict.size()) + "]"); + +#ifdef TOOLS_ENABLED + + bool unfolded = get_edited_object()->editor_is_section_unfolded(get_edited_property()); + if (edit->is_pressed() != unfolded) { + edit->set_pressed(unfolded); + } + + if (unfolded) { + + updating = true; + + if (!vbox) { + + vbox = memnew(VBoxContainer); + add_child(vbox); + set_bottom_editor(vbox); + + page_hb = memnew(HBoxContainer); + vbox->add_child(page_hb); + Label *label = memnew(Label(TTR("Page: "))); + label->set_h_size_flags(SIZE_EXPAND_FILL); + page_hb->add_child(label); + page = memnew(EditorSpinSlider); + page->set_step(1); + page_hb->add_child(page); + page->set_h_size_flags(SIZE_EXPAND_FILL); + page->connect("value_changed", this, "_page_changed"); + } else { + //bye bye children of the box + while (vbox->get_child_count() > 1) { + memdelete(vbox->get_child(1)); + } + } + + int len = dict.size(); + + int pages = MAX(0, len - 1) / page_len + 1; + + page->set_max(pages); + page_idx = MIN(page_idx, pages - 1); + page->set_value(page_idx); + page_hb->set_visible(pages > 1); + + int offset = page_idx * page_len; + + int amount = MIN(len - offset, page_len); + + dict = dict.duplicate(); + + object->set_dict(dict); + VBoxContainer *add_vbox = NULL; + + for (int i = 0; i < amount + 2; i++) { + String prop_name; + Variant key; + Variant value; + + if (i < amount) { + prop_name = "indices/" + itos(i + offset); + key = dict.get_key_at_index(i + offset); + value = dict.get_value_at_index(i + offset); + } else if (i == amount) { + prop_name = "new_item_key"; + value = object->get_new_item_key(); + } else if (i == amount + 1) { + prop_name = "new_item_value"; + value = object->get_new_item_value(); + } + + EditorProperty *prop = NULL; + + switch (value.get_type()) { + case Variant::NIL: { + prop = memnew(EditorPropertyNil); + + } break; + + // atomic types + case Variant::BOOL: { + + prop = memnew(EditorPropertyCheck); + + } break; + case Variant::INT: { + EditorPropertyInteger *ed = memnew(EditorPropertyInteger); + ed->setup(-100000, 100000, true, true); + prop = ed; + + } break; + case Variant::REAL: { + + EditorPropertyFloat *ed = memnew(EditorPropertyFloat); + ed->setup(-100000, 100000, 0.001, true, false, true, true); + prop = ed; + } break; + case Variant::STRING: { + + prop = memnew(EditorPropertyText); + + } break; + + // math types + + case Variant::VECTOR2: { + + EditorPropertyVector2 *ed = memnew(EditorPropertyVector2); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::RECT2: { + + EditorPropertyRect2 *ed = memnew(EditorPropertyRect2); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::VECTOR3: { + + EditorPropertyVector3 *ed = memnew(EditorPropertyVector3); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::TRANSFORM2D: { + + EditorPropertyTransform2D *ed = memnew(EditorPropertyTransform2D); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::PLANE: { + + EditorPropertyPlane *ed = memnew(EditorPropertyPlane); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::QUAT: { + + EditorPropertyQuat *ed = memnew(EditorPropertyQuat); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::AABB: { + + EditorPropertyAABB *ed = memnew(EditorPropertyAABB); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::BASIS: { + EditorPropertyBasis *ed = memnew(EditorPropertyBasis); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + case Variant::TRANSFORM: { + EditorPropertyTransform *ed = memnew(EditorPropertyTransform); + ed->setup(-100000, 100000, 0.001, true); + prop = ed; + + } break; + + // misc types + case Variant::COLOR: { + prop = memnew(EditorPropertyColor); + + } break; + case Variant::NODE_PATH: { + prop = memnew(EditorPropertyNodePath); + + } break; + case Variant::_RID: { + prop = memnew(EditorPropertyNil); + + } break; + case Variant::OBJECT: { + + prop = memnew(EditorPropertyResource); + + } break; + case Variant::DICTIONARY: { + prop = memnew(EditorPropertyDictionary); + + } break; + case Variant::ARRAY: { + + prop = memnew(EditorPropertyArray); + + } break; + + // arrays + case Variant::POOL_BYTE_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + case Variant::POOL_INT_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + case Variant::POOL_REAL_ARRAY: { + + prop = memnew(EditorPropertyArray); + } break; + case Variant::POOL_STRING_ARRAY: { + + prop = memnew(EditorPropertyArray); + } break; + case Variant::POOL_VECTOR2_ARRAY: { + + prop = memnew(EditorPropertyArray); + } break; + case Variant::POOL_VECTOR3_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + case Variant::POOL_COLOR_ARRAY: { + prop = memnew(EditorPropertyArray); + + } break; + default: {} + } + + if (i == amount) { + PanelContainer *pc = memnew(PanelContainer); + vbox->add_child(pc); + Ref<StyleBoxFlat> flat; + flat.instance(); + for (int j = 0; j < 4; j++) { + flat->set_default_margin(Margin(j), 2 * EDSCALE); + } + flat->set_bg_color(get_color("prop_subsection", "Editor")); + + pc->add_style_override("panel", flat); + add_vbox = memnew(VBoxContainer); + pc->add_child(add_vbox); + } + prop->set_object_and_property(object.ptr(), prop_name); + int change_index; + + if (i < amount) { + String cs = key.get_construct_string(); + prop->set_label(key.get_construct_string()); + prop->set_tooltip(cs); + change_index = i + offset; + } else if (i == amount) { + prop->set_label(TTR("New Key:")); + change_index = -1; + } else if (i == amount + 1) { + prop->set_label(TTR("New Value:")); + change_index = -2; + } + + prop->set_selectable(false); + prop->connect("property_changed", this, "_property_changed"); + + HBoxContainer *hb = memnew(HBoxContainer); + if (add_vbox) { + add_vbox->add_child(hb); + } else { + vbox->add_child(hb); + } + hb->add_child(prop); + prop->set_h_size_flags(SIZE_EXPAND_FILL); + Button *edit = memnew(Button); + edit->set_icon(get_icon("Edit", "EditorIcons")); + hb->add_child(edit); + edit->connect("pressed", this, "_change_type", varray(edit, change_index)); + + prop->update_property(); + + if (i == amount + 1) { + Button *add_item = memnew(Button); + add_item->set_text(TTR("Add Key/Value Pair")); + add_vbox->add_child(add_item); + add_item->connect("pressed", this, "_add_key_value"); + } + } + + updating = false; + + } else { + if (vbox) { + set_bottom_editor(NULL); + memdelete(vbox); + vbox = NULL; + } + } +#endif +} + +void EditorPropertyDictionary::_notification(int p_what) { + + if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) { + } +} +void EditorPropertyDictionary::_edit_pressed() { + + get_edited_object()->editor_set_section_unfold(get_edited_property(), edit->is_pressed()); + update_property(); +} + +void EditorPropertyDictionary::_page_changed(double p_page) { + if (updating) + return; + page_idx = p_page; + update_property(); +} + +void EditorPropertyDictionary::_bind_methods() { + ClassDB::bind_method("_edit_pressed", &EditorPropertyDictionary::_edit_pressed); + ClassDB::bind_method("_page_changed", &EditorPropertyDictionary::_page_changed); + ClassDB::bind_method("_property_changed", &EditorPropertyDictionary::_property_changed); + ClassDB::bind_method("_change_type", &EditorPropertyDictionary::_change_type); + ClassDB::bind_method("_change_type_menu", &EditorPropertyDictionary::_change_type_menu); + ClassDB::bind_method("_add_key_value", &EditorPropertyDictionary::_add_key_value); +} + +EditorPropertyDictionary::EditorPropertyDictionary() { + + object.instance(); + page_idx = 0; + page_len = 10; + edit = memnew(Button); + edit->set_flat(true); + edit->set_h_size_flags(SIZE_EXPAND_FILL); + edit->set_clip_text(true); + edit->connect("pressed", this, "_edit_pressed"); + edit->set_toggle_mode(true); + add_child(edit); + add_focusable(edit); + vbox = NULL; + page = NULL; + updating = false; + change_type = memnew(PopupMenu); + add_child(change_type); + change_type->connect("id_pressed", this, "_change_type_menu"); + changing_type_idx = -1; + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + String type = Variant::get_type_name(Variant::Type(i)); + change_type->add_item(type, i); + } + change_type->add_separator(); + change_type->add_item(TTR("Remove Item"), Variant::VARIANT_MAX); + changing_type_idx = -1; +} diff --git a/editor/editor_properties_array_dict.h b/editor/editor_properties_array_dict.h new file mode 100644 index 0000000000..7f6203ee88 --- /dev/null +++ b/editor/editor_properties_array_dict.h @@ -0,0 +1,115 @@ +#ifndef EDITOR_PROPERTIES_ARRAY_DICT_H +#define EDITOR_PROPERTIES_ARRAY_DICT_H + +#include "editor/editor_inspector.h" +#include "editor/editor_spin_slider.h" +#include "scene/gui/button.h" + +class EditorPropertyArrayObject : public Reference { + + GDCLASS(EditorPropertyArrayObject, Reference); + + Variant array; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + +public: + void set_array(const Variant &p_array); + Variant get_array(); + + EditorPropertyArrayObject(); +}; + +class EditorPropertyDictionaryObject : public Reference { + + GDCLASS(EditorPropertyDictionaryObject, Reference); + + Variant new_item_key; + Variant new_item_value; + Dictionary dict; + +protected: + bool _set(const StringName &p_name, const Variant &p_value); + bool _get(const StringName &p_name, Variant &r_ret) const; + +public: + void set_dict(const Dictionary &p_dict); + Dictionary get_dict(); + + void set_new_item_key(const Variant &p_new_item); + Variant get_new_item_key(); + + void set_new_item_value(const Variant &p_new_item); + Variant get_new_item_value(); + + EditorPropertyDictionaryObject(); +}; + +class EditorPropertyArray : public EditorProperty { + GDCLASS(EditorPropertyArray, EditorProperty) + + PopupMenu *change_type; + bool updating; + + Ref<EditorPropertyArrayObject> object; + int page_len; + int page_idx; + int changing_type_idx; + Button *edit; + VBoxContainer *vbox; + EditorSpinSlider *length; + EditorSpinSlider *page; + HBoxContainer *page_hb; + + void _page_changed(double p_page); + void _length_changed(double p_page); + void _edit_pressed(); + void _property_changed(const String &p_prop, Variant p_value); + void _change_type(Object *p_button, int p_index); + void _change_type_menu(int p_index); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + virtual void update_property(); + EditorPropertyArray(); +}; + +class EditorPropertyDictionary : public EditorProperty { + GDCLASS(EditorPropertyDictionary, EditorProperty) + + PopupMenu *change_type; + bool updating; + + Ref<EditorPropertyDictionaryObject> object; + int page_len; + int page_idx; + int changing_type_idx; + Button *edit; + VBoxContainer *vbox; + EditorSpinSlider *length; + EditorSpinSlider *page; + HBoxContainer *page_hb; + + void _page_changed(double p_page); + void _edit_pressed(); + void _property_changed(const String &p_prop, Variant p_value); + void _change_type(Object *p_button, int p_index); + void _change_type_menu(int p_index); + + void _add_key_value(); + +protected: + static void _bind_methods(); + void _notification(int p_what); + +public: + virtual void update_property(); + EditorPropertyDictionary(); +}; + +#endif // EDITOR_PROPERTIES_ARRAY_DICT_H diff --git a/editor/editor_themes.cpp b/editor/editor_themes.cpp index d0b842f231..8d29e0d40b 100644 --- a/editor/editor_themes.cpp +++ b/editor/editor_themes.cpp @@ -1050,7 +1050,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { const Color function_definition_color = Color::html(dark_theme ? "#01e1ff" : "#00a5ba"); const Color node_path_color = Color::html(dark_theme ? "64c15a" : "#518b4b"); - const Color te_background_color = Color(0, 0, 0, 0); + const Color te_background_color = dark_theme ? background_color : Color::html("#ffffff"); const Color completion_background_color = base_color; const Color completion_selected_color = alpha1; const Color completion_existing_color = alpha2; @@ -1084,7 +1084,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { setting->set_initial_value("text_editor/highlighting/engine_type_color", type_color, true); setting->set_initial_value("text_editor/highlighting/comment_color", comment_color, true); setting->set_initial_value("text_editor/highlighting/string_color", string_color, true); - setting->set_initial_value("text_editor/highlighting/background_color", background_color, true); + setting->set_initial_value("text_editor/highlighting/background_color", te_background_color, true); setting->set_initial_value("text_editor/highlighting/completion_background_color", completion_background_color, true); setting->set_initial_value("text_editor/highlighting/completion_selected_color", completion_selected_color, true); setting->set_initial_value("text_editor/highlighting/completion_existing_color", completion_existing_color, true); @@ -1118,7 +1118,7 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) { setting->set_initial_value("text_editor/highlighting/engine_type_color", Color::html("83d3ff"), true); setting->set_initial_value("text_editor/highlighting/comment_color", Color::html("676767"), true); setting->set_initial_value("text_editor/highlighting/string_color", Color::html("ef6ebe"), true); - setting->set_initial_value("text_editor/highlighting/background_color", Color::html("3b000000"), true); + setting->set_initial_value("text_editor/highlighting/background_color", dark_theme ? Color::html("3b000000") : Color::html("#323b4f"), true); setting->set_initial_value("text_editor/highlighting/completion_background_color", Color::html("2C2A32"), true); setting->set_initial_value("text_editor/highlighting/completion_selected_color", Color::html("434244"), true); setting->set_initial_value("text_editor/highlighting/completion_existing_color", Color::html("21dfdfdf"), true); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index e7741c7926..297373d299 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -383,11 +383,11 @@ void FileSystemDock::_update_file_display_toggle_button() { if (button_display_mode->is_pressed()) { display_mode = DISPLAY_LIST; button_display_mode->set_icon(get_icon("FileThumbnail", "EditorIcons")); - button_display_mode->set_tooltip(TTR("View items as a grid of thumbnails")); + button_display_mode->set_tooltip(TTR("View items as a grid of thumbnails.")); } else { display_mode = DISPLAY_THUMBNAILS; button_display_mode->set_icon(get_icon("FileList", "EditorIcons")); - button_display_mode->set_tooltip(TTR("View items as a list")); + button_display_mode->set_tooltip(TTR("View items as a list.")); } } @@ -1860,7 +1860,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { button_favorite->set_flat(true); button_favorite->set_toggle_mode(true); button_favorite->connect("pressed", this, "_favorites_pressed"); - button_favorite->set_tooltip(TTR("Toggle folder status as Favorite")); + button_favorite->set_tooltip(TTR("Toggle folder status as Favorite.")); button_favorite->set_focus_mode(FOCUS_NONE); toolbar_hbc->add_child(button_favorite); @@ -1916,11 +1916,13 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) { file_list_vb->add_child(path_hb); button_tree = memnew(ToolButton); + button_tree->set_tooltip(TTR("Enter tree-view.")); button_tree->hide(); path_hb->add_child(button_tree); search_box = memnew(LineEdit); search_box->set_h_size_flags(SIZE_EXPAND_FILL); + search_box->set_placeholder(TTR("Search files")); search_box->connect("text_changed", this, "_search_changed"); path_hb->add_child(search_box); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 74ea46838b..004a49e2b4 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -109,6 +109,7 @@ void FindInFiles::start() { _current_dir = ""; PoolStringArray init_folder; init_folder.append(_root_dir); + _folders_stack.clear(); _folders_stack.push_back(init_folder); _initial_files_count = 0; @@ -127,11 +128,12 @@ void FindInFiles::_process() { // This part can be moved to a thread if needed OS &os = *OS::get_singleton(); - float duration = 0.0; - while (duration < 1.0 / 120.0) { - float time_before = os.get_ticks_msec(); + float time_before = os.get_ticks_msec(); + while (is_processing()) { _iterate(); - duration += (os.get_ticks_msec() - time_before); + float elapsed = (os.get_ticks_msec() - time_before); + if (elapsed > 1000.0 / 120.0) + break; } } @@ -428,6 +430,7 @@ FindInFilesDialog::FindInFilesDialog() { void FindInFilesDialog::set_search_text(String text) { _search_text_line_edit->set_text(text); + _on_search_text_modified(text); } String FindInFilesDialog::get_search_text() const { diff --git a/editor/icons/icon_oriented_path_follow.svg b/editor/icons/icon_oriented_path_follow.svg new file mode 100644 index 0000000000..bd3f585e54 --- /dev/null +++ b/editor/icons/icon_oriented_path_follow.svg @@ -0,0 +1,5 @@ +<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(0 -1036.4)"> +<path transform="translate(0 1036.4)" d="m13 0l-3 4h1.9473c-0.1385 1.3203-0.5583 1.9074-1.084 2.2754-0.64426 0.451-1.7129 0.60547-2.9629 0.73047s-2.6814 0.22053-3.9121 1.082c-0.89278 0.62493-1.5321 1.6522-1.8184 3.0957a2 2 0 0 0 -1.1699 1.8164 2 2 0 0 0 2 2 2 2 0 0 0 2 -2 2 2 0 0 0 -0.84961 -1.6328c0.19235-0.88496 0.55306-1.3373 0.98633-1.6406 0.64426-0.451 1.7129-0.60547 2.9629-0.73047s2.6814-0.22053 3.9121-1.082c1.0528-0.73697 1.7552-2.032 1.9375-3.9141h2.0508l-3-4z" fill="#fc9c9c" fill-opacity=".99608"/> +</g> +</svg> diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index 1d7545f182..2fb3bf7b1e 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -339,7 +339,7 @@ Error ColladaImport::_create_scene(Collada::Node *p_node, Spatial *p_parent) { NodeMap nm; nm.node = node; node_map[p_node->id] = nm; - node_name_map[p_node->name] = p_node->id; + node_name_map[node->get_name()] = p_node->id; Transform xf = p_node->default_transform; xf = collada.fix_transform(xf) * p_node->post_transform; diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 128196be5a..f91802b352 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -407,6 +407,7 @@ ImportDock::ImportDock() { set_name("Import"); imported = memnew(Label); imported->add_style_override("normal", EditorNode::get_singleton()->get_gui_base()->get_stylebox("normal", "LineEdit")); + imported->set_clip_text(true); add_child(imported); HBoxContainer *hb = memnew(HBoxContainer); add_margin_child(TTR("Import As:"), hb); diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index d21c84eb61..d595d4dd98 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -705,7 +705,18 @@ void EditorAssetLibrary::_image_update(bool use_cache, bool final, const PoolByt int len = image_data.size(); PoolByteArray::Read r = image_data.read(); - Ref<Image> image = Ref<Image>(memnew(Image(r.ptr(), len))); + Ref<Image> image = Ref<Image>(memnew(Image)); + + uint8_t png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + uint8_t jpg_signature[3] = { 255, 216, 255 }; + + if (r.ptr()) { + if (memcmp(&r[0], &png_signature[0], 8) == 0) { + image->copy_internals_from(Image::_png_mem_loader_func(r.ptr(), len)); + } else if (memcmp(&r[0], &jpg_signature[0], 3) == 0) { + image->copy_internals_from(Image::_jpg_mem_loader_func(r.ptr(), len)); + } + } if (!image->empty()) { switch (image_queue[p_queue_id].image_type) { @@ -750,7 +761,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons ERR_FAIL_COND(!image_queue.has(p_queue_id)); - if (p_status == HTTPRequest::RESULT_SUCCESS) { + if (p_status == HTTPRequest::RESULT_SUCCESS && p_code < HTTPClient::RESPONSE_BAD_REQUEST) { if (p_code != HTTPClient::RESPONSE_NOT_MODIFIED) { for (int i = 0; i < headers.size(); i++) { @@ -781,7 +792,7 @@ void EditorAssetLibrary::_image_request_completed(int p_status, int p_code, cons _image_update(p_code == HTTPClient::RESPONSE_NOT_MODIFIED, true, p_data, p_queue_id); } else { - WARN_PRINTS("Error getting PNG file from URL: " + image_queue[p_queue_id].image_url); + // WARN_PRINTS("Error getting image file from URL: " + image_queue[p_queue_id].image_url); Object *obj = ObjectDB::get_instance(image_queue[p_queue_id].target); if (obj) { obj->call("set_image", image_queue[p_queue_id].image_type, image_queue[p_queue_id].image_index, get_icon("DefaultProjectIcon", "EditorIcons")); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 488f687515..ca5aa7039d 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -2689,6 +2689,9 @@ void CanvasItemEditor::_draw_bones() { continue; Node2D *from_node = Object::cast_to<Node2D>(ObjectDB::get_instance(E->key().from)); + if (!from_node->is_visible_in_tree()) + continue; + Vector<Color> colors; if (from_node->has_meta("_edit_ik_")) { colors.push_back(bone_ik_color); diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index d76c515c1f..ac4166bb98 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -37,6 +37,7 @@ #include "io/resource_loader.h" #include "os/os.h" #include "scene/resources/bit_mask.h" +#include "scene/resources/dynamic_font.h" #include "scene/resources/material.h" #include "scene/resources/mesh.h" @@ -933,3 +934,100 @@ EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() { VS::get_singleton()->free(camera); VS::get_singleton()->free(scenario); } + +/////////////////////////////////////////////////////////////////////////// + +void EditorFontPreviewPlugin::_preview_done(const Variant &p_udata) { + + preview_done = true; +} + +void EditorFontPreviewPlugin::_bind_methods() { + + ClassDB::bind_method("_preview_done", &EditorFontPreviewPlugin::_preview_done); +} + +bool EditorFontPreviewPlugin::handles(const String &p_type) const { + + return ClassDB::is_parent_class(p_type, "DynamicFontData"); +} + +Ref<Texture> EditorFontPreviewPlugin::generate_from_path(const String &p_path) { + if (canvas.is_valid()) { + VS::get_singleton()->viewport_remove_canvas(viewport, canvas); + } + + canvas = VS::get_singleton()->canvas_create(); + canvas_item = VS::get_singleton()->canvas_item_create(); + + VS::get_singleton()->viewport_attach_canvas(viewport, canvas); + VS::get_singleton()->canvas_item_set_parent(canvas_item, canvas); + + Ref<DynamicFontData> SampledFont; + SampledFont.instance(); + SampledFont->set_font_path(p_path); + + int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); + thumbnail_size *= EDSCALE; + + Ref<DynamicFont> sampled_font; + sampled_font.instance(); + sampled_font->set_size(50); + sampled_font->set_font_data(SampledFont); + + String sampled_text = "Abg"; + Vector2 size = sampled_font->get_string_size(sampled_text); + + Vector2 pos; + + pos.x = 64 - size.x / 2; + pos.y = 80; + + Ref<Font> font = sampled_font; + + font->draw(canvas_item, pos, sampled_text); + + VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture + + preview_done = false; + VS::get_singleton()->request_frame_drawn_callback(this, "_preview_done", Variant()); + + while (!preview_done) { + OS::get_singleton()->delay_usec(10); + } + + Ref<Image> img = VS::get_singleton()->VS::get_singleton()->texture_get_data(viewport_texture); + ERR_FAIL_COND_V(img.is_null(), Ref<ImageTexture>()); + + img->convert(Image::FORMAT_RGBA8); + img->resize(thumbnail_size, thumbnail_size); + + post_process_preview(img); + + Ref<ImageTexture> ptex = Ref<ImageTexture>(memnew(ImageTexture)); + ptex->create_from_image(img, 0); + + return ptex; +} + +Ref<Texture> EditorFontPreviewPlugin::generate(const RES &p_from) { + + return generate_from_path(p_from->get_path()); +} + +EditorFontPreviewPlugin::EditorFontPreviewPlugin() { + + viewport = VS::get_singleton()->viewport_create(); + VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED); + VS::get_singleton()->viewport_set_vflip(viewport, true); + VS::get_singleton()->viewport_set_size(viewport, 128, 128); + VS::get_singleton()->viewport_set_active(viewport, true); + viewport_texture = VS::get_singleton()->viewport_get_texture(viewport); +} + +EditorFontPreviewPlugin::~EditorFontPreviewPlugin() { + + VS::get_singleton()->free(canvas_item); + VS::get_singleton()->free(canvas); + VS::get_singleton()->free(viewport); +} diff --git a/editor/plugins/editor_preview_plugins.h b/editor/plugins/editor_preview_plugins.h index 35b5c3a5f0..332f991b49 100644 --- a/editor/plugins/editor_preview_plugins.h +++ b/editor/plugins/editor_preview_plugins.h @@ -140,4 +140,27 @@ public: ~EditorMeshPreviewPlugin(); }; +class EditorFontPreviewPlugin : public EditorResourcePreviewGenerator { + + GDCLASS(EditorFontPreviewPlugin, EditorResourcePreviewGenerator) + + RID viewport; + RID viewport_texture; + RID canvas; + RID canvas_item; + volatile bool preview_done; + + void _preview_done(const Variant &p_udata); + +protected: + static void _bind_methods(); + +public: + virtual bool handles(const String &p_type) const; + virtual Ref<Texture> generate(const RES &p_from); + virtual Ref<Texture> generate_from_path(const String &p_path); + + EditorFontPreviewPlugin(); + ~EditorFontPreviewPlugin(); +}; #endif // EDITORPREVIEWPLUGINS_H diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index 422d19c0e4..94dcbd8e18 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -1404,6 +1404,7 @@ void ScriptEditor::_update_members_overview_visibility() { ScriptEditorBase *se = _get_current_editor(); if (!se) { + members_overview_buttons_hbox->set_visible(false); members_overview->set_visible(false); return; } @@ -2681,7 +2682,7 @@ ScriptEditor::ScriptEditor(EditorNode *p_editor) { members_overview_vbox->add_child(members_overview_buttons_hbox); members_overview_alphabeta_sort_button = memnew(ToolButton); - members_overview_alphabeta_sort_button->set_tooltip(TTR("Sort alphabetically")); + members_overview_alphabeta_sort_button->set_tooltip(TTR("Toggle alphabetical sorting of the method list.")); members_overview_alphabeta_sort_button->set_toggle_mode(true); members_overview_alphabeta_sort_button->set_pressed(EditorSettings::get_singleton()->get("text_editor/tools/sort_members_outline_alphabetically")); members_overview_alphabeta_sort_button->connect("toggled", this, "_toggle_members_overview_alpha_sort"); diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index 97d3a070ab..0d06b71420 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -199,6 +199,7 @@ private: sp = TTR("Imported Project"); project_name->set_text(sp); + _text_changed(sp); } } @@ -222,6 +223,7 @@ private: } String sp = p.simplify_path(); project_path->set_text(sp); + _path_text_changed(sp); get_ok()->call_deferred("grab_focus"); } @@ -230,6 +232,7 @@ private: String p = p_path; String sp = p.simplify_path(); project_path->set_text(sp); + _path_text_changed(sp); get_ok()->call_deferred("grab_focus"); } @@ -263,7 +266,9 @@ private: if (d->make_dir(project_name->get_text()) == OK) { d->change_dir(project_name->get_text()); - project_path->set_text(d->get_current_dir()); + String dir_str = d->get_current_dir(); + project_path->set_text(dir_str); + _path_text_changed(dir_str); created_folder_path = d->get_current_dir(); create_dir->set_disabled(true); } else { @@ -475,7 +480,9 @@ private: _remove_created_folder(); project_path->clear(); + _path_text_changed(""); project_name->clear(); + _text_changed(""); if (status_rect->get_texture() == get_icon("StatusError", "EditorIcons")) msg->show(); @@ -540,7 +547,9 @@ public: msg->show(); get_ok()->set_disabled(true); } else if (current->has_setting("application/config/name")) { - project_name->set_text(current->get("application/config/name")); + String proj = current->get("application/config/name"); + project_name->set_text(proj); + _text_changed(proj); } project_name->call_deferred("grab_focus"); @@ -559,7 +568,9 @@ public: fdialog->set_current_dir(d->get_current_dir()); memdelete(d); } - project_name->set_text(TTR("New Game Project")); + String proj = TTR("New Game Project"); + project_name->set_text(proj); + _text_changed(proj); project_path->set_editable(true); browse->set_disabled(false); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index b82a036130..32b4e7f962 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -113,7 +113,7 @@ void SceneTreeDock::instance(const String &p_file) { Node *parent = scene_tree->get_selected(); if (!parent) { - Node *parent = edited_scene; + parent = edited_scene; }; if (!edited_scene) { diff --git a/editor/script_editor_debugger.cpp b/editor/script_editor_debugger.cpp index 9ce4305683..62848a6035 100644 --- a/editor/script_editor_debugger.cpp +++ b/editor/script_editor_debugger.cpp @@ -872,7 +872,7 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType reason->add_color_override("font_color", get_color("success_color", "Editor")); } reason->set_text(p_reason); - reason->set_tooltip(p_reason); + reason->set_tooltip(p_reason.word_wrap(80)); } void ScriptEditorDebugger::_performance_select() { @@ -1877,6 +1877,9 @@ ScriptEditorDebugger::ScriptEditorDebugger(EditorNode *p_editor) { reason->set_text(""); hbc->add_child(reason); reason->set_h_size_flags(SIZE_EXPAND_FILL); + reason->set_autowrap(true); + reason->set_max_lines_visible(3); + reason->set_mouse_filter(Control::MOUSE_FILTER_PASS); hbc->add_child(memnew(VSeparator)); diff --git a/main/main.cpp b/main/main.cpp index c287bc81cb..ad49e1f5bd 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -1444,7 +1444,7 @@ bool Main::start() { } #endif - if (!project_manager) { // game or editor + if (!project_manager && !editor) { // game if (game_path != "" || script != "") { //autoload List<PropertyInfo> props; @@ -1465,24 +1465,13 @@ bool Main::start() { if (global_var) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { -#ifdef TOOLS_ENABLED - if (editor) { - ScriptServer::get_language(i)->add_named_global_constant(name, Variant()); - } else { - ScriptServer::get_language(i)->add_global_constant(name, Variant()); - } -#else ScriptServer::get_language(i)->add_global_constant(name, Variant()); -#endif } } } //second pass, load into global constants List<Node *> to_add; -#ifdef TOOLS_ENABLED - ResourceLoader::set_timestamp_on_load(editor); // Avoid problems when editing -#endif for (List<PropertyInfo>::Element *E = props.front(); E; E = E->next()) { String s = E->get().name; @@ -1528,23 +1517,11 @@ bool Main::start() { if (global_var) { for (int i = 0; i < ScriptServer::get_language_count(); i++) { -#ifdef TOOLS_ENABLED - if (editor) { - ScriptServer::get_language(i)->add_named_global_constant(name, n); - } else { - ScriptServer::get_language(i)->add_global_constant(name, n); - } -#else ScriptServer::get_language(i)->add_global_constant(name, n); -#endif } } } -#ifdef TOOLS_ENABLED - ResourceLoader::set_timestamp_on_load(false); -#endif - for (List<Node *>::Element *E = to_add.front(); E; E = E->next()) { sml->get_root()->add_child(E->get()); @@ -1729,7 +1706,7 @@ bool Main::start() { uint64_t Main::last_ticks = 0; uint64_t Main::target_ticks = 0; -uint32_t Main::frames = 0; +Array Main::frame_times = Array(); uint32_t Main::frame = 0; bool Main::force_redraw_requested = false; @@ -1848,10 +1825,19 @@ bool Main::iteration() { script_debugger->idle_poll(); } - frames++; Engine::get_singleton()->_idle_frames++; - if (frame > 1000000) { + // FPS counter + frame_times.push_back(ticks); + int frames = frame_times.size(); + + while (frame_times.size() > 0 && (int)frame_times.get(0) <= ticks - 1000000) { + frame_times.pop_front(); + } + + int update_frequency = MAX(1, (int)GLOBAL_GET("debug/settings/performance/update_frequency_msec")); + + if (frame > update_frequency * 1000) { if (editor || project_manager) { if (print_fps) { @@ -1867,8 +1853,7 @@ bool Main::iteration() { idle_process_max = 0; physics_process_max = 0; - frame %= 1000000; - frames = 0; + frame %= update_frequency * 1000; } if (fixed_fps != -1) diff --git a/main/main.h b/main/main.h index c20592bf3b..8f264d7720 100644 --- a/main/main.h +++ b/main/main.h @@ -44,7 +44,7 @@ class Main { static void print_help(const char *p_binary); static uint64_t last_ticks; static uint64_t target_ticks; - static uint32_t frames; + static Array frame_times; static uint32_t frame; static bool force_redraw_requested; diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index 9947512444..5c834966c5 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -738,6 +738,9 @@ int GDScriptCompiler::_parse_expression(CodeGen &codegen, const GDScriptParser:: case GDScriptParser::OperatorNode::OP_NEG: { if (!_create_unary_operator(codegen, on, Variant::OP_NEGATE, p_stack_level)) return -1; } break; + case GDScriptParser::OperatorNode::OP_POS: { + if (!_create_unary_operator(codegen, on, Variant::OP_POSITIVE, p_stack_level)) return -1; + } break; case GDScriptParser::OperatorNode::OP_NOT: { if (!_create_unary_operator(codegen, on, Variant::OP_NOT, p_stack_level)) return -1; } break; diff --git a/modules/gdscript/gdscript_editor.cpp b/modules/gdscript/gdscript_editor.cpp index 30ef167466..4286412c14 100644 --- a/modules/gdscript/gdscript_editor.cpp +++ b/modules/gdscript/gdscript_editor.cpp @@ -416,7 +416,7 @@ String GDScriptLanguage::make_function(const String &p_class, const String &p_na s += p_args[i].get_slice(":", 0); } } - s += "):\n" + _get_indentation() + "pass # replace with function body\n"; + s += "):\n" + _get_indentation() + "pass # Replace with function body.\n"; return s; } diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 161e62c81f..24292b77ed 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -446,7 +446,7 @@ String CSharpLanguage::make_function(const String &p_class, const String &p_name s += variant_type_to_managed_name(arg.get_slice(":", 1)) + " " + escape_csharp_keyword(arg.get_slice(":", 0)); } - s += ")\n{\n // Replace with function body\n}\n"; + s += ")\n{\n // Replace with function body.\n}\n"; return s; #else @@ -1954,11 +1954,6 @@ Variant CSharpScript::_new(const Variant **p_args, int p_argcount, Variant::Call ScriptInstance *CSharpScript::instance_create(Object *p_this) { - if (!script_class) { - ERR_EXPLAIN("Cannot find class " + name + " for script " + get_path()); - ERR_FAIL_V(NULL); - } - ERR_FAIL_COND_V(!valid, NULL); if (!tool && !ScriptServer::is_scripting_enabled()) { @@ -1972,6 +1967,18 @@ ScriptInstance *CSharpScript::instance_create(Object *p_this) { return NULL; #endif } + + if (!script_class) { + if (GDMono::get_singleton()->get_project_assembly() == NULL) { + // The project assembly is not loaded + ERR_EXPLAIN("Cannot instance script because the project assembly is not loaded. Script: " + get_path()); + ERR_FAIL_V(NULL); + } + + // The project assembly is loaded, but the class could not found + ERR_EXPLAIN("Cannot instance script because the class '" + name + "' could not be found. Script: " + get_path()); + ERR_FAIL_V(NULL); + } update_signals(); diff --git a/modules/mono/glue/cs_files/Basis.cs b/modules/mono/glue/cs_files/Basis.cs index 270f3b80a2..aa49a5e04f 100644 --- a/modules/mono/glue/cs_files/Basis.cs +++ b/modules/mono/glue/cs_files/Basis.cs @@ -453,15 +453,15 @@ namespace Godot c = Mathf.Cos(euler.x); s = Mathf.Sin(euler.x); - var xmat = new Basis((real_t)1.0, (real_t)0.0, (real_t)0.0, (real_t)0.0, c, -s, (real_t)0.0, s, c); + var xmat = new Basis(1, 0, 0, 0, c, -s, 0, s, c); c = Mathf.Cos(euler.y); s = Mathf.Sin(euler.y); - var ymat = new Basis(c, (real_t)0.0, s, (real_t)0.0, (real_t)1.0, (real_t)0.0, -s, (real_t)0.0, c); + var ymat = new Basis(c, 0, s, 0, 1, 0, -s, 0, c); c = Mathf.Cos(euler.z); s = Mathf.Sin(euler.z); - var zmat = new Basis(c, -s, (real_t)0.0, s, c, (real_t)0.0, (real_t)0.0, (real_t)0.0, (real_t)1.0); + var zmat = new Basis(c, -s, 0, s, c, 0, 0, 0, 1); this = ymat * xmat * zmat; } diff --git a/modules/mono/glue/cs_files/StringExtensions.cs b/modules/mono/glue/cs_files/StringExtensions.cs index 21090fb68d..eaeed7b37b 100644 --- a/modules/mono/glue/cs_files/StringExtensions.cs +++ b/modules/mono/glue/cs_files/StringExtensions.cs @@ -225,7 +225,7 @@ namespace Godot if (pos < 0) return instance; - return instance.Substring(pos + 1, instance.Length); + return instance.Substring(pos + 1); } // <summary> diff --git a/modules/mono/glue/cs_files/VERSION.txt b/modules/mono/glue/cs_files/VERSION.txt index 0cfbf08886..00750edc07 100755 --- a/modules/mono/glue/cs_files/VERSION.txt +++ b/modules/mono/glue/cs_files/VERSION.txt @@ -1 +1 @@ -2 +3 diff --git a/modules/mono/glue/cs_files/Vector2.cs b/modules/mono/glue/cs_files/Vector2.cs index 9bc40cf8df..c274364895 100644 --- a/modules/mono/glue/cs_files/Vector2.cs +++ b/modules/mono/glue/cs_files/Vector2.cs @@ -62,7 +62,7 @@ namespace Godot } } - private real_t Cross(Vector2 b) + public real_t Cross(Vector2 b) { return x * b.y - y * b.x; } @@ -210,6 +210,12 @@ namespace Godot x = v.x; y = v.y; } + + public Vector2 Slerp(Vector2 b, real_t t) + { + real_t theta = AngleTo(b); + return Rotated(theta * t); + } public Vector2 Slide(Vector2 n) { diff --git a/modules/mono/glue/cs_files/Vector3.cs b/modules/mono/glue/cs_files/Vector3.cs index 57e4494f7e..085a4f0043 100644 --- a/modules/mono/glue/cs_files/Vector3.cs +++ b/modules/mono/glue/cs_files/Vector3.cs @@ -242,6 +242,12 @@ namespace Godot z = v.z; } + public Vector3 Slerp(Vector3 b, real_t t) + { + real_t theta = AngleTo(b); + return Rotated(Cross(b), theta * t); + } + public Vector3 Slide(Vector3 n) { return this - n * Dot(n); diff --git a/modules/mono/mono_gd/gd_mono_marshal.cpp b/modules/mono/mono_gd/gd_mono_marshal.cpp index aa1a8e39c7..e6baea3089 100644 --- a/modules/mono/mono_gd/gd_mono_marshal.cpp +++ b/modules/mono/mono_gd/gd_mono_marshal.cpp @@ -607,10 +607,11 @@ MonoArray *Array_to_mono_array(const Array &p_array) { Array mono_array_to_Array(MonoArray *p_array) { Array ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { MonoObject *elem = mono_array_get(p_array, MonoObject *, i); - ret.push_back(mono_object_to_variant(elem)); + ret[i] = mono_object_to_variant(elem); } return ret; @@ -631,10 +632,10 @@ MonoArray *PoolIntArray_to_mono_array(const PoolIntArray &p_array) { PoolIntArray mono_array_to_PoolIntArray(MonoArray *p_array) { PoolIntArray ret; int length = mono_array_length(p_array); - + ret.resize(length); for (int i = 0; i < length; i++) { int32_t elem = mono_array_get(p_array, int32_t, i); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -653,10 +654,11 @@ MonoArray *PoolByteArray_to_mono_array(const PoolByteArray &p_array) { PoolByteArray mono_array_to_PoolByteArray(MonoArray *p_array) { PoolByteArray ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { uint8_t elem = mono_array_get(p_array, uint8_t, i); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -675,10 +677,11 @@ MonoArray *PoolRealArray_to_mono_array(const PoolRealArray &p_array) { PoolRealArray mono_array_to_PoolRealArray(MonoArray *p_array) { PoolRealArray ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t elem = mono_array_get(p_array, real_t, i); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -698,10 +701,11 @@ MonoArray *PoolStringArray_to_mono_array(const PoolStringArray &p_array) { PoolStringArray mono_array_to_PoolStringArray(MonoArray *p_array) { PoolStringArray ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { MonoString *elem = mono_array_get(p_array, MonoString *, i); - ret.push_back(mono_string_to_godot(elem)); + ret.set(i, mono_string_to_godot(elem)); } return ret; @@ -729,11 +733,12 @@ MonoArray *PoolColorArray_to_mono_array(const PoolColorArray &p_array) { PoolColorArray mono_array_to_PoolColorArray(MonoArray *p_array) { PoolColorArray ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 4, i); MARSHALLED_IN(Color, raw_elem, elem); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -759,11 +764,12 @@ MonoArray *PoolVector2Array_to_mono_array(const PoolVector2Array &p_array) { PoolVector2Array mono_array_to_PoolVector2Array(MonoArray *p_array) { PoolVector2Array ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 2, i); MARSHALLED_IN(Vector2, raw_elem, elem); - ret.push_back(elem); + ret.set(i, elem); } return ret; @@ -790,11 +796,12 @@ MonoArray *PoolVector3Array_to_mono_array(const PoolVector3Array &p_array) { PoolVector3Array mono_array_to_PoolVector3Array(MonoArray *p_array) { PoolVector3Array ret; int length = mono_array_length(p_array); + ret.resize(length); for (int i = 0; i < length; i++) { real_t *raw_elem = (real_t *)mono_array_addr_with_size(p_array, sizeof(real_t) * 3, i); MARSHALLED_IN(Vector3, raw_elem, elem); - ret.push_back(elem); + ret.set(i, elem); } return ret; diff --git a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp index 18ab616826..c95a8ac2dd 100644 --- a/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp +++ b/modules/stb_vorbis/audio_stream_ogg_vorbis.cpp @@ -263,8 +263,8 @@ float AudioStreamOGGVorbis::get_length() const { void AudioStreamOGGVorbis::_bind_methods() { - ClassDB::bind_method(D_METHOD("_set_data", "data"), &AudioStreamOGGVorbis::set_data); - ClassDB::bind_method(D_METHOD("_get_data"), &AudioStreamOGGVorbis::get_data); + ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamOGGVorbis::set_data); + ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamOGGVorbis::get_data); ClassDB::bind_method(D_METHOD("set_loop", "enable"), &AudioStreamOGGVorbis::set_loop); ClassDB::bind_method(D_METHOD("has_loop"), &AudioStreamOGGVorbis::has_loop); @@ -272,7 +272,7 @@ void AudioStreamOGGVorbis::_bind_methods() { ClassDB::bind_method(D_METHOD("set_loop_offset", "seconds"), &AudioStreamOGGVorbis::set_loop_offset); ClassDB::bind_method(D_METHOD("get_loop_offset"), &AudioStreamOGGVorbis::get_loop_offset); - ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop", "has_loop"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "loop_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_loop_offset", "get_loop_offset"); } diff --git a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml index ac95a7197f..e2281babf7 100644 --- a/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml +++ b/modules/stb_vorbis/doc_classes/AudioStreamOGGVorbis.xml @@ -13,6 +13,9 @@ <methods> </methods> <members> + <member name="data" type="PoolByteArray" setter="set_data" getter="get_data"> + Contains the audio data in bytes. + </member> <member name="loop" type="bool" setter="set_loop" getter="has_loop"> </member> <member name="loop_offset" type="float" setter="set_loop_offset" getter="get_loop_offset"> diff --git a/modules/visual_script/visual_script.cpp b/modules/visual_script/visual_script.cpp index 03bc4c114a..318fb7fb9c 100644 --- a/modules/visual_script/visual_script.cpp +++ b/modules/visual_script/visual_script.cpp @@ -121,6 +121,10 @@ Array VisualScriptNode::_get_default_input_values() const { return default_input_values; } +String VisualScriptNode::get_text() const { + return ""; +} + void VisualScriptNode::_bind_methods() { ClassDB::bind_method(D_METHOD("get_visual_script"), &VisualScriptNode::get_visual_script); diff --git a/modules/visual_script/visual_script.h b/modules/visual_script/visual_script.h index dad9c68312..a15360ad39 100644 --- a/modules/visual_script/visual_script.h +++ b/modules/visual_script/visual_script.h @@ -78,7 +78,7 @@ public: Variant get_default_input_value(int p_port) const; virtual String get_caption() const = 0; - virtual String get_text() const = 0; + virtual String get_text() const; virtual String get_category() const = 0; //used by editor, this is not really saved diff --git a/modules/visual_script/visual_script_builtin_funcs.cpp b/modules/visual_script/visual_script_builtin_funcs.cpp index 7f0a42da82..73b6d702c1 100644 --- a/modules/visual_script/visual_script_builtin_funcs.cpp +++ b/modules/visual_script/visual_script_builtin_funcs.cpp @@ -666,12 +666,14 @@ PropertyInfo VisualScriptBuiltinFunc::get_output_value_port_info(int p_idx) cons return PropertyInfo(t, ""); } +/* String VisualScriptBuiltinFunc::get_caption() const { return "BuiltinFunc"; } +*/ -String VisualScriptBuiltinFunc::get_text() const { +String VisualScriptBuiltinFunc::get_caption() const { return func_name[func]; } diff --git a/modules/visual_script/visual_script_builtin_funcs.h b/modules/visual_script/visual_script_builtin_funcs.h index f862d5c26f..3345762b9f 100644 --- a/modules/visual_script/visual_script_builtin_funcs.h +++ b/modules/visual_script/visual_script_builtin_funcs.h @@ -129,7 +129,7 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; + //virtual String get_text() const; virtual String get_category() const { return "functions"; } void set_func(BuiltinFunc p_which); diff --git a/modules/visual_script/visual_script_editor.cpp b/modules/visual_script/visual_script_editor.cpp index dfaa873b13..0618064ea6 100644 --- a/modules/visual_script/visual_script_editor.cpp +++ b/modules/visual_script/visual_script_editor.cpp @@ -527,6 +527,7 @@ void VisualScriptEditor::_update_graph(int p_only_id) { GraphNode *gnode = memnew(GraphNode); gnode->set_title(node->get_caption()); + gnode->set_offset(pos * EDSCALE); if (error_line == E->get()) { gnode->set_overlay(GraphNode::OVERLAY_POSITION); } else if (node->is_breakpoint()) { @@ -543,8 +544,10 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->set_show_close_button(true); } - if (Object::cast_to<VisualScriptExpression>(node.ptr())) { + bool has_gnode_text = false; + if (Object::cast_to<VisualScriptExpression>(node.ptr())) { + has_gnode_text = true; LineEdit *line_edit = memnew(LineEdit); line_edit->set_text(node->get_text()); line_edit->set_expand_to_text_length(true); @@ -552,9 +555,13 @@ void VisualScriptEditor::_update_graph(int p_only_id) { gnode->add_child(line_edit); line_edit->connect("text_changed", this, "_expression_text_changed", varray(E->get())); } else { - Label *text = memnew(Label); - text->set_text(node->get_text()); - gnode->add_child(text); + String text = node->get_text(); + if (!text.empty()) { + has_gnode_text = true; + Label *label = memnew(Label); + label->set_text(text); + gnode->add_child(label); + } } if (Object::cast_to<VisualScriptComment>(node.ptr())) { @@ -589,9 +596,21 @@ void VisualScriptEditor::_update_graph(int p_only_id) { int slot_idx = 0; bool single_seq_output = node->get_output_sequence_port_count() == 1 && node->get_output_sequence_port_text(0) == String(); - gnode->set_slot(0, node->has_input_sequence_port(), TYPE_SEQUENCE, mono_color, single_seq_output, TYPE_SEQUENCE, mono_color, seq_port, seq_port); - gnode->set_offset(pos * EDSCALE); - slot_idx++; + if ((node->has_input_sequence_port() || single_seq_output) || has_gnode_text) { + // IF has_gnode_text is true BUT we have no sequence ports to draw (in here), + // we still draw the disabled default ones to shift up the slots by one, + // so the slots DON'T start with the content text. + + // IF has_gnode_text is false, but we DO want to draw default sequence ports, + // we draw a dummy text to take up the position of the sequence nodes, so all the other ports are still aligned correctly. + if (!has_gnode_text) { + Label *dummy = memnew(Label); + dummy->set_text(" "); + gnode->add_child(dummy); + } + gnode->set_slot(0, node->has_input_sequence_port(), TYPE_SEQUENCE, mono_color, single_seq_output, TYPE_SEQUENCE, mono_color, seq_port, seq_port); + slot_idx++; + } int mixed_seq_ports = 0; diff --git a/modules/visual_script/visual_script_flow_control.cpp b/modules/visual_script/visual_script_flow_control.cpp index 5c097dfa76..ea23ab1b2a 100644 --- a/modules/visual_script/visual_script_flow_control.cpp +++ b/modules/visual_script/visual_script_flow_control.cpp @@ -772,7 +772,7 @@ PropertyInfo VisualScriptTypeCast::get_output_value_port_info(int p_idx) const { String VisualScriptTypeCast::get_caption() const { - return "TypeCast"; + return "Type Cast"; } String VisualScriptTypeCast::get_text() const { diff --git a/modules/visual_script/visual_script_func_nodes.cpp b/modules/visual_script/visual_script_func_nodes.cpp index 187c9b0b9e..bdf5705ecd 100644 --- a/modules/visual_script/visual_script_func_nodes.cpp +++ b/modules/visual_script/visual_script_func_nodes.cpp @@ -262,26 +262,6 @@ PropertyInfo VisualScriptFunctionCall::get_output_value_port_info(int p_idx) con } String VisualScriptFunctionCall::get_caption() const { - - static const char *cname[5] = { - "CallSelf", - "CallNode", - "CallInstance", - "CallBasic", - "CallSingleton" - }; - - String caption = cname[call_mode]; - - if (rpc_call_mode) { - caption += " (RPC)"; - } - - return caption; -} - -String VisualScriptFunctionCall::get_text() const { - if (call_mode == CALL_MODE_SELF) return " " + String(function) + "()"; if (call_mode == CALL_MODE_SINGLETON) @@ -294,6 +274,14 @@ String VisualScriptFunctionCall::get_text() const { return " " + base_type + "." + String(function) + "()"; } +String VisualScriptFunctionCall::get_text() const { + + if (rpc_call_mode) { + return "RPC"; + } + return ""; +} + void VisualScriptFunctionCall::set_basic_type(Variant::Type p_type) { if (basic_type == p_type) @@ -1075,36 +1063,31 @@ PropertyInfo VisualScriptPropertySet::get_output_value_port_info(int p_idx) cons String VisualScriptPropertySet::get_caption() const { - static const char *cname[4] = { - "Self", - "Node", - "Instance", - "Basic" - }; - static const char *opname[ASSIGN_OP_MAX] = { - "Set", "Add", "Sub", "Mul", "Div", "Mod", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitXor" + "Set", "Add", "Subtract", "Multiply", "Divide", "Mod", "ShiftLeft", "ShiftRight", "BitAnd", "BitOr", "BitXor" }; - return String(cname[call_mode]) + opname[assign_op]; + + String prop = String(opname[assign_op]) + " " + property; + if (index != StringName()) { + prop += "." + String(index); + } + + return prop; } String VisualScriptPropertySet::get_text() const { - String prop; + if (call_mode == CALL_MODE_BASIC_TYPE) { + return String("On ") + Variant::get_type_name(basic_type); + } - if (call_mode == CALL_MODE_BASIC_TYPE) - prop = Variant::get_type_name(basic_type) + "." + property; - else if (call_mode == CALL_MODE_NODE_PATH) - prop = String(base_path) + ":" + property; - else if (call_mode == CALL_MODE_SELF) - prop = property; - else if (call_mode == CALL_MODE_INSTANCE) - prop = String(base_type) + ":" + property; + static const char *cname[3] = { + "Self", + "Scene Node", + "Instance" + }; - if (index != StringName()) { - prop += "." + String(index); - } - return prop; + return String("On ") + cname[call_mode]; } void VisualScriptPropertySet::_update_base_type() { @@ -1838,30 +1821,22 @@ PropertyInfo VisualScriptPropertyGet::get_output_value_port_info(int p_idx) cons String VisualScriptPropertyGet::get_caption() const { - static const char *cname[4] = { - "SelfGet", - "NodeGet", - "InstanceGet", - "BasicGet" - }; - - return cname[call_mode]; + return String("Get ") + property; } String VisualScriptPropertyGet::get_text() const { - String prop; + if (call_mode == CALL_MODE_BASIC_TYPE) { + return String("On ") + Variant::get_type_name(basic_type); + } - if (call_mode == CALL_MODE_BASIC_TYPE) - prop = Variant::get_type_name(basic_type) + "." + property; - else if (call_mode == CALL_MODE_NODE_PATH) - prop = String(base_path) + ":" + property; - else if (call_mode == CALL_MODE_SELF) - prop = property; - else if (call_mode == CALL_MODE_INSTANCE) - prop = String(base_type) + ":" + property; + static const char *cname[3] = { + "Self", + "Scene Node", + "Instance" + }; - return prop; + return String("On ") + cname[call_mode]; } void VisualScriptPropertyGet::set_base_type(const StringName &p_type) { @@ -2399,12 +2374,7 @@ PropertyInfo VisualScriptEmitSignal::get_output_value_port_info(int p_idx) const String VisualScriptEmitSignal::get_caption() const { - return "EmitSignal"; -} - -String VisualScriptEmitSignal::get_text() const { - - return "emit " + String(name); + return "Emit " + String(name); } void VisualScriptEmitSignal::set_signal(const StringName &p_type) { diff --git a/modules/visual_script/visual_script_func_nodes.h b/modules/visual_script/visual_script_func_nodes.h index 0b30eae65a..3b522564d4 100644 --- a/modules/visual_script/visual_script_func_nodes.h +++ b/modules/visual_script/visual_script_func_nodes.h @@ -346,7 +346,7 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; + //virtual String get_text() const; virtual String get_category() const { return "functions"; } void set_signal(const StringName &p_type); diff --git a/modules/visual_script/visual_script_nodes.cpp b/modules/visual_script/visual_script_nodes.cpp index c5654a5a20..4803f29519 100644 --- a/modules/visual_script/visual_script_nodes.cpp +++ b/modules/visual_script/visual_script_nodes.cpp @@ -467,12 +467,12 @@ PropertyInfo VisualScriptOperator::get_output_value_port_info(int p_idx) const { static const char *op_names[] = { //comparison - "Equal", //OP_EQUAL, - "NotEqual", //OP_NOT_EQUAL, - "Less", //OP_LESS, - "LessEqual", //OP_LESS_EQUAL, - "Greater", //OP_GREATER, - "GreaterEq", //OP_GREATER_EQUAL, + "Are Equal", //OP_EQUAL, + "Are Not Equal", //OP_NOT_EQUAL, + "Less Than", //OP_LESS, + "Less Than or Equal", //OP_LESS_EQUAL, + "Greater Than", //OP_GREATER, + "Greater Than or Equal", //OP_GREATER_EQUAL, //mathematic "Add", //OP_ADD, "Subtract", //OP_SUBTRACT, @@ -481,14 +481,14 @@ static const char *op_names[] = { "Negate", //OP_NEGATE, "Positive", //OP_POSITIVE, "Remainder", //OP_MODULE, - "Concat", //OP_STRING_CONCAT, + "Concatenate", //OP_STRING_CONCAT, //bitwise - "ShiftLeft", //OP_SHIFT_LEFT, - "ShiftRight", //OP_SHIFT_RIGHT, - "BitAnd", //OP_BIT_AND, - "BitOr", //OP_BIT_OR, - "BitXor", //OP_BIT_XOR, - "BitNeg", //OP_BIT_NEGATE, + "Bit Shift Left", //OP_SHIFT_LEFT, + "Bit Shift Right", //OP_SHIFT_RIGHT, + "Bit And", //OP_BIT_AND, + "Bit Or", //OP_BIT_OR, + "Bit Xor", //OP_BIT_XOR, + "Bit Negate", //OP_BIT_NEGATE, //logic "And", //OP_AND, "Or", //OP_OR, @@ -500,11 +500,6 @@ static const char *op_names[] = { String VisualScriptOperator::get_caption() const { - return op_names[op]; -} - -String VisualScriptOperator::get_text() const { - static const wchar_t *op_names[] = { //comparison L"A = B", //OP_EQUAL, @@ -803,14 +798,8 @@ PropertyInfo VisualScriptVariableGet::get_output_value_port_info(int p_idx) cons String VisualScriptVariableGet::get_caption() const { - return "Variable"; + return "Get " + variable; } - -String VisualScriptVariableGet::get_text() const { - - return variable; -} - void VisualScriptVariableGet::set_variable(StringName p_variable) { if (variable == p_variable) @@ -928,12 +917,7 @@ PropertyInfo VisualScriptVariableSet::get_output_value_port_info(int p_idx) cons String VisualScriptVariableSet::get_caption() const { - return "VariableSet"; -} - -String VisualScriptVariableSet::get_text() const { - - return variable; + return "Set " + variable; } void VisualScriptVariableSet::set_variable(StringName p_variable) { @@ -1044,7 +1028,7 @@ PropertyInfo VisualScriptConstant::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptConstant::get_output_value_port_info(int p_idx) const { PropertyInfo pinfo; - pinfo.name = "get"; + pinfo.name = String(value); pinfo.type = type; return pinfo; } @@ -1054,11 +1038,6 @@ String VisualScriptConstant::get_caption() const { return "Constant"; } -String VisualScriptConstant::get_text() const { - - return String(value); -} - void VisualScriptConstant::set_constant_type(Variant::Type p_type) { if (type == p_type) @@ -1174,10 +1153,20 @@ PropertyInfo VisualScriptPreload::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptPreload::get_output_value_port_info(int p_idx) const { - PropertyInfo pinfo = PropertyInfo(Variant::OBJECT, "res"); + PropertyInfo pinfo; + pinfo.type = Variant::OBJECT; if (preload.is_valid()) { pinfo.hint = PROPERTY_HINT_RESOURCE_TYPE; pinfo.hint_string = preload->get_class(); + if (preload->get_path().is_resource_file()) { + pinfo.name = preload->get_path(); + } else if (preload->get_name() != String()) { + pinfo.name = preload->get_name(); + } else { + pinfo.name = preload->get_class(); + } + } else { + pinfo.name = "<empty>"; } return pinfo; @@ -1188,21 +1177,6 @@ String VisualScriptPreload::get_caption() const { return "Preload"; } -String VisualScriptPreload::get_text() const { - - if (preload.is_valid()) { - if (preload->get_path().is_resource_file()) { - return preload->get_path(); - } else if (preload->get_name() != String()) { - return preload->get_name(); - } else { - return preload->get_class(); - } - } else { - return "<empty>"; - } -} - void VisualScriptPreload::set_preload(const Ref<Resource> &p_preload) { if (preload == p_preload) @@ -1291,12 +1265,7 @@ PropertyInfo VisualScriptIndexGet::get_output_value_port_info(int p_idx) const { String VisualScriptIndexGet::get_caption() const { - return "IndexGet"; -} - -String VisualScriptIndexGet::get_text() const { - - return String("get"); + return "Get Index"; } class VisualScriptNodeInstanceIndexGet : public VisualScriptNodeInstance { @@ -1371,12 +1340,7 @@ PropertyInfo VisualScriptIndexSet::get_output_value_port_info(int p_idx) const { String VisualScriptIndexSet::get_caption() const { - return "IndexSet"; -} - -String VisualScriptIndexSet::get_text() const { - - return String("set"); + return "Set Index"; } class VisualScriptNodeInstanceIndexSet : public VisualScriptNodeInstance { @@ -1439,18 +1403,13 @@ PropertyInfo VisualScriptGlobalConstant::get_input_value_port_info(int p_idx) co } PropertyInfo VisualScriptGlobalConstant::get_output_value_port_info(int p_idx) const { - - return PropertyInfo(Variant::REAL, "value"); + String name = GlobalConstants::get_global_constant_name(index); + return PropertyInfo(Variant::REAL, name); } String VisualScriptGlobalConstant::get_caption() const { - return "GlobalConst"; -} - -String VisualScriptGlobalConstant::get_text() const { - - return GlobalConstants::get_global_constant_name(index); + return "Global Constant"; } void VisualScriptGlobalConstant::set_global_constant(int p_which) { @@ -1539,17 +1498,12 @@ PropertyInfo VisualScriptClassConstant::get_input_value_port_info(int p_idx) con PropertyInfo VisualScriptClassConstant::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::INT, "value"); + return PropertyInfo(Variant::INT, String(base_type) + "." + String(name)); } String VisualScriptClassConstant::get_caption() const { - return "ClassConst"; -} - -String VisualScriptClassConstant::get_text() const { - - return String(base_type) + "." + String(name); + return "Class Constant"; } void VisualScriptClassConstant::set_class_constant(const StringName &p_which) { @@ -1673,7 +1627,7 @@ PropertyInfo VisualScriptBasicTypeConstant::get_output_value_port_info(int p_idx String VisualScriptBasicTypeConstant::get_caption() const { - return "BasicConst"; + return "Basic Constant"; } String VisualScriptBasicTypeConstant::get_text() const { @@ -1828,17 +1782,12 @@ PropertyInfo VisualScriptMathConstant::get_input_value_port_info(int p_idx) cons PropertyInfo VisualScriptMathConstant::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::REAL, "value"); + return PropertyInfo(Variant::REAL, const_name[constant]); } String VisualScriptMathConstant::get_caption() const { - return "MathConst"; -} - -String VisualScriptMathConstant::get_text() const { - - return const_name[constant]; + return "Math Constant"; } void VisualScriptMathConstant::set_math_constant(MathConstant p_which) { @@ -1903,7 +1852,7 @@ VisualScriptMathConstant::VisualScriptMathConstant() { } ////////////////////////////////////////// -////////////////GLOBALSINGLETON/////////// +////////////////ENGINESINGLETON/////////// ////////////////////////////////////////// int VisualScriptEngineSingleton::get_output_sequence_port_count() const { @@ -1937,17 +1886,12 @@ PropertyInfo VisualScriptEngineSingleton::get_input_value_port_info(int p_idx) c PropertyInfo VisualScriptEngineSingleton::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "instance"); + return PropertyInfo(Variant::OBJECT, singleton); } String VisualScriptEngineSingleton::get_caption() const { - return "EngineSingleton"; -} - -String VisualScriptEngineSingleton::get_text() const { - - return singleton; + return "Get Engine Singleton"; } void VisualScriptEngineSingleton::set_singleton(const String &p_string) { @@ -2058,17 +2002,12 @@ PropertyInfo VisualScriptSceneNode::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptSceneNode::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "node"); + return PropertyInfo(Variant::OBJECT, path.simplified()); } String VisualScriptSceneNode::get_caption() const { - return "SceneNode"; -} - -String VisualScriptSceneNode::get_text() const { - - return path.simplified(); + return "Get Scene Node"; } void VisualScriptSceneNode::set_node_path(const NodePath &p_path) { @@ -2259,17 +2198,12 @@ PropertyInfo VisualScriptSceneTree::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptSceneTree::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "instance"); + return PropertyInfo(Variant::OBJECT, "Scene Tree"); } String VisualScriptSceneTree::get_caption() const { - return "SceneTree"; -} - -String VisualScriptSceneTree::get_text() const { - - return ""; + return "Get Scene Tree"; } class VisualScriptNodeInstanceSceneTree : public VisualScriptNodeInstance { @@ -2361,17 +2295,12 @@ PropertyInfo VisualScriptResourcePath::get_input_value_port_info(int p_idx) cons PropertyInfo VisualScriptResourcePath::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::STRING, "path"); + return PropertyInfo(Variant::STRING, path); } String VisualScriptResourcePath::get_caption() const { - return "ResourcePath"; -} - -String VisualScriptResourcePath::get_text() const { - - return path; + return "Resource Path"; } void VisualScriptResourcePath::set_resource_path(const String &p_path) { @@ -2453,20 +2382,18 @@ PropertyInfo VisualScriptSelf::get_input_value_port_info(int p_idx) const { PropertyInfo VisualScriptSelf::get_output_value_port_info(int p_idx) const { - return PropertyInfo(Variant::OBJECT, "instance"); -} - -String VisualScriptSelf::get_caption() const { + String type_name; + if (get_visual_script().is_valid()) + type_name = get_visual_script()->get_instance_base_type(); + else + type_name = "instance"; - return "Self"; + return PropertyInfo(Variant::OBJECT, type_name); } -String VisualScriptSelf::get_text() const { +String VisualScriptSelf::get_caption() const { - if (get_visual_script().is_valid()) - return get_visual_script()->get_instance_base_type(); - else - return ""; + return "Get Self"; } class VisualScriptNodeInstanceSelf : public VisualScriptNodeInstance { @@ -3032,12 +2959,7 @@ PropertyInfo VisualScriptConstructor::get_output_value_port_info(int p_idx) cons String VisualScriptConstructor::get_caption() const { - return "Construct"; -} - -String VisualScriptConstructor::get_text() const { - - return "new " + Variant::get_type_name(type) + "()"; + return "Construct " + Variant::get_type_name(type); } String VisualScriptConstructor::get_category() const { @@ -3163,17 +3085,12 @@ PropertyInfo VisualScriptLocalVar::get_input_value_port_info(int p_idx) const { } PropertyInfo VisualScriptLocalVar::get_output_value_port_info(int p_idx) const { - return PropertyInfo(type, "get"); + return PropertyInfo(type, name); } String VisualScriptLocalVar::get_caption() const { - return "LocalVarGet"; -} - -String VisualScriptLocalVar::get_text() const { - - return name; + return "Get Local Var"; } String VisualScriptLocalVar::get_category() const { @@ -3289,7 +3206,7 @@ PropertyInfo VisualScriptLocalVarSet::get_output_value_port_info(int p_idx) cons String VisualScriptLocalVarSet::get_caption() const { - return "LocalVarSet"; + return "Set Local Var"; } String VisualScriptLocalVarSet::get_text() const { @@ -3427,12 +3344,7 @@ PropertyInfo VisualScriptInputAction::get_output_value_port_info(int p_idx) cons String VisualScriptInputAction::get_caption() const { - return "Action"; -} - -String VisualScriptInputAction::get_text() const { - - return name; + return "Action " + name; } String VisualScriptInputAction::get_category() const { @@ -3600,12 +3512,7 @@ PropertyInfo VisualScriptDeconstruct::get_output_value_port_info(int p_idx) cons String VisualScriptDeconstruct::get_caption() const { - return "Deconstruct"; -} - -String VisualScriptDeconstruct::get_text() const { - - return "from " + Variant::get_type_name(type) + ":"; + return "Deconstruct " + Variant::get_type_name(type); } String VisualScriptDeconstruct::get_category() const { diff --git a/modules/visual_script/visual_script_nodes.h b/modules/visual_script/visual_script_nodes.h index a581e81c8c..a0bc35dd92 100644 --- a/modules/visual_script/visual_script_nodes.h +++ b/modules/visual_script/visual_script_nodes.h @@ -124,7 +124,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "operators"; } void set_operator(Variant::Operator p_op); @@ -194,7 +193,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_variable(StringName p_variable); @@ -228,7 +226,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_variable(StringName p_variable); @@ -263,7 +260,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_constant_type(Variant::Type p_type); @@ -299,7 +295,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_preload(const Ref<Resource> &p_preload); @@ -327,7 +322,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "operators"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -352,7 +346,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "operators"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -381,7 +374,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_global_constant(int p_which); @@ -416,7 +408,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_class_constant(const StringName &p_which); @@ -505,7 +496,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "constants"; } void set_math_constant(MathConstant p_which); @@ -539,7 +529,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_singleton(const String &p_string); @@ -575,7 +564,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_node_path(const NodePath &p_path); @@ -609,7 +597,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -641,7 +628,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } void set_resource_path(const String &p_path); @@ -672,7 +658,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const { return "data"; } virtual VisualScriptNodeInstance *instance(VisualScriptInstance *p_instance); @@ -822,7 +807,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_constructor_type(Variant::Type p_type); @@ -859,7 +843,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_var_name(const StringName &p_name); @@ -942,7 +925,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_action_name(const StringName &p_name); @@ -993,7 +975,6 @@ public: virtual PropertyInfo get_output_value_port_info(int p_idx) const; virtual String get_caption() const; - virtual String get_text() const; virtual String get_category() const; void set_deconstruct_type(Variant::Type p_type); diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index 54d4755bd7..68a2d72464 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -56,8 +56,6 @@ extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) { int main(int argc, char *argv[]) { - printf("let it go dude!\n"); - // sync from persistent state into memory and then // run the 'main_after_fs_sync' function /* clang-format off */ diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index c1022a1aca..2b2d21553b 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -109,6 +109,7 @@ public: bool minimized; bool maximized; bool zoomed; + bool resizable; Size2 window_size; Rect2 restore_rect; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index bde0b4e898..5589f93a5d 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -913,7 +913,7 @@ static int remapKey(unsigned int key) { CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); if (!layoutData) - return nil; + return 0; const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData); @@ -1184,6 +1184,7 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a if (p_desired.borderless_window) { styleMask = NSWindowStyleMaskBorderless; } else { + resizable = p_desired.resizable; styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (p_desired.resizable ? NSWindowStyleMaskResizable : 0); } @@ -1480,7 +1481,7 @@ void OS_OSX::set_cursor_shape(CursorShape p_shape) { if (cursor_shape == p_shape) return; - if (mouse_mode != MOUSE_MODE_VISIBLE) { + if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { cursor_shape = p_shape; return; } @@ -1740,7 +1741,8 @@ String OS_OSX::get_godot_dir_name() const { String OS_OSX::get_system_dir(SystemDir p_dir) const { - NSSearchPathDirectory id = 0; + NSSearchPathDirectory id; + bool found = true; switch (p_dir) { case SYSTEM_DIR_DESKTOP: { @@ -1761,10 +1763,13 @@ String OS_OSX::get_system_dir(SystemDir p_dir) const { case SYSTEM_DIR_PICTURES: { id = NSPicturesDirectory; } break; + default: { + found = false; + } } String ret; - if (id) { + if (found) { NSArray *paths = NSSearchPathForDirectoriesInDomains(id, NSUserDomainMask, YES); if (paths && [paths count] >= 1) { @@ -2110,6 +2115,8 @@ void OS_OSX::set_window_resizable(bool p_enabled) { [window_object setStyleMask:[window_object styleMask] | NSWindowStyleMaskResizable]; else [window_object setStyleMask:[window_object styleMask] & ~NSWindowStyleMaskResizable]; + + resizable = p_enabled; }; bool OS_OSX::is_window_resizable() const { @@ -2219,7 +2226,7 @@ void OS_OSX::set_borderless_window(bool p_borderless) { if (layered_window) set_window_per_pixel_transparency_enabled(false); - [window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable]; + [window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (resizable ? NSWindowStyleMaskResizable : 0)]; // Force update of the window styles NSRect frameRect = [window_object frame]; @@ -2615,6 +2622,7 @@ OS_OSX::OS_OSX() { minimized = false; window_size = Vector2(1024, 600); zoomed = false; + resizable = false; Vector<Logger *> loggers; loggers.push_back(memnew(OSXTerminalLogger)); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index d6cdea7b88..8d664b5832 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -623,9 +623,12 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) case WM_SIZE: { int window_w = LOWORD(lParam); int window_h = HIWORD(lParam); - if (window_w > 0 && window_h > 0) { + if (window_w > 0 && window_h > 0 && !preserve_window_size) { video_mode.width = window_w; video_mode.height = window_h; + } else { + preserve_window_size = false; + set_window_size(Size2(video_mode.width, video_mode.height)); } if (wParam == SIZE_MAXIMIZED) { maximized = true; @@ -777,7 +780,9 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) SetCursor(NULL); } else { if (hCursor != NULL) { - SetCursor(hCursor); + CursorShape c = cursor_shape; + cursor_shape = CURSOR_MAX; + set_cursor_shape(c); hCursor = NULL; } } @@ -1561,6 +1566,15 @@ void OS_Windows::set_window_size(const Size2 p_size) { } MoveWindow(hWnd, rect.left, rect.top, w, h, TRUE); + + // Don't let the mouse leave the window when resizing to a smaller resolution + if (mouse_mode == MOUSE_MODE_CONFINED) { + RECT rect; + GetClientRect(hWnd, &rect); + ClientToScreen(hWnd, (POINT *)&rect.left); + ClientToScreen(hWnd, (POINT *)&rect.right); + ClipCursor(&rect); + } } void OS_Windows::set_window_fullscreen(bool p_enabled) { @@ -1767,6 +1781,7 @@ void OS_Windows::set_borderless_window(bool p_borderless) { video_mode.borderless_window = p_borderless; + preserve_window_size = true; _update_window_style(); } @@ -1785,7 +1800,7 @@ void OS_Windows::_update_window_style(bool repaint) { } } - SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); + SetWindowPos(hWnd, video_mode.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); if (repaint) { RECT rect; @@ -1996,7 +2011,7 @@ void OS_Windows::set_cursor_shape(CursorShape p_shape) { if (cursor_shape == p_shape) return; - if (mouse_mode != MOUSE_MODE_VISIBLE) { + if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { cursor_shape = p_shape; return; } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 221109318e..81849497ee 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -105,6 +105,7 @@ class OS_Windows : public OS { Size2 window_rect; VideoMode video_mode; + bool preserve_window_size = false; MainLoop *main_loop; diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index eec371865e..7b514d0f90 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1292,6 +1292,9 @@ void OS_X11::set_borderless_window(bool p_borderless) { hints.decorations = current_videomode.borderless_window ? 0 : 1; property = XInternAtom(x11_display, "_MOTIF_WM_HINTS", True); XChangeProperty(x11_display, x11_window, property, property, 32, PropModeReplace, (unsigned char *)&hints, 5); + + // Preserve window size + set_window_size(Size2(current_videomode.width, current_videomode.height)); } bool OS_X11::get_borderless_window() { @@ -2407,7 +2410,7 @@ void OS_X11::set_cursor_shape(CursorShape p_shape) { if (p_shape == current_cursor) return; - if (mouse_mode == MOUSE_MODE_VISIBLE) { + if (mouse_mode == MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) { if (cursors[p_shape] != None) XDefineCursor(x11_display, x11_window, cursors[p_shape]); else if (cursors[CURSOR_ARROW] != None) diff --git a/scene/3d/path.cpp b/scene/3d/path.cpp index 154dcb4259..9acaa15641 100644 --- a/scene/3d/path.cpp +++ b/scene/3d/path.cpp @@ -329,3 +329,219 @@ PathFollow::PathFollow() { cubic = true; loop = true; } + +////////////// + +void OrientedPathFollow::_update_transform() { + + if (!path) + return; + + Ref<Curve3D> c = path->get_curve(); + if (!c.is_valid()) + return; + + int count = c->get_point_count(); + if (count < 2) + return; + + if (delta_offset == 0) { + return; + } + + float offset = get_offset(); + float bl = c->get_baked_length(); + float bi = c->get_bake_interval(); + float o = offset; + float o_next = offset + bi; + + if (has_loop()) { + o = Math::fposmod(o, bl); + o_next = Math::fposmod(o_next, bl); + } else if (o_next >= bl) { + o = bl - bi; + o_next = bl; + } + + bool cubic = get_cubic_interpolation(); + Vector3 pos = c->interpolate_baked(o, cubic); + Vector3 forward = c->interpolate_baked(o_next, cubic) - pos; + + if (forward.length_squared() < CMP_EPSILON2) + forward = Vector3(0, 0, 1); + else + forward.normalize(); + + Vector3 up = c->interpolate_baked_up_vector(o, true); + + if (o_next < o) { + Vector3 up1 = c->interpolate_baked_up_vector(o_next, true); + Vector3 axis = up.cross(up1); + + if (axis.length_squared() < CMP_EPSILON2) + axis = forward; + else + axis.normalize(); + + up.rotate(axis, up.angle_to(up1) * 0.5f); + } + + Transform t = get_transform(); + Vector3 scale = t.basis.get_scale(); + + Vector3 sideways = up.cross(forward).normalized(); + up = forward.cross(sideways).normalized(); + + t.basis.set(sideways, up, forward); + t.basis.scale_local(scale); + + t.origin = pos + sideways * get_h_offset() + up * get_v_offset(); + + set_transform(t); +} + +void OrientedPathFollow::_notification(int p_what) { + + switch (p_what) { + + case NOTIFICATION_ENTER_TREE: { + + Node *parent = get_parent(); + if (parent) { + path = Object::cast_to<Path>(parent); + if (path) { + _update_transform(); + } + } + + } break; + case NOTIFICATION_EXIT_TREE: { + + path = NULL; + } break; + } +} + +void OrientedPathFollow::set_cubic_interpolation(bool p_enable) { + + cubic = p_enable; +} + +bool OrientedPathFollow::get_cubic_interpolation() const { + + return cubic; +} + +void OrientedPathFollow::_validate_property(PropertyInfo &property) const { + + if (property.name == "offset") { + + float max = 10000; + if (path && path->get_curve().is_valid()) + max = path->get_curve()->get_baked_length(); + + property.hint_string = "0," + rtos(max) + ",0.01"; + } +} + +void OrientedPathFollow::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_offset", "offset"), &OrientedPathFollow::set_offset); + ClassDB::bind_method(D_METHOD("get_offset"), &OrientedPathFollow::get_offset); + + ClassDB::bind_method(D_METHOD("set_h_offset", "h_offset"), &OrientedPathFollow::set_h_offset); + ClassDB::bind_method(D_METHOD("get_h_offset"), &OrientedPathFollow::get_h_offset); + + ClassDB::bind_method(D_METHOD("set_v_offset", "v_offset"), &OrientedPathFollow::set_v_offset); + ClassDB::bind_method(D_METHOD("get_v_offset"), &OrientedPathFollow::get_v_offset); + + ClassDB::bind_method(D_METHOD("set_unit_offset", "unit_offset"), &OrientedPathFollow::set_unit_offset); + ClassDB::bind_method(D_METHOD("get_unit_offset"), &OrientedPathFollow::get_unit_offset); + + ClassDB::bind_method(D_METHOD("set_cubic_interpolation", "enable"), &OrientedPathFollow::set_cubic_interpolation); + ClassDB::bind_method(D_METHOD("get_cubic_interpolation"), &OrientedPathFollow::get_cubic_interpolation); + + ClassDB::bind_method(D_METHOD("set_loop", "loop"), &OrientedPathFollow::set_loop); + ClassDB::bind_method(D_METHOD("has_loop"), &OrientedPathFollow::has_loop); + + ADD_PROPERTY(PropertyInfo(Variant::REAL, "offset", PROPERTY_HINT_RANGE, "0,10000,0.01"), "set_offset", "get_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "unit_offset", PROPERTY_HINT_RANGE, "0,1,0.0001", PROPERTY_USAGE_EDITOR), "set_unit_offset", "get_unit_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "h_offset"), "set_h_offset", "get_h_offset"); + ADD_PROPERTY(PropertyInfo(Variant::REAL, "v_offset"), "set_v_offset", "get_v_offset"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "cubic_interp"), "set_cubic_interpolation", "get_cubic_interpolation"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "loop"), "set_loop", "has_loop"); +} + +void OrientedPathFollow::set_offset(float p_offset) { + delta_offset = p_offset - offset; + offset = p_offset; + + if (path) + _update_transform(); + _change_notify("offset"); + _change_notify("unit_offset"); +} + +void OrientedPathFollow::set_h_offset(float p_h_offset) { + + h_offset = p_h_offset; + if (path) + _update_transform(); +} + +float OrientedPathFollow::get_h_offset() const { + + return h_offset; +} + +void OrientedPathFollow::set_v_offset(float p_v_offset) { + + v_offset = p_v_offset; + if (path) + _update_transform(); +} + +float OrientedPathFollow::get_v_offset() const { + + return v_offset; +} + +float OrientedPathFollow::get_offset() const { + + return offset; +} + +void OrientedPathFollow::set_unit_offset(float p_unit_offset) { + + if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) + set_offset(p_unit_offset * path->get_curve()->get_baked_length()); +} + +float OrientedPathFollow::get_unit_offset() const { + + if (path && path->get_curve().is_valid() && path->get_curve()->get_baked_length()) + return get_offset() / path->get_curve()->get_baked_length(); + else + return 0; +} + +void OrientedPathFollow::set_loop(bool p_loop) { + + loop = p_loop; +} + +bool OrientedPathFollow::has_loop() const { + + return loop; +} + +OrientedPathFollow::OrientedPathFollow() { + + offset = 0; + delta_offset = 0; + h_offset = 0; + v_offset = 0; + path = NULL; + cubic = true; + loop = true; +} diff --git a/scene/3d/path.h b/scene/3d/path.h index 2ed686ac3c..f73bf17dfe 100644 --- a/scene/3d/path.h +++ b/scene/3d/path.h @@ -111,4 +111,47 @@ public: VARIANT_ENUM_CAST(PathFollow::RotationMode); +class OrientedPathFollow : public Spatial { + + GDCLASS(OrientedPathFollow, Spatial); + +private: + Path *path; + real_t delta_offset; // change in offset since last _update_transform + real_t offset; + real_t h_offset; + real_t v_offset; + bool cubic; + bool loop; + + void _update_transform(); + +protected: + virtual void _validate_property(PropertyInfo &property) const; + + void _notification(int p_what); + static void _bind_methods(); + +public: + void set_offset(float p_offset); + float get_offset() const; + + void set_h_offset(float p_h_offset); + float get_h_offset() const; + + void set_v_offset(float p_v_offset); + float get_v_offset() const; + + void set_unit_offset(float p_unit_offset); + float get_unit_offset() const; + + void set_loop(bool p_loop); + bool has_loop() const; + + void set_cubic_interpolation(bool p_enable); + bool get_cubic_interpolation() const; + + OrientedPathFollow(); +}; + #endif // PATH_H diff --git a/scene/3d/vehicle_body.cpp b/scene/3d/vehicle_body.cpp index ee8d249981..385956dc16 100644 --- a/scene/3d/vehicle_body.cpp +++ b/scene/3d/vehicle_body.cpp @@ -583,11 +583,14 @@ void VehicleBody::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vec rel_vel = normal.dot(vel); // !BAS! We had this set to 0.4, in bullet its 0.2 - // real_t contactDamping = real_t(0.2); + real_t contactDamping = real_t(0.2); + + if (p_rollInfluence > 0.0) { + // !BAS! But seeing we apply this frame by frame, makes more sense to me to make this time based + // keeping in mind our anti roll factor if it is set + contactDamping = s->get_step() / p_rollInfluence; + } - // !BAS! But seeing we apply this frame by frame, makes more sense to me to make this time based - // keeping in mind our anti roll factor - real_t contactDamping = s->get_step() / p_rollInfluence; #define ONLY_USE_LINEAR_MASS #ifdef ONLY_USE_LINEAR_MASS real_t massTerm = real_t(1.) / ((1.0 / mass) + b2invmass); diff --git a/scene/animation/animation_tree_player.cpp b/scene/animation/animation_tree_player.cpp index ce5b372d72..143684bdf9 100644 --- a/scene/animation/animation_tree_player.cpp +++ b/scene/animation/animation_tree_player.cpp @@ -1216,6 +1216,12 @@ String AnimationTreePlayer::animation_node_get_master_animation(const StringName return n->from; } +float AnimationTreePlayer::animation_node_get_position(const StringName &p_node) const { + + GET_NODE_V(NODE_ANIMATION, AnimationNode, 0); + return n->time; +} + bool AnimationTreePlayer::animation_node_is_path_filtered(const StringName &p_node, const NodePath &p_path) const { GET_NODE_V(NODE_ANIMATION, AnimationNode, 0); @@ -1724,6 +1730,7 @@ void AnimationTreePlayer::_bind_methods() { ClassDB::bind_method(D_METHOD("animation_node_set_master_animation", "id", "source"), &AnimationTreePlayer::animation_node_set_master_animation); ClassDB::bind_method(D_METHOD("animation_node_get_master_animation", "id"), &AnimationTreePlayer::animation_node_get_master_animation); + ClassDB::bind_method(D_METHOD("animation_node_get_position", "id"), &AnimationTreePlayer::animation_node_get_position); ClassDB::bind_method(D_METHOD("animation_node_set_filter_path", "id", "path", "enable"), &AnimationTreePlayer::animation_node_set_filter_path); ClassDB::bind_method(D_METHOD("oneshot_node_set_fadein_time", "id", "time_sec"), &AnimationTreePlayer::oneshot_node_set_fadein_time); diff --git a/scene/animation/animation_tree_player.h b/scene/animation/animation_tree_player.h index 09d6f6fcb4..d2d7b1c9ec 100644 --- a/scene/animation/animation_tree_player.h +++ b/scene/animation/animation_tree_player.h @@ -348,6 +348,7 @@ public: Ref<Animation> animation_node_get_animation(const StringName &p_node) const; void animation_node_set_master_animation(const StringName &p_node, const String &p_master_animation); String animation_node_get_master_animation(const StringName &p_node) const; + float animation_node_get_position(const StringName &p_node) const; void animation_node_set_filter_path(const StringName &p_node, const NodePath &p_track_path, bool p_filter); void animation_node_set_get_filtered_paths(const StringName &p_node, List<NodePath> *r_paths) const; diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 49013b160a..4eefcc9ced 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -886,6 +886,10 @@ real_t Tween::tell() const { real_t Tween::get_runtime() const { + if (speed_scale == 0) { + return INFINITY; + } + pending_update++; real_t runtime = 0; for (const List<InterpolateData>::Element *E = interpolates.front(); E; E = E->next()) { @@ -896,7 +900,8 @@ real_t Tween::get_runtime() const { runtime = t; } pending_update--; - return runtime; + + return runtime / speed_scale; } bool Tween::_calc_delta_val(const Variant &p_initial_val, const Variant &p_final_val, Variant &p_delta_val) { diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index e57af0a4c0..f1f1a66b47 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -215,12 +215,14 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) { case (KEY_A): { //Select All select(); } break; +#ifdef APPLE_STYLE_KEYS case (KEY_LEFT): { // Go to start of text - like HOME key set_cursor_position(0); } break; case (KEY_RIGHT): { // Go to end of text - like END key set_cursor_position(text.length()); } break; +#endif default: { handled = false; } } @@ -1005,7 +1007,6 @@ void LineEdit::set_text(String p_text) { update(); cursor_pos = 0; window_pos = 0; - _text_changed(); } void LineEdit::clear() { diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 0c2e5980b1..55a650ff12 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -4110,7 +4110,7 @@ Control::CursorShape TextEdit::get_cursor_shape(const Point2 &p_pos) const { void TextEdit::set_text(String p_text) { setting_text = true; - clear(); + _clear(); _insert_text_at_cursor(p_text); clear_undo_history(); cursor.column = 0; @@ -4123,7 +4123,7 @@ void TextEdit::set_text(String p_text) { cursor_set_column(0); update(); setting_text = false; - _text_changed_emit(); + //get_range()->set(0); }; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index f631fd6f3a..ca9be9823a 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1562,7 +1562,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { if (mb->is_pressed()) { Size2 pos = mpos; - if (gui.mouse_focus && mb->get_button_index() != gui.mouse_focus_button && mb->get_button_index() == BUTTON_LEFT) { + if (gui.mouse_focus && mb->get_button_index() != gui.mouse_focus_button) { //do not steal mouse focus and stuff diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 7533fa5f6c..2f3d4df329 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -404,6 +404,7 @@ void register_scene_types() { ClassDB::register_class<Curve3D>(); ClassDB::register_class<Path>(); ClassDB::register_class<PathFollow>(); + ClassDB::register_class<OrientedPathFollow>(); ClassDB::register_class<VisibilityNotifier>(); ClassDB::register_class<VisibilityEnabler>(); ClassDB::register_class<WorldEnvironment>(); diff --git a/scene/resources/audio_stream_sample.cpp b/scene/resources/audio_stream_sample.cpp index b77143cd9d..02a9e4d69b 100644 --- a/scene/resources/audio_stream_sample.cpp +++ b/scene/resources/audio_stream_sample.cpp @@ -524,6 +524,9 @@ String AudioStreamSample::get_stream_name() const { void AudioStreamSample::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_data", "data"), &AudioStreamSample::set_data); + ClassDB::bind_method(D_METHOD("get_data"), &AudioStreamSample::get_data); + ClassDB::bind_method(D_METHOD("set_format", "format"), &AudioStreamSample::set_format); ClassDB::bind_method(D_METHOD("get_format"), &AudioStreamSample::get_format); @@ -542,16 +545,13 @@ void AudioStreamSample::_bind_methods() { ClassDB::bind_method(D_METHOD("set_stereo", "stereo"), &AudioStreamSample::set_stereo); ClassDB::bind_method(D_METHOD("is_stereo"), &AudioStreamSample::is_stereo); - ClassDB::bind_method(D_METHOD("_set_data", "data"), &AudioStreamSample::set_data); - ClassDB::bind_method(D_METHOD("_get_data"), &AudioStreamSample::get_data); - + ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::INT, "format", PROPERTY_HINT_ENUM, "8-Bit,16-Bit,IMA-ADPCM"), "set_format", "get_format"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "Disabled,Forward,Ping-Pong"), "set_loop_mode", "get_loop_mode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_begin"), "set_loop_begin", "get_loop_begin"); ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_end"), "set_loop_end", "get_loop_end"); ADD_PROPERTY(PropertyInfo(Variant::INT, "mix_rate"), "set_mix_rate", "get_mix_rate"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "stereo"), "set_stereo", "is_stereo"); - ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); BIND_ENUM_CONSTANT(FORMAT_8_BITS); BIND_ENUM_CONSTANT(FORMAT_16_BITS); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 4ec1e8973d..7f902fc982 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -1169,6 +1169,7 @@ void Curve3D::_bake() const { if (points.size() == 0) { baked_point_cache.resize(0); baked_tilt_cache.resize(0); + baked_up_vector_cache.resize(0); return; } @@ -1178,6 +1179,14 @@ void Curve3D::_bake() const { baked_point_cache.set(0, points[0].pos); baked_tilt_cache.resize(1); baked_tilt_cache.set(0, points[0].tilt); + + if (up_vector_enabled) { + + baked_up_vector_cache.resize(1); + baked_up_vector_cache.set(0, Vector3(0, 1, 0)); + } else + baked_up_vector_cache.resize(0); + return; } @@ -1247,10 +1256,51 @@ void Curve3D::_bake() const { baked_tilt_cache.resize(pointlist.size()); PoolRealArray::Write wt = baked_tilt_cache.write(); + baked_up_vector_cache.resize(up_vector_enabled ? pointlist.size() : 0); + PoolVector3Array::Write up_write = baked_up_vector_cache.write(); + + Vector3 sideways; + Vector3 up; + Vector3 forward; + + Vector3 prev_sideways = Vector3(1, 0, 0); + Vector3 prev_up = Vector3(0, 1, 0); + Vector3 prev_forward = Vector3(0, 0, 1); + for (List<Plane>::Element *E = pointlist.front(); E; E = E->next()) { w[idx] = E->get().normal; wt[idx] = E->get().d; + + if (!up_vector_enabled) { + idx++; + continue; + } + + forward = idx > 0 ? (w[idx] - w[idx - 1]).normalized() : prev_forward; + + float y_dot = prev_up.dot(forward); + + if (y_dot > (1.0f - CMP_EPSILON)) { + sideways = prev_sideways; + up = -prev_forward; + } else if (y_dot < -(1.0f - CMP_EPSILON)) { + sideways = prev_sideways; + up = prev_forward; + } else { + sideways = prev_up.cross(forward).normalized(); + up = forward.cross(sideways).normalized(); + } + + if (idx == 1) + up_write[0] = up; + + up_write[idx] = up; + + prev_sideways = sideways; + prev_up = up; + prev_forward = forward; + idx++; } } @@ -1343,6 +1393,53 @@ float Curve3D::interpolate_baked_tilt(float p_offset) const { return Math::lerp(r[idx], r[idx + 1], frac); } +Vector3 Curve3D::interpolate_baked_up_vector(float p_offset, bool p_apply_tilt) const { + + if (baked_cache_dirty) + _bake(); + + //validate// + // curve may not have baked up vectors + int count = baked_up_vector_cache.size(); + if (count == 0) { + ERR_EXPLAIN("No up vectors in Curve3D"); + ERR_FAIL_COND_V(count == 0, Vector3(0, 1, 0)); + } + + if (count == 1) + return baked_up_vector_cache.get(0); + + PoolVector3Array::Read r = baked_up_vector_cache.read(); + PoolVector3Array::Read rp = baked_point_cache.read(); + PoolRealArray::Read rt = baked_tilt_cache.read(); + + float offset = CLAMP(p_offset, 0.0f, baked_max_ofs); + + int idx = Math::floor((double)offset / (double)bake_interval); + float frac = Math::fmod(offset, bake_interval) / bake_interval; + + if (idx == count - 1) + return p_apply_tilt ? r[idx].rotated((rp[idx] - rp[idx - 1]).normalized(), rt[idx]) : r[idx]; + + Vector3 forward = (rp[idx + 1] - rp[idx]).normalized(); + Vector3 up = r[idx]; + Vector3 up1 = r[idx + 1]; + + if (p_apply_tilt) { + up.rotate(forward, rt[idx]); + up1.rotate(idx + 2 >= count ? forward : (rp[idx + 2] - rp[idx + 1]).normalized(), rt[idx + 1]); + } + + Vector3 axis = up.cross(up1); + + if (axis.length_squared() < CMP_EPSILON2) + axis = forward; + else + axis.normalize(); + + return up.rotated(axis, up.angle_to(up1) * frac); +} + PoolVector3Array Curve3D::get_baked_points() const { if (baked_cache_dirty) @@ -1359,6 +1456,14 @@ PoolRealArray Curve3D::get_baked_tilts() const { return baked_tilt_cache; } +PoolVector3Array Curve3D::get_baked_up_vectors() const { + + if (baked_cache_dirty) + _bake(); + + return baked_up_vector_cache; +} + Vector3 Curve3D::get_closest_point(const Vector3 &p_to_point) const { // Brute force method @@ -1452,6 +1557,18 @@ float Curve3D::get_bake_interval() const { return bake_interval; } +void Curve3D::set_up_vector_enabled(bool p_enable) { + + up_vector_enabled = p_enable; + baked_cache_dirty = true; + emit_signal(CoreStringNames::get_singleton()->changed); +} + +bool Curve3D::is_up_vector_enabled() const { + + return up_vector_enabled; +} + Dictionary Curve3D::_get_data() const { Dictionary dc; @@ -1563,11 +1680,15 @@ void Curve3D::_bind_methods() { //ClassDB::bind_method(D_METHOD("bake","subdivs"),&Curve3D::bake,DEFVAL(10)); ClassDB::bind_method(D_METHOD("set_bake_interval", "distance"), &Curve3D::set_bake_interval); ClassDB::bind_method(D_METHOD("get_bake_interval"), &Curve3D::get_bake_interval); + ClassDB::bind_method(D_METHOD("set_up_vector_enabled", "enable"), &Curve3D::set_up_vector_enabled); + ClassDB::bind_method(D_METHOD("is_up_vector_enabled"), &Curve3D::is_up_vector_enabled); ClassDB::bind_method(D_METHOD("get_baked_length"), &Curve3D::get_baked_length); ClassDB::bind_method(D_METHOD("interpolate_baked", "offset", "cubic"), &Curve3D::interpolate_baked, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("interpolate_baked_up_vector", "offset", "apply_tilt"), &Curve3D::interpolate_baked_up_vector, DEFVAL(false)); ClassDB::bind_method(D_METHOD("get_baked_points"), &Curve3D::get_baked_points); ClassDB::bind_method(D_METHOD("get_baked_tilts"), &Curve3D::get_baked_tilts); + ClassDB::bind_method(D_METHOD("get_baked_up_vectors"), &Curve3D::get_baked_up_vectors); ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve3D::get_closest_point); ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve3D::get_closest_offset); ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4)); @@ -1577,6 +1698,9 @@ void Curve3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::REAL, "bake_interval", PROPERTY_HINT_RANGE, "0.01,512,0.01"), "set_bake_interval", "get_bake_interval"); ADD_PROPERTY(PropertyInfo(Variant::INT, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); + + ADD_GROUP("Up Vector", "up_vector_"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "up_vector_enabled"), "set_up_vector_enabled", "is_up_vector_enabled"); } Curve3D::Curve3D() { @@ -1586,4 +1710,5 @@ Curve3D::Curve3D() { add_point(Vector3(0,2,0)); add_point(Vector3(0,3,5));*/ bake_interval = 0.2; + up_vector_enabled = true; } diff --git a/scene/resources/curve.h b/scene/resources/curve.h index 492eb05d1e..9cb12a4345 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -232,11 +232,13 @@ class Curve3D : public Resource { mutable bool baked_cache_dirty; mutable PoolVector3Array baked_point_cache; mutable PoolRealArray baked_tilt_cache; + mutable PoolVector3Array baked_up_vector_cache; mutable float baked_max_ofs; void _bake() const; float bake_interval; + bool up_vector_enabled; void _bake_segment3d(Map<float, Vector3> &r_bake, float p_begin, float p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, float p_tol) const; Dictionary _get_data() const; @@ -264,12 +266,16 @@ public: void set_bake_interval(float p_tolerance); float get_bake_interval() const; + void set_up_vector_enabled(bool p_enable); + bool is_up_vector_enabled() const; float get_baked_length() const; Vector3 interpolate_baked(float p_offset, bool p_cubic = false) const; float interpolate_baked_tilt(float p_offset) const; + Vector3 interpolate_baked_up_vector(float p_offset, bool p_apply_tilt = false) const; PoolVector3Array get_baked_points() const; //useful for going through PoolRealArray get_baked_tilts() const; //useful for going through + PoolVector3Array get_baked_up_vectors() const; Vector3 get_closest_point(const Vector3 &p_to_point) const; float get_closest_offset(const Vector3 &p_to_point) const; diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 503ca0af4a..0e1f74d8d0 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -181,12 +181,15 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans Rect2 aabb = p_xform.xform(shape->get_aabb()); aabb = aabb.grow(p_margin); - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, p_result_max, space->intersection_query_subindex_results); + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space2DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); int cc = 0; for (int i = 0; i < amount; i++) { + if (cc >= p_result_max) + break; + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask)) continue; diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp index fafc239c7f..cb7669ec24 100644 --- a/servers/physics_2d_server.cpp +++ b/servers/physics_2d_server.cpp @@ -540,6 +540,8 @@ void Physics2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &Physics2DServer::area_get_object_instance_id); ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_area_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &Physics2DServer::area_set_monitorable); ClassDB::bind_method(D_METHOD("body_create"), &Physics2DServer::body_create); diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp index 08af26c24b..82c4eb2e13 100644 --- a/servers/physics_server.cpp +++ b/servers/physics_server.cpp @@ -444,6 +444,8 @@ void PhysicsServer::_bind_methods() { ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &PhysicsServer::area_get_object_instance_id); ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer::area_set_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer::area_set_area_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer::area_set_monitorable); ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer::area_set_ray_pickable); ClassDB::bind_method(D_METHOD("area_is_ray_pickable", "area"), &PhysicsServer::area_is_ray_pickable); diff --git a/thirdparty/README.md b/thirdparty/README.md index 09b016ad4d..25d6e3df9a 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -191,7 +191,7 @@ Files extracted from upstream source: ## libvorbis - Upstream: https://www.xiph.org/vorbis -- Version: 1.3.5 +- Version: 1.3.6 - License: BSD-3-Clause Files extracted from upstream source: @@ -342,11 +342,11 @@ Collection of single-file libraries used in Godot components. * License: zlib - `stb_truetype.h` * Upstream: https://github.com/nothings/stb - * Version: 1.17 + * Version: 1.19 * License: Public Domain (Unlicense) or MIT - `stb_vorbis.c` * Upstream: https://github.com/nothings/stb - * Version: 1.11 + * Version: 1.14 * License: Public Domain (Unlicense) or MIT diff --git a/thirdparty/libvorbis/COPYING b/thirdparty/libvorbis/COPYING index 8f1d18cc2b..153b926a15 100644 --- a/thirdparty/libvorbis/COPYING +++ b/thirdparty/libvorbis/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 2002-2015 Xiph.org Foundation +Copyright (c) 2002-2018 Xiph.org Foundation Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions diff --git a/thirdparty/libvorbis/analysis.c b/thirdparty/libvorbis/analysis.c index 01aa6f30db..0e11a167be 100644 --- a/thirdparty/libvorbis/analysis.c +++ b/thirdparty/libvorbis/analysis.c @@ -11,7 +11,6 @@ ******************************************************************** function: single-block PCM analysis mode dispatch - last mod: $Id: analysis.c 16226 2009-07-08 06:43:49Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/backends.h b/thirdparty/libvorbis/backends.h index ff5bcc95fe..22809d46d5 100644 --- a/thirdparty/libvorbis/backends.h +++ b/thirdparty/libvorbis/backends.h @@ -12,7 +12,6 @@ function: libvorbis backend and mapping structures; needed for static mode headers - last mod: $Id: backends.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/barkmel.c b/thirdparty/libvorbis/barkmel.c index 37b6c4c7ba..4b19935f30 100644 --- a/thirdparty/libvorbis/barkmel.c +++ b/thirdparty/libvorbis/barkmel.c @@ -11,7 +11,6 @@ ******************************************************************** function: bark scale utility - last mod: $Id: barkmel.c 19454 2015-03-02 22:39:28Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/bitrate.c b/thirdparty/libvorbis/bitrate.c index 3a71b1dc23..96055140f7 100644 --- a/thirdparty/libvorbis/bitrate.c +++ b/thirdparty/libvorbis/bitrate.c @@ -11,7 +11,6 @@ ******************************************************************** function: bitrate tracking and management - last mod: $Id: bitrate.c 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/bitrate.h b/thirdparty/libvorbis/bitrate.h index db48fcb645..655a68cc09 100644 --- a/thirdparty/libvorbis/bitrate.h +++ b/thirdparty/libvorbis/bitrate.h @@ -11,7 +11,6 @@ ******************************************************************** function: bitrate tracking and management - last mod: $Id: bitrate.h 13293 2007-07-24 00:09:47Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/block.c b/thirdparty/libvorbis/block.c index 345c042769..db245b3e69 100644 --- a/thirdparty/libvorbis/block.c +++ b/thirdparty/libvorbis/block.c @@ -11,7 +11,6 @@ ******************************************************************** function: PCM data vector blocking, windowing and dis/reassembly - last mod: $Id: block.c 19457 2015-03-03 00:15:29Z giles $ Handle windowing, overlap-add, etc of the PCM vectors. This is made more amusing by Vorbis' current two allowed block sizes. diff --git a/thirdparty/libvorbis/books/coupled/res_books_51.h b/thirdparty/libvorbis/books/coupled/res_books_51.h index 93910ff481..47df4b221b 100644 --- a/thirdparty/libvorbis/books/coupled/res_books_51.h +++ b/thirdparty/libvorbis/books/coupled/res_books_51.h @@ -11,7 +11,6 @@ ******************************************************************** * * function: static codebooks for 5.1 surround - * last modified: $Id: res_books_51.h 19057 2014-01-22 12:32:31Z xiphmont $ * ********************************************************************/ diff --git a/thirdparty/libvorbis/books/coupled/res_books_stereo.h b/thirdparty/libvorbis/books/coupled/res_books_stereo.h index 9a9049f6ed..61d934046d 100644 --- a/thirdparty/libvorbis/books/coupled/res_books_stereo.h +++ b/thirdparty/libvorbis/books/coupled/res_books_stereo.h @@ -11,7 +11,6 @@ ******************************************************************** function: static codebooks autogenerated by huff/huffbuld - last modified: $Id: res_books_stereo.h 19057 2014-01-22 12:32:31Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/books/floor/floor_books.h b/thirdparty/libvorbis/books/floor/floor_books.h index e925313f7b..67d5f31a3b 100644 --- a/thirdparty/libvorbis/books/floor/floor_books.h +++ b/thirdparty/libvorbis/books/floor/floor_books.h @@ -11,7 +11,6 @@ ******************************************************************** function: static codebooks autogenerated by huff/huffbuld - last modified: $Id: floor_books.h 19057 2014-01-22 12:32:31Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h b/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h index 736353b675..3d658ec470 100644 --- a/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h +++ b/thirdparty/libvorbis/books/uncoupled/res_books_uncoupled.h @@ -11,7 +11,6 @@ ******************************************************************** function: static codebooks autogenerated by huff/huffbuld - last modified: $Id: res_books_uncoupled.h 19057 2014-01-22 12:32:31Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/codebook.c b/thirdparty/libvorbis/codebook.c index 72f8a17a35..78672e222d 100644 --- a/thirdparty/libvorbis/codebook.c +++ b/thirdparty/libvorbis/codebook.c @@ -11,7 +11,6 @@ ******************************************************************** function: basic codebook pack/unpack/code/decode operations - last mod: $Id: codebook.c 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ @@ -387,7 +386,7 @@ long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){ t[i] = book->valuelist+entry[i]*book->dim; } for(i=0,o=0;i<book->dim;i++,o+=step) - for (j=0;j<step;j++) + for (j=0;o+j<n && j<step;j++) a[o+j]+=t[j][i]; } return(0); @@ -399,41 +398,12 @@ long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){ int i,j,entry; float *t; - if(book->dim>8){ - for(i=0;i<n;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - t = book->valuelist+entry*book->dim; - for (j=0;j<book->dim;) - a[i++]+=t[j++]; - } - }else{ - for(i=0;i<n;){ - entry = decode_packed_entry_number(book,b); - if(entry==-1)return(-1); - t = book->valuelist+entry*book->dim; - j=0; - switch((int)book->dim){ - case 8: - a[i++]+=t[j++]; - case 7: - a[i++]+=t[j++]; - case 6: - a[i++]+=t[j++]; - case 5: - a[i++]+=t[j++]; - case 4: - a[i++]+=t[j++]; - case 3: - a[i++]+=t[j++]; - case 2: - a[i++]+=t[j++]; - case 1: - a[i++]+=t[j++]; - case 0: - break; - } - } + for(i=0;i<n;){ + entry = decode_packed_entry_number(book,b); + if(entry==-1)return(-1); + t = book->valuelist+entry*book->dim; + for(j=0;i<n && j<book->dim;) + a[i++]+=t[j++]; } } return(0); @@ -471,12 +441,13 @@ long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch, long i,j,entry; int chptr=0; if(book->used_entries>0){ - for(i=offset/ch;i<(offset+n)/ch;){ + int m=(offset+n)/ch; + for(i=offset/ch;i<m;){ entry = decode_packed_entry_number(book,b); if(entry==-1)return(-1); { const float *t = book->valuelist+entry*book->dim; - for (j=0;j<book->dim;j++){ + for (j=0;i<m && j<book->dim;j++){ a[chptr++][i]+=t[j]; if(chptr==ch){ chptr=0; diff --git a/thirdparty/libvorbis/codebook.h b/thirdparty/libvorbis/codebook.h index 537d6c12d3..08440c6962 100644 --- a/thirdparty/libvorbis/codebook.h +++ b/thirdparty/libvorbis/codebook.h @@ -11,7 +11,6 @@ ******************************************************************** function: basic shared codebook operations - last mod: $Id: codebook.h 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/codec_internal.h b/thirdparty/libvorbis/codec_internal.h index de1bccaedf..e522be18da 100644 --- a/thirdparty/libvorbis/codec_internal.h +++ b/thirdparty/libvorbis/codec_internal.h @@ -11,7 +11,6 @@ ******************************************************************** function: libvorbis codec headers - last mod: $Id: codec_internal.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/envelope.c b/thirdparty/libvorbis/envelope.c index 010c66e2d6..da75237542 100644 --- a/thirdparty/libvorbis/envelope.c +++ b/thirdparty/libvorbis/envelope.c @@ -11,7 +11,6 @@ ******************************************************************** function: PCM data envelope analysis - last mod: $Id: envelope.c 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/envelope.h b/thirdparty/libvorbis/envelope.h index fd15fb32a7..f466efde8a 100644 --- a/thirdparty/libvorbis/envelope.h +++ b/thirdparty/libvorbis/envelope.h @@ -11,7 +11,6 @@ ******************************************************************** function: PCM data envelope analysis and manipulation - last mod: $Id: envelope.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/floor0.c b/thirdparty/libvorbis/floor0.c index 213cce4ec8..443c0e5a96 100644 --- a/thirdparty/libvorbis/floor0.c +++ b/thirdparty/libvorbis/floor0.c @@ -11,7 +11,6 @@ ******************************************************************** function: floor backend 0 implementation - last mod: $Id: floor0.c 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/floor1.c b/thirdparty/libvorbis/floor1.c index d8bd4645c1..673e954c53 100644 --- a/thirdparty/libvorbis/floor1.c +++ b/thirdparty/libvorbis/floor1.c @@ -11,7 +11,6 @@ ******************************************************************** function: floor backend 1 implementation - last mod: $Id: floor1.c 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/highlevel.h b/thirdparty/libvorbis/highlevel.h index e38f370fd6..337b75bfa4 100644 --- a/thirdparty/libvorbis/highlevel.h +++ b/thirdparty/libvorbis/highlevel.h @@ -11,7 +11,6 @@ ******************************************************************** function: highlevel encoder setup struct separated out for vorbisenc clarity - last mod: $Id: highlevel.h 17195 2010-05-05 21:49:51Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/info.c b/thirdparty/libvorbis/info.c index 8a2a001f99..3fbb7c757a 100644 --- a/thirdparty/libvorbis/info.c +++ b/thirdparty/libvorbis/info.c @@ -11,7 +11,6 @@ ******************************************************************** function: maintain the info structure, info <-> header packets - last mod: $Id: info.c 19441 2015-01-21 01:17:41Z xiphmont $ ********************************************************************/ @@ -31,8 +30,8 @@ #include "misc.h" #include "os.h" -#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.5" -#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20150105 (⛄⛄⛄⛄)" +#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.6" +#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20180316 (Now 100% fewer shells)" /* helpers */ static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){ @@ -65,11 +64,13 @@ void vorbis_comment_add(vorbis_comment *vc,const char *comment){ } void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents){ - char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */ + /* Length for key and value +2 for = and \0 */ + char *comment=_ogg_malloc(strlen(tag)+strlen(contents)+2); strcpy(comment, tag); strcat(comment, "="); strcat(comment, contents); vorbis_comment_add(vc, comment); + _ogg_free(comment); } /* This is more or less the same as strncasecmp - but that doesn't exist @@ -88,27 +89,30 @@ char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){ long i; int found = 0; int taglen = strlen(tag)+1; /* +1 for the = we append */ - char *fulltag = alloca(taglen+ 1); + char *fulltag = _ogg_malloc(taglen+1); strcpy(fulltag, tag); strcat(fulltag, "="); for(i=0;i<vc->comments;i++){ if(!tagcompare(vc->user_comments[i], fulltag, taglen)){ - if(count == found) + if(count == found) { /* We return a pointer to the data, not a copy */ - return vc->user_comments[i] + taglen; - else + _ogg_free(fulltag); + return vc->user_comments[i] + taglen; + } else { found++; + } } } + _ogg_free(fulltag); return NULL; /* didn't find anything */ } int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){ int i,count=0; int taglen = strlen(tag)+1; /* +1 for the = we append */ - char *fulltag = alloca(taglen+1); + char *fulltag = _ogg_malloc(taglen+1); strcpy(fulltag,tag); strcat(fulltag, "="); @@ -117,6 +121,7 @@ int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){ count++; } + _ogg_free(fulltag); return count; } @@ -206,9 +211,9 @@ static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){ vi->channels=oggpack_read(opb,8); vi->rate=oggpack_read(opb,32); - vi->bitrate_upper=oggpack_read(opb,32); - vi->bitrate_nominal=oggpack_read(opb,32); - vi->bitrate_lower=oggpack_read(opb,32); + vi->bitrate_upper=(ogg_int32_t)oggpack_read(opb,32); + vi->bitrate_nominal=(ogg_int32_t)oggpack_read(opb,32); + vi->bitrate_lower=(ogg_int32_t)oggpack_read(opb,32); ci->blocksizes[0]=1<<oggpack_read(opb,4); ci->blocksizes[1]=1<<oggpack_read(opb,4); @@ -583,7 +588,8 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v, oggpack_buffer opb; private_state *b=v->backend_state; - if(!b||vi->channels<=0){ + if(!b||vi->channels<=0||vi->channels>256){ + b = NULL; ret=OV_EFAULT; goto err_out; } @@ -642,7 +648,7 @@ int vorbis_analysis_headerout(vorbis_dsp_state *v, memset(op_code,0,sizeof(*op_code)); if(b){ - oggpack_writeclear(&opb); + if(vi->channels>0)oggpack_writeclear(&opb); if(b->header)_ogg_free(b->header); if(b->header1)_ogg_free(b->header1); if(b->header2)_ogg_free(b->header2); diff --git a/thirdparty/libvorbis/lookup.c b/thirdparty/libvorbis/lookup.c index 3321ed3dbc..1cc1f88ee9 100644 --- a/thirdparty/libvorbis/lookup.c +++ b/thirdparty/libvorbis/lookup.c @@ -11,7 +11,6 @@ ******************************************************************** function: lookup based functions - last mod: $Id: lookup.c 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/lookup.h b/thirdparty/libvorbis/lookup.h index f8b5b82730..4bc0f3a206 100644 --- a/thirdparty/libvorbis/lookup.h +++ b/thirdparty/libvorbis/lookup.h @@ -11,7 +11,6 @@ ******************************************************************** function: lookup based functions - last mod: $Id: lookup.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/lookup_data.h b/thirdparty/libvorbis/lookup_data.h index 2424a1b386..5de3cfdc7e 100644 --- a/thirdparty/libvorbis/lookup_data.h +++ b/thirdparty/libvorbis/lookup_data.h @@ -11,7 +11,6 @@ ******************************************************************** function: lookup data; generated by lookups.pl; edit there - last mod: $Id: lookup_data.h 16037 2009-05-26 21:10:58Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/lpc.c b/thirdparty/libvorbis/lpc.c index f5199ec235..798f4cf076 100644 --- a/thirdparty/libvorbis/lpc.c +++ b/thirdparty/libvorbis/lpc.c @@ -11,7 +11,6 @@ ******************************************************************** function: LPC low level routines - last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/lpc.h b/thirdparty/libvorbis/lpc.h index 39d237601b..9cc79451b6 100644 --- a/thirdparty/libvorbis/lpc.h +++ b/thirdparty/libvorbis/lpc.h @@ -11,7 +11,6 @@ ******************************************************************** function: LPC low level routines - last mod: $Id: lpc.h 16037 2009-05-26 21:10:58Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/lsp.c b/thirdparty/libvorbis/lsp.c index 6a619f7b0c..8588054515 100644 --- a/thirdparty/libvorbis/lsp.c +++ b/thirdparty/libvorbis/lsp.c @@ -11,7 +11,6 @@ ******************************************************************** function: LSP (also called LSF) conversion routines - last mod: $Id: lsp.c 19453 2015-03-02 22:35:34Z xiphmont $ The LSP generation code is taken (with minimal modification and a few bugfixes) from "On the Computation of the LSP Frequencies" by diff --git a/thirdparty/libvorbis/lsp.h b/thirdparty/libvorbis/lsp.h index bacfb0971f..8a8d10e978 100644 --- a/thirdparty/libvorbis/lsp.h +++ b/thirdparty/libvorbis/lsp.h @@ -11,7 +11,6 @@ ******************************************************************** function: LSP (also called LSF) conversion routines - last mod: $Id: lsp.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/mapping0.c b/thirdparty/libvorbis/mapping0.c index 85c7d22d83..ccb4493d4c 100644 --- a/thirdparty/libvorbis/mapping0.c +++ b/thirdparty/libvorbis/mapping0.c @@ -11,7 +11,6 @@ ******************************************************************** function: channel mapping 0 implementation - last mod: $Id: mapping0.c 19441 2015-01-21 01:17:41Z xiphmont $ ********************************************************************/ @@ -93,7 +92,6 @@ static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb) int i,b; vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info)); codec_setup_info *ci=vi->codec_setup; - memset(info,0,sizeof(*info)); if(vi->channels<=0)goto err_out; b=oggpack_read(opb,1); diff --git a/thirdparty/libvorbis/masking.h b/thirdparty/libvorbis/masking.h index 3576ab7885..955e18c719 100644 --- a/thirdparty/libvorbis/masking.h +++ b/thirdparty/libvorbis/masking.h @@ -11,7 +11,6 @@ ******************************************************************** function: masking curve data for psychoacoustics - last mod: $Id: masking.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/mdct.c b/thirdparty/libvorbis/mdct.c index 0816331805..f3f1ed805b 100644 --- a/thirdparty/libvorbis/mdct.c +++ b/thirdparty/libvorbis/mdct.c @@ -12,7 +12,6 @@ function: normalized modified discrete cosine transform power of two length transform only [64 <= n ] - last mod: $Id: mdct.c 16227 2009-07-08 06:58:46Z xiphmont $ Original algorithm adapted long ago from _The use of multirate filter banks for coding of high quality digital audio_, by T. Sporer, diff --git a/thirdparty/libvorbis/mdct.h b/thirdparty/libvorbis/mdct.h index 3ed94333c5..3b8c9ba4a2 100644 --- a/thirdparty/libvorbis/mdct.h +++ b/thirdparty/libvorbis/mdct.h @@ -11,7 +11,6 @@ ******************************************************************** function: modified discrete cosine transform prototypes - last mod: $Id: mdct.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/misc.h b/thirdparty/libvorbis/misc.h index 73b4519898..13788445a3 100644 --- a/thirdparty/libvorbis/misc.h +++ b/thirdparty/libvorbis/misc.h @@ -11,7 +11,6 @@ ******************************************************************** function: miscellaneous prototypes - last mod: $Id: misc.h 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/floor_all.h b/thirdparty/libvorbis/modes/floor_all.h index 4292be326e..20928aac87 100644 --- a/thirdparty/libvorbis/modes/floor_all.h +++ b/thirdparty/libvorbis/modes/floor_all.h @@ -11,7 +11,6 @@ ******************************************************************** function: key floor settings - last mod: $Id: floor_all.h 17050 2010-03-26 01:34:42Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/psych_11.h b/thirdparty/libvorbis/modes/psych_11.h index 844a8ed3cd..cc5eea2402 100644 --- a/thirdparty/libvorbis/modes/psych_11.h +++ b/thirdparty/libvorbis/modes/psych_11.h @@ -11,7 +11,6 @@ ******************************************************************** function: 11kHz settings - last mod: $Id: psych_11.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/psych_16.h b/thirdparty/libvorbis/modes/psych_16.h index 1c10b3954e..477cb4d90f 100644 --- a/thirdparty/libvorbis/modes/psych_16.h +++ b/thirdparty/libvorbis/modes/psych_16.h @@ -11,7 +11,6 @@ ******************************************************************** function: 16kHz settings - last mod: $Id: psych_16.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/psych_44.h b/thirdparty/libvorbis/modes/psych_44.h index f05c032653..6c9eaa4e5f 100644 --- a/thirdparty/libvorbis/modes/psych_44.h +++ b/thirdparty/libvorbis/modes/psych_44.h @@ -11,7 +11,6 @@ ******************************************************************** function: key psychoacoustic settings for 44.1/48kHz - last mod: $Id: psych_44.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/psych_8.h b/thirdparty/libvorbis/modes/psych_8.h index 0e2dd57371..277db8436c 100644 --- a/thirdparty/libvorbis/modes/psych_8.h +++ b/thirdparty/libvorbis/modes/psych_8.h @@ -11,7 +11,6 @@ ******************************************************************** function: 8kHz psychoacoustic settings - last mod: $Id: psych_8.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/residue_16.h b/thirdparty/libvorbis/modes/residue_16.h index dcaca5451e..3e05471cec 100644 --- a/thirdparty/libvorbis/modes/residue_16.h +++ b/thirdparty/libvorbis/modes/residue_16.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel residue templates 16/22kHz - last mod: $Id: residue_16.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/residue_44.h b/thirdparty/libvorbis/modes/residue_44.h index 236c18341b..e89bc0e486 100644 --- a/thirdparty/libvorbis/modes/residue_44.h +++ b/thirdparty/libvorbis/modes/residue_44.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel residue templates for 32/44.1/48kHz - last mod: $Id: residue_44.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/residue_44p51.h b/thirdparty/libvorbis/modes/residue_44p51.h index a52cc5245e..7f33e250e2 100644 --- a/thirdparty/libvorbis/modes/residue_44p51.h +++ b/thirdparty/libvorbis/modes/residue_44p51.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel residue templates for 32/44.1/48kHz uncoupled - last mod: $Id: residue_44p51.h 19013 2013-11-12 04:04:50Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/residue_44u.h b/thirdparty/libvorbis/modes/residue_44u.h index 92c4a09ce3..e55ac12548 100644 --- a/thirdparty/libvorbis/modes/residue_44u.h +++ b/thirdparty/libvorbis/modes/residue_44u.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel residue templates for 32/44.1/48kHz uncoupled - last mod: $Id: residue_44u.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/residue_8.h b/thirdparty/libvorbis/modes/residue_8.h index 94c6d84c44..ae123a276a 100644 --- a/thirdparty/libvorbis/modes/residue_8.h +++ b/thirdparty/libvorbis/modes/residue_8.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel residue templates 8/11kHz - last mod: $Id: residue_8.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_11.h b/thirdparty/libvorbis/modes/setup_11.h index 4c2d619ca2..0cbcaafcb2 100644 --- a/thirdparty/libvorbis/modes/setup_11.h +++ b/thirdparty/libvorbis/modes/setup_11.h @@ -11,7 +11,6 @@ ******************************************************************** function: 11kHz settings - last mod: $Id: setup_11.h 16894 2010-02-12 20:32:12Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_16.h b/thirdparty/libvorbis/modes/setup_16.h index 336007f98e..d59ad70d2e 100644 --- a/thirdparty/libvorbis/modes/setup_16.h +++ b/thirdparty/libvorbis/modes/setup_16.h @@ -11,7 +11,6 @@ ******************************************************************** function: 16kHz settings - last mod: $Id: setup_16.h 16894 2010-02-12 20:32:12Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_22.h b/thirdparty/libvorbis/modes/setup_22.h index 4fd5e57111..bc38af9630 100644 --- a/thirdparty/libvorbis/modes/setup_22.h +++ b/thirdparty/libvorbis/modes/setup_22.h @@ -11,7 +11,6 @@ ******************************************************************** function: 22kHz settings - last mod: $Id: setup_22.h 17026 2010-03-25 05:00:27Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_32.h b/thirdparty/libvorbis/modes/setup_32.h index 2275ac9615..f66a0bcd00 100644 --- a/thirdparty/libvorbis/modes/setup_32.h +++ b/thirdparty/libvorbis/modes/setup_32.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel settings for 32kHz - last mod: $Id: setup_32.h 16894 2010-02-12 20:32:12Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_44.h b/thirdparty/libvorbis/modes/setup_44.h index 3b88a89ac5..a189b5fb95 100644 --- a/thirdparty/libvorbis/modes/setup_44.h +++ b/thirdparty/libvorbis/modes/setup_44.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel settings for 44.1/48kHz - last mod: $Id: setup_44.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_44p51.h b/thirdparty/libvorbis/modes/setup_44p51.h index 67d9979608..3bde7b340c 100644 --- a/thirdparty/libvorbis/modes/setup_44p51.h +++ b/thirdparty/libvorbis/modes/setup_44p51.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel settings for 44.1/48kHz 5.1 surround modes - last mod: $Id: setup_44p51.h 19013 2013-11-12 04:04:50Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_44u.h b/thirdparty/libvorbis/modes/setup_44u.h index 568b5f8959..7ae3af6b2a 100644 --- a/thirdparty/libvorbis/modes/setup_44u.h +++ b/thirdparty/libvorbis/modes/setup_44u.h @@ -11,7 +11,6 @@ ******************************************************************** function: toplevel settings for 44.1/48kHz uncoupled modes - last mod: $Id: setup_44u.h 16962 2010-03-11 07:30:34Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_8.h b/thirdparty/libvorbis/modes/setup_8.h index 14c48374fa..7502556879 100644 --- a/thirdparty/libvorbis/modes/setup_8.h +++ b/thirdparty/libvorbis/modes/setup_8.h @@ -11,7 +11,6 @@ ******************************************************************** function: 8kHz settings - last mod: $Id: setup_8.h 16894 2010-02-12 20:32:12Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/modes/setup_X.h b/thirdparty/libvorbis/modes/setup_X.h index a69f5d40a2..2229a5ef2f 100644 --- a/thirdparty/libvorbis/modes/setup_X.h +++ b/thirdparty/libvorbis/modes/setup_X.h @@ -11,7 +11,6 @@ ******************************************************************** function: catch-all toplevel settings for q modes only - last mod: $Id: setup_X.h 16894 2010-02-12 20:32:12Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/os.h b/thirdparty/libvorbis/os.h index 8bc3e5fe9c..416a401dd1 100644 --- a/thirdparty/libvorbis/os.h +++ b/thirdparty/libvorbis/os.h @@ -13,7 +13,6 @@ ******************************************************************** function: #ifdef jail to whip a few platforms into the UNIX ideal. - last mod: $Id: os.h 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ @@ -31,7 +30,7 @@ # ifdef __GNUC__ # define STIN static __inline__ -# elif _WIN32 +# elif defined(_WIN32) # define STIN static __inline # else # define STIN static diff --git a/thirdparty/libvorbis/psy.c b/thirdparty/libvorbis/psy.c index f7a44c6d00..422c6f1e41 100644 --- a/thirdparty/libvorbis/psy.c +++ b/thirdparty/libvorbis/psy.c @@ -11,7 +11,6 @@ ******************************************************************** function: psychoacoustics not including preecho - last mod: $Id: psy.c 18077 2011-09-02 02:49:00Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/psy.h b/thirdparty/libvorbis/psy.h index c1ea824401..ab2534db3a 100644 --- a/thirdparty/libvorbis/psy.h +++ b/thirdparty/libvorbis/psy.h @@ -11,7 +11,6 @@ ******************************************************************** function: random psychoacoustics (not including preecho) - last mod: $Id: psy.h 16946 2010-03-03 16:12:40Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/psytune.c b/thirdparty/libvorbis/psytune.c index 64c13171f7..6952136c6b 100644 --- a/thirdparty/libvorbis/psytune.c +++ b/thirdparty/libvorbis/psytune.c @@ -12,7 +12,6 @@ function: simple utility that runs audio through the psychoacoustics without encoding - last mod: $Id: psytune.c 16037 2009-05-26 21:10:58Z xiphmont $ ********************************************************************/ @@ -41,11 +40,11 @@ static vorbis_info_psy_global _psy_set0G={ 0, /* decaydBpms */ 8, /* lines per eighth octave */ - + /* thresh sample period, preecho clamp trigger threshhold, range, minenergy */ 256, {26.f,26.f,26.f,30.f}, {-90.f,-90.f,-90.f,-90.f}, -90.f, - -6.f, - + -6.f, + 0, 0., @@ -68,7 +67,7 @@ static vp_couple _vp_couple0[]={ static vorbis_info_psy _psy_set0={ ATH_Bark_dB_lineaggressive, - + -100.f, -140.f, 6.f, /* floor master att */ @@ -148,7 +147,7 @@ static vorbis_info_psy _psy_set0={ .900f, 0.f, /*11500*/ .900f, 1.f, /*16000*/ }, - + 95.f, /* even decade + 5 is important; saves an rint() later in a tight loop) */ -44., @@ -159,7 +158,7 @@ static vorbis_info_psy _psy_set0={ static vorbis_info_floor1 _floor_set0={1, {0}, - + {32}, {0}, {0}, @@ -171,12 +170,12 @@ static vorbis_info_floor1 _floor_set0={1, 88,31,243, 14,54,143,460, - - 6,3,10, 22,18,26, 41,36,47, - 69,61,78, 112,99,126, 185,162,211, + + 6,3,10, 22,18,26, 41,36,47, + 69,61,78, 112,99,126, 185,162,211, 329,282,387, 672,553,825 }, - + 60,30,400, 20,8,1,18., 20,600, @@ -184,8 +183,8 @@ static vorbis_info_floor1 _floor_set0={1, static vorbis_info_mapping0 mapping_info={1,{0,1},{0},{0},{0},0, 1, {0},{1}}; -static codec_setup_info codec_setup0={ {0,0}, - 1,1,1,1,1,0,1, +static codec_setup_info codec_setup0={ {0,0}, + 1,1,1,1,1,0,1, {NULL}, {0},{&mapping_info}, {0},{NULL}, @@ -194,7 +193,7 @@ static codec_setup_info codec_setup0={ {0,0}, {NULL}, {&_psy_set0}, &_psy_set0G}; - + static int noisy=0; void analysis(char *base,int i,float *v,int n,int bark,int dB){ if(noisy){ @@ -212,7 +211,7 @@ void analysis(char *base,int i,float *v,int n,int bark,int dB){ fprintf(of,"%g ",toBARK(22050.f*j/n)); else fprintf(of,"%g ",(float)j); - + if(dB){ fprintf(of,"%g\n",todB(v+j)); }else{ @@ -269,7 +268,7 @@ int main(int argc,char *argv[]){ framesize=atoi(argv[0]); argv++; } - + vi.channels=2; vi.codec_setup=&codec_setup0; @@ -292,7 +291,7 @@ int main(int argc,char *argv[]){ /* we cheat on the WAV header; we just bypass 44 bytes and never verify that it matches 16bit/stereo/44.1kHz. */ - + fread(buffer,1,44,stdin); fwrite(buffer,1,44,stdout); memset(buffer,0,framesize*2); @@ -302,10 +301,10 @@ int main(int argc,char *argv[]){ fprintf(stderr,"Processing for frame size %d...\n",framesize); while(!eos){ - long bytes=fread(buffer2,1,framesize*2,stdin); + long bytes=fread(buffer2,1,framesize*2,stdin); if(bytes<framesize*2) memset(buffer2+bytes,0,framesize*2-bytes); - + if(bytes!=0){ int nonzero[2]; @@ -316,10 +315,10 @@ int main(int argc,char *argv[]){ pcm[1][i]=((buffer[i*4+3]<<8)| (0x00ff&(int)buffer[i*4+2]))/32768.f; } - + { float secs=framesize/44100.; - + ampmax+=secs*ampmax_att_per_sec; if(ampmax<-9999)ampmax=-9999; } @@ -331,11 +330,11 @@ int main(int argc,char *argv[]){ float *logmdct=mdct+framesize/2; analysis("pre",frameno+i,pcm[i],framesize,0,0); - + /* fft and mdct transforms */ for(j=0;j<framesize;j++) fft[j]=pcm[i][j]*=window[j]; - + drft_forward(&f_look,fft); local_ampmax[i]=-9999.f; @@ -347,7 +346,7 @@ int main(int argc,char *argv[]){ if(temp>local_ampmax[i])local_ampmax[i]=temp; } if(local_ampmax[i]>ampmax)ampmax=local_ampmax[i]; - + mdct_forward(&m_look,pcm[i],mdct); for(j=0;j<framesize/2;j++) logmdct[j]=todB(mdct+j); @@ -391,7 +390,7 @@ int main(int argc,char *argv[]){ logmdct, mask, logmax, - + flr[i]); } @@ -406,7 +405,7 @@ int main(int argc,char *argv[]){ for(j=0;j<framesize/2;j++) if(fabs(pcm[i][j])>1500) fprintf(stderr,"%ld ",frameno+i); - + analysis("res",frameno+i,pcm[i],framesize/2,1,0); analysis("codedflr",frameno+i,flr[i],framesize/2,1,1); } @@ -416,7 +415,7 @@ int main(int argc,char *argv[]){ &vi, pcm, nonzero); - + for(i=0;i<2;i++) analysis("quant",frameno+i,pcm[i],framesize/2,1,0); @@ -426,7 +425,7 @@ int main(int argc,char *argv[]){ &mapping_info, pcm, nonzero); - + for(i=0;i<2;i++) analysis("coupled",frameno+i,pcm[i],framesize/2,1,0); @@ -434,11 +433,11 @@ int main(int argc,char *argv[]){ for(i=mapping_info.coupling_steps-1;i>=0;i--){ float *pcmM=pcm[mapping_info.coupling_mag[i]]; float *pcmA=pcm[mapping_info.coupling_ang[i]]; - + for(j=0;j<framesize/2;j++){ float mag=pcmM[j]; float ang=pcmA[j]; - + if(mag>0) if(ang>0){ pcmM[j]=mag; @@ -457,7 +456,7 @@ int main(int argc,char *argv[]){ } } } - + for(i=0;i<2;i++) analysis("decoupled",frameno+i,pcm[i],framesize/2,1,0); @@ -479,7 +478,7 @@ int main(int argc,char *argv[]){ } - + /* write data. Use the part of buffer we're about to shift out */ for(i=0;i<2;i++){ char *ptr=buffer+i*2; @@ -503,7 +502,7 @@ int main(int argc,char *argv[]){ ptr+=4; } } - + fprintf(stderr,"*"); fwrite(buffer,1,framesize*2,stdout); memmove(buffer,buffer2,framesize*2); diff --git a/thirdparty/libvorbis/registry.c b/thirdparty/libvorbis/registry.c index 3961ed1403..74f7ef0396 100644 --- a/thirdparty/libvorbis/registry.c +++ b/thirdparty/libvorbis/registry.c @@ -11,7 +11,6 @@ ******************************************************************** function: registry for time, floor, res backends and channel mappings - last mod: $Id: registry.c 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/registry.h b/thirdparty/libvorbis/registry.h index 3ae04776d8..599d959942 100644 --- a/thirdparty/libvorbis/registry.h +++ b/thirdparty/libvorbis/registry.h @@ -11,7 +11,6 @@ ******************************************************************** function: registry for time, floor, res backends and channel mappings - last mod: $Id: registry.h 15531 2008-11-24 23:50:06Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/res0.c b/thirdparty/libvorbis/res0.c index ec11488c2f..6d623d730f 100644 --- a/thirdparty/libvorbis/res0.c +++ b/thirdparty/libvorbis/res0.c @@ -11,7 +11,6 @@ ******************************************************************** function: residue backend 0, 1 and 2 implementation - last mod: $Id: res0.c 19441 2015-01-21 01:17:41Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/scales.h b/thirdparty/libvorbis/scales.h index 613f796e77..18bc4e7518 100644 --- a/thirdparty/libvorbis/scales.h +++ b/thirdparty/libvorbis/scales.h @@ -11,7 +11,6 @@ ******************************************************************** function: linear scale -> dB, Bark and Mel scales - last mod: $Id: scales.h 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/sharedbook.c b/thirdparty/libvorbis/sharedbook.c index 6bfdf7311e..4545d4f459 100644 --- a/thirdparty/libvorbis/sharedbook.c +++ b/thirdparty/libvorbis/sharedbook.c @@ -11,11 +11,11 @@ ******************************************************************** function: basic shared codebook operations - last mod: $Id: sharedbook.c 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ #include <stdlib.h> +#include <limits.h> #include <math.h> #include <string.h> #include <ogg/ogg.h> @@ -158,25 +158,34 @@ ogg_uint32_t *_make_words(char *l,long n,long sparsecount){ that's portable and totally safe against roundoff, but I haven't thought of it. Therefore, we opt on the side of caution */ long _book_maptype1_quantvals(const static_codebook *b){ - long vals=floor(pow((float)b->entries,1.f/b->dim)); + long vals; + if(b->entries<1){ + return(0); + } + vals=floor(pow((float)b->entries,1.f/b->dim)); /* the above *should* be reliable, but we'll not assume that FP is ever reliable when bitstream sync is at stake; verify via integer means that vals really is the greatest value of dim for which vals^b->bim <= b->entries */ /* treat the above as an initial guess */ + if(vals<1){ + vals=1; + } while(1){ long acc=1; long acc1=1; int i; for(i=0;i<b->dim;i++){ + if(b->entries/vals<acc)break; acc*=vals; - acc1*=vals+1; + if(LONG_MAX/(vals+1)<acc1)acc1=LONG_MAX; + else acc1*=vals+1; } - if(acc<=b->entries && acc1>b->entries){ + if(i>=b->dim && acc<=b->entries && acc1>b->entries){ return(vals); }else{ - if(acc>b->entries){ + if(i<b->dim || acc>b->entries){ vals--; }else{ vals++; diff --git a/thirdparty/libvorbis/smallft.c b/thirdparty/libvorbis/smallft.c index ae2bc41b6b..6d528af423 100644 --- a/thirdparty/libvorbis/smallft.c +++ b/thirdparty/libvorbis/smallft.c @@ -11,7 +11,6 @@ ******************************************************************** function: *unnormalized* fft transform - last mod: $Id: smallft.c 16227 2009-07-08 06:58:46Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/smallft.h b/thirdparty/libvorbis/smallft.h index 456497326c..9e867c67d2 100644 --- a/thirdparty/libvorbis/smallft.h +++ b/thirdparty/libvorbis/smallft.h @@ -11,7 +11,6 @@ ******************************************************************** function: fft transform - last mod: $Id: smallft.h 13293 2007-07-24 00:09:47Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/synthesis.c b/thirdparty/libvorbis/synthesis.c index 932d271a63..5f6092c3d3 100644 --- a/thirdparty/libvorbis/synthesis.c +++ b/thirdparty/libvorbis/synthesis.c @@ -11,7 +11,6 @@ ******************************************************************** function: single-block PCM synthesis - last mod: $Id: synthesis.c 19441 2015-01-21 01:17:41Z xiphmont $ ********************************************************************/ @@ -117,7 +116,7 @@ int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){ if(!ci->mode_param[mode]){ return(OV_EBADPACKET); } - + vb->W=ci->mode_param[mode]->blockflag; if(vb->W){ vb->lW=oggpack_read(opb,1); diff --git a/thirdparty/libvorbis/tone.c b/thirdparty/libvorbis/tone.c index 73afc67d4c..5b8b020604 100644 --- a/thirdparty/libvorbis/tone.c +++ b/thirdparty/libvorbis/tone.c @@ -12,7 +12,7 @@ int main (int argc,char *argv[]){ int i,j; double *f; double *amp; - + if(argc<2)usage(); f=alloca(sizeof(*f)*(argc-1)); @@ -21,7 +21,7 @@ int main (int argc,char *argv[]){ i=0; while(argv[i+1]){ char *pos=strchr(argv[i+1],','); - + f[i]=atof(argv[i+1]); if(pos) amp[i]=atof(pos+1)*32767.f; diff --git a/thirdparty/libvorbis/vorbis/codec.h b/thirdparty/libvorbis/vorbis/codec.h index 999aa33510..42aa29138e 100644 --- a/thirdparty/libvorbis/vorbis/codec.h +++ b/thirdparty/libvorbis/vorbis/codec.h @@ -11,7 +11,6 @@ ******************************************************************** function: libvorbis codec headers - last mod: $Id: codec.h 17021 2010-03-24 09:29:41Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/vorbis/vorbisenc.h b/thirdparty/libvorbis/vorbis/vorbisenc.h index 02332b50ca..55f3b4a667 100644 --- a/thirdparty/libvorbis/vorbis/vorbisenc.h +++ b/thirdparty/libvorbis/vorbis/vorbisenc.h @@ -11,7 +11,6 @@ ******************************************************************** function: vorbis encode-engine setup - last mod: $Id: vorbisenc.h 17021 2010-03-24 09:29:41Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/vorbis/vorbisfile.h b/thirdparty/libvorbis/vorbis/vorbisfile.h index 9271331e72..56626119bb 100644 --- a/thirdparty/libvorbis/vorbis/vorbisfile.h +++ b/thirdparty/libvorbis/vorbis/vorbisfile.h @@ -11,7 +11,6 @@ ******************************************************************** function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id: vorbisfile.h 17182 2010-04-29 03:48:32Z xiphmont $ ********************************************************************/ diff --git a/thirdparty/libvorbis/vorbisenc.c b/thirdparty/libvorbis/vorbisenc.c index b5d621e900..4a4607cb41 100644 --- a/thirdparty/libvorbis/vorbisenc.c +++ b/thirdparty/libvorbis/vorbisenc.c @@ -11,7 +11,6 @@ ******************************************************************** function: simple programmatic interface for encoder mode setup - last mod: $Id: vorbisenc.c 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/vorbisfile.c b/thirdparty/libvorbis/vorbisfile.c index fc0c86ff11..b570c3c5f6 100644 --- a/thirdparty/libvorbis/vorbisfile.c +++ b/thirdparty/libvorbis/vorbisfile.c @@ -11,7 +11,6 @@ ******************************************************************** function: stdio-based convenience library for opening/seeking/decoding - last mod: $Id: vorbisfile.c 19457 2015-03-03 00:15:29Z giles $ ********************************************************************/ diff --git a/thirdparty/libvorbis/window.c b/thirdparty/libvorbis/window.c index 0305b79297..b3b7ce0163 100644 --- a/thirdparty/libvorbis/window.c +++ b/thirdparty/libvorbis/window.c @@ -11,7 +11,6 @@ ******************************************************************** function: window functions - last mod: $Id: window.c 19028 2013-12-02 23:23:39Z tterribe $ ********************************************************************/ diff --git a/thirdparty/libvorbis/window.h b/thirdparty/libvorbis/window.h index 51f97599f5..6ac260749e 100644 --- a/thirdparty/libvorbis/window.h +++ b/thirdparty/libvorbis/window.h @@ -11,7 +11,6 @@ ******************************************************************** function: window functions - last mod: $Id: window.h 19028 2013-12-02 23:23:39Z tterribe $ ********************************************************************/ diff --git a/thirdparty/misc/stb_truetype.h b/thirdparty/misc/stb_truetype.h index cec2425471..e2efae2285 100644 --- a/thirdparty/misc/stb_truetype.h +++ b/thirdparty/misc/stb_truetype.h @@ -1,4 +1,4 @@ -// stb_truetype.h - v1.17 - public domain +// stb_truetype.h - v1.19 - public domain // authored from 2009-2016 by Sean Barrett / RAD Game Tools // // This library processes TrueType files: @@ -22,41 +22,35 @@ // Mikko Mononen: compound shape support, more cmap formats // Tor Andersson: kerning, subpixel rendering // Dougall Johnson: OpenType / Type 2 font handling +// Daniel Ribeiro Maciel: basic GPOS-based kerning // // Misc other: // Ryan Gordon // Simon Glass // github:IntellectualKitty // Imanol Celaya +// Daniel Ribeiro Maciel // // Bug/warning reports/fixes: -// "Zer" on mollyrocket -// Cass Everitt -// stoiko (Haemimont Games) -// Brian Hook -// Walter van Niftrik -// David Gow -// David Given -// Ivan-Assen Ivanov -// Anthony Pesch -// Johan Duparc -// Hou Qiming -// Fabian "ryg" Giesen -// Martins Mozeiko -// Cap Petschulat -// Omar Cornut -// github:aloucks -// Peter LaValle -// Sergey Popov -// Giumo X. Clanjor -// Higor Euripedes -// Thomas Fields -// Derek Vinyard -// Cort Stratton -// github:oyvindjam +// "Zer" on mollyrocket Fabian "ryg" Giesen +// Cass Everitt Martins Mozeiko +// stoiko (Haemimont Games) Cap Petschulat +// Brian Hook Omar Cornut +// Walter van Niftrik github:aloucks +// David Gow Peter LaValle +// David Given Sergey Popov +// Ivan-Assen Ivanov Giumo X. Clanjor +// Anthony Pesch Higor Euripedes +// Johan Duparc Thomas Fields +// Hou Qiming Derek Vinyard +// Rob Loach Cort Stratton +// Kenney Phillis Jr. github:oyvindjam +// Brian Costabile github:vassvik // // VERSION HISTORY // +// 1.19 (2018-02-11) GPOS kerning, STBTT_fmod +// 1.18 (2018-01-29) add missing function // 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support // 1.15 (2017-03-03) make more arguments const @@ -171,7 +165,7 @@ // measurement for describing font size, defined as 72 points per inch. // stb_truetype provides a point API for compatibility. However, true // "per inch" conventions don't make much sense on computer displays -// since they different monitors have different number of pixels per +// since different monitors have different number of pixels per // inch. For example, Windows traditionally uses a convention that // there are 96 pixels per inch, thus making 'inch' measurements have // nothing to do with inches, and thus effectively defining a point to @@ -181,6 +175,39 @@ // for non-commercial fonts, thus making fonts scaled in points // according to the TrueType spec incoherently sized in practice. // +// DETAILED USAGE: +// +// Scale: +// Select how high you want the font to be, in points or pixels. +// Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute +// a scale factor SF that will be used by all other functions. +// +// Baseline: +// You need to select a y-coordinate that is the baseline of where +// your text will appear. Call GetFontBoundingBox to get the baseline-relative +// bounding box for all characters. SF*-y0 will be the distance in pixels +// that the worst-case character could extend above the baseline, so if +// you want the top edge of characters to appear at the top of the +// screen where y=0, then you would set the baseline to SF*-y0. +// +// Current point: +// Set the current point where the first character will appear. The +// first character could extend left of the current point; this is font +// dependent. You can either choose a current point that is the leftmost +// point and hope, or add some padding, or check the bounding box or +// left-side-bearing of the first character to be displayed and set +// the current point based on that. +// +// Displaying a character: +// Compute the bounding box of the character. It will contain signed values +// relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1, +// then the character should be displayed in the rectangle from +// <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1). +// +// Advancing for the next character: +// Call GlyphHMetrics, and compute 'current_point += SF * advance'. +// +// // ADVANCED USAGE // // Quality: @@ -224,7 +251,7 @@ // Curve tesselation 120 LOC \__ 550 LOC Bitmap creation // Bitmap management 100 LOC / // Baked bitmap interface 70 LOC / -// Font name matching & access 150 LOC ---- 150 +// Font name matching & access 150 LOC ---- 150 // C runtime library abstraction 60 LOC ---- 60 // // @@ -317,7 +344,7 @@ int main(int argc, char **argv) } return 0; } -#endif +#endif // // Output: // @@ -331,9 +358,9 @@ int main(int argc, char **argv) // :@@. M@M // @@@o@@@@ // :M@@V:@@. -// +// ////////////////////////////////////////////////////////////////////////////// -// +// // Complete program: print "Hello World!" banner, with bugs // #if 0 @@ -387,7 +414,8 @@ int main(int arg, char **argv) //// INTEGRATION WITH YOUR CODEBASE //// //// The following sections allow you to supply alternate definitions -//// of C library functions used by stb_truetype. +//// of C library functions used by stb_truetype, e.g. if you don't +//// link with the C runtime library. #ifdef STB_TRUETYPE_IMPLEMENTATION // #define your own (u)stbtt_int8/16/32 before including to override this @@ -403,7 +431,7 @@ int main(int arg, char **argv) typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; - // #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h + // e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h #ifndef STBTT_ifloor #include <math.h> #define STBTT_ifloor(x) ((int) floor(x)) @@ -416,15 +444,15 @@ int main(int arg, char **argv) #define STBTT_pow(x,y) pow(x,y) #endif - #ifndef STBTT_cos + #ifndef STBTT_fmod #include <math.h> - #define STBTT_cos(x) cos(x) - #define STBTT_acos(x) acos(x) + #define STBTT_fmod(x,y) fmod(x,y) #endif - #ifndef STBTT_fabs + #ifndef STBTT_cos #include <math.h> - #define STBTT_fabs(x) fabs(x) + #define STBTT_cos(x) cos(x) + #define STBTT_acos(x) acos(x) #endif #ifndef STBTT_fabs @@ -625,7 +653,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, cons // Calling these functions in sequence is roughly equivalent to calling // stbtt_PackFontRanges(). If you more control over the packing of multiple // fonts, or if you want to pack custom data into a font texture, take a look -// at the source to of stbtt_PackFontRanges() and create a custom version +// at the source to of stbtt_PackFontRanges() and create a custom version // using these functions, e.g. call GatherRects multiple times, // building up a single array of rects, then call PackRects once, // then call RenderIntoRects repeatedly. This may result in a @@ -676,7 +704,7 @@ struct stbtt_fontinfo int numGlyphs; // number of glyphs, needed for range checking - int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf + int loca,head,glyf,hhea,hmtx,kern,gpos; // table locations as offset from start of .ttf int index_map; // a cmap mapping for our chosen character encoding int indexToLocFormat; // format needed to map from glyph index to glyph @@ -931,7 +959,7 @@ STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, floa // and computing from that can allow drop-out prevention). // // The algorithm has not been optimized at all, so expect it to be slow -// if computing lots of characters or very large sizes. +// if computing lots of characters or very large sizes. @@ -1319,6 +1347,7 @@ static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, in info->hhea = stbtt__find_table(data, fontstart, "hhea"); // required info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); // required info->kern = stbtt__find_table(data, fontstart, "kern"); // not required + info->gpos = stbtt__find_table(data, fontstart, "GPOS"); // not required if (!cmap || !info->head || !info->hhea || !info->hmtx) return 0; @@ -1687,7 +1716,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s if (i != 0) num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - // now start the new one + // now start the new one start_off = !(flags & 1); if (start_off) { // if we start off with an off-curve point, then when we need to find a point on the curve @@ -1740,7 +1769,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s int comp_num_verts = 0, i; stbtt_vertex *comp_verts = 0, *tmp = 0; float mtx[6] = {1,0,0,1,0,0}, m, n; - + flags = ttSHORT(comp); comp+=2; gidx = ttSHORT(comp); comp+=2; @@ -1770,7 +1799,7 @@ static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, s mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; } - + // Find transformation scales. m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); @@ -2172,7 +2201,7 @@ static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, st // push immediate if (b0 == 255) { - f = (float)stbtt__buf_get32(&b) / 0x10000; + f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; } else { stbtt__buf_skip(&b, -1); f = (float)(stbtt_int16)stbtt__cff_int(&b); @@ -2210,12 +2239,10 @@ static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, in { stbtt__csctx c = STBTT__CSCTX_INIT(1); int r = stbtt__run_charstring(info, glyph_index, &c); - if (x0) { - *x0 = r ? c.min_x : 0; - *y0 = r ? c.min_y : 0; - *x1 = r ? c.max_x : 0; - *y1 = r ? c.max_y : 0; - } + if (x0) *x0 = r ? c.min_x : 0; + if (y0) *y0 = r ? c.min_y : 0; + if (x1) *x1 = r ? c.max_x : 0; + if (y1) *y1 = r ? c.max_y : 0; return r ? c.num_vertices : 0; } @@ -2239,7 +2266,7 @@ STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_inde } } -STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) { stbtt_uint8 *data = info->data + info->kern; stbtt_uint32 needle, straw; @@ -2269,9 +2296,260 @@ STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, return 0; } +static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) +{ + stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); + switch(coverageFormat) { + case 1: { + stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); + + // Binary search. + stbtt_int32 l=0, r=glyphCount-1, m; + int straw, needle=glyph; + while (l <= r) { + stbtt_uint8 *glyphArray = coverageTable + 4; + stbtt_uint16 glyphID; + m = (l + r) >> 1; + glyphID = ttUSHORT(glyphArray + 2 * m); + straw = glyphID; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + return m; + } + } + } break; + + case 2: { + stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); + stbtt_uint8 *rangeArray = coverageTable + 4; + + // Binary search. + stbtt_int32 l=0, r=rangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *rangeRecord; + m = (l + r) >> 1; + rangeRecord = rangeArray + 6 * m; + strawStart = ttUSHORT(rangeRecord); + strawEnd = ttUSHORT(rangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else { + stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); + return startCoverageIndex + glyph - strawStart; + } + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) +{ + stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); + switch(classDefFormat) + { + case 1: { + stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); + stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); + stbtt_uint8 *classDef1ValueArray = classDefTable + 6; + + if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) + return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); + + classDefTable = classDef1ValueArray + 2 * glyphCount; + } break; + + case 2: { + stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); + stbtt_uint8 *classRangeRecords = classDefTable + 4; + + // Binary search. + stbtt_int32 l=0, r=classRangeCount-1, m; + int strawStart, strawEnd, needle=glyph; + while (l <= r) { + stbtt_uint8 *classRangeRecord; + m = (l + r) >> 1; + classRangeRecord = classRangeRecords + 6 * m; + strawStart = ttUSHORT(classRangeRecord); + strawEnd = ttUSHORT(classRangeRecord + 2); + if (needle < strawStart) + r = m - 1; + else if (needle > strawEnd) + l = m + 1; + else + return (stbtt_int32)ttUSHORT(classRangeRecord + 4); + } + + classDefTable = classRangeRecords + 6 * classRangeCount; + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + } break; + } + + return -1; +} + +// Define to STBTT_assert(x) if you want to break on unimplemented formats. +#define STBTT_GPOS_TODO_assert(x) + +static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) +{ + stbtt_uint16 lookupListOffset; + stbtt_uint8 *lookupList; + stbtt_uint16 lookupCount; + stbtt_uint8 *data; + stbtt_int32 i; + + if (!info->gpos) return 0; + + data = info->data + info->gpos; + + if (ttUSHORT(data+0) != 1) return 0; // Major version 1 + if (ttUSHORT(data+2) != 0) return 0; // Minor version 0 + + lookupListOffset = ttUSHORT(data+8); + lookupList = data + lookupListOffset; + lookupCount = ttUSHORT(lookupList); + + for (i=0; i<lookupCount; ++i) { + stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i); + stbtt_uint8 *lookupTable = lookupList + lookupOffset; + + stbtt_uint16 lookupType = ttUSHORT(lookupTable); + stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4); + stbtt_uint8 *subTableOffsets = lookupTable + 6; + switch(lookupType) { + case 2: { // Pair Adjustment Positioning Subtable + stbtt_int32 sti; + for (sti=0; sti<subTableCount; sti++) { + stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti); + stbtt_uint8 *table = lookupTable + subtableOffset; + stbtt_uint16 posFormat = ttUSHORT(table); + stbtt_uint16 coverageOffset = ttUSHORT(table + 2); + stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1); + if (coverageIndex == -1) continue; + + switch (posFormat) { + case 1: { + stbtt_int32 l, r, m; + int straw, needle; + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + stbtt_int32 valueRecordPairSizeInBytes = 2; + stbtt_uint16 pairSetCount = ttUSHORT(table + 8); + stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex); + stbtt_uint8 *pairValueTable = table + pairPosOffset; + stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable); + stbtt_uint8 *pairValueArray = pairValueTable + 2; + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + STBTT_assert(coverageIndex < pairSetCount); + + needle=glyph2; + r=pairValueCount-1; + l=0; + + // Binary search. + while (l <= r) { + stbtt_uint16 secondGlyph; + stbtt_uint8 *pairValue; + m = (l + r) >> 1; + pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; + secondGlyph = ttUSHORT(pairValue); + straw = secondGlyph; + if (needle < straw) + r = m - 1; + else if (needle > straw) + l = m + 1; + else { + stbtt_int16 xAdvance = ttSHORT(pairValue + 2); + return xAdvance; + } + } + } break; + + case 2: { + stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); + stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); + + stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); + stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); + int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); + int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); + + stbtt_uint16 class1Count = ttUSHORT(table + 12); + stbtt_uint16 class2Count = ttUSHORT(table + 14); + STBTT_assert(glyph1class < class1Count); + STBTT_assert(glyph2class < class2Count); + + // TODO: Support more formats. + STBTT_GPOS_TODO_assert(valueFormat1 == 4); + if (valueFormat1 != 4) return 0; + STBTT_GPOS_TODO_assert(valueFormat2 == 0); + if (valueFormat2 != 0) return 0; + + if (glyph1class >= 0 && glyph1class < class1Count && glyph2class >= 0 && glyph2class < class2Count) { + stbtt_uint8 *class1Records = table + 16; + stbtt_uint8 *class2Records = class1Records + 2 * (glyph1class * class2Count); + stbtt_int16 xAdvance = ttSHORT(class2Records + 2 * glyph2class); + return xAdvance; + } + } break; + + default: { + // There are no other cases. + STBTT_assert(0); + break; + }; + } + } + break; + }; + + default: + // TODO: Implement other stuff. + break; + } + } + + return 0; +} + +STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) +{ + int xAdvance = 0; + + if (info->gpos) + xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); + + if (info->kern) + xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); + + return xAdvance; +} + STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) { - if (!info->kern) // if no kerning table, don't waste time looking up both codepoint->glyphs + if (!info->kern && !info->gpos) // if no kerning table, don't waste time looking up both codepoint->glyphs return 0; return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); } @@ -2395,7 +2673,7 @@ static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * hh->num_remaining_in_head_chunk; + return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; } } @@ -2449,7 +2727,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); STBTT_assert(z != NULL); if (!z) return z; - + // round dx down to avoid overshooting if (dxdy < 0) z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); @@ -2527,7 +2805,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac } } } - + e = e->next; } } @@ -3229,8 +3507,9 @@ error: STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) { - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; + float scale = scale_x > scale_y ? scale_y : scale_x; + int winding_count = 0; + int *winding_lengths = NULL; stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); if (windings) { stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); @@ -3248,7 +3527,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info { int ix0,iy0,ix1,iy1; stbtt__bitmap gbm; - stbtt_vertex *vertices; + stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); if (scale_x == 0) scale_x = scale_y; @@ -3271,7 +3550,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info if (height) *height = gbm.h; if (xoff ) *xoff = ix0; if (yoff ) *yoff = iy0; - + if (gbm.w && gbm.h) { gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); if (gbm.pixels) { @@ -3282,7 +3561,7 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info } STBTT_free(vertices, info->userdata); return gbm.pixels; -} +} STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) { @@ -3294,7 +3573,7 @@ STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigne int ix0,iy0; stbtt_vertex *vertices; int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); - stbtt__bitmap gbm; + stbtt__bitmap gbm; stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); gbm.pixels = output; @@ -3316,7 +3595,12 @@ STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char * STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); -} +} + +STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) +{ + stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); +} STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) { @@ -3326,7 +3610,7 @@ STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, uns STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) { return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); -} +} STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) { @@ -3451,7 +3735,7 @@ static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *no con->y = 0; con->bottom_y = 0; STBTT__NOTUSED(nodes); - STBTT__NOTUSED(num_nodes); + STBTT__NOTUSED(num_nodes); } static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) @@ -3826,7 +4110,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char n = 0; for (i=0; i < num_ranges; ++i) n += ranges[i].num_chars; - + rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); if (rects == NULL) return 0; @@ -3837,7 +4121,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); stbtt_PackFontRangesPackRects(spc, rects, n); - + return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); STBTT_free(rects, spc->user_allocator_context); @@ -3909,7 +4193,7 @@ static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float discr = b*b - a*c; if (discr > 0.0) { float rcpna = -1 / a; - float d = (float) sqrt(discr); + float d = (float) STBTT_sqrt(discr); s0 = (b+d) * rcpna; s1 = (b-d) * rcpna; if (s0 >= 0.0 && s0 <= 1.0) @@ -3971,7 +4255,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex orig[1] = y; // make sure y never passes through a vertex of the shape - y_frac = (float) fmod(y, 1.0f); + y_frac = (float) STBTT_fmod(y, 1.0f); if (y_frac < 0.01f) y += 0.01f; else if (y_frac > 0.99f) @@ -3985,7 +4269,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) + if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } } @@ -4011,7 +4295,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex y1 = (int)verts[i ].y; if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; - if (x_inter < x) + if (x_inter < x) winding += (y0 < y1) ? 1 : -1; } } else { @@ -4023,7 +4307,7 @@ static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex if (hits[1][0] < 0) winding += (hits[1][1] < 0 ? -1 : 1); } - } + } } } return winding; @@ -4104,7 +4388,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc // invert for y-downwards bitmaps scale_y = -scale_y; - + { int x,y,i,j; float *precompute; @@ -4253,7 +4537,7 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc STBTT_free(verts, info->userdata); } return data; -} +} STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) { @@ -4271,7 +4555,7 @@ STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) // // check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string -static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) +static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) { stbtt_int32 i=0; @@ -4310,7 +4594,7 @@ static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, s return i; } -static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) +static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) { return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); } @@ -4439,7 +4723,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) { - return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); + return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); } STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) @@ -4471,6 +4755,9 @@ STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const // FULL VERSION HISTORY // +// 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod +// 1.18 (2018-01-29) add missing function +// 1.17 (2017-07-23) make more arguments const; doc fix // 1.16 (2017-07-12) SDF support // 1.15 (2017-03-03) make more arguments const // 1.14 (2017-01-16) num-fonts-in-TTC function @@ -4529,38 +4816,38 @@ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ diff --git a/thirdparty/misc/stb_vorbis.c b/thirdparty/misc/stb_vorbis.c index 14cebbf87e..8edcf0f38a 100644 --- a/thirdparty/misc/stb_vorbis.c +++ b/thirdparty/misc/stb_vorbis.c @@ -1,11 +1,11 @@ -// Ogg Vorbis audio decoder - v1.11 - public domain +// Ogg Vorbis audio decoder - v1.14 - public domain // http://nothings.org/stb_vorbis/ // // Original version written by Sean Barrett in 2007. // -// Originally sponsored by RAD Game Tools. Seeking sponsored -// by Phillip Bennefall, Marc Andersen, Aaron Baker, Elias Software, -// Aras Pranckevicius, and Sean Barrett. +// Originally sponsored by RAD Game Tools. Seeking implementation +// sponsored by Phillip Bennefall, Marc Andersen, Aaron Baker, +// Elias Software, Aras Pranckevicius, and Sean Barrett. // // LICENSE // @@ -30,22 +30,26 @@ // Tom Beaumont Ingo Leitgeb Nicolas Guillemot // Phillip Bennefall Rohit Thiago Goulart // manxorist@github saga musix github:infatum +// Timur Gagiev // // Partial history: -// 1.11 - 2017/07/23 - fix MinGW compilation -// 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory -// 1.09 - 2016/04/04 - back out 'truncation of last frame' fix from previous version -// 1.08 - 2016/04/02 - warnings; setup memory leaks; truncation of last frame -// 1.07 - 2015/01/16 - fixes for crashes on invalid files; warning fixes; const -// 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) +// 1.14 - 2018-02-11 - delete bogus dealloca usage +// 1.13 - 2018-01-29 - fix truncation of last frame (hopefully) +// 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files +// 1.11 - 2017-07-23 - fix MinGW compilation +// 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory +// 1.09 - 2016-04-04 - back out 'truncation of last frame' fix from previous version +// 1.08 - 2016-04-02 - warnings; setup memory leaks; truncation of last frame +// 1.07 - 2015-01-16 - fixes for crashes on invalid files; warning fixes; const +// 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) // some crash fixes when out of memory or with corrupt files // fix some inappropriately signed shifts -// 1.05 - 2015/04/19 - don't define __forceinline if it's redundant -// 1.04 - 2014/08/27 - fix missing const-correct case in API -// 1.03 - 2014/08/07 - warning fixes -// 1.02 - 2014/07/09 - declare qsort comparison as explicitly _cdecl in Windows -// 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float (interleaved was correct) -// 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in >2-channel; +// 1.05 - 2015-04-19 - don't define __forceinline if it's redundant +// 1.04 - 2014-08-27 - fix missing const-correct case in API +// 1.03 - 2014-08-07 - warning fixes +// 1.02 - 2014-07-09 - declare qsort comparison as explicitly _cdecl in Windows +// 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float (interleaved was correct) +// 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in >2-channel; // (API change) report sample rate for decode-full-file funcs // // See end of file for full version history. @@ -816,7 +820,7 @@ struct stb_vorbis int current_loc_valid; // per-blocksize precomputed data - + // twiddle factors float *A[2],*B[2],*C[2]; float *window[2]; @@ -880,11 +884,7 @@ static int error(vorb *f, enum STBVorbisError e) #define array_size_required(count,size) (count*(sizeof(void *)+(size))) #define temp_alloc(f,size) (f->alloc.alloc_buffer ? setup_temp_malloc(f,size) : alloca(size)) -#ifdef dealloca -#define temp_free(f,p) (f->alloc.alloc_buffer ? 0 : dealloca(size)) -#else #define temp_free(f,p) 0 -#endif #define temp_alloc_save(f) ((f)->temp_offset) #define temp_alloc_restore(f,p) ((f)->temp_offset = (p)) @@ -1142,7 +1142,7 @@ static void compute_sorted_huffman(Codebook *c, uint8 *lengths, uint32 *values) if (!c->sparse) { int k = 0; for (i=0; i < c->entries; ++i) - if (include_in_sort(c, lengths[i])) + if (include_in_sort(c, lengths[i])) c->sorted_codewords[k++] = bit_reverse(c->codewords[i]); assert(k == c->sorted_entries); } else { @@ -1323,7 +1323,7 @@ static int getn(vorb *z, uint8 *data, int n) return 1; } - #ifndef STB_VORBIS_NO_STDIO + #ifndef STB_VORBIS_NO_STDIO if (fread(data, n, 1, z->f) == 1) return 1; else { @@ -1403,7 +1403,7 @@ static int start_page_no_capturepattern(vorb *f) // header flag f->page_flag = get8(f); // absolute granule position - loc0 = get32(f); + loc0 = get32(f); loc1 = get32(f); // @TODO: validate loc0,loc1 as valid positions? // stream serial number -- vorbis doesn't interleave, so discard @@ -1888,69 +1888,69 @@ static int predict_point(int x, int x0, int x1, int y0, int y1) // the following table is block-copied from the specification static float inverse_db_table[256] = { - 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, - 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, - 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, - 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, - 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, - 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, - 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, - 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, - 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, - 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, - 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, - 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, - 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, - 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, - 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, - 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, - 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, - 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, - 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, - 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, - 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, - 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, - 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, - 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, - 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, - 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, - 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, - 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, - 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, - 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, - 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, - 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, - 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, - 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, - 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, - 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, - 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, - 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, - 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, - 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, - 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, - 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, - 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, - 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, - 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, - 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, - 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, - 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, - 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, - 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, - 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, - 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, - 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, - 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, - 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, - 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, - 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, - 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, - 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, - 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, - 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, - 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, - 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, + 1.0649863e-07f, 1.1341951e-07f, 1.2079015e-07f, 1.2863978e-07f, + 1.3699951e-07f, 1.4590251e-07f, 1.5538408e-07f, 1.6548181e-07f, + 1.7623575e-07f, 1.8768855e-07f, 1.9988561e-07f, 2.1287530e-07f, + 2.2670913e-07f, 2.4144197e-07f, 2.5713223e-07f, 2.7384213e-07f, + 2.9163793e-07f, 3.1059021e-07f, 3.3077411e-07f, 3.5226968e-07f, + 3.7516214e-07f, 3.9954229e-07f, 4.2550680e-07f, 4.5315863e-07f, + 4.8260743e-07f, 5.1396998e-07f, 5.4737065e-07f, 5.8294187e-07f, + 6.2082472e-07f, 6.6116941e-07f, 7.0413592e-07f, 7.4989464e-07f, + 7.9862701e-07f, 8.5052630e-07f, 9.0579828e-07f, 9.6466216e-07f, + 1.0273513e-06f, 1.0941144e-06f, 1.1652161e-06f, 1.2409384e-06f, + 1.3215816e-06f, 1.4074654e-06f, 1.4989305e-06f, 1.5963394e-06f, + 1.7000785e-06f, 1.8105592e-06f, 1.9282195e-06f, 2.0535261e-06f, + 2.1869758e-06f, 2.3290978e-06f, 2.4804557e-06f, 2.6416497e-06f, + 2.8133190e-06f, 2.9961443e-06f, 3.1908506e-06f, 3.3982101e-06f, + 3.6190449e-06f, 3.8542308e-06f, 4.1047004e-06f, 4.3714470e-06f, + 4.6555282e-06f, 4.9580707e-06f, 5.2802740e-06f, 5.6234160e-06f, + 5.9888572e-06f, 6.3780469e-06f, 6.7925283e-06f, 7.2339451e-06f, + 7.7040476e-06f, 8.2047000e-06f, 8.7378876e-06f, 9.3057248e-06f, + 9.9104632e-06f, 1.0554501e-05f, 1.1240392e-05f, 1.1970856e-05f, + 1.2748789e-05f, 1.3577278e-05f, 1.4459606e-05f, 1.5399272e-05f, + 1.6400004e-05f, 1.7465768e-05f, 1.8600792e-05f, 1.9809576e-05f, + 2.1096914e-05f, 2.2467911e-05f, 2.3928002e-05f, 2.5482978e-05f, + 2.7139006e-05f, 2.8902651e-05f, 3.0780908e-05f, 3.2781225e-05f, + 3.4911534e-05f, 3.7180282e-05f, 3.9596466e-05f, 4.2169667e-05f, + 4.4910090e-05f, 4.7828601e-05f, 5.0936773e-05f, 5.4246931e-05f, + 5.7772202e-05f, 6.1526565e-05f, 6.5524908e-05f, 6.9783085e-05f, + 7.4317983e-05f, 7.9147585e-05f, 8.4291040e-05f, 8.9768747e-05f, + 9.5602426e-05f, 0.00010181521f, 0.00010843174f, 0.00011547824f, + 0.00012298267f, 0.00013097477f, 0.00013948625f, 0.00014855085f, + 0.00015820453f, 0.00016848555f, 0.00017943469f, 0.00019109536f, + 0.00020351382f, 0.00021673929f, 0.00023082423f, 0.00024582449f, + 0.00026179955f, 0.00027881276f, 0.00029693158f, 0.00031622787f, + 0.00033677814f, 0.00035866388f, 0.00038197188f, 0.00040679456f, + 0.00043323036f, 0.00046138411f, 0.00049136745f, 0.00052329927f, + 0.00055730621f, 0.00059352311f, 0.00063209358f, 0.00067317058f, + 0.00071691700f, 0.00076350630f, 0.00081312324f, 0.00086596457f, + 0.00092223983f, 0.00098217216f, 0.0010459992f, 0.0011139742f, + 0.0011863665f, 0.0012634633f, 0.0013455702f, 0.0014330129f, + 0.0015261382f, 0.0016253153f, 0.0017309374f, 0.0018434235f, + 0.0019632195f, 0.0020908006f, 0.0022266726f, 0.0023713743f, + 0.0025254795f, 0.0026895994f, 0.0028643847f, 0.0030505286f, + 0.0032487691f, 0.0034598925f, 0.0036847358f, 0.0039241906f, + 0.0041792066f, 0.0044507950f, 0.0047400328f, 0.0050480668f, + 0.0053761186f, 0.0057254891f, 0.0060975636f, 0.0064938176f, + 0.0069158225f, 0.0073652516f, 0.0078438871f, 0.0083536271f, + 0.0088964928f, 0.009474637f, 0.010090352f, 0.010746080f, + 0.011444421f, 0.012188144f, 0.012980198f, 0.013823725f, + 0.014722068f, 0.015678791f, 0.016697687f, 0.017782797f, + 0.018938423f, 0.020169149f, 0.021479854f, 0.022875735f, + 0.024362330f, 0.025945531f, 0.027631618f, 0.029427276f, + 0.031339626f, 0.033376252f, 0.035545228f, 0.037855157f, + 0.040315199f, 0.042935108f, 0.045725273f, 0.048696758f, + 0.051861348f, 0.055231591f, 0.058820850f, 0.062643361f, + 0.066714279f, 0.071049749f, 0.075666962f, 0.080584227f, + 0.085821044f, 0.091398179f, 0.097337747f, 0.10366330f, + 0.11039993f, 0.11757434f, 0.12521498f, 0.13335215f, + 0.14201813f, 0.15124727f, 0.16107617f, 0.17154380f, + 0.18269168f, 0.19456402f, 0.20720788f, 0.22067342f, + 0.23501402f, 0.25028656f, 0.26655159f, 0.28387361f, + 0.30232132f, 0.32196786f, 0.34289114f, 0.36517414f, + 0.38890521f, 0.41417847f, 0.44109412f, 0.46975890f, + 0.50028648f, 0.53279791f, 0.56742212f, 0.60429640f, + 0.64356699f, 0.68538959f, 0.72993007f, 0.77736504f, 0.82788260f, 0.88168307f, 0.9389798f, 1.0f }; @@ -2042,6 +2042,8 @@ static int residue_decode(vorb *f, Codebook *book, float *target, int offset, in return TRUE; } +// n is 1/2 of the blocksize -- +// specification: "Correct per-vector decode length is [n]/2" static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int rn, uint8 *do_not_decode) { int i,j,pass; @@ -2049,7 +2051,10 @@ static void decode_residue(vorb *f, float *residue_buffers[], int ch, int n, int int rtype = f->residue_types[rn]; int c = r->classbook; int classwords = f->codebooks[c].dimensions; - int n_read = r->end - r->begin; + unsigned int actual_size = rtype == 2 ? n*2 : n; + unsigned int limit_r_begin = (r->begin < actual_size ? r->begin : actual_size); + unsigned int limit_r_end = (r->end < actual_size ? r->end : actual_size); + int n_read = limit_r_end - limit_r_begin; int part_read = n_read / r->part_size; int temp_alloc_point = temp_alloc_save(f); #ifndef STB_VORBIS_DIVIDES_IN_RESIDUE @@ -2346,11 +2351,11 @@ void inverse_mdct_slow(float *buffer, int n, vorb *f, int blocktype) #if LIBVORBIS_MDCT // directly call the vorbis MDCT using an interface documented // by Jeff Roberts... useful for performance comparison -typedef struct +typedef struct { int n; int log2n; - + float *trig; int *bitrev; @@ -2369,7 +2374,7 @@ void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) if (M1.n == n) M = &M1; else if (M2.n == n) M = &M2; else if (M1.n == 0) { mdct_init(&M1, n); M = &M1; } - else { + else { if (M2.n) __asm int 3; mdct_init(&M2, n); M = &M2; @@ -2782,7 +2787,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) d1[0] = u[k4+1]; d0[1] = u[k4+2]; d0[0] = u[k4+3]; - + d0 -= 4; d1 -= 4; bitrev += 2; @@ -2863,7 +2868,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) float p0,p1,p2,p3; p3 = e[6]*B[7] - e[7]*B[6]; - p2 = -e[6]*B[6] - e[7]*B[7]; + p2 = -e[6]*B[6] - e[7]*B[7]; d0[0] = p3; d1[3] = - p3; @@ -2871,7 +2876,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) d3[3] = p2; p1 = e[4]*B[5] - e[5]*B[4]; - p0 = -e[4]*B[4] - e[5]*B[5]; + p0 = -e[4]*B[4] - e[5]*B[5]; d0[1] = p1; d1[2] = - p1; @@ -2879,7 +2884,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) d3[2] = p0; p3 = e[2]*B[3] - e[3]*B[2]; - p2 = -e[2]*B[2] - e[3]*B[3]; + p2 = -e[2]*B[2] - e[3]*B[3]; d0[2] = p3; d1[1] = - p3; @@ -2887,7 +2892,7 @@ static void inverse_mdct(float *buffer, int n, vorb *f, int blocktype) d3[1] = p2; p1 = e[0]*B[1] - e[1]*B[0]; - p0 = -e[0]*B[0] - e[1]*B[1]; + p0 = -e[0]*B[0] - e[1]*B[1]; d0[3] = p1; d1[0] = - p1; @@ -3391,7 +3396,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, if (f->last_seg_which == f->end_seg_with_known_loc) { // if we have a valid current loc, and this is final: if (f->current_loc_valid && (f->page_flag & PAGEFLAG_last_page)) { - uint32 current_end = f->known_loc_for_packet - (n-right_end); + uint32 current_end = f->known_loc_for_packet; // then let's infer the size of the (probably) short final frame if (current_end < f->current_loc + (right_end-left_start)) { if (current_end < f->current_loc) { @@ -3400,7 +3405,7 @@ static int vorbis_decode_packet_rest(vorb *f, int *len, Mode *m, int left_start, } else { *len = current_end - f->current_loc; } - *len += left_start; + *len += left_start; // this doesn't seem right, but has no ill effect on my test files if (*len > right_end) *len = right_end; // this should never happen f->current_loc += *len; return TRUE; @@ -3521,7 +3526,7 @@ static int is_whole_packet_present(stb_vorbis *f, int end_page) first = FALSE; } for (; s == -1;) { - uint8 *q; + uint8 *q; int n; // check that we have the page header ready @@ -3874,7 +3879,7 @@ static int start_decoder(vorb *f) } else { stbv__floor_ordering p[31*8+2]; Floor1 *g = &f->floor_config[i].floor1; - int max_class = -1; + int max_class = -1; g->partitions = get_bits(f, 5); for (j=0; j < g->partitions; ++j) { g->partition_class_list[j] = get_bits(f, 4); @@ -3984,7 +3989,7 @@ static int start_decoder(vorb *f) if (f->mapping == NULL) return error(f, VORBIS_outofmem); memset(f->mapping, 0, f->mapping_count * sizeof(*f->mapping)); for (i=0; i < f->mapping_count; ++i) { - Mapping *m = f->mapping + i; + Mapping *m = f->mapping + i; int mapping_type = get_bits(f,16); if (mapping_type != 0) return error(f, VORBIS_invalid_setup); m->chan = (MappingChannel *) setup_malloc(f, f->channels * sizeof(*m->chan)); @@ -4050,6 +4055,7 @@ static int start_decoder(vorb *f) f->previous_window[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); f->finalY[i] = (int16 *) setup_malloc(f, sizeof(int16) * longest_floorlist); if (f->channel_buffers[i] == NULL || f->previous_window[i] == NULL || f->finalY[i] == NULL) return error(f, VORBIS_outofmem); + memset(f->channel_buffers[i], 0, sizeof(float) * f->blocksize_1); #ifdef STB_VORBIS_NO_DEFER_FLOOR f->floor_buffers[i] = (float *) setup_malloc(f, sizeof(float) * f->blocksize_1/2); if (f->floor_buffers[i] == NULL) return error(f, VORBIS_outofmem); @@ -4077,7 +4083,10 @@ static int start_decoder(vorb *f) int i,max_part_read=0; for (i=0; i < f->residue_count; ++i) { Residue *r = f->residue_config + i; - int n_read = r->end - r->begin; + unsigned int actual_size = f->blocksize_1 / 2; + unsigned int limit_r_begin = r->begin < actual_size ? r->begin : actual_size; + unsigned int limit_r_end = r->end < actual_size ? r->end : actual_size; + int n_read = limit_r_end - limit_r_begin; int part_read = n_read / r->part_size; if (part_read > max_part_read) max_part_read = part_read; @@ -4088,6 +4097,8 @@ static int start_decoder(vorb *f) classify_mem = f->channels * (sizeof(void*) + max_part_read * sizeof(int *)); #endif + // maximum reasonable partition size is f->blocksize_1 + f->temp_memory_required = classify_mem; if (imdct_mem > f->temp_memory_required) f->temp_memory_required = imdct_mem; @@ -4963,7 +4974,7 @@ stb_vorbis * stb_vorbis_open_file(FILE *file, int close_on_free, int *error, con stb_vorbis * stb_vorbis_open_filename(const char *filename, int *error, const stb_vorbis_alloc *alloc) { FILE *f = fopen(filename, "rb"); - if (f) + if (f) return stb_vorbis_open_file(f, TRUE, error, alloc); if (error) *error = VORBIS_file_open_failure; return NULL; @@ -5026,7 +5037,7 @@ static int8 channel_position[7][6] = #define MAGIC(SHIFT) (1.5f * (1 << (23-SHIFT)) + 0.5f/(1 << SHIFT)) #define ADDEND(SHIFT) (((150-SHIFT) << 23) + (1 << 22)) #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) (temp.f = (x) + MAGIC(s), temp.i - ADDEND(s)) - #define check_endianness() + #define check_endianness() #else #define FAST_SCALED_FLOAT_TO_INT(temp,x,s) ((int) ((x) * (1 << (s)))) #define check_endianness() @@ -5351,20 +5362,22 @@ int stb_vorbis_get_samples_float(stb_vorbis *f, int channels, float **buffer, in #endif // STB_VORBIS_NO_PULLDATA_API /* Version history - 1.10 - 2017/03/03 - more robust seeking; fix negative ilog(); clear error in open_memory - 1.09 - 2016/04/04 - back out 'avoid discarding last frame' fix from previous version - 1.08 - 2016/04/02 - fixed multiple warnings; fix setup memory leaks; + 1.12 - 2017-11-21 - limit residue begin/end to blocksize/2 to avoid large temp allocs in bad/corrupt files + 1.11 - 2017-07-23 - fix MinGW compilation + 1.10 - 2017-03-03 - more robust seeking; fix negative ilog(); clear error in open_memory + 1.09 - 2016-04-04 - back out 'avoid discarding last frame' fix from previous version + 1.08 - 2016-04-02 - fixed multiple warnings; fix setup memory leaks; avoid discarding last frame of audio data - 1.07 - 2015/01/16 - fixed some warnings, fix mingw, const-correct API - some more crash fixes when out of memory or with corrupt files - 1.06 - 2015/08/31 - full, correct support for seeking API (Dougall Johnson) + 1.07 - 2015-01-16 - fixed some warnings, fix mingw, const-correct API + some more crash fixes when out of memory or with corrupt files + 1.06 - 2015-08-31 - full, correct support for seeking API (Dougall Johnson) some crash fixes when out of memory or with corrupt files - 1.05 - 2015/04/19 - don't define __forceinline if it's redundant - 1.04 - 2014/08/27 - fix missing const-correct case in API - 1.03 - 2014/08/07 - Warning fixes - 1.02 - 2014/07/09 - Declare qsort compare function _cdecl on windows - 1.01 - 2014/06/18 - fix stb_vorbis_get_samples_float - 1.0 - 2014/05/26 - fix memory leaks; fix warnings; fix bugs in multichannel + 1.05 - 2015-04-19 - don't define __forceinline if it's redundant + 1.04 - 2014-08-27 - fix missing const-correct case in API + 1.03 - 2014-08-07 - Warning fixes + 1.02 - 2014-07-09 - Declare qsort compare function _cdecl on windows + 1.01 - 2014-06-18 - fix stb_vorbis_get_samples_float + 1.0 - 2014-05-26 - fix memory leaks; fix warnings; fix bugs in multichannel (API change) report sample rate for decode-full-file funcs 0.99996 - bracket #include <malloc.h> for macintosh compilation by Laurent Gomila 0.99995 - use union instead of pointer-cast for fast-float-to-int to avoid alias-optimization problem @@ -5412,38 +5425,38 @@ This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------ ALTERNATIVE A - MIT License Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ ALTERNATIVE B - Public Domain (www.unlicense.org) This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ */ |