diff options
470 files changed, 7400 insertions, 4369 deletions
diff --git a/core/config/engine.cpp b/core/config/engine.cpp index 3efc0e822a..94db3612b4 100644 --- a/core/config/engine.cpp +++ b/core/config/engine.cpp @@ -191,11 +191,11 @@ String Engine::get_architecture_name() const { #elif defined(__i386) || defined(__i386__) || defined(_M_IX86) return "x86_32"; -#elif defined(__aarch64__) || defined(_M_ARM64) +#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) return "arm64"; -#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__) - return "armv7"; +#elif defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7S__) || defined(_M_ARM) + return "arm32"; #elif defined(__riscv) #if __riscv_xlen == 8 diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index 26b683db82..d46e242610 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -442,6 +442,15 @@ void ProjectSettings::_convert_to_last_version(int p_from_version) { * If nothing was found, error out. */ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, bool p_upwards, bool p_ignore_override) { + if (!OS::get_singleton()->get_resource_dir().is_empty()) { + // OS will call ProjectSettings->get_resource_path which will be empty if not overridden! + // If the OS would rather use a specific location, then it will not be empty. + resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/"); + if (!resource_path.is_empty() && resource_path[resource_path.length() - 1] == '/') { + resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end. + } + } + // If looking for files in a network client, use it directly if (FileAccessNetworkClient::get_singleton()) { @@ -524,13 +533,6 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b // (Only Android -when reading from pck- and iOS use this.) if (!OS::get_singleton()->get_resource_dir().is_empty()) { - // OS will call ProjectSettings->get_resource_path which will be empty if not overridden! - // If the OS would rather use a specific location, then it will not be empty. - resource_path = OS::get_singleton()->get_resource_dir().replace("\\", "/"); - if (!resource_path.is_empty() && resource_path[resource_path.length() - 1] == '/') { - resource_path = resource_path.substr(0, resource_path.length() - 1); // Chop end. - } - Error err = _load_settings_text_or_binary("res://project.godot", "res://project.binary"); if (err == OK && !p_ignore_override) { // Optional, we don't mind if it fails. diff --git a/core/core_constants.cpp b/core/core_constants.cpp index 299b60872d..c4d83d4765 100644 --- a/core/core_constants.cpp +++ b/core/core_constants.cpp @@ -613,6 +613,7 @@ void register_global_constants() { BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_LOCALIZABLE_STRING); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_TYPE); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_HIDE_QUATERNION_EDIT); + BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_PASSWORD); BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX); BIND_CORE_ENUM_CONSTANT(PROPERTY_USAGE_NONE); diff --git a/core/math/audio_frame.h b/core/math/audio_frame.h index b3d63c0094..1a80faaa12 100644 --- a/core/math/audio_frame.h +++ b/core/math/audio_frame.h @@ -48,7 +48,7 @@ static inline float undenormalise(volatile float f) { } static const float AUDIO_PEAK_OFFSET = 0.0000000001f; -static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear2db(AUDIO_PEAK_OFFSET) +static const float AUDIO_MIN_PEAK_DB = -200.0f; // linear_to_db(AUDIO_PEAK_OFFSET) struct AudioFrame { //left and right samples diff --git a/core/math/math_funcs.h b/core/math/math_funcs.h index 463e119add..cae76b182a 100644 --- a/core/math/math_funcs.h +++ b/core/math/math_funcs.h @@ -229,11 +229,11 @@ public: return value; } - static _ALWAYS_INLINE_ double deg2rad(double p_y) { return p_y * (Math_PI / 180.0); } - static _ALWAYS_INLINE_ float deg2rad(float p_y) { return p_y * (float)(Math_PI / 180.0); } + static _ALWAYS_INLINE_ double deg_to_rad(double p_y) { return p_y * (Math_PI / 180.0); } + static _ALWAYS_INLINE_ float deg_to_rad(float p_y) { return p_y * (float)(Math_PI / 180.0); } - static _ALWAYS_INLINE_ double rad2deg(double p_y) { return p_y * (180.0 / Math_PI); } - static _ALWAYS_INLINE_ float rad2deg(float p_y) { return p_y * (float)(180.0 / Math_PI); } + static _ALWAYS_INLINE_ double rad_to_deg(double p_y) { return p_y * (180.0 / Math_PI); } + static _ALWAYS_INLINE_ float rad_to_deg(float p_y) { return p_y * (float)(180.0 / Math_PI); } static _ALWAYS_INLINE_ double lerp(double p_from, double p_to, double p_weight) { return p_from + (p_to - p_from) * p_weight; } static _ALWAYS_INLINE_ float lerp(float p_from, float p_to, float p_weight) { return p_from + (p_to - p_from) * p_weight; } @@ -253,6 +253,35 @@ public: (-p_pre + 3.0f * p_from - 3.0f * p_to + p_post) * (p_weight * p_weight * p_weight)); } + static _ALWAYS_INLINE_ double cubic_interpolate_angle(double p_from, double p_to, double p_pre, double p_post, double p_weight) { + double from_rot = fmod(p_from, Math_TAU); + + double pre_diff = fmod(p_pre - from_rot, Math_TAU); + double pre_rot = from_rot + fmod(2.0 * pre_diff, Math_TAU) - pre_diff; + + double to_diff = fmod(p_to - from_rot, Math_TAU); + double to_rot = from_rot + fmod(2.0 * to_diff, Math_TAU) - to_diff; + + double post_diff = fmod(p_post - to_rot, Math_TAU); + double post_rot = to_rot + fmod(2.0 * post_diff, Math_TAU) - post_diff; + + return cubic_interpolate(from_rot, to_rot, pre_rot, post_rot, p_weight); + } + static _ALWAYS_INLINE_ float cubic_interpolate_angle(float p_from, float p_to, float p_pre, float p_post, float p_weight) { + float from_rot = fmod(p_from, (float)Math_TAU); + + float pre_diff = fmod(p_pre - from_rot, (float)Math_TAU); + float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)Math_TAU) - pre_diff; + + float to_diff = fmod(p_to - from_rot, (float)Math_TAU); + float to_rot = from_rot + fmod(2.0f * to_diff, (float)Math_TAU) - to_diff; + + float post_diff = fmod(p_post - to_rot, (float)Math_TAU); + float post_rot = to_rot + fmod(2.0f * post_diff, (float)Math_TAU) - post_diff; + + return cubic_interpolate(from_rot, to_rot, pre_rot, post_rot, p_weight); + } + static _ALWAYS_INLINE_ double cubic_interpolate_in_time(double p_from, double p_to, double p_pre, double p_post, double p_weight, double p_to_t, double p_pre_t, double p_post_t) { /* Barry-Goldman method */ @@ -276,6 +305,37 @@ public: return Math::lerp(b1, b2, p_to_t == 0 ? 0.5f : t / p_to_t); } + static _ALWAYS_INLINE_ double cubic_interpolate_angle_in_time(double p_from, double p_to, double p_pre, double p_post, double p_weight, + double p_to_t, double p_pre_t, double p_post_t) { + double from_rot = fmod(p_from, Math_TAU); + + double pre_diff = fmod(p_pre - from_rot, Math_TAU); + double pre_rot = from_rot + fmod(2.0 * pre_diff, Math_TAU) - pre_diff; + + double to_diff = fmod(p_to - from_rot, Math_TAU); + double to_rot = from_rot + fmod(2.0 * to_diff, Math_TAU) - to_diff; + + double post_diff = fmod(p_post - to_rot, Math_TAU); + double post_rot = to_rot + fmod(2.0 * post_diff, Math_TAU) - post_diff; + + return cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t); + } + static _ALWAYS_INLINE_ float cubic_interpolate_angle_in_time(float p_from, float p_to, float p_pre, float p_post, float p_weight, + float p_to_t, float p_pre_t, float p_post_t) { + float from_rot = fmod(p_from, (float)Math_TAU); + + float pre_diff = fmod(p_pre - from_rot, (float)Math_TAU); + float pre_rot = from_rot + fmod(2.0f * pre_diff, (float)Math_TAU) - pre_diff; + + float to_diff = fmod(p_to - from_rot, (float)Math_TAU); + float to_rot = from_rot + fmod(2.0f * to_diff, (float)Math_TAU) - to_diff; + + float post_diff = fmod(p_post - to_rot, (float)Math_TAU); + float post_rot = to_rot + fmod(2.0f * post_diff, (float)Math_TAU) - post_diff; + + return cubic_interpolate_in_time(from_rot, to_rot, pre_rot, post_rot, p_weight, p_to_t, p_pre_t, p_post_t); + } + static _ALWAYS_INLINE_ double bezier_interpolate(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { /* Formula from Wikipedia article on Bezier curves. */ double omt = (1.0 - p_t); @@ -331,11 +391,11 @@ public: static _ALWAYS_INLINE_ double move_toward(double p_from, double p_to, double p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } static _ALWAYS_INLINE_ float move_toward(float p_from, float p_to, float p_delta) { return abs(p_to - p_from) <= p_delta ? p_to : p_from + SIGN(p_to - p_from) * p_delta; } - static _ALWAYS_INLINE_ double linear2db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } - static _ALWAYS_INLINE_ float linear2db(float p_linear) { return Math::log(p_linear) * (float)8.6858896380650365530225783783321; } + static _ALWAYS_INLINE_ double linear_to_db(double p_linear) { return Math::log(p_linear) * 8.6858896380650365530225783783321; } + static _ALWAYS_INLINE_ float linear_to_db(float p_linear) { return Math::log(p_linear) * (float)8.6858896380650365530225783783321; } - static _ALWAYS_INLINE_ double db2linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } - static _ALWAYS_INLINE_ float db2linear(float p_db) { return Math::exp(p_db * (float)0.11512925464970228420089957273422); } + static _ALWAYS_INLINE_ double db_to_linear(double p_db) { return Math::exp(p_db * 0.11512925464970228420089957273422); } + static _ALWAYS_INLINE_ float db_to_linear(float p_db) { return Math::exp(p_db * (float)0.11512925464970228420089957273422); } static _ALWAYS_INLINE_ double round(double p_val) { return ::round(p_val); } static _ALWAYS_INLINE_ float round(float p_val) { return ::roundf(p_val); } diff --git a/core/math/projection.cpp b/core/math/projection.cpp index edf8bf36cd..863fe6ee79 100644 --- a/core/math/projection.cpp +++ b/core/math/projection.cpp @@ -255,7 +255,7 @@ void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t } real_t sine, cotangent, deltaZ; - real_t radians = Math::deg2rad(p_fovy_degrees / 2.0); + real_t radians = Math::deg_to_rad(p_fovy_degrees / 2.0); deltaZ = p_z_far - p_z_near; sine = Math::sin(radians); @@ -282,7 +282,7 @@ void Projection::set_perspective(real_t p_fovy_degrees, real_t p_aspect, real_t real_t left, right, modeltranslation, ymax, xmax, frustumshift; - ymax = p_z_near * tan(Math::deg2rad(p_fovy_degrees / 2.0)); + ymax = p_z_near * tan(Math::deg_to_rad(p_fovy_degrees / 2.0)); xmax = ymax * p_aspect; frustumshift = (p_intraocular_dist / 2.0) * p_z_near / p_convergence_dist; @@ -816,7 +816,7 @@ real_t Projection::get_fov() const { right_plane.normalize(); if ((matrix[8] == 0) && (matrix[9] == 0)) { - return Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0; + return Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x))) * 2.0; } else { // our frustum is asymmetrical need to calculate the left planes angle separately.. Plane left_plane = Plane(matrix[3] + matrix[0], @@ -825,7 +825,7 @@ real_t Projection::get_fov() const { matrix[15] + matrix[12]); left_plane.normalize(); - return Math::rad2deg(Math::acos(Math::abs(left_plane.normal.x))) + Math::rad2deg(Math::acos(Math::abs(right_plane.normal.x))); + return Math::rad_to_deg(Math::acos(Math::abs(left_plane.normal.x))) + Math::rad_to_deg(Math::acos(Math::abs(right_plane.normal.x))); } } diff --git a/core/math/projection.h b/core/math/projection.h index a3d2d7720b..f149d307b3 100644 --- a/core/math/projection.h +++ b/core/math/projection.h @@ -96,7 +96,7 @@ struct Projection { Projection jitter_offseted(const Vector2 &p_offset) const; static real_t get_fovy(real_t p_fovx, real_t p_aspect) { - return Math::rad2deg(Math::atan(p_aspect * Math::tan(Math::deg2rad(p_fovx) * 0.5)) * 2.0); + return Math::rad_to_deg(Math::atan(p_aspect * Math::tan(Math::deg_to_rad(p_fovx) * 0.5)) * 2.0); } real_t get_z_far() const; diff --git a/core/object/object.h b/core/object/object.h index 13a40191e6..1784c1fe70 100644 --- a/core/object/object.h +++ b/core/object/object.h @@ -95,6 +95,7 @@ enum PropertyHint { PROPERTY_HINT_LOCALIZABLE_STRING, PROPERTY_HINT_NODE_TYPE, ///< a node object type PROPERTY_HINT_HIDE_QUATERNION_EDIT, /// Only Node3D::transform should hide the quaternion editor. + PROPERTY_HINT_PASSWORD, PROPERTY_HINT_MAX, // When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit }; diff --git a/core/variant/variant_utility.cpp b/core/variant/variant_utility.cpp index 21c9c483a5..1be17405c7 100644 --- a/core/variant/variant_utility.cpp +++ b/core/variant/variant_utility.cpp @@ -367,11 +367,20 @@ struct VariantUtilityFunctions { return Math::cubic_interpolate(from, to, pre, post, weight); } + static inline double cubic_interpolate_angle(double from, double to, double pre, double post, double weight) { + return Math::cubic_interpolate_angle(from, to, pre, post, weight); + } + static inline double cubic_interpolate_in_time(double from, double to, double pre, double post, double weight, double to_t, double pre_t, double post_t) { return Math::cubic_interpolate_in_time(from, to, pre, post, weight, to_t, pre_t, post_t); } + static inline double cubic_interpolate_angle_in_time(double from, double to, double pre, double post, double weight, + double to_t, double pre_t, double post_t) { + return Math::cubic_interpolate_angle_in_time(from, to, pre, post, weight, to_t, pre_t, post_t); + } + static inline double bezier_interpolate(double p_start, double p_control_1, double p_control_2, double p_end, double p_t) { return Math::bezier_interpolate(p_start, p_control_1, p_control_2, p_end, p_t); } @@ -396,20 +405,20 @@ struct VariantUtilityFunctions { return Math::move_toward(from, to, delta); } - static inline double deg2rad(double angle_deg) { - return Math::deg2rad(angle_deg); + static inline double deg_to_rad(double angle_deg) { + return Math::deg_to_rad(angle_deg); } - static inline double rad2deg(double angle_rad) { - return Math::rad2deg(angle_rad); + static inline double rad_to_deg(double angle_rad) { + return Math::rad_to_deg(angle_rad); } - static inline double linear2db(double linear) { - return Math::linear2db(linear); + static inline double linear_to_db(double linear) { + return Math::linear_to_db(linear); } - static inline double db2linear(double db) { - return Math::db2linear(db); + static inline double db_to_linear(double db) { + return Math::db_to_linear(db); } static inline Variant wrap(const Variant &p_x, const Variant &p_min, const Variant &p_max, Callable::CallError &r_error) { @@ -837,13 +846,13 @@ struct VariantUtilityFunctions { r_error.error = Callable::CallError::CALL_OK; } - static inline String var2str(const Variant &p_var) { + static inline String var_to_str(const Variant &p_var) { String vars; VariantWriter::write_to_string(p_var, vars); return vars; } - static inline Variant str2var(const String &p_var) { + static inline Variant str_to_var(const String &p_var) { VariantParser::StreamString ss; ss.s = p_var; @@ -855,7 +864,7 @@ struct VariantUtilityFunctions { return ret; } - static inline PackedByteArray var2bytes(const Variant &p_var) { + static inline PackedByteArray var_to_bytes(const Variant &p_var) { int len; Error err = encode_variant(p_var, nullptr, len, false); if (err != OK) { @@ -875,7 +884,7 @@ struct VariantUtilityFunctions { return barr; } - static inline PackedByteArray var2bytes_with_objects(const Variant &p_var) { + static inline PackedByteArray var_to_bytes_with_objects(const Variant &p_var) { int len; Error err = encode_variant(p_var, nullptr, len, true); if (err != OK) { @@ -895,7 +904,7 @@ struct VariantUtilityFunctions { return barr; } - static inline Variant bytes2var(const PackedByteArray &p_arr) { + static inline Variant bytes_to_var(const PackedByteArray &p_arr) { Variant ret; { const uint8_t *r = p_arr.ptr(); @@ -907,7 +916,7 @@ struct VariantUtilityFunctions { return ret; } - static inline Variant bytes2var_with_objects(const PackedByteArray &p_arr) { + static inline Variant bytes_to_var_with_objects(const PackedByteArray &p_arr) { Variant ret; { const uint8_t *r = p_arr.ptr(); @@ -1419,7 +1428,9 @@ void Variant::_register_variant_utility_functions() { FUNCBINDVR3(lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerpf, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(cubic_interpolate, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(cubic_interpolate_angle, sarray("from", "to", "pre", "post", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(cubic_interpolate_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(cubic_interpolate_angle_in_time, sarray("from", "to", "pre", "post", "weight", "to_t", "pre_t", "post_t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(bezier_interpolate, sarray("start", "control_1", "control_2", "end", "t"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(lerp_angle, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(inverse_lerp, sarray("from", "to", "weight"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1428,10 +1439,10 @@ void Variant::_register_variant_utility_functions() { FUNCBINDR(smoothstep, sarray("from", "to", "x"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(move_toward, sarray("from", "to", "delta"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(deg2rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(rad2deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(linear2db, sarray("lin"), Variant::UTILITY_FUNC_TYPE_MATH); - FUNCBINDR(db2linear, sarray("db"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(deg_to_rad, sarray("deg"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(rad_to_deg, sarray("rad"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(linear_to_db, sarray("lin"), Variant::UTILITY_FUNC_TYPE_MATH); + FUNCBINDR(db_to_linear, sarray("db"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDVR3(wrap, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); FUNCBINDR(wrapi, sarray("value", "min", "max"), Variant::UTILITY_FUNC_TYPE_MATH); @@ -1479,14 +1490,14 @@ void Variant::_register_variant_utility_functions() { FUNCBINDVARARGV(push_error, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDVARARGV(push_warning, sarray(), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(var2str, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(str2var, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(var_to_str, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(str_to_var, sarray("string"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(var2bytes, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(bytes2var, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(var_to_bytes, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(bytes_to_var, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(var2bytes_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); - FUNCBINDR(bytes2var_with_objects, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(var_to_bytes_with_objects, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); + FUNCBINDR(bytes_to_var_with_objects, sarray("bytes"), Variant::UTILITY_FUNC_TYPE_GENERAL); FUNCBINDR(hash, sarray("variable"), Variant::UTILITY_FUNC_TYPE_GENERAL); diff --git a/doc/classes/@GlobalScope.xml b/doc/classes/@GlobalScope.xml index bd500f6b35..71579d5173 100644 --- a/doc/classes/@GlobalScope.xml +++ b/doc/classes/@GlobalScope.xml @@ -66,7 +66,7 @@ <description> Returns the arc cosine of [param x] in radians. Use to get the angle of cosine [param x]. [param x] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method acos] will return [constant @GDScript.NAN]. [codeblock] - # c is 0.523599 or 30 degrees if converted with rad2deg(c) + # c is 0.523599 or 30 degrees if converted with rad_to_deg(c) var c = acos(0.866025) [/codeblock] </description> @@ -77,7 +77,7 @@ <description> Returns the arc sine of [param x] in radians. Use to get the angle of sine [param x]. [param x] must be between [code]-1.0[/code] and [code]1.0[/code] (inclusive), otherwise, [method asin] will return [constant @GDScript.NAN]. [codeblock] - # s is 0.523599 or 30 degrees if converted with rad2deg(s) + # s is 0.523599 or 30 degrees if converted with rad_to_deg(s) var s = asin(0.5) [/codeblock] </description> @@ -117,15 +117,15 @@ Returns the point at the given [param t] on a one-dimnesional [url=https://en.wikipedia.org/wiki/B%C3%A9zier_curve]Bezier curve[/url] defined by the given [param control_1], [param control_2], and [param end] points. </description> </method> - <method name="bytes2var"> + <method name="bytes_to_var"> <return type="Variant" /> <param index="0" name="bytes" type="PackedByteArray" /> <description> Decodes a byte array back to a [Variant] value, without decoding objects. - [b]Note:[/b] If you need object deserialization, see [method bytes2var_with_objects]. + [b]Note:[/b] If you need object deserialization, see [method bytes_to_var_with_objects]. </description> </method> - <method name="bytes2var_with_objects"> + <method name="bytes_to_var_with_objects"> <return type="Variant" /> <param index="0" name="bytes" type="PackedByteArray" /> <description> @@ -232,9 +232,9 @@ <description> Returns the cosine of angle [param angle_rad] in radians. [codeblock] - cos(PI * 2) # Returns 1.0 - cos(PI) # Returns -1.0 - cos(deg2rad(90)) # Returns 0.0 + cos(PI * 2) # Returns 1.0 + cos(PI) # Returns -1.0 + cos(deg_to_rad(90)) # Returns 0.0 [/codeblock] </description> </method> @@ -260,6 +260,32 @@ Cubic interpolates between two values by the factor defined in [param weight] with pre and post values. </description> </method> + <method name="cubic_interpolate_angle"> + <return type="float" /> + <param index="0" name="from" type="float" /> + <param index="1" name="to" type="float" /> + <param index="2" name="pre" type="float" /> + <param index="3" name="post" type="float" /> + <param index="4" name="weight" type="float" /> + <description> + Cubic interpolates between two rotation values with shortest path by the factor defined in [param weight] with pre and post values. See also [method lerp_angle]. + </description> + </method> + <method name="cubic_interpolate_angle_in_time"> + <return type="float" /> + <param index="0" name="from" type="float" /> + <param index="1" name="to" type="float" /> + <param index="2" name="pre" type="float" /> + <param index="3" name="post" type="float" /> + <param index="4" name="weight" type="float" /> + <param index="5" name="to_t" type="float" /> + <param index="6" name="pre_t" type="float" /> + <param index="7" name="post_t" type="float" /> + <description> + Cubic interpolates between two rotation values with shortest path by the factor defined in [param weight] with pre and post values. See also [method lerp_angle]. + It can perform smoother interpolation than [code]cubic_interpolate()[/code] by the time values. + </description> + </method> <method name="cubic_interpolate_in_time"> <return type="float" /> <param index="0" name="from" type="float" /> @@ -275,21 +301,21 @@ It can perform smoother interpolation than [code]cubic_interpolate()[/code] by the time values. </description> </method> - <method name="db2linear"> + <method name="db_to_linear"> <return type="float" /> <param index="0" name="db" type="float" /> <description> Converts from decibels to linear energy (audio). </description> </method> - <method name="deg2rad"> + <method name="deg_to_rad"> <return type="float" /> <param index="0" name="deg" type="float" /> <description> Converts an angle expressed in degrees to radians. [codeblock] # r is 3.141593 - var r = deg2rad(180) + var r = deg_to_rad(180) [/codeblock] </description> </method> @@ -513,8 +539,8 @@ extends Sprite var elapsed = 0.0 func _process(delta): - var min_angle = deg2rad(0.0) - var max_angle = deg2rad(90.0) + var min_angle = deg_to_rad(0.0) + var max_angle = deg_to_rad(90.0) rotation = lerp_angle(min_angle, max_angle, elapsed) elapsed += delta [/codeblock] @@ -534,7 +560,7 @@ See also [method inverse_lerp] which performs the reverse of this operation. To perform eased interpolation with [method lerp], combine it with [method ease] or [method smoothstep]. </description> </method> - <method name="linear2db"> + <method name="linear_to_db"> <return type="float" /> <param index="0" name="lin" type="float" /> <description> @@ -543,7 +569,7 @@ # "Slider" refers to a node that inherits Range such as HSlider or VSlider. # Its range must be configured to go from 0 to 1. # Change the bus name if you'd like to change the volume of a specific bus only. - AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear2db($Slider.value)) + AudioServer.set_bus_volume_db(AudioServer.get_bus_index("Master"), linear_to_db($Slider.value)) [/codeblock] </description> </method> @@ -787,13 +813,13 @@ [/codeblock] </description> </method> - <method name="rad2deg"> + <method name="rad_to_deg"> <return type="float" /> <param index="0" name="rad" type="float" /> <description> Converts an angle expressed in radians to degrees. [codeblock] - rad2deg(0.523599) # Returns 30 + rad_to_deg(0.523599) # Returns 30 [/codeblock] </description> </method> @@ -974,8 +1000,8 @@ <description> Returns the sine of angle [param angle_rad] in radians. [codeblock] - sin(0.523599) # Returns 0.5 - sin(deg2rad(90)) # Returns 1.0 + sin(0.523599) # Returns 0.5 + sin(deg_to_rad(90)) # Returns 1.0 [/codeblock] </description> </method> @@ -1054,14 +1080,14 @@ Converts one or more arguments of any type to string in the best way possible. </description> </method> - <method name="str2var"> + <method name="str_to_var"> <return type="Variant" /> <param index="0" name="string" type="String" /> <description> - Converts a formatted string that was returned by [method var2str] to the original value. + Converts a formatted [param string] that was returned by [method var_to_str] to the original value. [codeblock] var a = '{ "a": 1, "b": 2 }' - var b = str2var(a) + var b = str_to_var(a) print(b["a"]) # Prints 1 [/codeblock] </description> @@ -1072,7 +1098,7 @@ <description> Returns the tangent of angle [param angle_rad] in radians. [codeblock] - tan(deg2rad(45)) # Returns 1 + tan(deg_to_rad(45)) # Returns 1 [/codeblock] </description> </method> @@ -1103,29 +1129,29 @@ [/codeblock] </description> </method> - <method name="var2bytes"> + <method name="var_to_bytes"> <return type="PackedByteArray" /> <param index="0" name="variable" type="Variant" /> <description> - Encodes a [Variant] value to a byte array, without encoding objects. Deserialization can be done with [method bytes2var]. - [b]Note:[/b] If you need object serialization, see [method var2bytes_with_objects]. + Encodes a [Variant] value to a byte array, without encoding objects. Deserialization can be done with [method bytes_to_var]. + [b]Note:[/b] If you need object serialization, see [method var_to_bytes_with_objects]. </description> </method> - <method name="var2bytes_with_objects"> + <method name="var_to_bytes_with_objects"> <return type="PackedByteArray" /> <param index="0" name="variable" type="Variant" /> <description> - Encodes a [Variant] value to a byte array. Encoding objects is allowed (and can potentially include code). Deserialization can be done with [method bytes2var_with_objects]. + Encodes a [Variant] value to a byte array. Encoding objects is allowed (and can potentially include code). Deserialization can be done with [method bytes_to_var_with_objects]. </description> </method> - <method name="var2str"> + <method name="var_to_str"> <return type="String" /> <param index="0" name="variable" type="Variant" /> <description> - Converts a Variant [param variable] to a formatted string that can later be parsed using [method str2var]. + Converts a Variant [param variable] to a formatted string that can later be parsed using [method str_to_var]. [codeblock] a = { "a": 1, "b": 2 } - print(var2str(a)) + print(var_to_str(a)) [/codeblock] prints [codeblock] @@ -2711,7 +2737,10 @@ <constant name="PROPERTY_HINT_HIDE_QUATERNION_EDIT" value="45" enum="PropertyHint"> Hints that a quaternion property should disable the temporary euler editor. </constant> - <constant name="PROPERTY_HINT_MAX" value="46" enum="PropertyHint"> + <constant name="PROPERTY_HINT_PASSWORD" value="46" enum="PropertyHint"> + Hints that a string property is a password, and every character is replaced with the secret character. + </constant> + <constant name="PROPERTY_HINT_MAX" value="47" enum="PropertyHint"> </constant> <constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags"> </constant> diff --git a/doc/classes/Animation.xml b/doc/classes/Animation.xml index faa9ae3569..df0fb11ac7 100644 --- a/doc/classes/Animation.xml +++ b/doc/classes/Animation.xml @@ -600,8 +600,13 @@ <constant name="INTERPOLATION_CUBIC" value="2" enum="InterpolationType"> Cubic interpolation. </constant> - <constant name="INTERPOLATION_CUBIC_IN_TIME" value="3" enum="InterpolationType"> - Cubic interpolation with uniformed time. + <constant name="INTERPOLATION_LINEAR_ANGLE" value="3" enum="InterpolationType"> + Linear interpolation with shortest path rotation. + [b]Note:[/b] The result value is always normalized and may not match the key value. + </constant> + <constant name="INTERPOLATION_CUBIC_ANGLE" value="4" enum="InterpolationType"> + Cubic interpolation with shortest path rotation. + [b]Note:[/b] The result value is always normalized and may not match the key value. </constant> <constant name="UPDATE_CONTINUOUS" value="0" enum="UpdateMode"> Update between keyframes. diff --git a/doc/classes/BaseMaterial3D.xml b/doc/classes/BaseMaterial3D.xml index fcdf59e36e..33a129a48e 100644 --- a/doc/classes/BaseMaterial3D.xml +++ b/doc/classes/BaseMaterial3D.xml @@ -718,7 +718,7 @@ </constant> <constant name="BILLBOARD_PARTICLES" value="3" enum="BillboardMode"> Used for particle systems when assigned to [GPUParticles3D] and [CPUParticles3D] nodes. Enables [code]particles_anim_*[/code] properties. - The [member ParticlesMaterial.anim_speed_min] or [member CPUParticles3D.anim_speed_min] should also be set to a value bigger than zero for the animation to play. + The [member ParticleProcessMaterial.anim_speed_min] or [member CPUParticles3D.anim_speed_min] should also be set to a value bigger than zero for the animation to play. </constant> <constant name="TEXTURE_CHANNEL_RED" value="0" enum="TextureChannel"> Used to read from the red channel of a texture. diff --git a/doc/classes/CPUParticles2D.xml b/doc/classes/CPUParticles2D.xml index 64e9310181..906789d09f 100644 --- a/doc/classes/CPUParticles2D.xml +++ b/doc/classes/CPUParticles2D.xml @@ -15,7 +15,7 @@ <return type="void" /> <param index="0" name="particles" type="Node" /> <description> - Sets this node's properties to match a given [GPUParticles2D] node with an assigned [ParticlesMaterial]. + Sets this node's properties to match a given [GPUParticles2D] node with an assigned [ParticleProcessMaterial]. </description> </method> <method name="get_param_curve" qualifiers="const"> diff --git a/doc/classes/CPUParticles3D.xml b/doc/classes/CPUParticles3D.xml index bb1dcd322f..99fd0501fc 100644 --- a/doc/classes/CPUParticles3D.xml +++ b/doc/classes/CPUParticles3D.xml @@ -14,7 +14,7 @@ <return type="void" /> <param index="0" name="particles" type="Node" /> <description> - Sets this node's properties to match a given [GPUParticles3D] node with an assigned [ParticlesMaterial]. + Sets this node's properties to match a given [GPUParticles3D] node with an assigned [ParticleProcessMaterial]. </description> </method> <method name="get_param_curve" qualifiers="const"> diff --git a/doc/classes/CanvasItem.xml b/doc/classes/CanvasItem.xml index fe1fe498d1..d1fdca5814 100644 --- a/doc/classes/CanvasItem.xml +++ b/doc/classes/CanvasItem.xml @@ -9,7 +9,7 @@ Canvas items are drawn in tree order. By default, children are on top of their parents so a root [CanvasItem] will be drawn behind everything. This behavior can be changed on a per-item basis. A [CanvasItem] can also be hidden, which will also hide its children. It provides many ways to change parameters such as modulation (for itself and its children) and self modulation (only for itself), as well as its blend mode. Ultimately, a transform notification can be requested, which will notify the node that its global position changed in case the parent tree changed. - [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg2rad]. + [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg_to_rad]. </description> <tutorials> <link title="Viewport and canvas transforms">$DOCS_URL/tutorials/2d/2d_transforms.html</link> @@ -107,6 +107,23 @@ After submitting all animations slices via [method draw_animation_slice], this function can be used to revert drawing to its default state (all subsequent drawing commands will be visible). If you don't care about this particular use case, usage of this function after submitting the slices is not required. </description> </method> + <method name="draw_lcd_texture_rect_region"> + <return type="void" /> + <param index="0" name="texture" type="Texture2D" /> + <param index="1" name="rect" type="Rect2" /> + <param index="2" name="src_rect" type="Rect2" /> + <param index="3" name="modulate" type="Color" default="Color(1, 1, 1, 1)" /> + <description> + Draws a textured rectangle region of the font texture with LCD sub-pixel anti-aliasing at a given position, optionally modulated by a color. + Texture is drawn using the following blend operation, blend mode of the [CanvasItemMaterial] is ignored: + [codeblock] + dst.r = texture.r * modulate.r * modulate.a + dst.r * (1.0 - texture.r * modulate.a); + dst.g = texture.g * modulate.g * modulate.a + dst.g * (1.0 - texture.g * modulate.a); + dst.b = texture.b * modulate.b * modulate.a + dst.b * (1.0 - texture.b * modulate.a); + dst.a = modulate.a + dst.a * (1.0 - modulate.a); + [/codeblock] + </description> + </method> <method name="draw_line"> <return type="void" /> <param index="0" name="from" type="Vector2" /> diff --git a/doc/classes/CanvasItemMaterial.xml b/doc/classes/CanvasItemMaterial.xml index 22daf79074..59226840bc 100644 --- a/doc/classes/CanvasItemMaterial.xml +++ b/doc/classes/CanvasItemMaterial.xml @@ -28,7 +28,7 @@ [b]Note:[/b] This property is only used and visible in the editor if [member particles_animation] is [code]true[/code]. </member> <member name="particles_animation" type="bool" setter="set_particles_animation" getter="get_particles_animation" default="false"> - If [code]true[/code], enable spritesheet-based animation features when assigned to [GPUParticles2D] and [CPUParticles2D] nodes. The [member ParticlesMaterial.anim_speed_max] or [member CPUParticles2D.anim_speed_max] should also be set to a positive value for the animation to play. + If [code]true[/code], enable spritesheet-based animation features when assigned to [GPUParticles2D] and [CPUParticles2D] nodes. The [member ParticleProcessMaterial.anim_speed_max] or [member CPUParticles2D.anim_speed_max] should also be set to a positive value for the animation to play. This property (and other [code]particles_anim_*[/code] properties that depend on it) has no effect on other types of nodes. </member> </members> diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml index 2d169904f7..2f8e1a7bb8 100644 --- a/doc/classes/CharacterBody2D.xml +++ b/doc/classes/CharacterBody2D.xml @@ -131,7 +131,7 @@ <method name="move_and_slide"> <return type="bool" /> <description> - Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body (by default only on floor) rather than stop immediately. If the other body is a [CharacterBody2D] or [RigidDynamicBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. + Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body (by default only on floor) rather than stop immediately. If the other body is a [CharacterBody2D] or [RigidBody2D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. Modifies [member velocity] if a slide collision occurred. To get the latest collision call [method get_last_slide_collision], for detailed information about collisions that occurred, use [method get_slide_collision]. When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions. The general behavior and available properties change according to the [member motion_mode]. diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml index cbcd6b3af7..6a1975d40f 100644 --- a/doc/classes/CharacterBody3D.xml +++ b/doc/classes/CharacterBody3D.xml @@ -117,7 +117,7 @@ <method name="move_and_slide"> <return type="bool" /> <description> - Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody3D] or [RigidDynamicBody3D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. + Moves the body based on [member velocity]. If the body collides with another, it will slide along the other body rather than stop immediately. If the other body is a [CharacterBody3D] or [RigidBody3D], it will also be affected by the motion of the other body. You can use this to make moving and rotating platforms, or to make nodes push other nodes. Modifies [member velocity] if a slide collision occurred. To get the latest collision call [method get_last_slide_collision], for more detailed information about collisions that occurred, use [method get_slide_collision]. When the body touches a moving platform, the platform's velocity is automatically added to the body motion. If a collision occurs due to the platform's motion, it will always be first in the slide collisions. Returns [code]true[/code] if the body collided, otherwise, returns [code]false[/code]. diff --git a/doc/classes/ConcavePolygonShape2D.xml b/doc/classes/ConcavePolygonShape2D.xml index 902993e439..ee3e4f6de4 100644 --- a/doc/classes/ConcavePolygonShape2D.xml +++ b/doc/classes/ConcavePolygonShape2D.xml @@ -4,7 +4,7 @@ Concave polygon shape resource for 2D physics. </brief_description> <description> - 2D concave polygon shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. It is made out of segments and is optimal for complex polygonal concave collisions. However, it is not advised to use for [RigidDynamicBody2D] nodes. A CollisionPolygon2D in convex decomposition mode (solids) or several convex objects are advised for that instead. Otherwise, a concave polygon 2D shape is better for static collisions. + 2D concave polygon shape to be added as a [i]direct[/i] child of a [PhysicsBody2D] or [Area2D] using a [CollisionShape2D] node. It is made out of segments and is optimal for complex polygonal concave collisions. However, it is not advised to use for [RigidBody2D] nodes. A CollisionPolygon2D in convex decomposition mode (solids) or several convex objects are advised for that instead. Otherwise, a concave polygon 2D shape is better for static collisions. The main difference between a [ConvexPolygonShape2D] and a [ConcavePolygonShape2D] is that a concave polygon assumes it is concave and uses a more complex method of collision detection, and a convex one forces itself to be convex to speed up collision detection. [b]Performance:[/b] Due to its complexity, [ConcavePolygonShape2D] is the slowest collision shape to check collisions against. Its use should generally be limited to level geometry. For convex geometry, using [ConvexPolygonShape2D] will perform better. For dynamic physics bodies that need concave collision, several [ConvexPolygonShape2D]s can be used to represent its collision by using convex decomposition; see [ConvexPolygonShape2D]'s documentation for instructions. However, consider using primitive collision shapes such as [CircleShape2D] or [RectangleShape2D] first. [b]Warning:[/b] Using this shape for an [Area2D] (via a [CollisionShape2D] node) may give unexpected results: the area will only detect collisions with the segments in the [ConcavePolygonShape2D] (and not with any "inside" of the shape, for example). diff --git a/doc/classes/ConcavePolygonShape3D.xml b/doc/classes/ConcavePolygonShape3D.xml index d22793e52c..f01ca8efaf 100644 --- a/doc/classes/ConcavePolygonShape3D.xml +++ b/doc/classes/ConcavePolygonShape3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> 3D concave polygon shape resource (also called "trimesh") to be added as a [i]direct[/i] child of a [PhysicsBody3D] or [Area3D] using a [CollisionShape3D] node. This shape is created by feeding a list of triangles. Despite its name, [ConcavePolygonShape3D] can also store convex polygon shapes. However, unlike [ConvexPolygonShape3D], [ConcavePolygonShape3D] is [i]not[/i] limited to storing convex shapes exclusively. - [b]Note:[/b] When used for collision, [ConcavePolygonShape3D] is intended to work with static [PhysicsBody3D] nodes like [StaticBody3D] and will not work with [CharacterBody3D] or [RigidDynamicBody3D] with a mode other than Static. + [b]Note:[/b] When used for collision, [ConcavePolygonShape3D] is intended to work with static [PhysicsBody3D] nodes like [StaticBody3D] and will not work with [CharacterBody3D] or [RigidBody3D] with a mode other than Static. [b]Performance:[/b] Due to its complexity, [ConcavePolygonShape3D] is the slowest collision shape to check collisions against. Its use should generally be limited to level geometry. For convex geometry, using [ConvexPolygonShape3D] will perform better. For dynamic physics bodies that need concave collision, several [ConvexPolygonShape3D]s can be used to represent its collision by using convex decomposition; see [ConvexPolygonShape3D]'s documentation for instructions. However, consider using primitive collision shapes such as [SphereShape3D] or [BoxShape3D] first. [b]Warning:[/b] Using this shape for an [Area3D] (via a [CollisionShape3D] node, created e.g. by using the [i]Create Trimesh Collision Sibling[/i] option in the [i]Mesh[/i] menu that appears when selecting a [MeshInstance3D] node) may give unexpected results: the area will only detect collisions with the triangle faces in the [ConcavePolygonShape3D] (and not with any "inside" of the shape, for example); moreover it will only detect all such collisions if [member backface_collision] is [code]true[/code]. </description> diff --git a/doc/classes/Control.xml b/doc/classes/Control.xml index b7a9ae235e..330879390b 100644 --- a/doc/classes/Control.xml +++ b/doc/classes/Control.xml @@ -154,9 +154,9 @@ <return type="Object" /> <param index="0" name="for_text" type="String" /> <description> - Virtual method to be implemented by the user. Returns a [Control] node that should be used as a tooltip instead of the default one. The [param for_text] includes the contents of the [member hint_tooltip] property. + Virtual method to be implemented by the user. Returns a [Control] node that should be used as a tooltip instead of the default one. The [param for_text] includes the contents of the [member tooltip_text] property. The returned node must be of type [Control] or Control-derived. It can have child nodes of any type. It is freed when the tooltip disappears, so make sure you always provide a new instance (if you want to use a pre-existing node from your scene tree, you can duplicate it and pass the duplicated instance). When [code]null[/code] or a non-Control node is returned, the default tooltip will be used instead. - The returned node will be added as child to a [PopupPanel], so you should only provide the contents of that panel. That [PopupPanel] can be themed using [method Theme.set_stylebox] for the type [code]"TooltipPanel"[/code] (see [member hint_tooltip] for an example). + The returned node will be added as child to a [PopupPanel], so you should only provide the contents of that panel. That [PopupPanel] can be themed using [method Theme.set_stylebox] for the type [code]"TooltipPanel"[/code] (see [member tooltip_text] for an example). [b]Note:[/b] The tooltip is shrunk to minimal size. If you want to ensure it's fully visible, you might want to set its [member custom_minimum_size] to some non-zero value. [b]Note:[/b] The node (and any relevant children) should be [member CanvasItem.visible] when returned, otherwise, the viewport that instantiates it will not be able to calculate its minimum size reliably. Example of usage with a custom-constructed node: @@ -527,7 +527,8 @@ <return type="String" /> <param index="0" name="at_position" type="Vector2" default="Vector2(0, 0)" /> <description> - Returns the tooltip, which will appear when the cursor is resting over this control. See [member hint_tooltip]. + Returns the tooltip text [param at_position] in local coordinates, which will typically appear when the cursor is resting over this control. By default, it returns [member tooltip_text]. + [b]Note:[/b] This method can be overriden to customise its behaviour. If this method returns an empty [String], no tooltip is displayed. </description> </method> <method name="grab_click_focus"> @@ -1005,28 +1006,6 @@ <member name="grow_vertical" type="int" setter="set_v_grow_direction" getter="get_v_grow_direction" enum="Control.GrowDirection" default="1"> Controls the direction on the vertical axis in which the control should grow if its vertical minimum size is changed to be greater than its current size, as the control always has to be at least the minimum size. </member> - <member name="hint_tooltip" type="String" setter="set_tooltip" getter="_get_tooltip" default=""""> - Changes the tooltip text. The tooltip appears when the user's mouse cursor stays idle over this control for a few moments, provided that the [member mouse_filter] property is not [constant MOUSE_FILTER_IGNORE]. You can change the time required for the tooltip to appear with [code]gui/timers/tooltip_delay_sec[/code] option in Project Settings. - The tooltip popup will use either a default implementation, or a custom one that you can provide by overriding [method _make_custom_tooltip]. The default tooltip includes a [PopupPanel] and [Label] whose theme properties can be customized using [Theme] methods with the [code]"TooltipPanel"[/code] and [code]"TooltipLabel"[/code] respectively. For example: - [codeblocks] - [gdscript] - var style_box = StyleBoxFlat.new() - style_box.set_bg_color(Color(1, 1, 0)) - style_box.set_border_width_all(2) - # We assume here that the `theme` property has been assigned a custom Theme beforehand. - theme.set_stylebox("panel", "TooltipPanel", style_box) - theme.set_color("font_color", "TooltipLabel", Color(0, 1, 1)) - [/gdscript] - [csharp] - var styleBox = new StyleBoxFlat(); - styleBox.SetBgColor(new Color(1, 1, 0)); - styleBox.SetBorderWidthAll(2); - // We assume here that the `Theme` property has been assigned a custom Theme beforehand. - Theme.SetStyleBox("panel", "TooltipPanel", styleBox); - Theme.SetColor("font_color", "TooltipLabel", new Color(0, 1, 1)); - [/csharp] - [/codeblocks] - </member> <member name="layout_direction" type="int" setter="set_layout_direction" getter="get_layout_direction" enum="Control.LayoutDirection" default="0"> Controls layout direction and text writing direction. Right-to-left layouts are necessary for certain languages (e.g. Arabic and Hebrew). </member> @@ -1067,7 +1046,7 @@ The node's rotation around its pivot, in radians. See [member pivot_offset] to change the pivot's position. </member> <member name="scale" type="Vector2" setter="set_scale" getter="get_scale" default="Vector2(1, 1)"> - The node's scale, relative to its [member size]. Change this property to scale the node around its [member pivot_offset]. The Control's [member hint_tooltip] will also scale according to this value. + The node's scale, relative to its [member size]. Change this property to scale the node around its [member pivot_offset]. The Control's [member tooltip_text] will also scale according to this value. [b]Note:[/b] This property is mainly intended to be used for animation purposes. Text inside the Control will look pixelated or blurry when the Control is scaled. To support multiple resolutions in your project, use an appropriate viewport stretch mode as described in the [url=$DOCS_URL/tutorials/viewports/multiple_resolutions.html]documentation[/url] instead of scaling Controls individually. [b]Note:[/b] If the Control node is a child of a [Container] node, the scale will be reset to [code]Vector2(1, 1)[/code] when the scene is instantiated. To set the Control's scale when it's instantiated, wait for one frame using [code]await get_tree().process_frame[/code] then set its [member scale] property. </member> @@ -1092,6 +1071,28 @@ [b]Note:[/b] To look up [Control]'s own items use various [code]get_theme_*[/code] methods without specifying [code]theme_type[/code]. [b]Note:[/b] Theme items are looked for in the tree order, from branch to root, where each [Control] node is checked for its [member theme] property. The earliest match against any type/class name is returned. The project-level Theme and the default Theme are checked last. </member> + <member name="tooltip_text" type="String" setter="set_tooltip_text" getter="get_tooltip_text" default=""""> + The default tooltip text. The tooltip appears when the user's mouse cursor stays idle over this control for a few moments, provided that the [member mouse_filter] property is not [constant MOUSE_FILTER_IGNORE]. The time required for the tooltip to appear can be changed with the [code]gui/timers/tooltip_delay_sec[/code] option in Project Settings. See also [method get_tooltip]. + The tooltip popup will use either a default implementation, or a custom one that you can provide by overriding [method _make_custom_tooltip]. The default tooltip includes a [PopupPanel] and [Label] whose theme properties can be customized using [Theme] methods with the [code]"TooltipPanel"[/code] and [code]"TooltipLabel"[/code] respectively. For example: + [codeblocks] + [gdscript] + var style_box = StyleBoxFlat.new() + style_box.set_bg_color(Color(1, 1, 0)) + style_box.set_border_width_all(2) + # We assume here that the `theme` property has been assigned a custom Theme beforehand. + theme.set_stylebox("panel", "TooltipPanel", style_box) + theme.set_color("font_color", "TooltipLabel", Color(0, 1, 1)) + [/gdscript] + [csharp] + var styleBox = new StyleBoxFlat(); + styleBox.SetBgColor(new Color(1, 1, 0)); + styleBox.SetBorderWidthAll(2); + // We assume here that the `Theme` property has been assigned a custom Theme beforehand. + Theme.SetStyleBox("panel", "TooltipPanel", styleBox); + Theme.SetColor("font_color", "TooltipLabel", new Color(0, 1, 1)); + [/csharp] + [/codeblocks] + </member> </members> <signals> <signal name="focus_entered"> @@ -1145,6 +1146,7 @@ </signal> <signal name="theme_changed"> <description> + Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent. </description> </signal> </signals> @@ -1174,7 +1176,12 @@ Sent when the node loses focus. </constant> <constant name="NOTIFICATION_THEME_CHANGED" value="45"> - Sent when the node's [member theme] changes, right before Godot redraws the control. Happens when you call one of the [code]add_theme_*_override[/code] methods. + Sent when the node needs to refresh its theme items. This happens in one of the following cases: + - The [member theme] property is changed on this node or any of its ancestors. + - The [member theme_type_variation] property is changed on this node. + - One of the node's theme property overrides is changed. + - The node enters the scene tree. + [b]Note:[/b] As an optimization, this notification won't be sent from changes that occur while this node is outside of the scene tree. Instead, all of the theme item updates can be applied at once when the node enters the scene tree. </constant> <constant name="NOTIFICATION_SCROLL_BEGIN" value="47"> Sent when this node is inside a [ScrollContainer] which has begun being scrolled. diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index bcad75215a..c5f61cdfd3 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -1068,6 +1068,13 @@ <description> </description> </method> + <method name="window_get_safe_title_margins" qualifiers="const"> + <return type="Vector2i" /> + <param index="0" name="window_id" type="int" default="0" /> + <description> + Returns left and right margins of the title that are safe to use (contains no buttons or other elements) when [constant WINDOW_FLAG_EXTEND_TO_TITLE] flag is set. + </description> + </method> <method name="window_get_size" qualifiers="const"> <return type="Vector2i" /> <param index="0" name="window_id" type="int" default="0" /> @@ -1081,6 +1088,20 @@ Returns the V-Sync mode of the given window. </description> </method> + <method name="window_maximize_on_title_dbl_click" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code], if double-click on a window title should maximize it. + [b]Note:[/b] This method is implemented on macOS. + </description> + </method> + <method name="window_minimize_on_title_dbl_click" qualifiers="const"> + <return type="bool" /> + <description> + Returns [code]true[/code], if double-click on a window title should minimize it. + [b]Note:[/b] This method is implemented on macOS. + </description> + </method> <method name="window_move_to_foreground"> <return type="void" /> <param index="0" name="window_id" type="int" default="0" /> @@ -1316,6 +1337,9 @@ <constant name="FEATURE_TEXT_TO_SPEECH" value="19" enum="Feature"> Display server supports text-to-speech. See [code]tts_*[/code] methods. </constant> + <constant name="FEATURE_EXTEND_TO_TITLE" value="20" enum="Feature"> + Display server supports expanding window content to the title. See [constant WINDOW_FLAG_EXTEND_TO_TITLE]. + </constant> <constant name="MOUSE_MODE_VISIBLE" value="0" enum="MouseMode"> Makes the mouse cursor visible if it is hidden. </constant> @@ -1446,7 +1470,11 @@ <constant name="WINDOW_FLAG_POPUP" value="5" enum="WindowFlags"> Window is part of menu or [OptionButton] dropdown. This flag can't be changed when window is visible. An active popup window will exclusively receive all input, without stealing focus from its parent. Popup windows are automatically closed when uses click outside it, or when an application is switched. Popup window must have [constant WINDOW_FLAG_TRANSPARENT] set. </constant> - <constant name="WINDOW_FLAG_MAX" value="6" enum="WindowFlags"> + <constant name="WINDOW_FLAG_EXTEND_TO_TITLE" value="6" enum="WindowFlags"> + Window content is expanded to the full size of the window. Unlike borderless window, the frame is left intact and can be used to resize the window, title bar is transparent, but have minimize/maximize/close buttons. + [b]Note:[/b] This flag is implemented on macOS. + </constant> + <constant name="WINDOW_FLAG_MAX" value="7" enum="WindowFlags"> </constant> <constant name="WINDOW_EVENT_MOUSE_ENTER" value="0" enum="WindowEvent"> </constant> @@ -1483,13 +1511,13 @@ Window handle: - Windows: [code]HWND[/code] for the window. - Linux: [code]X11::Window*[/code] for the window. - - MacOS: [code]NSWindow*[/code] for the window. + - macOS: [code]NSWindow*[/code] for the window. - iOS: [code]UIViewController*[/code] for the view controller. - Android: [code]jObject[/code] for the activity. </constant> <constant name="WINDOW_VIEW" value="2" enum="HandleType"> Window view: - - MacOS: [code]NSView*[/code] for the window main view. + - macOS: [code]NSView*[/code] for the window main view. - iOS: [code]UIView*[/code] for the window main view. </constant> <constant name="TTS_UTTERANCE_STARTED" value="0" enum="TTSUtteranceEvent"> diff --git a/doc/classes/EditorProperty.xml b/doc/classes/EditorProperty.xml index 4a6a0e7226..67204f2a15 100644 --- a/doc/classes/EditorProperty.xml +++ b/doc/classes/EditorProperty.xml @@ -44,12 +44,6 @@ Gets the edited property. If your editor is for a single property (added via [method EditorInspectorPlugin._parse_property]), then this will return the property. </description> </method> - <method name="get_tooltip_text" qualifiers="const"> - <return type="String" /> - <description> - Must be implemented to provide a custom tooltip to the property editor. - </description> - </method> <method name="set_bottom_editor"> <return type="void" /> <param index="0" name="editor" type="Control" /> diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 7fc9c81985..56c1f6e55a 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -495,8 +495,12 @@ The language to use for the editor interface. Translations are provided by the community. If you spot a mistake, [url=https://docs.godotengine.org/en/latest/community/contributing/editor_and_docs_localization.html]contribute to editor translations on Weblate![/url] </member> - <member name="interface/editor/font_antialiased" type="bool" setter="" getter=""> - If [code]true[/code], enables FreeType's font antialiasing on the editor fonts. Most fonts are not designed to look good with antialiasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font. + <member name="interface/editor/expand_to_title" type="bool" setter="" getter=""> + Expanding main editor window content to the title, if supported by [DisplayServer]. See [constant DisplayServer.WINDOW_FLAG_EXTEND_TO_TITLE]. + Specific to the macOS platform. + </member> + <member name="interface/editor/font_antialiasing" type="int" setter="" getter=""> + FreeType's font anti-aliasing mode used to render the editor fonts. Most fonts are not designed to look good with anti-aliasing disabled, so it's recommended to leave this enabled unless you're using a pixel art font. </member> <member name="interface/editor/font_hinting" type="int" setter="" getter=""> The font hinting mode to use for the editor fonts. FreeType supports the following font hinting modes: diff --git a/doc/classes/FontFile.xml b/doc/classes/FontFile.xml index b9b20dc75b..df378d9d2f 100644 --- a/doc/classes/FontFile.xml +++ b/doc/classes/FontFile.xml @@ -543,8 +543,8 @@ </method> </methods> <members> - <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true"> - If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled. + <member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1"> + Font anti-aliasing mode. </member> <member name="data" type="PackedByteArray" setter="set_data" getter="get_data" default="PackedByteArray()"> Contents of the dynamic font source file. diff --git a/doc/classes/GPUParticles2D.xml b/doc/classes/GPUParticles2D.xml index 606d2456c5..f41e34c43a 100644 --- a/doc/classes/GPUParticles2D.xml +++ b/doc/classes/GPUParticles2D.xml @@ -5,7 +5,7 @@ </brief_description> <description> 2D particle node used to create a variety of particle systems and effects. [GPUParticles2D] features an emitter that generates some number of particles at a given rate. - Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. + Use the [code]process_material[/code] property to add a [ParticleProcessMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. </description> <tutorials> <link title="Particle systems (2D)">$DOCS_URL/tutorials/2d/particle_systems_2d.html</link> @@ -73,7 +73,7 @@ Particle system starts as if it had already run for this many seconds. </member> <member name="process_material" type="Material" setter="set_process_material" getter="get_process_material"> - [Material] for processing particles. Can be a [ParticlesMaterial] or a [ShaderMaterial]. + [Material] for processing particles. Can be a [ParticleProcessMaterial] or a [ShaderMaterial]. </member> <member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio" default="0.0"> Emission lifetime randomness ratio. diff --git a/doc/classes/GPUParticles3D.xml b/doc/classes/GPUParticles3D.xml index fc7b12e64f..e7b436010e 100644 --- a/doc/classes/GPUParticles3D.xml +++ b/doc/classes/GPUParticles3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> 3D particle node used to create a variety of particle systems and effects. [GPUParticles3D] features an emitter that generates some number of particles at a given rate. - Use the [code]process_material[/code] property to add a [ParticlesMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. + Use the [code]process_material[/code] property to add a [ParticleProcessMaterial] to configure particle appearance and behavior. Alternatively, you can add a [ShaderMaterial] which will be applied to all particles. </description> <tutorials> <link title="Controlling thousands of fish with Particles">$DOCS_URL/tutorials/performance/vertex_animation/controlling_thousands_of_fish.html</link> @@ -105,7 +105,7 @@ Amount of time to preprocess the particles before animation starts. Lets you start the animation some time after particles have started emitting. </member> <member name="process_material" type="Material" setter="set_process_material" getter="get_process_material"> - [Material] for processing particles. Can be a [ParticlesMaterial] or a [ShaderMaterial]. + [Material] for processing particles. Can be a [ParticleProcessMaterial] or a [ShaderMaterial]. </member> <member name="randomness" type="float" setter="set_randomness_ratio" getter="get_randomness_ratio" default="0.0"> Emission randomness ratio. diff --git a/doc/classes/GPUParticlesAttractor3D.xml b/doc/classes/GPUParticlesAttractor3D.xml index e69255cc31..a1c49afcca 100644 --- a/doc/classes/GPUParticlesAttractor3D.xml +++ b/doc/classes/GPUParticlesAttractor3D.xml @@ -18,7 +18,7 @@ <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="4294967295"> The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the attractor. By default, all particles are affected by an attractor. After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by attractors. For example, this can be used if you're using an attractor as part of a spell effect but don't want the attractor to affect unrelated weather particles at the same position. - Particle attraction can also be disabled on a per-process material basis by setting [member ParticlesMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. + Particle attraction can also be disabled on a per-process material basis by setting [member ParticleProcessMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. </member> <member name="directionality" type="float" setter="set_directionality" getter="get_directionality" default="0.0"> Adjusts how directional the attractor is. At [code]0.0[/code], the attractor is not directional at all: it will attract particles towards its center. At [code]1.0[/code], the attractor is fully directional: particles will always be pushed towards local -Z (or +Z if [member strength] is negative). diff --git a/doc/classes/GPUParticlesCollision3D.xml b/doc/classes/GPUParticlesCollision3D.xml index 27e3590e75..1b744f7ed6 100644 --- a/doc/classes/GPUParticlesCollision3D.xml +++ b/doc/classes/GPUParticlesCollision3D.xml @@ -7,7 +7,7 @@ Particle collision shapes can be used to make particles stop or bounce against them. Particle collision shapes in real-time and can be moved, rotated and scaled during gameplay. Unlike attractors, non-uniform scaling of collision shapes is [i]not[/i] supported. Particle collision shapes can be temporarily disabled by hiding them. - [b]Note:[/b] [member ParticlesMaterial.collision_mode] must be [constant ParticlesMaterial.COLLISION_RIGID] or [constant ParticlesMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. [b]Note:[/b] Particles pushed by a collider that is being moved will not be interpolated, which can result in visible stuttering. This can be alleviated by setting [member GPUParticles3D.fixed_fps] to [code]0[/code] or a value that matches or exceeds the target framerate. </description> @@ -15,9 +15,9 @@ </tutorials> <members> <member name="cull_mask" type="int" setter="set_cull_mask" getter="get_cull_mask" default="4294967295"> - The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the collision shape. By default, all particles that have [member ParticlesMaterial.collision_mode] set to [constant ParticlesMaterial.COLLISION_RIGID] or [constant ParticlesMaterial.COLLISION_HIDE_ON_CONTACT] will be affected by a collision shape. + The particle rendering layers ([member VisualInstance3D.layers]) that will be affected by the collision shape. By default, all particles that have [member ParticleProcessMaterial.collision_mode] set to [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] will be affected by a collision shape. After configuring particle nodes accordingly, specific layers can be unchecked to prevent certain particles from being affected by attractors. For example, this can be used if you're using an attractor as part of a spell effect but don't want the attractor to affect unrelated weather particles at the same position. - Particle attraction can also be disabled on a per-process material basis by setting [member ParticlesMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. + Particle attraction can also be disabled on a per-process material basis by setting [member ParticleProcessMaterial.attractor_interaction_enabled] on the [GPUParticles3D] node. </member> </members> </class> diff --git a/doc/classes/GPUParticlesCollisionBox3D.xml b/doc/classes/GPUParticlesCollisionBox3D.xml index 65b69c0098..103be18bfd 100644 --- a/doc/classes/GPUParticlesCollisionBox3D.xml +++ b/doc/classes/GPUParticlesCollisionBox3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Box-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. - [b]Note:[/b] [member ParticlesMaterial.collision_mode] must be [constant ParticlesMaterial.COLLISION_RIGID] or [constant ParticlesMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/GPUParticlesCollisionHeightField3D.xml b/doc/classes/GPUParticlesCollisionHeightField3D.xml index 72d273112e..6e996d5fbd 100644 --- a/doc/classes/GPUParticlesCollisionHeightField3D.xml +++ b/doc/classes/GPUParticlesCollisionHeightField3D.xml @@ -7,7 +7,7 @@ Real-time heightmap-shaped 3D particle attractor affecting [GPUParticles3D] nodes. Heightmap shapes allow for efficiently representing collisions for convex and concave objects with a single "floor" (such as terrain). This is less flexible than [GPUParticlesCollisionSDF3D], but it doesn't require a baking step. [GPUParticlesCollisionHeightField3D] can also be regenerated in real-time when it is moved, when the camera moves, or even continuously. This makes [GPUParticlesCollisionHeightField3D] a good choice for weather effects such as rain and snow and games with highly dynamic geometry. However, since heightmaps cannot represent overhangs, [GPUParticlesCollisionHeightField3D] is not suited for indoor particle collision. - [b]Note:[/b] [member ParticlesMaterial.collision_mode] must be [constant ParticlesMaterial.COLLISION_RIGID] or [constant ParticlesMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [code]true[/code] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/GPUParticlesCollisionSDF3D.xml b/doc/classes/GPUParticlesCollisionSDF3D.xml index 0e7640ba89..8467cfdda1 100644 --- a/doc/classes/GPUParticlesCollisionSDF3D.xml +++ b/doc/classes/GPUParticlesCollisionSDF3D.xml @@ -8,7 +8,7 @@ Signed distance fields (SDF) allow for efficiently representing approximate collision shapes for convex and concave objects of any shape. This is more flexible than [GPUParticlesCollisionHeightField3D], but it requires a baking step. [b]Baking:[/b] The signed distance field texture can be baked by selecting the [GPUParticlesCollisionSDF3D] node in the editor, then clicking [b]Bake SDF[/b] at the top of the 3D viewport. Any [i]visible[/i] [MeshInstance3D]s touching the [member extents] will be taken into account for baking, regardless of their [member GeometryInstance3D.gi_mode]. [b]Note:[/b] Baking a [GPUParticlesCollisionSDF3D]'s [member texture] is only possible within the editor, as there is no bake method exposed for use in exported projects. However, it's still possible to load pre-baked [Texture3D]s into its [member texture] property in an exported project. - [b]Note:[/b] [member ParticlesMaterial.collision_mode] must be [constant ParticlesMaterial.COLLISION_RIGID] or [constant ParticlesMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/GPUParticlesCollisionSphere3D.xml b/doc/classes/GPUParticlesCollisionSphere3D.xml index bfebe05005..ee582108dd 100644 --- a/doc/classes/GPUParticlesCollisionSphere3D.xml +++ b/doc/classes/GPUParticlesCollisionSphere3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Sphere-shaped 3D particle collision shape affecting [GPUParticles3D] nodes. - [b]Note:[/b] [member ParticlesMaterial.collision_mode] must be [constant ParticlesMaterial.COLLISION_RIGID] or [constant ParticlesMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. + [b]Note:[/b] [member ParticleProcessMaterial.collision_mode] must be [constant ParticleProcessMaterial.COLLISION_RIGID] or [constant ParticleProcessMaterial.COLLISION_HIDE_ON_CONTACT] on the [GPUParticles3D]'s process material for collision to work. [b]Note:[/b] Particle collision only affects [GPUParticles3D], not [CPUParticles3D]. </description> <tutorials> diff --git a/doc/classes/GraphEdit.xml b/doc/classes/GraphEdit.xml index e5aa78971e..dc093acdcd 100644 --- a/doc/classes/GraphEdit.xml +++ b/doc/classes/GraphEdit.xml @@ -221,6 +221,9 @@ </method> </methods> <members> + <member name="arrange_nodes_button_hidden" type="bool" setter="set_arrange_nodes_button_hidden" getter="is_arrange_nodes_button_hidden" default="false"> + If [code]true[/code], the Arrange Nodes button is hidden. + </member> <member name="clip_contents" type="bool" setter="set_clip_contents" getter="is_clipping_contents" overrides="Control" default="true" /> <member name="connection_lines_antialiased" type="bool" setter="set_connection_lines_antialiased" getter="is_connection_lines_antialiased" default="true"> If [code]true[/code], the lines between nodes will use antialiasing. diff --git a/doc/classes/GraphNode.xml b/doc/classes/GraphNode.xml index 009c329ee2..ebd4525b19 100644 --- a/doc/classes/GraphNode.xml +++ b/doc/classes/GraphNode.xml @@ -156,7 +156,7 @@ <description> Sets properties of the slot with ID [param idx]. If [param enable_left]/[param enable_right], a port will appear and the slot will be able to be connected from this side. - [param type_left]/[param type_right] is an arbitrary type of the port. Only ports with the same type values can be connected. + [param type_left]/[param type_right] is an arbitrary type of the port. Only ports with the same type values can be connected and negative values will disallow all connections to be made via user inputs. [param color_left]/[param color_right] is the tint of the port's icon on this side. [param custom_left]/[param custom_right] is a custom texture for this side's port. [b]Note:[/b] This method only sets properties of the slot. To create the slot, add a [Control]-derived child to the GraphNode. @@ -208,7 +208,7 @@ <param index="0" name="idx" type="int" /> <param index="1" name="type_left" type="int" /> <description> - Sets the left (input) type of the slot [param idx] to [param type_left]. + Sets the left (input) type of the slot [param idx] to [param type_left]. If the value is negative, all connections will be disallowed to be created via user inputs. </description> </method> <method name="set_slot_type_right"> @@ -216,7 +216,7 @@ <param index="0" name="idx" type="int" /> <param index="1" name="type_right" type="int" /> <description> - Sets the right (output) type of the slot [param idx] to [param type_right]. + Sets the right (output) type of the slot [param idx] to [param type_right]. If the value is negative, all connections will be disallowed to be created via user inputs. </description> </method> </methods> @@ -224,6 +224,9 @@ <member name="comment" type="bool" setter="set_comment" getter="is_comment" default="false"> If [code]true[/code], the GraphNode is a comment node. </member> + <member name="draggable" type="bool" setter="set_draggable" getter="is_draggable" default="true"> + If [code]true[/code], the user can drag the GraphNode. + </member> <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for line-breaking and text shaping algorithms, if left empty current locale is used instead. </member> @@ -239,6 +242,9 @@ If [code]true[/code], the user can resize the GraphNode. [b]Note:[/b] Dragging the handle will only emit the [signal resize_request] signal, the GraphNode needs to be resized manually. </member> + <member name="selectable" type="bool" setter="set_selectable" getter="is_selectable" default="true"> + If [code]true[/code], the user can select the GraphNode. + </member> <member name="selected" type="bool" setter="set_selected" getter="is_selected" default="false"> If [code]true[/code], the GraphNode is selected. </member> diff --git a/doc/classes/Label.xml b/doc/classes/Label.xml index 52b2e9a729..615aceac53 100644 --- a/doc/classes/Label.xml +++ b/doc/classes/Label.xml @@ -5,7 +5,7 @@ </brief_description> <description> Label displays plain text on the screen. It gives you control over the horizontal and vertical alignment and can wrap the text inside the node's bounding rectangle. It doesn't support bold, italics, or other formatting. For that, use [RichTextLabel] instead. - [b]Note:[/b] Contrarily to most other [Control]s, Label's [member Control.mouse_filter] defaults to [constant Control.MOUSE_FILTER_IGNORE] (i.e. it doesn't react to mouse input events). This implies that a label won't display any configured [member Control.hint_tooltip], unless you change its mouse filter. + [b]Note:[/b] Contrarily to most other [Control]s, Label's [member Control.mouse_filter] defaults to [constant Control.MOUSE_FILTER_IGNORE] (i.e. it doesn't react to mouse input events). This implies that a label won't display any configured [member Control.tooltip_text], unless you change its mouse filter. </description> <tutorials> <link title="2D Dodge The Creeps Demo">https://godotengine.org/asset-library/asset/515</link> @@ -61,10 +61,6 @@ Limits the lines of text the node shows on screen. </member> <member name="mouse_filter" type="int" setter="set_mouse_filter" getter="get_mouse_filter" overrides="Control" enum="Control.MouseFilter" default="2" /> - <member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible" default="1.0"> - The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. - </member> <member name="size_flags_vertical" type="int" setter="set_v_size_flags" getter="get_v_size_flags" overrides="Control" default="4" /> <member name="structured_text_bidi_override" type="int" setter="set_structured_text_bidi_override" getter="get_structured_text_bidi_override" enum="TextServer.StructuredTextParser" default="0"> Set BiDi algorithm override for the structured text. @@ -89,10 +85,14 @@ </member> <member name="visible_characters" type="int" setter="set_visible_characters" getter="get_visible_characters" default="-1"> The number of characters to display. If set to [code]-1[/code], all characters are displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member percent_visible] accordingly. + [b]Note:[/b] Setting this property updates [member visible_ratio] accordingly. </member> <member name="visible_characters_behavior" type="int" setter="set_visible_characters_behavior" getter="get_visible_characters_behavior" enum="TextServer.VisibleCharactersBehavior" default="0"> - Sets the clipping behavior when [member visible_characters] or [member percent_visible] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + Sets the clipping behavior when [member visible_characters] or [member visible_ratio] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + </member> + <member name="visible_ratio" type="float" setter="set_visible_ratio" getter="get_visible_ratio" default="1.0"> + The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. + [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. </member> </members> <theme_items> diff --git a/doc/classes/LineEdit.xml b/doc/classes/LineEdit.xml index 20703f680c..5ca2a22749 100644 --- a/doc/classes/LineEdit.xml +++ b/doc/classes/LineEdit.xml @@ -65,7 +65,7 @@ </description> </method> <method name="get_scroll_offset" qualifiers="const"> - <return type="int" /> + <return type="float" /> <description> Returns the scroll offset due to [member caret_column], as a number of characters. </description> diff --git a/doc/classes/Node3D.xml b/doc/classes/Node3D.xml index 53b93beb40..c8e2f1ac68 100644 --- a/doc/classes/Node3D.xml +++ b/doc/classes/Node3D.xml @@ -6,7 +6,7 @@ <description> Most basic 3D game object, with a 3D [Transform3D] and visibility settings. All other 3D game objects inherit from Node3D. Use [Node3D] as a parent node to move, scale, rotate and show/hide children in a 3D project. Affine operations (rotate, scale, translate) happen in parent's local coordinate system, unless the [Node3D] object is set as top-level. Affine operations in this coordinate system correspond to direct affine operations on the [Node3D]'s transform. The word local below refers to this coordinate system. The coordinate system that is attached to the [Node3D] object itself is referred to as object-local coordinate system. - [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg2rad]. + [b]Note:[/b] Unless otherwise specified, all methods that have angle parameters must have angles specified as [i]radians[/i]. To convert degrees to radians, use [method @GlobalScope.deg_to_rad]. </description> <tutorials> <link title="Introduction to 3D">$DOCS_URL/tutorials/3d/introduction_to_3d.html</link> diff --git a/doc/classes/PackedScene.xml b/doc/classes/PackedScene.xml index c7fe7d8c37..754d3ac73d 100644 --- a/doc/classes/PackedScene.xml +++ b/doc/classes/PackedScene.xml @@ -22,12 +22,12 @@ AddChild(scene); [/csharp] [/codeblocks] - [b]Example of saving a node with different owners:[/b] The following example creates 3 objects: [Node2D] ([code]node[/code]), [RigidDynamicBody2D] ([code]body[/code]) and [CollisionObject2D] ([code]collision[/code]). [code]collision[/code] is a child of [code]body[/code] which is a child of [code]node[/code]. Only [code]body[/code] is owned by [code]node[/code] and [code]pack[/code] will therefore only save those two nodes, but not [code]collision[/code]. + [b]Example of saving a node with different owners:[/b] The following example creates 3 objects: [Node2D] ([code]node[/code]), [RigidBody2D] ([code]body[/code]) and [CollisionObject2D] ([code]collision[/code]). [code]collision[/code] is a child of [code]body[/code] which is a child of [code]node[/code]. Only [code]body[/code] is owned by [code]node[/code] and [code]pack[/code] will therefore only save those two nodes, but not [code]collision[/code]. [codeblocks] [gdscript] # Create the objects. var node = Node2D.new() - var body = RigidDynamicBody2D.new() + var body = RigidBody2D.new() var collision = CollisionShape2D.new() # Create the object hierarchy. @@ -48,7 +48,7 @@ [csharp] // Create the objects. var node = new Node2D(); - var body = new RigidDynamicBody2D(); + var body = new RigidBody2D(); var collision = new CollisionShape2D(); // Create the object hierarchy. diff --git a/doc/classes/ParticlesMaterial.xml b/doc/classes/ParticleProcessMaterial.xml index 55f4c4dcdd..1526658eed 100644 --- a/doc/classes/ParticlesMaterial.xml +++ b/doc/classes/ParticleProcessMaterial.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="ParticlesMaterial" inherits="Material" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="ParticleProcessMaterial" inherits="Material" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Particle properties for [GPUParticles3D] and [GPUParticles2D] nodes. </brief_description> <description> - ParticlesMaterial defines particle properties and behavior. It is used in the [code]process_material[/code] of [GPUParticles3D] and [GPUParticles2D] emitter nodes. + ParticleProcessMaterial defines particle properties and behavior. It is used in the [code]process_material[/code] of [GPUParticles3D] and [GPUParticles2D] emitter nodes. Some of this material's properties are applied to each particle when emitted, while others can have a [CurveTexture] applied to vary values over the lifetime of the particle. Particle animation is available only in [GPUParticles2D]. To use it, attach a [CanvasItemMaterial], with [member CanvasItemMaterial.particles_animation] enabled, to the particles node. </description> @@ -13,35 +13,35 @@ <methods> <method name="get_param_max" qualifiers="const"> <return type="float" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <description> Returns the maximum value range for the given parameter. </description> </method> <method name="get_param_min" qualifiers="const"> <return type="float" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <description> Returns the minimum value range for the given parameter. </description> </method> <method name="get_param_texture" qualifiers="const"> <return type="Texture2D" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <description> Returns the [Texture2D] used by the specified parameter. </description> </method> <method name="get_particle_flag" qualifiers="const"> <return type="bool" /> - <param index="0" name="particle_flag" type="int" enum="ParticlesMaterial.ParticleFlags" /> + <param index="0" name="particle_flag" type="int" enum="ParticleProcessMaterial.ParticleFlags" /> <description> Returns [code]true[/code] if the specified particle flag is enabled. See [enum ParticleFlags] for options. </description> </method> <method name="set_param_max"> <return type="void" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <param index="1" name="value" type="float" /> <description> Sets the maximum value range for the given parameter. @@ -49,7 +49,7 @@ </method> <method name="set_param_min"> <return type="void" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <param index="1" name="value" type="float" /> <description> Sets the minimum value range for the given parameter. @@ -57,7 +57,7 @@ </method> <method name="set_param_texture"> <return type="void" /> - <param index="0" name="param" type="int" enum="ParticlesMaterial.Parameter" /> + <param index="0" name="param" type="int" enum="ParticleProcessMaterial.Parameter" /> <param index="1" name="texture" type="Texture2D" /> <description> Sets the [Texture2D] for the specified [enum Parameter]. @@ -65,7 +65,7 @@ </method> <method name="set_particle_flag"> <return type="void" /> - <param index="0" name="particle_flag" type="int" enum="ParticlesMaterial.ParticleFlags" /> + <param index="0" name="particle_flag" type="int" enum="ParticleProcessMaterial.ParticleFlags" /> <param index="1" name="enable" type="bool" /> <description> If [code]true[/code], enables the specified particle flag. See [enum ParticleFlags] for options. @@ -121,7 +121,7 @@ <member name="collision_friction" type="float" setter="set_collision_friction" getter="get_collision_friction"> The particles' friction. Values range from [code]0[/code] (frictionless) to [code]1[/code] (maximum friction). Only effective if [member collision_mode] is [constant COLLISION_RIGID]. </member> - <member name="collision_mode" type="int" setter="set_collision_mode" getter="get_collision_mode" enum="ParticlesMaterial.CollisionMode" default="0"> + <member name="collision_mode" type="int" setter="set_collision_mode" getter="get_collision_mode" enum="ParticleProcessMaterial.CollisionMode" default="0"> The particles' collision mode. [b]Note:[/b] Particles can only collide with [GPUParticlesCollision3D] nodes, not [PhysicsBody3D] nodes. To make particles collide with various objects, you can add [GPUParticlesCollision3D] nodes as children of [PhysicsBody3D] nodes. </member> @@ -176,7 +176,7 @@ <member name="emission_ring_radius" type="float" setter="set_emission_ring_radius" getter="get_emission_ring_radius"> The radius of the ring when using the emitter [constant EMISSION_SHAPE_RING]. </member> - <member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticlesMaterial.EmissionShape" default="0"> + <member name="emission_shape" type="int" setter="set_emission_shape" getter="get_emission_shape" enum="ParticleProcessMaterial.EmissionShape" default="0"> Particles will be emitted inside this region. Use [enum EmissionShape] constants for values. </member> <member name="emission_sphere_radius" type="float" setter="set_emission_sphere_radius" getter="get_emission_sphere_radius"> @@ -261,7 +261,7 @@ </member> <member name="sub_emitter_keep_velocity" type="bool" setter="set_sub_emitter_keep_velocity" getter="get_sub_emitter_keep_velocity" default="false"> </member> - <member name="sub_emitter_mode" type="int" setter="set_sub_emitter_mode" getter="get_sub_emitter_mode" enum="ParticlesMaterial.SubEmitterMode" default="0"> + <member name="sub_emitter_mode" type="int" setter="set_sub_emitter_mode" getter="get_sub_emitter_mode" enum="ParticleProcessMaterial.SubEmitterMode" default="0"> </member> <member name="tangential_accel_curve" type="Texture2D" setter="set_param_texture" getter="get_param_texture"> Each particle's tangential acceleration will vary along this [CurveTexture]. @@ -409,7 +409,7 @@ No collision for particles. Particles will go through [GPUParticlesCollision3D] nodes. </constant> <constant name="COLLISION_RIGID" value="1" enum="CollisionMode"> - [RigidDynamicBody3D]-style collision for particles using [GPUParticlesCollision3D] nodes. + [RigidBody3D]-style collision for particles using [GPUParticlesCollision3D] nodes. </constant> <constant name="COLLISION_HIDE_ON_CONTACT" value="2" enum="CollisionMode"> Hide particles instantly when colliding with a [GPUParticlesCollision3D] node. This can be combined with a subemitter that uses the [constant COLLISION_RIGID] collision mode to "replace" the parent particle with the subemitter on impact. diff --git a/doc/classes/Performance.xml b/doc/classes/Performance.xml index 92fa1040af..381fa3e9ef 100644 --- a/doc/classes/Performance.xml +++ b/doc/classes/Performance.xml @@ -171,7 +171,7 @@ The amount of render buffer memory used (in bytes). [i]Lower is better.[/i] </constant> <constant name="PHYSICS_2D_ACTIVE_OBJECTS" value="16" enum="Monitor"> - Number of active [RigidDynamicBody2D] nodes in the game. [i]Lower is better.[/i] + Number of active [RigidBody2D] nodes in the game. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_2D_COLLISION_PAIRS" value="17" enum="Monitor"> Number of collision pairs in the 2D physics engine. [i]Lower is better.[/i] @@ -180,7 +180,7 @@ Number of islands in the 2D physics engine. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_3D_ACTIVE_OBJECTS" value="19" enum="Monitor"> - Number of active [RigidDynamicBody3D] and [VehicleBody3D] nodes in the game. [i]Lower is better.[/i] + Number of active [RigidBody3D] and [VehicleBody3D] nodes in the game. [i]Lower is better.[/i] </constant> <constant name="PHYSICS_3D_COLLISION_PAIRS" value="20" enum="Monitor"> Number of collision pairs in the 3D physics engine. [i]Lower is better.[/i] diff --git a/doc/classes/PhysicalBone2D.xml b/doc/classes/PhysicalBone2D.xml index 738568ed03..26fce1a90b 100644 --- a/doc/classes/PhysicalBone2D.xml +++ b/doc/classes/PhysicalBone2D.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="PhysicalBone2D" inherits="RigidDynamicBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="PhysicalBone2D" inherits="RigidBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> A 2D node that can be used for physically aware bones in 2D. </brief_description> <description> - The [code]PhysicalBone2D[/code] node is a [RigidDynamicBody2D]-based node that can be used to make [Bone2D] nodes in a [Skeleton2D] react to physics. This node is very similar to the [PhysicalBone3D] node, just for 2D instead of 3D. + The [code]PhysicalBone2D[/code] node is a [RigidBody2D]-based node that can be used to make [Bone2D] nodes in a [Skeleton2D] react to physics. This node is very similar to the [PhysicalBone3D] node, just for 2D instead of 3D. [b]Note:[/b] To have the Bone2D nodes visually follow the [code]PhysicalBone2D[/code] node, use a [SkeletonModification2DPhysicalBones] modification on the [Skeleton2D] node with the [Bone2D] nodes. [b]Note:[/b] The PhysicalBone2D node does not automatically create a [Joint2D] node to keep [code]PhysicalBone2D[/code] nodes together. You will need to create these manually. For most cases, you want to use a [PinJoint2D] node. The [code]PhysicalBone2D[/code] node can automatically configure the [Joint2D] node once it's been created as a child node. </description> diff --git a/doc/classes/PhysicsDirectBodyState2D.xml b/doc/classes/PhysicsDirectBodyState2D.xml index 93c9f83ff2..fdc3a44e9d 100644 --- a/doc/classes/PhysicsDirectBodyState2D.xml +++ b/doc/classes/PhysicsDirectBodyState2D.xml @@ -4,7 +4,7 @@ Direct access object to a physics body in the [PhysicsServer2D]. </brief_description> <description> - Provides direct access to a physics body in the [PhysicsServer2D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidDynamicBody2D._integrate_forces]. + Provides direct access to a physics body in the [PhysicsServer2D], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid bodies, and is intended for changing the direct state of that body. See [method RigidBody2D._integrate_forces]. </description> <tutorials> <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> @@ -146,7 +146,7 @@ <return type="int" /> <description> Returns the number of contacts this body has with other bodies. - [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidDynamicBody2D.contact_monitor]. + [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidBody2D.contact_monitor]. </description> </method> <method name="get_contact_local_normal" qualifiers="const"> diff --git a/doc/classes/PhysicsDirectBodyState3D.xml b/doc/classes/PhysicsDirectBodyState3D.xml index 62eb9f6ac4..efe63e4093 100644 --- a/doc/classes/PhysicsDirectBodyState3D.xml +++ b/doc/classes/PhysicsDirectBodyState3D.xml @@ -4,7 +4,7 @@ Direct access object to a physics body in the [PhysicsServer3D]. </brief_description> <description> - Provides direct access to a physics body in the [PhysicsServer3D], allowing safe changes to physics properties. This object is passed via the direct state callback of dynamic bodies, and is intended for changing the direct state of that body. See [method RigidDynamicBody3D._integrate_forces]. + Provides direct access to a physics body in the [PhysicsServer3D], allowing safe changes to physics properties. This object is passed via the direct state callback of rigid bodies, and is intended for changing the direct state of that body. See [method RigidBody3D._integrate_forces]. </description> <tutorials> <link title="Physics introduction">$DOCS_URL/tutorials/physics/physics_introduction.html</link> @@ -146,7 +146,7 @@ <return type="int" /> <description> Returns the number of contacts this body has with other bodies. - [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidDynamicBody3D.contact_monitor]. + [b]Note:[/b] By default, this returns 0 unless bodies are configured to monitor contacts. See [member RigidBody3D.contact_monitor]. </description> </method> <method name="get_contact_impulse" qualifiers="const"> diff --git a/doc/classes/PhysicsServer2D.xml b/doc/classes/PhysicsServer2D.xml index 7ba52c40c6..5ae7423a71 100644 --- a/doc/classes/PhysicsServer2D.xml +++ b/doc/classes/PhysicsServer2D.xml @@ -980,11 +980,11 @@ <constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode"> Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path. </constant> - <constant name="BODY_MODE_DYNAMIC" value="2" enum="BodyMode"> - Constant for dynamic bodies. In this mode, a body can be pushed by other bodies and has forces applied. + <constant name="BODY_MODE_RIGID" value="2" enum="BodyMode"> + Constant for rigid bodies. In this mode, a body can be pushed by other bodies and has forces applied. </constant> - <constant name="BODY_MODE_DYNAMIC_LINEAR" value="3" enum="BodyMode"> - Constant for linear dynamic bodies. In this mode, a body is dynamic but can not rotate, and only its linear velocity is affected by external forces. + <constant name="BODY_MODE_RIGID_LINEAR" value="3" enum="BodyMode"> + Constant for linear rigid bodies. In this mode, a body can not rotate, and only its linear velocity is affected by external forces. </constant> <constant name="BODY_PARAM_BOUNCE" value="0" enum="BodyParameter"> Constant to set/get a body's bounce factor. diff --git a/doc/classes/PhysicsServer3D.xml b/doc/classes/PhysicsServer3D.xml index d4796fe2cf..da9e10c420 100644 --- a/doc/classes/PhysicsServer3D.xml +++ b/doc/classes/PhysicsServer3D.xml @@ -1340,11 +1340,11 @@ <constant name="BODY_MODE_KINEMATIC" value="1" enum="BodyMode"> Constant for kinematic bodies. In this mode, a body can be only moved by user code and collides with other bodies along its path. </constant> - <constant name="BODY_MODE_DYNAMIC" value="2" enum="BodyMode"> - Constant for dynamic bodies. In this mode, a body can be pushed by other bodies and has forces applied. + <constant name="BODY_MODE_RIGID" value="2" enum="BodyMode"> + Constant for rigid bodies. In this mode, a body can be pushed by other bodies and has forces applied. </constant> - <constant name="BODY_MODE_DYNAMIC_LINEAR" value="3" enum="BodyMode"> - Constant for linear dynamic bodies. In this mode, a body is dynamic but can not rotate, and only its linear velocity is affected by external forces. + <constant name="BODY_MODE_RIGID_LINEAR" value="3" enum="BodyMode"> + Constant for linear rigid bodies. In this mode, a body can not rotate, and only its linear velocity is affected by external forces. </constant> <constant name="BODY_PARAM_BOUNCE" value="0" enum="BodyParameter"> Constant to set/get a body's bounce factor. diff --git a/doc/classes/ProjectSettings.xml b/doc/classes/ProjectSettings.xml index a2e202b218..bafd5d57d9 100644 --- a/doc/classes/ProjectSettings.xml +++ b/doc/classes/ProjectSettings.xml @@ -648,8 +648,8 @@ <member name="gui/theme/custom_font" type="String" setter="" getter="" default=""""> Path to a custom [Font] resource to use as default for all GUI elements of the project. </member> - <member name="gui/theme/default_font_antialiased" type="bool" setter="" getter="" default="true"> - If set to [code]true[/code], default font uses 8-bit anitialiased glyph rendering. See [member FontFile.antialiased]. + <member name="gui/theme/default_font_antialiasing" type="int" setter="" getter="" default="1"> + Font anti-aliasing mode. See [member FontFile.antialiasing], </member> <member name="gui/theme/default_font_generate_mipmaps" type="bool" setter="" getter="" default="false"> If set to [code]true[/code], the default font will have mipmaps generated. This prevents text from looking grainy when a [Control] is scaled down, or when a [Label3D] is viewed from a long distance (if [member Label3D.texture_filter] is set to a mode that displays mipmaps). @@ -669,6 +669,9 @@ </member> <member name="gui/theme/default_theme_scale" type="float" setter="" getter="" default="1.0"> </member> + <member name="gui/theme/lcd_subpixel_layout" type="int" setter="" getter="" default="1"> + LCD sub-pixel layout used for font anti-aliasing. See [enum TextServer.FontLCDSubpixelLayout]. + </member> <member name="gui/timers/incremental_search_max_interval_msec" type="int" setter="" getter="" default="2000"> Timer setting for incremental search in [Tree], [ItemList], etc. controls (in milliseconds). </member> @@ -1640,13 +1643,13 @@ Sets the number of MSAA samples to use (as a power of two). MSAA is used to reduce aliasing around the edges of polygons. A higher MSAA value results in smoother edges but can be significantly slower on some hardware. See also bilinear scaling 3d [member rendering/scaling_3d/mode] for supersampling, which provides higher quality but is much more expensive. </member> <member name="rendering/anti_aliasing/quality/screen_space_aa" type="int" setter="" getter="" default="0"> - Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]). + Sets the screen-space antialiasing mode for the default screen [Viewport]. Screen-space antialiasing works by selectively blurring edges in a post-process shader. It differs from MSAA which takes multiple coverage samples while rendering objects. Screen-space AA methods are typically faster than MSAA and will smooth out specular aliasing, but tend to make scenes appear blurry. The blurriness is partially counteracted by automatically using a negative mipmap LOD bias (see [member rendering/textures/default_filters/texture_mipmap_bias]). Another way to combat specular aliasing is to enable [member rendering/anti_aliasing/screen_space_roughness_limiter/enabled]. </member> <member name="rendering/anti_aliasing/quality/use_debanding" type="bool" setter="" getter="" default="false"> </member> <member name="rendering/anti_aliasing/quality/use_taa" type="bool" setter="" getter="" default="false"> - Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which can be counteracted to an extent by using a negative mipmap LOD bias ([member rendering/textures/default_filters/texture_mipmap_bias]). + Enables Temporal Anti-Aliasing for the default screen [Viewport]. TAA works by jittering the camera and accumulating the images of the last rendered frames, motion vector rendering is used to account for camera and object motion. Enabling TAA can make the image blurrier, which is partially counteracted by automatically using a negative mipmap LOD bias (see [member rendering/textures/default_filters/texture_mipmap_bias]). [b]Note:[/b] The implementation is not complete yet, some visual instances such as particles and skinned meshes may show artifacts. </member> <member name="rendering/anti_aliasing/screen_space_roughness_limiter/amount" type="float" setter="" getter="" default="0.25"> @@ -1949,7 +1952,8 @@ [b]Note:[/b] This property is only read when the project starts. There is currently no way to change this setting at run-time. </member> <member name="rendering/textures/default_filters/texture_mipmap_bias" type="float" setter="" getter="" default="0.0"> - Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias. + Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). + Enabling temporal antialiasing ([member rendering/anti_aliasing/quality/use_taa]) will automatically apply a [code]-0.5[/code] offset to this value, while enabling FXAA ([member rendering/anti_aliasing/quality/screen_space_aa]) will automatically apply a [code]-0.25[/code] offset to this value. If both TAA and FXAA are enbled at the same time, an offset of [code]-0.75[/code] is applied to this value. [b]Note:[/b] If [member rendering/scaling_3d/scale] is lower than [code]1.0[/code] (exclusive), [member rendering/textures/default_filters/texture_mipmap_bias] is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]log2(scaling_3d_scale) + mipmap_bias[/code]. [b]Note:[/b] This property is only read when the project starts. To change the mipmap LOD bias at run-time, set [member Viewport.texture_mipmap_bias] instead. </member> diff --git a/doc/classes/RenderingDevice.xml b/doc/classes/RenderingDevice.xml index 2f0b9dae72..718a161323 100644 --- a/doc/classes/RenderingDevice.xml +++ b/doc/classes/RenderingDevice.xml @@ -227,6 +227,14 @@ <description> </description> </method> + <method name="draw_list_set_blend_constants"> + <return type="void" /> + <param index="0" name="draw_list" type="int" /> + <param index="1" name="color" type="Color" /> + <description> + Sets blend constants for draw list, blend constants are used only if the graphics pipeline is created with [code]DYNAMIC_STATE_BLEND_CONSTANTS[/code] flag set. + </description> + </method> <method name="draw_list_set_push_constant"> <return type="void" /> <param index="0" name="draw_list" type="int" /> diff --git a/doc/classes/RenderingServer.xml b/doc/classes/RenderingServer.xml index a12bd71454..639db6b3b5 100644 --- a/doc/classes/RenderingServer.xml +++ b/doc/classes/RenderingServer.xml @@ -176,6 +176,16 @@ <description> </description> </method> + <method name="canvas_item_add_lcd_texture_rect_region"> + <return type="void" /> + <param index="0" name="item" type="RID" /> + <param index="1" name="rect" type="Rect2" /> + <param index="2" name="texture" type="RID" /> + <param index="3" name="src_rect" type="Rect2" /> + <param index="4" name="modulate" type="Color" /> + <description> + </description> + </method> <method name="canvas_item_add_line"> <return type="void" /> <param index="0" name="item" type="RID" /> diff --git a/doc/classes/RichTextLabel.xml b/doc/classes/RichTextLabel.xml index f96e136a57..f4cbf4c442 100644 --- a/doc/classes/RichTextLabel.xml +++ b/doc/classes/RichTextLabel.xml @@ -480,10 +480,6 @@ <member name="override_selected_font_color" type="bool" setter="set_override_selected_font_color" getter="is_overriding_selected_font_color" default="false"> If [code]true[/code], the label uses the custom font color. </member> - <member name="percent_visible" type="float" setter="set_percent_visible" getter="get_percent_visible" default="1.0"> - The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. - </member> <member name="progress_bar_delay" type="int" setter="set_progress_bar_delay" getter="get_progress_bar_delay" default="1000"> The delay after which the loading progress bar is displayed, in milliseconds. Set to [code]-1[/code] to disable progress bar entirely. [b]Note:[/b] Progress bar is displayed only if [member threaded] is enabled. @@ -521,10 +517,14 @@ </member> <member name="visible_characters" type="int" setter="set_visible_characters" getter="get_visible_characters" default="-1"> The number of characters to display. If set to [code]-1[/code], all characters are displayed. This can be useful when animating the text appearing in a dialog box. - [b]Note:[/b] Setting this property updates [member percent_visible] accordingly. + [b]Note:[/b] Setting this property updates [member visible_ratio] accordingly. </member> <member name="visible_characters_behavior" type="int" setter="set_visible_characters_behavior" getter="get_visible_characters_behavior" enum="TextServer.VisibleCharactersBehavior" default="0"> - Sets the clipping behavior when [member visible_characters] or [member percent_visible] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + Sets the clipping behavior when [member visible_characters] or [member visible_ratio] is set. See [enum TextServer.VisibleCharactersBehavior] for more info. + </member> + <member name="visible_ratio" type="float" setter="set_visible_ratio" getter="get_visible_ratio" default="1.0"> + The fraction of characters to display, relative to the total number of characters (see [method get_total_character_count]). If set to [code]1.0[/code], all characters are displayed. If set to [code]0.5[/code], only half of the characters will be displayed. This can be useful when animating the text appearing in a dialog box. + [b]Note:[/b] Setting this property updates [member visible_characters] accordingly. </member> </members> <signals> diff --git a/doc/classes/RigidDynamicBody2D.xml b/doc/classes/RigidBody2D.xml index 1434affee1..9eedc3a24c 100644 --- a/doc/classes/RigidDynamicBody2D.xml +++ b/doc/classes/RigidBody2D.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RigidDynamicBody2D" inherits="PhysicsBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="RigidBody2D" inherits="PhysicsBody2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Physics Body which is moved by 2D physics simulation. Useful for objects that have gravity and can be pushed by other objects. </brief_description> <description> - This node implements simulated 2D physics. You do not control a RigidDynamicBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. + This node implements simulated 2D physics. You do not control a RigidBody2D directly. Instead, you apply forces to it (gravity, impulses, etc.) and the physics simulation calculates the resulting movement based on its mass, friction, and other physical properties. You can switch the body's behavior using [member lock_rotation], [member freeze], and [member freeze_mode]. - [b]Note:[/b] You should not change a RigidDynamicBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. + [b]Note:[/b] You should not change a RigidBody2D's [code]position[/code] or [code]linear_velocity[/code] every frame or even very often. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. Please also keep in mind that physics bodies manage their own transform which overwrites the ones you set. So any direct or indirect transformation (including scaling of the node or its parent) will be visible in the editor only, and immediately reset at runtime. If you need to override the default physics behavior or add a transformation at runtime, you can write a custom force integration. See [member custom_integrator]. </description> @@ -124,7 +124,7 @@ Damps the body's rotation. By default, the body will use the [b]Default Angular Damp[/b] in [b]Project > Project Settings > Physics > 2d[/b] or any value override set by an [Area2D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/2d/default_angular_damp] for more details about damping. </member> - <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidDynamicBody2D.DampMode" default="0"> + <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidBody2D.DampMode" default="0"> Defines how [member angular_damp] is applied. See [enum DampMode] for possible values. </member> <member name="angular_velocity" type="float" setter="set_angular_velocity" getter="get_angular_velocity" default="0.0"> @@ -137,7 +137,7 @@ The body's custom center of mass, relative to the body's origin position, when [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_CUSTOM]. This is the balanced point of the body, where applied forces only cause linear acceleration. Applying forces outside of the center of mass causes angular acceleration. When [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_AUTO] (default value), the center of mass is automatically computed. </member> - <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidDynamicBody2D.CenterOfMassMode" default="0"> + <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidBody2D.CenterOfMassMode" default="0"> Defines the way the body's center of mass is set. See [enum CenterOfMassMode] for possible values. </member> <member name="constant_force" type="Vector2" setter="set_constant_force" getter="get_constant_force" default="Vector2(0, 0)"> @@ -149,10 +149,10 @@ See [method add_constant_torque]. </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false"> - If [code]true[/code], the RigidDynamicBody2D will emit signals when it collides with another RigidDynamicBody2D. + If [code]true[/code], the RigidBody2D will emit signals when it collides with another RigidBody2D. [b]Note:[/b] By default the maximum contacts reported is set to 0, meaning nothing will be recorded, see [member max_contacts_reported]. </member> - <member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidDynamicBody2D.CCDMode" default="0"> + <member name="continuous_cd" type="int" setter="set_continuous_collision_detection_mode" getter="get_continuous_collision_detection_mode" enum="RigidBody2D.CCDMode" default="0"> Continuous collision detection mode. Continuous collision detection tries to predict where a moving body will collide instead of moving it and correcting its movement after collision. Continuous collision detection is slower, but more precise and misses fewer collisions with small, fast-moving objects. Raycasting and shapecasting methods are available. See [enum CCDMode] for details. </member> @@ -164,7 +164,7 @@ See [member freeze_mode] to set the body's behavior when frozen. For a body that is always frozen, use [StaticBody2D] or [AnimatableBody2D] instead. </member> - <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidDynamicBody2D.FreezeMode" default="0"> + <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidBody2D.FreezeMode" default="0"> The body's freeze mode. Can be used to set the body's behavior when [member freeze] is enabled. See [enum FreezeMode] for possible values. For a body that is always frozen, use [StaticBody2D] or [AnimatableBody2D] instead. </member> @@ -179,7 +179,7 @@ Damps the body's movement. By default, the body will use the [b]Default Linear Damp[/b] in [b]Project > Project Settings > Physics > 2d[/b] or any value override set by an [Area2D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/2d/default_linear_damp] for more details about damping. </member> - <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidDynamicBody2D.DampMode" default="0"> + <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidBody2D.DampMode" default="0"> Defines how [member linear_damp] is applied. See [enum DampMode] for possible values. </member> <member name="linear_velocity" type="Vector2" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector2(0, 0)"> @@ -224,11 +224,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when one of this RigidDynamicBody2D's [Shape2D]s collides with another [PhysicsBody2D] or [TileMap]'s [Shape2D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. + Emitted when one of this RigidBody2D's [Shape2D]s collides with another [PhysicsBody2D] or [TileMap]'s [Shape2D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. [param body_rid] the [RID] of the other [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D]. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap]. [param body_shape_index] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape2D] of this RigidBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="body_shape_exited"> @@ -237,11 +237,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when the collision between one of this RigidDynamicBody2D's [Shape2D]s and another [PhysicsBody2D] or [TileMap]'s [Shape2D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. + Emitted when the collision between one of this RigidBody2D's [Shape2D]s and another [PhysicsBody2D] or [TileMap]'s [Shape2D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [TileMap]s are detected if the [TileSet] has Collision [Shape2D]s. [param body_rid] the [RID] of the other [PhysicsBody2D] or [TileSet]'s [CollisionObject2D] used by the [PhysicsServer2D]. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody2D] or [TileMap]. [param body_shape_index] the index of the [Shape2D] of the other [PhysicsBody2D] or [TileMap] used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape2D] of this RigidDynamicBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape2D] of this RigidBody2D used by the [PhysicsServer2D]. Get the [CollisionShape2D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="sleeping_state_changed"> diff --git a/doc/classes/RigidDynamicBody3D.xml b/doc/classes/RigidBody3D.xml index fb747177ae..3ee3f25df1 100644 --- a/doc/classes/RigidDynamicBody3D.xml +++ b/doc/classes/RigidBody3D.xml @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="RigidDynamicBody3D" inherits="PhysicsBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="RigidBody3D" inherits="PhysicsBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Physics Body which is moved by 3D physics simulation. Useful for objects that have gravity and can be pushed by other objects. </brief_description> <description> - This is the node that implements full 3D physics. This means that you do not control a RigidDynamicBody3D directly. Instead, you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. + This is the node that implements full 3D physics. This means that you do not control a RigidBody3D directly. Instead, you can apply forces to it (gravity, impulses, etc.), and the physics simulation will calculate the resulting movement, collision, bouncing, rotating, etc. You can switch the body's behavior using [member lock_rotation], [member freeze], and [member freeze_mode]. - [b]Note:[/b] Don't change a RigidDynamicBody3D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed Hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop may result in strange behavior. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. + [b]Note:[/b] Don't change a RigidBody3D's position every frame or very often. Sporadic changes work fine, but physics runs at a different granularity (fixed Hz) than usual rendering (process callback) and maybe even in a separate thread, so changing this from a process loop may result in strange behavior. If you need to directly affect the body's state, use [method _integrate_forces], which allows you to directly access the physics state. If you need to override the default physics behavior, you can write a custom force integration function. See [member custom_integrator]. </description> <tutorials> @@ -114,7 +114,7 @@ <method name="get_inverse_inertia_tensor" qualifiers="const"> <return type="Basis" /> <description> - Returns the inverse inertia tensor basis. This is used to calculate the angular acceleration resulting from a torque applied to the [RigidDynamicBody3D]. + Returns the inverse inertia tensor basis. This is used to calculate the angular acceleration resulting from a torque applied to the [RigidBody3D]. </description> </method> <method name="set_axis_velocity"> @@ -130,11 +130,11 @@ Damps the body's rotation. By default, the body will use the [b]Default Angular Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member angular_damp_mode], you can set [member angular_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/3d/default_angular_damp] for more details about damping. </member> - <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidDynamicBody3D.DampMode" default="0"> + <member name="angular_damp_mode" type="int" setter="set_angular_damp_mode" getter="get_angular_damp_mode" enum="RigidBody3D.DampMode" default="0"> Defines how [member angular_damp] is applied. See [enum DampMode] for possible values. </member> <member name="angular_velocity" type="Vector3" setter="set_angular_velocity" getter="get_angular_velocity" default="Vector3(0, 0, 0)"> - The RigidDynamicBody3D's rotational velocity in [i]radians[/i] per second. + The RigidBody3D's rotational velocity in [i]radians[/i] per second. </member> <member name="can_sleep" type="bool" setter="set_can_sleep" getter="is_able_to_sleep" default="true"> If [code]true[/code], the body can enter sleep mode when there is no movement. See [member sleeping]. @@ -143,7 +143,7 @@ The body's custom center of mass, relative to the body's origin position, when [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_CUSTOM]. This is the balanced point of the body, where applied forces only cause linear acceleration. Applying forces outside of the center of mass causes angular acceleration. When [member center_of_mass_mode] is set to [constant CENTER_OF_MASS_MODE_AUTO] (default value), the center of mass is automatically computed. </member> - <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidDynamicBody3D.CenterOfMassMode" default="0"> + <member name="center_of_mass_mode" type="int" setter="set_center_of_mass_mode" getter="get_center_of_mass_mode" enum="RigidBody3D.CenterOfMassMode" default="0"> Defines the way the body's center of mass is set. See [enum CenterOfMassMode] for possible values. </member> <member name="constant_force" type="Vector3" setter="set_constant_force" getter="get_constant_force" default="Vector3(0, 0, 0)"> @@ -155,7 +155,7 @@ See [method add_constant_torque]. </member> <member name="contact_monitor" type="bool" setter="set_contact_monitor" getter="is_contact_monitor_enabled" default="false"> - If [code]true[/code], the RigidDynamicBody3D will emit signals when it collides with another RigidDynamicBody3D. + If [code]true[/code], the RigidBody3D will emit signals when it collides with another RigidBody3D. [b]Note:[/b] By default the maximum contacts reported is set to 0, meaning nothing will be recorded, see [member max_contacts_reported]. </member> <member name="continuous_cd" type="bool" setter="set_use_continuous_collision_detection" getter="is_using_continuous_collision_detection" default="false"> @@ -170,12 +170,12 @@ See [member freeze_mode] to set the body's behavior when frozen. For a body that is always frozen, use [StaticBody3D] or [AnimatableBody3D] instead. </member> - <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidDynamicBody3D.FreezeMode" default="0"> + <member name="freeze_mode" type="int" setter="set_freeze_mode" getter="get_freeze_mode" enum="RigidBody3D.FreezeMode" default="0"> The body's freeze mode. Can be used to set the body's behavior when [member freeze] is enabled. See [enum FreezeMode] for possible values. For a body that is always frozen, use [StaticBody3D] or [AnimatableBody3D] instead. </member> <member name="gravity_scale" type="float" setter="set_gravity_scale" getter="get_gravity_scale" default="1.0"> - This is multiplied by the global 3D gravity setting found in [b]Project > Project Settings > Physics > 3d[/b] to produce RigidDynamicBody3D's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. + This is multiplied by the global 3D gravity setting found in [b]Project > Project Settings > Physics > 3d[/b] to produce RigidBody3D's gravity. For example, a value of 1 will be normal gravity, 2 will apply double gravity, and 0.5 will apply half gravity to this object. </member> <member name="inertia" type="Vector3" setter="set_inertia" getter="get_inertia" default="Vector3(0, 0, 0)"> The body's moment of inertia. This is like mass, but for rotation: it determines how much torque it takes to rotate the body on each axis. The moment of inertia is usually computed automatically from the mass and the shapes, but this property allows you to set a custom value. @@ -185,7 +185,7 @@ Damps the body's movement. By default, the body will use the [b]Default Linear Damp[/b] in [b]Project > Project Settings > Physics > 3d[/b] or any value override set by an [Area3D] the body is in. Depending on [member linear_damp_mode], you can set [member linear_damp] to be added to or to replace the body's damping value. See [member ProjectSettings.physics/3d/default_linear_damp] for more details about damping. </member> - <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidDynamicBody3D.DampMode" default="0"> + <member name="linear_damp_mode" type="int" setter="set_linear_damp_mode" getter="get_linear_damp_mode" enum="RigidBody3D.DampMode" default="0"> Defines how [member linear_damp] is applied. See [enum DampMode] for possible values. </member> <member name="linear_velocity" type="Vector3" setter="set_linear_velocity" getter="get_linear_velocity" default="Vector3(0, 0, 0)"> @@ -230,11 +230,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when one of this RigidDynamicBody3D's [Shape3D]s collides with another [PhysicsBody3D] or [GridMap]'s [Shape3D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. + Emitted when one of this RigidBody3D's [Shape3D]s collides with another [PhysicsBody3D] or [GridMap]'s [Shape3D]s. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. [param body_rid] the [RID] of the other [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D]. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap]. [param body_shape_index] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape3D] of this RigidBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="body_shape_exited"> @@ -243,11 +243,11 @@ <param index="2" name="body_shape_index" type="int" /> <param index="3" name="local_shape_index" type="int" /> <description> - Emitted when the collision between one of this RigidDynamicBody3D's [Shape3D]s and another [PhysicsBody3D] or [GridMap]'s [Shape3D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. + Emitted when the collision between one of this RigidBody3D's [Shape3D]s and another [PhysicsBody3D] or [GridMap]'s [Shape3D]s ends. Requires [member contact_monitor] to be set to [code]true[/code] and [member max_contacts_reported] to be set high enough to detect all the collisions. [GridMap]s are detected if the [MeshLibrary] has Collision [Shape3D]s. [param body_rid] the [RID] of the other [PhysicsBody3D] or [MeshLibrary]'s [CollisionObject3D] used by the [PhysicsServer3D]. [GridMap]s are detected if the Meshes have [Shape3D]s. [param body] the [Node], if it exists in the tree, of the other [PhysicsBody3D] or [GridMap]. [param body_shape_index] the index of the [Shape3D] of the other [PhysicsBody3D] or [GridMap] used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]body.shape_owner_get_owner(body.shape_find_owner(body_shape_index))[/code]. - [param local_shape_index] the index of the [Shape3D] of this RigidDynamicBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. + [param local_shape_index] the index of the [Shape3D] of this RigidBody3D used by the [PhysicsServer3D]. Get the [CollisionShape3D] node with [code]self.shape_owner_get_owner(self.shape_find_owner(local_shape_index))[/code]. </description> </signal> <signal name="sleeping_state_changed"> diff --git a/doc/classes/Skeleton3D.xml b/doc/classes/Skeleton3D.xml index 75f7a37752..45ca330b87 100644 --- a/doc/classes/Skeleton3D.xml +++ b/doc/classes/Skeleton3D.xml @@ -231,7 +231,7 @@ <param index="0" name="exception" type="RID" /> <description> Adds a collision exception to the physical bone. - Works just like the [RigidDynamicBody3D] node. + Works just like the [RigidBody3D] node. </description> </method> <method name="physical_bones_remove_collision_exception"> @@ -239,7 +239,7 @@ <param index="0" name="exception" type="RID" /> <description> Removes a collision exception to the physical bone. - Works just like the [RigidDynamicBody3D] node. + Works just like the [RigidBody3D] node. </description> </method> <method name="physical_bones_start_simulation"> diff --git a/doc/classes/SoftDynamicBody3D.xml b/doc/classes/SoftBody3D.xml index 7f0a1d94d0..7006bca6f0 100644 --- a/doc/classes/SoftDynamicBody3D.xml +++ b/doc/classes/SoftBody3D.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="SoftDynamicBody3D" inherits="MeshInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="SoftBody3D" inherits="MeshInstance3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> A soft mesh physics body. </brief_description> <description> A deformable physics body. Used to create elastic or deformable objects such as cloth, rubber, or other flexible materials. - [b]Note:[/b] There are many known bugs in [SoftDynamicBody3D]. Therefore, it's not recommended to use them for things that can affect gameplay (such as a player character made entirely out of soft bodies). + [b]Note:[/b] There are many known bugs in [SoftBody3D]. Therefore, it's not recommended to use them for things that can affect gameplay (such as a player character made entirely out of soft bodies). </description> <tutorials> <link title="SoftBody">$DOCS_URL/tutorials/physics/soft_body.html</link> @@ -92,16 +92,16 @@ </methods> <members> <member name="collision_layer" type="int" setter="set_collision_layer" getter="get_collision_layer" default="1"> - The physics layers this SoftDynamicBody3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. + The physics layers this SoftBody3D [b]is in[/b]. Collision objects can exist in one or more of 32 different layers. See also [member collision_mask]. [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="collision_mask" type="int" setter="set_collision_mask" getter="get_collision_mask" default="1"> - The physics layers this SoftDynamicBody3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. + The physics layers this SoftBody3D [b]scans[/b]. Collision objects can scan one or more of 32 different layers. See also [member collision_layer]. [b]Note:[/b] Object A can detect a contact with object B only if object B is in any of the layers that object A scans. See [url=$DOCS_URL/tutorials/physics/physics_introduction.html#collision-layers-and-masks]Collision layers and masks[/url] in the documentation for more information. </member> <member name="damping_coefficient" type="float" setter="set_damping_coefficient" getter="get_damping_coefficient" default="0.01"> </member> - <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftDynamicBody3D.DisableMode" default="0"> + <member name="disable_mode" type="int" setter="set_disable_mode" getter="get_disable_mode" enum="SoftBody3D.DisableMode" default="0"> Defines the behavior in physics when [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED]. See [enum DisableMode] for more details about the different modes. </member> <member name="drag_coefficient" type="float" setter="set_drag_coefficient" getter="get_drag_coefficient" default="0.0"> @@ -109,23 +109,23 @@ <member name="linear_stiffness" type="float" setter="set_linear_stiffness" getter="get_linear_stiffness" default="0.5"> </member> <member name="parent_collision_ignore" type="NodePath" setter="set_parent_collision_ignore" getter="get_parent_collision_ignore" default="NodePath("")"> - [NodePath] to a [CollisionObject3D] this SoftDynamicBody3D should avoid clipping. + [NodePath] to a [CollisionObject3D] this SoftBody3D should avoid clipping. </member> <member name="pressure_coefficient" type="float" setter="set_pressure_coefficient" getter="get_pressure_coefficient" default="0.0"> </member> <member name="ray_pickable" type="bool" setter="set_ray_pickable" getter="is_ray_pickable" default="true"> - If [code]true[/code], the [SoftDynamicBody3D] will respond to [RayCast3D]s. + If [code]true[/code], the [SoftBody3D] will respond to [RayCast3D]s. </member> <member name="simulation_precision" type="int" setter="set_simulation_precision" getter="get_simulation_precision" default="5"> Increasing this value will improve the resulting simulation, but can affect performance. Use with care. </member> <member name="total_mass" type="float" setter="set_total_mass" getter="get_total_mass" default="1.0"> - The SoftDynamicBody3D's mass. + The SoftBody3D's mass. </member> </members> <constants> <constant name="DISABLE_MODE_REMOVE" value="0" enum="DisableMode"> - When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [SoftDynamicBody3D]. + When [member Node.process_mode] is set to [constant Node.PROCESS_MODE_DISABLED], remove from the physics simulation to stop all physics interactions with this [SoftBody3D]. Automatically re-added to the physics simulation when the [Node] is processed again. </constant> <constant name="DISABLE_MODE_KEEP_ACTIVE" value="1" enum="DisableMode"> diff --git a/doc/classes/StaticBody2D.xml b/doc/classes/StaticBody2D.xml index e6e3559ae0..21c160b780 100644 --- a/doc/classes/StaticBody2D.xml +++ b/doc/classes/StaticBody2D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Static body for 2D physics. - A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidDynamicBody2D], it doesn't consume any CPU resources as long as they don't move. + A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody2D], it doesn't consume any CPU resources as long as they don't move. They have extra functionalities to move and affect other bodies: [b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path. [b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels. diff --git a/doc/classes/StaticBody3D.xml b/doc/classes/StaticBody3D.xml index a29f5fc147..daa71d1168 100644 --- a/doc/classes/StaticBody3D.xml +++ b/doc/classes/StaticBody3D.xml @@ -5,7 +5,7 @@ </brief_description> <description> Static body for 3D physics. - A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidDynamicBody3D], it doesn't consume any CPU resources as long as they don't move. + A static body is a simple body that can't be moved by external forces or contacts. It is ideal for implementing objects in the environment, such as walls or platforms. In contrast to [RigidBody3D], it doesn't consume any CPU resources as long as they don't move. They have extra functionalities to move and affect other bodies: [b]Static transform change:[/b] Static bodies can be moved by animation or script. In this case, they are just teleported and don't affect other bodies on their path. [b]Constant velocity:[/b] When [member constant_linear_velocity] or [member constant_angular_velocity] is set, static bodies don't move themselves but affect touching bodies as if they were moving. This is useful for simulating conveyor belts or conveyor wheels. diff --git a/doc/classes/SystemFont.xml b/doc/classes/SystemFont.xml index b7454cc7d2..c235843f3b 100644 --- a/doc/classes/SystemFont.xml +++ b/doc/classes/SystemFont.xml @@ -13,8 +13,8 @@ <tutorials> </tutorials> <members> - <member name="antialiased" type="bool" setter="set_antialiased" getter="is_antialiased" default="true"> - If set to [code]true[/code], font 8-bit anitialiased glyph rendering is supported and enabled. + <member name="antialiasing" type="int" setter="set_antialiasing" getter="get_antialiasing" enum="TextServer.FontAntialiasing" default="1"> + Font anti-aliasing mode. </member> <member name="fallbacks" type="Font[]" setter="set_fallbacks" getter="get_fallbacks" default="[]"> Array of fallback [Font]s. diff --git a/doc/classes/TextMesh.xml b/doc/classes/TextMesh.xml index 17a0ca32e4..678b95cc72 100644 --- a/doc/classes/TextMesh.xml +++ b/doc/classes/TextMesh.xml @@ -11,6 +11,9 @@ <tutorials> </tutorials> <members> + <member name="autowrap_mode" type="int" setter="set_autowrap_mode" getter="get_autowrap_mode" enum="TextServer.AutowrapMode" default="0"> + If set to something other than [constant TextServer.AUTOWRAP_OFF], the text gets wrapped inside the node's bounding rectangle. If you resize the node, it will change its height automatically to show all the text. To see how each mode behaves, see [enum TextServer.AutowrapMode]. + </member> <member name="curve_step" type="float" setter="set_curve_step" getter="get_curve_step" default="0.5"> Step (in pixels) used to approximate Bézier curves. </member> @@ -29,6 +32,12 @@ <member name="language" type="String" setter="set_language" getter="get_language" default=""""> Language code used for text shaping algorithms, if left empty current locale is used instead. </member> + <member name="line_spacing" type="float" setter="set_line_spacing" getter="get_line_spacing" default="0.0"> + Vertical space between lines in multiline [TextMesh]. + </member> + <member name="offset" type="Vector2" setter="set_offset" getter="get_offset" default="Vector2(0, 0)"> + The text drawing offset (in pixels). + </member> <member name="pixel_size" type="float" setter="set_pixel_size" getter="get_pixel_size" default="0.01"> The size of one pixel's width on the text to scale it in 3D. </member> @@ -47,6 +56,9 @@ <member name="uppercase" type="bool" setter="set_uppercase" getter="is_uppercase" default="false"> If [code]true[/code], all the text displays as UPPERCASE. </member> + <member name="vertical_alignment" type="int" setter="set_vertical_alignment" getter="get_vertical_alignment" enum="VerticalAlignment" default="1"> + Controls the text's vertical alignment. Supports top, center, bottom. Set it to one of the [enum VerticalAlignment] constants. + </member> <member name="width" type="float" setter="set_width" getter="get_width" default="500.0"> Text width (in pixels), used for fill alignment. </member> diff --git a/doc/classes/TextServer.xml b/doc/classes/TextServer.xml index 9c4f7857c7..aad83211f5 100644 --- a/doc/classes/TextServer.xml +++ b/doc/classes/TextServer.xml @@ -98,6 +98,13 @@ [b]Note:[/b] If there are pending glyphs to render, calling this function might trigger the texture cache update. </description> </method> + <method name="font_get_antialiasing" qualifiers="const"> + <return type="int" enum="TextServer.FontAntialiasing" /> + <param index="0" name="font_rid" type="RID" /> + <description> + Returns font anti-aliasing mode. + </description> + </method> <method name="font_get_ascent" qualifiers="const"> <return type="float" /> <param index="0" name="font_rid" type="RID" /> @@ -447,13 +454,6 @@ Returns [code]true[/code] if a Unicode [param char] is available in the font. </description> </method> - <method name="font_is_antialiased" qualifiers="const"> - <return type="bool" /> - <param index="0" name="font_rid" type="RID" /> - <description> - Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled. - </description> - </method> <method name="font_is_force_autohinter" qualifiers="const"> <return type="bool" /> <param index="0" name="font_rid" type="RID" /> @@ -556,12 +556,12 @@ Renders the range of characters to the font cache texture. </description> </method> - <method name="font_set_antialiased"> + <method name="font_set_antialiasing"> <return type="void" /> <param index="0" name="font_rid" type="RID" /> - <param index="1" name="antialiased" type="bool" /> + <param index="1" name="antialiasing" type="int" enum="TextServer.FontAntialiasing" /> <description> - If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only. + Sets font anti-aliasing mode. </description> </method> <method name="font_set_ascent"> @@ -1539,6 +1539,32 @@ </method> </methods> <constants> + <constant name="FONT_ANTIALIASING_NONE" value="0" enum="FontAntialiasing"> + Font glyphs are rasterized as 1-bit bitmaps. + </constant> + <constant name="FONT_ANTIALIASING_GRAY" value="1" enum="FontAntialiasing"> + Font glyphs are rasterized as 8-bit grayscale anti-aliased bitmaps. + </constant> + <constant name="FONT_ANTIALIASING_LCD" value="2" enum="FontAntialiasing"> + Font glyphs are rasterized for LCD screens. + LCD sub-pixel layout is determined by the value of [code]gui/theme/lcd_subpixel_layout[/code] project settings. + LCD sub-pixel anti-aliasing mode is suitable only for rendering horizontal, unscaled text in 2D. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_NONE" value="0" enum="FontLCDSubpixelLayout"> + Unknown or unsupported sub-pixel layout, LCD sub-pixel anti-aliasing is disabled. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_HRGB" value="1" enum="FontLCDSubpixelLayout"> + Horizontal RGB sub-pixel layout. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_HBGR" value="2" enum="FontLCDSubpixelLayout"> + Horizontal BGR sub-pixel layout. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_VRGB" value="3" enum="FontLCDSubpixelLayout"> + Vertical RGB sub-pixel layout. + </constant> + <constant name="FONT_LCD_SUBPIXEL_LAYOUT_VBGR" value="4" enum="FontLCDSubpixelLayout"> + Vertical BGR sub-pixel layout. + </constant> <constant name="DIRECTION_AUTO" value="0" enum="Direction"> Text direction is determined based on contents and current locale. </constant> @@ -1606,13 +1632,13 @@ Displays glyphs that are mapped to the first [member Label.visible_characters] or [member RichTextLabel.visible_characters] characters from the beginning of the text. </constant> <constant name="VC_GLYPHS_AUTO" value="2" enum="VisibleCharactersBehavior"> - Displays [member Label.percent_visible] or [member RichTextLabel.percent_visible] glyphs, starting from the left or from the right, depending on [member Control.layout_direction] value. + Displays [member Label.visible_ratio] or [member RichTextLabel.visible_ratio] glyphs, starting from the left or from the right, depending on [member Control.layout_direction] value. </constant> <constant name="VC_GLYPHS_LTR" value="3" enum="VisibleCharactersBehavior"> - Displays [member Label.percent_visible] or [member RichTextLabel.percent_visible] glyphs, starting from the left. + Displays [member Label.visible_ratio] or [member RichTextLabel.visible_ratio] glyphs, starting from the left. </constant> <constant name="VC_GLYPHS_RTL" value="4" enum="VisibleCharactersBehavior"> - Displays [member Label.percent_visible] or [member RichTextLabel.percent_visible] glyphs, starting from the right. + Displays [member Label.visible_ratio] or [member RichTextLabel.visible_ratio] glyphs, starting from the right. </constant> <constant name="OVERRUN_NO_TRIMMING" value="0" enum="OverrunBehavior"> No text trimming is performed. diff --git a/doc/classes/TextServerExtension.xml b/doc/classes/TextServerExtension.xml index 9eb7188846..23eb25dc10 100644 --- a/doc/classes/TextServerExtension.xml +++ b/doc/classes/TextServerExtension.xml @@ -91,6 +91,13 @@ Draws single glyph outline of size [param outline_size] into a canvas item at the position, using [param font_rid] at the size [param size]. </description> </method> + <method name="font_get_antialiasing" qualifiers="virtual const"> + <return type="int" enum="TextServer.FontAntialiasing" /> + <param index="0" name="font_rid" type="RID" /> + <description> + Returns font anti-aliasing mode. + </description> + </method> <method name="font_get_ascent" qualifiers="virtual const"> <return type="float" /> <param index="0" name="font_rid" type="RID" /> @@ -437,13 +444,6 @@ Returns [code]true[/code] if a Unicode [param char] is available in the font. </description> </method> - <method name="font_is_antialiased" qualifiers="virtual const"> - <return type="bool" /> - <param index="0" name="font_rid" type="RID" /> - <description> - Returns [code]true[/code] if font 8-bit anitialiased glyph rendering is supported and enabled. - </description> - </method> <method name="font_is_force_autohinter" qualifiers="virtual const"> <return type="bool" /> <param index="0" name="font_rid" type="RID" /> @@ -544,12 +544,12 @@ Renders the range of characters to the font cache texture. </description> </method> - <method name="font_set_antialiased" qualifiers="virtual"> + <method name="font_set_antialiasing" qualifiers="virtual"> <return type="void" /> <param index="0" name="font_rid" type="RID" /> - <param index="1" name="antialiased" type="bool" /> + <param index="1" name="antialiasing" type="int" enum="TextServer.FontAntialiasing" /> <description> - If set to [code]true[/code], 8-bit antialiased glyph rendering is used, otherwise 1-bit rendering is used. Used by dynamic fonts only. + Sets font anti-aliasing mode. </description> </method> <method name="font_set_ascent" qualifiers="virtual"> diff --git a/doc/classes/TileMap.xml b/doc/classes/TileMap.xml index 5530759628..e76c696021 100644 --- a/doc/classes/TileMap.xml +++ b/doc/classes/TileMap.xml @@ -41,7 +41,7 @@ <return type="void" /> <param index="0" name="to_position" type="int" /> <description> - Adds a layer at the given position [param to_position] in the array. If [param to_position] is -1, adds it at the end of the array. + Adds a layer at the given position [param to_position] in the array. If [param to_position] is negative, the position is counted from the end, with [code]-1[/code] adding the layer at the end of the array. </description> </method> <method name="clear"> @@ -285,14 +285,16 @@ <param index="1" name="enabled" type="bool" /> <description> Enables or disables the layer [param layer]. A disabled layer is not processed at all (no rendering, no physics, etc...). + If [param layer] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_modulate"> <return type="void" /> <param index="0" name="layer" type="int" /> - <param index="1" name="enabled" type="Color" /> + <param index="1" name="modulate" type="Color" /> <description> Sets a layer's color. It will be multiplied by tile's color and TileMap's modulate. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_name"> @@ -301,6 +303,7 @@ <param index="1" name="name" type="String" /> <description> Sets a layer's name. This is mostly useful in the editor. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_y_sort_enabled"> @@ -310,6 +313,7 @@ <description> Enables or disables a layer's Y-sorting. If a layer is Y-sorted, the layer will behave as a CanvasItem node where each of its tile gets Y-sorted. Y-sorted layers should usually be on different Z-index values than not Y-sorted layers, otherwise, each of those layer will be Y-sorted as whole with the Y-sorted one. This is usually an undesired behvaior. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_y_sort_origin"> @@ -319,6 +323,7 @@ <description> Sets a layer's Y-sort origin value. This Y-sort origin value is added to each tile's Y-sort origin value. This allows, for example, to fake a different height level on each layer. This can be useful for top-down view games. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_layer_z_index"> @@ -327,6 +332,7 @@ <param index="1" name="z_index" type="int" /> <description> Sets a layers Z-index value. This Z-index is added to each tile's Z-index value. + If [code]layer[/code] is negative, the layers are accessed from the last one. </description> </method> <method name="set_pattern"> diff --git a/doc/classes/Vector2.xml b/doc/classes/Vector2.xml index 19fe2e2bfc..2197947126 100644 --- a/doc/classes/Vector2.xml +++ b/doc/classes/Vector2.xml @@ -304,7 +304,7 @@ <return type="Vector2" /> <param index="0" name="angle" type="float" /> <description> - Returns the vector rotated by [param angle] (in radians). See also [method @GlobalScope.deg2rad]. + Returns the vector rotated by [param angle] (in radians). See also [method @GlobalScope.deg_to_rad]. </description> </method> <method name="round" qualifiers="const"> diff --git a/doc/classes/VehicleBody3D.xml b/doc/classes/VehicleBody3D.xml index 08309a8ecc..e1689133de 100644 --- a/doc/classes/VehicleBody3D.xml +++ b/doc/classes/VehicleBody3D.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="VehicleBody3D" inherits="RigidDynamicBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> +<class name="VehicleBody3D" inherits="RigidBody3D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> <brief_description> Physics body that simulates the behavior of a car. </brief_description> @@ -13,14 +13,14 @@ </tutorials> <members> <member name="brake" type="float" setter="set_brake" getter="get_brake" default="0.0"> - Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidDynamicBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. + Slows down the vehicle by applying a braking force. The vehicle is only slowed down if the wheels are in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0"> - Accelerates the vehicle by applying an engine force. The vehicle is only sped up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. + Accelerates the vehicle by applying an engine force. The vehicle is only sped up if the wheels that have [member VehicleWheel3D.use_as_traction] set to [code]true[/code] and are in contact with a surface. The [member RigidBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. [b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. A negative value will result in the vehicle reversing. </member> - <member name="mass" type="float" setter="set_mass" getter="get_mass" overrides="RigidDynamicBody3D" default="40.0" /> + <member name="mass" type="float" setter="set_mass" getter="get_mass" overrides="RigidBody3D" default="40.0" /> <member name="steering" type="float" setter="set_steering" getter="get_steering" default="0.0"> The steering angle for the vehicle, in radians. Setting this to a non-zero value will result in the vehicle turning when it's moving. Wheels that have [member VehicleWheel3D.use_as_steering] set to [code]true[/code] will automatically be rotated. </member> diff --git a/doc/classes/VehicleWheel3D.xml b/doc/classes/VehicleWheel3D.xml index ac126f824e..827c7e8f57 100644 --- a/doc/classes/VehicleWheel3D.xml +++ b/doc/classes/VehicleWheel3D.xml @@ -39,7 +39,7 @@ </methods> <members> <member name="brake" type="float" setter="set_brake" getter="get_brake" default="0.0"> - Slows down the wheel by applying a braking force. The wheel is only slowed down if it is in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidDynamicBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. + Slows down the wheel by applying a braking force. The wheel is only slowed down if it is in contact with a surface. The force you need to apply to adequately slow down your vehicle depends on the [member RigidBody3D.mass] of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 30 range for hard braking. </member> <member name="damping_compression" type="float" setter="set_damping_compression" getter="get_damping_compression" default="0.83"> The damping applied to the spring when the spring is being compressed. This value should be between 0.0 (no damping) and 1.0. A value of 0.0 means the car will keep bouncing as the spring keeps its energy. A good value for this is around 0.3 for a normal car, 0.5 for a race car. @@ -48,7 +48,7 @@ The damping applied to the spring when relaxing. This value should be between 0.0 (no damping) and 1.0. This value should always be slightly higher than the [member damping_compression] property. For a [member damping_compression] value of 0.3, try a relaxation value of 0.5. </member> <member name="engine_force" type="float" setter="set_engine_force" getter="get_engine_force" default="0.0"> - Accelerates the wheel by applying an engine force. The wheel is only sped up if it is in contact with a surface. The [member RigidDynamicBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. + Accelerates the wheel by applying an engine force. The wheel is only sped up if it is in contact with a surface. The [member RigidBody3D.mass] of the vehicle has an effect on the acceleration of the vehicle. For a vehicle with a mass set to 1000, try a value in the 25 - 50 range for acceleration. [b]Note:[/b] The simulation does not take the effect of gears into account, you will need to add logic for this if you wish to simulate gears. A negative value will result in the wheel reversing. </member> @@ -56,7 +56,7 @@ The steering angle for the wheel, in radians. Setting this to a non-zero value will result in the vehicle turning when it's moving. </member> <member name="suspension_max_force" type="float" setter="set_suspension_max_force" getter="get_suspension_max_force" default="6000.0"> - The maximum force the spring can resist. This value should be higher than a quarter of the [member RigidDynamicBody3D.mass] of the [VehicleBody3D] or the spring will not carry the weight of the vehicle. Good results are often obtained by a value that is about 3× to 4× this number. + The maximum force the spring can resist. This value should be higher than a quarter of the [member RigidBody3D.mass] of the [VehicleBody3D] or the spring will not carry the weight of the vehicle. Good results are often obtained by a value that is about 3× to 4× this number. </member> <member name="suspension_stiffness" type="float" setter="set_suspension_stiffness" getter="get_suspension_stiffness" default="5.88"> This value defines the stiffness of the suspension. Use a value lower than 50 for an off-road car, a value between 50 and 100 for a race car and try something around 200 for something like a Formula 1 car. diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 93e7e20f5a..0071834ccd 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -266,7 +266,8 @@ <member name="snap_2d_vertices_to_pixel" type="bool" setter="set_snap_2d_vertices_to_pixel" getter="is_snap_2d_vertices_to_pixel_enabled" default="false"> </member> <member name="texture_mipmap_bias" type="float" setter="set_texture_mipmap_bias" getter="get_texture_mipmap_bias" default="0.0"> - Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). To get sharper textures at a distance without introducing too much graininess, set this between [code]-0.75[/code] and [code]0.0[/code]. Enabling temporal antialiasing ([member ProjectSettings.rendering/anti_aliasing/quality/use_taa]) can help reduce the graininess visible when using negative mipmap bias. + Affects the final texture sharpness by reading from a lower or higher mipmap (also called "texture LOD bias"). Negative values make mipmapped textures sharper but grainier when viewed at a distance, while positive values make mipmapped textures blurrier (even when up close). + Enabling temporal antialiasing ([member use_taa]) will automatically apply a [code]-0.5[/code] offset to this value, while enabling FXAA ([member screen_space_aa]) will automatically apply a [code]-0.25[/code] offset to this value. If both TAA and FXAA are enbled at the same time, an offset of [code]-0.75[/code] is applied to this value. [b]Note:[/b] If [member scaling_3d_scale] is lower than [code]1.0[/code] (exclusive), [member texture_mipmap_bias] is used to adjust the automatic mipmap bias which is calculated internally based on the scale factor. The formula for this is [code]log2(scaling_3d_scale) + mipmap_bias[/code]. To control this property on the root viewport, set the [member ProjectSettings.rendering/textures/default_filters/texture_mipmap_bias] project setting. </member> diff --git a/doc/classes/VisibleOnScreenEnabler3D.xml b/doc/classes/VisibleOnScreenEnabler3D.xml index 5e03870005..a3f925ed3a 100644 --- a/doc/classes/VisibleOnScreenEnabler3D.xml +++ b/doc/classes/VisibleOnScreenEnabler3D.xml @@ -4,7 +4,7 @@ Enables certain nodes only when approximately visible. </brief_description> <description> - The VisibleOnScreenEnabler3D will disable [RigidDynamicBody3D] and [AnimationPlayer] nodes when they are not visible. It will only affect other nodes within the same scene as the VisibleOnScreenEnabler3D itself. + The VisibleOnScreenEnabler3D will disable [RigidBody3D] and [AnimationPlayer] nodes when they are not visible. It will only affect other nodes within the same scene as the VisibleOnScreenEnabler3D itself. If you just want to receive notifications, use [VisibleOnScreenNotifier3D] instead. [b]Note:[/b] VisibleOnScreenEnabler3D uses an approximate heuristic for performance reasons. It doesn't take walls and other occlusion into account. The heuristic is an implementation detail and may change in future versions. If you need precise visibility checking, use another method such as adding an [Area3D] node as a child of a [Camera3D] node and/or [method Vector3.dot]. [b]Note:[/b] VisibleOnScreenEnabler3D will not affect nodes added after scene initialization. diff --git a/doc/classes/VisualShaderNodeDistanceFade.xml b/doc/classes/VisualShaderNodeDistanceFade.xml new file mode 100644 index 0000000000..8ea0857776 --- /dev/null +++ b/doc/classes/VisualShaderNodeDistanceFade.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeDistanceFade" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/VisualShaderNodeLinearSceneDepth.xml b/doc/classes/VisualShaderNodeLinearSceneDepth.xml new file mode 100644 index 0000000000..fa8c01ac0a --- /dev/null +++ b/doc/classes/VisualShaderNodeLinearSceneDepth.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeLinearSceneDepth" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/VisualShaderNodeProximityFade.xml b/doc/classes/VisualShaderNodeProximityFade.xml new file mode 100644 index 0000000000..25051eed71 --- /dev/null +++ b/doc/classes/VisualShaderNodeProximityFade.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeProximityFade" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/VisualShaderNodeRandomRange.xml b/doc/classes/VisualShaderNodeRandomRange.xml new file mode 100644 index 0000000000..adc83d808c --- /dev/null +++ b/doc/classes/VisualShaderNodeRandomRange.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeRandomRange" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/VisualShaderNodeRemap.xml b/doc/classes/VisualShaderNodeRemap.xml new file mode 100644 index 0000000000..5a73a76e7f --- /dev/null +++ b/doc/classes/VisualShaderNodeRemap.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeRemap" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/VisualShaderNodeUVPolarCoord.xml b/doc/classes/VisualShaderNodeUVPolarCoord.xml new file mode 100644 index 0000000000..8582939db3 --- /dev/null +++ b/doc/classes/VisualShaderNodeUVPolarCoord.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<class name="VisualShaderNodeUVPolarCoord" inherits="VisualShaderNode" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../class.xsd"> + <brief_description> + </brief_description> + <description> + </description> + <tutorials> + </tutorials> +</class> diff --git a/doc/classes/Window.xml b/doc/classes/Window.xml index ce7ad1e64e..2c0a694ef9 100644 --- a/doc/classes/Window.xml +++ b/doc/classes/Window.xml @@ -342,6 +342,9 @@ If [code]true[/code], the [Window] will be in exclusive mode. Exclusive windows are always on top of their parent and will block all input going to the parent [Window]. Needs [member transient] enabled to work. </member> + <member name="extend_to_title" type="bool" setter="set_flag" getter="get_flag" default="false"> + If [code]true[/code], the [Window] contents is expanded to the full size of the window, window title bar is transparent. + </member> <member name="max_size" type="Vector2i" setter="set_max_size" getter="get_max_size" default="Vector2i(0, 0)"> If non-zero, the [Window] can't be resized to be bigger than this size. [b]Note:[/b] This property will be ignored if the value is lower than [member min_size]. @@ -448,7 +451,7 @@ </signal> <signal name="theme_changed"> <description> - Emitted when the [member theme] is modified or changed to another [Theme]. + Emitted when the [constant NOTIFICATION_THEME_CHANGED] notification is sent. </description> </signal> <signal name="visibility_changed"> @@ -467,6 +470,13 @@ <constant name="NOTIFICATION_VISIBILITY_CHANGED" value="30"> Emitted when [Window]'s visibility changes, right before [signal visibility_changed]. </constant> + <constant name="NOTIFICATION_THEME_CHANGED" value="32"> + Sent when the node needs to refresh its theme items. This happens in one of the following cases: + - The [member theme] property is changed on this node or any of its ancestors. + - The [member theme_type_variation] property is changed on this node. + - The node enters the scene tree. + [b]Note:[/b] As an optimization, this notification won't be sent from changes that occur while this node is outside of the scene tree. Instead, all of the theme item updates can be applied at once when the node enters the scene tree. + </constant> <constant name="MODE_WINDOWED" value="0" enum="Mode"> Windowed mode, i.e. [Window] doesn't occupy whole screen (unless set to the size of the screen). </constant> @@ -503,7 +513,10 @@ <constant name="FLAG_POPUP" value="5" enum="Flags"> Whether the window is popup or a regular window. Set with [member popup_window]. </constant> - <constant name="FLAG_MAX" value="6" enum="Flags"> + <constant name="FLAG_EXTEND_TO_TITLE" value="6" enum="Flags"> + Window contents is expanded to the full size of the window, window title bar is transparent. + </constant> + <constant name="FLAG_MAX" value="7" enum="Flags"> Max value of the [enum Flags]. </constant> <constant name="CONTENT_SCALE_MODE_DISABLED" value="0" enum="ContentScaleMode"> diff --git a/doc/tools/make_rst.py b/doc/tools/make_rst.py index 519554e026..bc50e39812 100755 --- a/doc/tools/make_rst.py +++ b/doc/tools/make_rst.py @@ -878,7 +878,7 @@ def make_rst_class(class_def: ClassDef, state: State, dry_run: bool, output_dir: f.write("----\n\n") if i == 0: - f.write(".. _class_{}_annotation_{}:\n\n".format(class_name, m.name.strip("@"))) + f.write(".. _class_{}_annotation_{}:\n\n".format(class_name, m.name)) _, signature = make_method_signature(class_def, m, "", state) f.write("- {}\n\n".format(signature)) @@ -1337,8 +1337,10 @@ def format_text_block( # Cross-references to items in this or other class documentation pages. elif is_in_tagset(cmd, RESERVED_CROSSLINK_TAGS): + link_type: str = "" link_target: str = "" if space_pos >= 0: + link_type = tag_text[:space_pos] link_target = tag_text[space_pos + 1 :].strip() if link_target == "": @@ -1350,11 +1352,13 @@ def format_text_block( else: if ( cmd.startswith("method") + or cmd.startswith("constructor") + or cmd.startswith("operator") or cmd.startswith("member") or cmd.startswith("signal") - or cmd.startswith("constant") or cmd.startswith("annotation") or cmd.startswith("theme_item") + or cmd.startswith("constant") ): if link_target.find(".") != -1: ss = link_target.split(".") @@ -1371,48 +1375,62 @@ def format_text_block( class_param = state.current_class method_param = link_target - ref_type = "" + # Default to the tag command name. This works by default for most tags, + # but member and theme_item have special cases. + ref_type = "_{}".format(link_type) + if link_type == "member": + ref_type = "_property" + if class_param in state.classes: class_def = state.classes[class_param] - if cmd.startswith("constructor"): - if method_param not in class_def.constructors: - print_error( - '{}.xml: Unresolved constructor reference "{}" in {}.'.format( - state.current_class, link_target, context_name - ), - state, - ) - ref_type = "_constructor" - elif cmd.startswith("method"): - if method_param not in class_def.methods: - print_error( - '{}.xml: Unresolved method reference "{}" in {}.'.format( - state.current_class, link_target, context_name - ), - state, - ) - ref_type = "_method" + if cmd.startswith("method") and method_param not in class_def.methods: + print_error( + '{}.xml: Unresolved method reference "{}" in {}.'.format( + state.current_class, link_target, context_name + ), + state, + ) - elif cmd.startswith("operator"): - if method_param not in class_def.operators: - print_error( - '{}.xml: Unresolved operator reference "{}" in {}.'.format( - state.current_class, link_target, context_name - ), - state, - ) - ref_type = "_operator" + elif cmd.startswith("constructor") and method_param not in class_def.constructors: + print_error( + '{}.xml: Unresolved constructor reference "{}" in {}.'.format( + state.current_class, link_target, context_name + ), + state, + ) - elif cmd.startswith("member"): - if method_param not in class_def.properties: - print_error( - '{}.xml: Unresolved member reference "{}" in {}.'.format( - state.current_class, link_target, context_name - ), - state, - ) - ref_type = "_property" + elif cmd.startswith("operator") and method_param not in class_def.operators: + print_error( + '{}.xml: Unresolved operator reference "{}" in {}.'.format( + state.current_class, link_target, context_name + ), + state, + ) + + elif cmd.startswith("member") and method_param not in class_def.properties: + print_error( + '{}.xml: Unresolved member reference "{}" in {}.'.format( + state.current_class, link_target, context_name + ), + state, + ) + + elif cmd.startswith("signal") and method_param not in class_def.signals: + print_error( + '{}.xml: Unresolved signal reference "{}" in {}.'.format( + state.current_class, link_target, context_name + ), + state, + ) + + elif cmd.startswith("annotation") and method_param not in class_def.annotations: + print_error( + '{}.xml: Unresolved annotation reference "{}" in {}.'.format( + state.current_class, link_target, context_name + ), + state, + ) elif cmd.startswith("theme_item"): if method_param not in class_def.theme_items: @@ -1422,27 +1440,9 @@ def format_text_block( ), state, ) - ref_type = "_theme_{}".format(class_def.theme_items[method_param].data_name) - - elif cmd.startswith("signal"): - if method_param not in class_def.signals: - print_error( - '{}.xml: Unresolved signal reference "{}" in {}.'.format( - state.current_class, link_target, context_name - ), - state, - ) - ref_type = "_signal" - - elif cmd.startswith("annotation"): - if method_param not in class_def.annotations: - print_error( - '{}.xml: Unresolved annotation reference "{}" in {}.'.format( - state.current_class, link_target, context_name - ), - state, - ) - ref_type = "_annotation" + else: + # Needs theme data type to be properly linked, which we cannot get without a class. + ref_type = "_theme_{}".format(class_def.theme_items[method_param].data_name) elif cmd.startswith("constant"): found = False @@ -1473,7 +1473,6 @@ def format_text_block( ), state, ) - ref_type = "_constant" else: print_error( diff --git a/drivers/gles3/rasterizer_canvas_gles3.cpp b/drivers/gles3/rasterizer_canvas_gles3.cpp index 28802f571c..b397d0c665 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.cpp +++ b/drivers/gles3/rasterizer_canvas_gles3.cpp @@ -322,6 +322,7 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou RID prev_material; uint32_t index = 0; GLES3::CanvasShaderData::BlendMode last_blend_mode = GLES3::CanvasShaderData::BLEND_MODE_MIX; + Color last_blend_color; GLES3::CanvasShaderData *shader_data_cache = nullptr; state.current_tex = texture_storage->texture_gl_get_default(GLES3::DEFAULT_GL_TEXTURE_WHITE); @@ -378,8 +379,80 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou GLES3::CanvasShaderData::BlendMode blend_mode = shader_data_cache ? shader_data_cache->blend_mode : GLES3::CanvasShaderData::BLEND_MODE_MIX; - if (last_blend_mode != blend_mode) { - if (last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { + _render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index, blend_mode, last_blend_mode, last_blend_color); + } + // Render last command + _render_batch(index); +} + +void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color) { + // Used by Polygon and Mesh. + static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP }; + + RS::CanvasItemTextureFilter current_filter = state.default_filter; + RS::CanvasItemTextureRepeat current_repeat = state.default_repeat; + + if (p_item->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { + current_filter = p_item->texture_filter; + } + + if (p_item->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { + current_repeat = p_item->texture_repeat; + } + + Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; + Transform2D draw_transform; // Used by transform command + + Color base_color = p_item->final_modulate; + + uint32_t base_flags = 0; + + bool reclip = false; + + bool skipping = false; + + const Item::Command *c = p_item->commands; + while (c) { + if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { + c = c->next; + continue; + } + + if (c->type != Item::Command::TYPE_MESH) { + // For Meshes, this gets updated below. + _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world); + } + + for (int i = 0; i < 4; i++) { + state.instance_data_array[r_index].modulation[i] = 0.0; + state.instance_data_array[r_index].ninepatch_margins[i] = 0.0; + state.instance_data_array[r_index].src_rect[i] = 0.0; + state.instance_data_array[r_index].dst_rect[i] = 0.0; + state.instance_data_array[r_index].lights[i] = uint32_t(0); + } + state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0; + state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0; + + state.instance_data_array[r_index].pad[0] = 0.0; + state.instance_data_array[r_index].pad[1] = 0.0; + + state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config + + GLES3::CanvasShaderData::BlendMode blend_mode = p_blend_mode; + Color blend_color; + + if (c->type == Item::Command::TYPE_RECT) { + const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c); + if (rect->flags & CANVAS_RECT_LCD) { + blend_mode = GLES3::CanvasShaderData::BLEND_MODE_LCD; + blend_color = rect->modulate; + } + } + + if (r_last_blend_mode != blend_mode || r_last_blend_color != blend_color) { + _render_batch(r_index); + + if (r_last_blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { // re-enable it glEnable(GL_BLEND); } else if (blend_mode == GLES3::CanvasShaderData::BLEND_MODE_DISABLED) { @@ -392,6 +465,16 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou // Nothing to do here. } break; + case GLES3::CanvasShaderData::BLEND_MODE_LCD: { + glBlendEquation(GL_FUNC_ADD); + if (state.transparent_render_target) { + glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + } else { + glBlendFuncSeparate(GL_CONSTANT_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_ZERO, GL_ONE); + } + glBlendColor(blend_color.r, blend_color.g, blend_color.b, blend_color.a); + + } break; case GLES3::CanvasShaderData::BLEND_MODE_MIX: { glBlendEquation(GL_FUNC_ADD); if (state.transparent_render_target) { @@ -437,68 +520,10 @@ void RasterizerCanvasGLES3::_render_items(RID p_to_render_target, int p_item_cou } break; } - last_blend_mode = blend_mode; - } - - _render_item(p_to_render_target, ci, canvas_transform_inverse, current_clip, p_lights, index); - } - // Render last command - _render_batch(index); -} - -void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index) { - // Used by Polygon and Mesh. - static const GLenum prim[5] = { GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP }; - - RS::CanvasItemTextureFilter current_filter = state.default_filter; - RS::CanvasItemTextureRepeat current_repeat = state.default_repeat; - - if (p_item->texture_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { - current_filter = p_item->texture_filter; - } - - if (p_item->texture_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { - current_repeat = p_item->texture_repeat; - } - - Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; - Transform2D draw_transform; // Used by transform command - - Color base_color = p_item->final_modulate; - - uint32_t base_flags = 0; - - bool reclip = false; - - bool skipping = false; - - const Item::Command *c = p_item->commands; - while (c) { - if (skipping && c->type != Item::Command::TYPE_ANIMATION_SLICE) { - c = c->next; - continue; - } - - if (c->type != Item::Command::TYPE_MESH) { - // For Meshes, this gets updated below. - _update_transform_2d_to_mat2x3(base_transform * draw_transform, state.instance_data_array[r_index].world); + r_last_blend_mode = blend_mode; + r_last_blend_color = blend_color; } - for (int i = 0; i < 4; i++) { - state.instance_data_array[r_index].modulation[i] = 0.0; - state.instance_data_array[r_index].ninepatch_margins[i] = 0.0; - state.instance_data_array[r_index].src_rect[i] = 0.0; - state.instance_data_array[r_index].dst_rect[i] = 0.0; - state.instance_data_array[r_index].lights[i] = uint32_t(0); - } - state.instance_data_array[r_index].color_texture_pixel_size[0] = 0.0; - state.instance_data_array[r_index].color_texture_pixel_size[1] = 0.0; - - state.instance_data_array[r_index].pad[0] = 0.0; - state.instance_data_array[r_index].pad[1] = 0.0; - - state.instance_data_array[r_index].flags = base_flags | (state.instance_data_array[r_index == 0 ? 0 : r_index - 1].flags & (FLAGS_DEFAULT_NORMAL_MAP_USED | FLAGS_DEFAULT_SPECULAR_MAP_USED)); //reset on each command for sanity, keep canvastexture binding config - switch (c->type) { case Item::Command::TYPE_RECT: { const Item::CommandRect *rect = static_cast<const Item::CommandRect *>(c); @@ -569,6 +594,8 @@ void RasterizerCanvasGLES3::_render_item(RID p_render_target, const Item *p_item state.instance_data_array[r_index].msdf[1] = rect->outline; // Outline size. state.instance_data_array[r_index].msdf[2] = 0.f; // Reserved. state.instance_data_array[r_index].msdf[3] = 0.f; // Reserved. + } else if (rect->flags & CANVAS_RECT_LCD) { + state.instance_data_array[r_index].flags |= FLAGS_USE_LCD; } state.instance_data_array[r_index].modulation[0] = rect->modulate.r * base_color.r; diff --git a/drivers/gles3/rasterizer_canvas_gles3.h b/drivers/gles3/rasterizer_canvas_gles3.h index f920e37130..372ac00493 100644 --- a/drivers/gles3/rasterizer_canvas_gles3.h +++ b/drivers/gles3/rasterizer_canvas_gles3.h @@ -73,6 +73,7 @@ class RasterizerCanvasGLES3 : public RendererCanvasRender { FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_USE_MSDF = (1 << 28), + FLAGS_USE_LCD = (1 << 29), }; enum { @@ -249,7 +250,7 @@ public: void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, Light *p_directional_list, const Transform2D &p_canvas_transform, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, bool &r_sdf_used) override; void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, bool p_to_backbuffer = false); - void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index); + void _render_item(RID p_render_target, const Item *p_item, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, uint32_t &r_index, GLES3::CanvasShaderData::BlendMode p_blend_mode, GLES3::CanvasShaderData::BlendMode &r_last_blend_mode, Color &r_last_blend_color); void _render_batch(uint32_t &p_max_index); void _bind_instance_data_buffer(uint32_t p_max_index); void _allocate_instance_data_buffer(); diff --git a/drivers/gles3/rasterizer_scene_gles3.cpp b/drivers/gles3/rasterizer_scene_gles3.cpp index 9bbe960d86..cb479dda39 100644 --- a/drivers/gles3/rasterizer_scene_gles3.cpp +++ b/drivers/gles3/rasterizer_scene_gles3.cpp @@ -648,7 +648,7 @@ void RasterizerSceneGLES3::_setup_sky(RID p_env, RID p_render_buffers, const Pag float angular_diameter = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); if (angular_diameter > 0.0) { - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); } else { angular_diameter = 0.0; } @@ -1518,7 +1518,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b light_data.color[2] = linear_col.b; float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset + light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset light_data.specular = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR); @@ -1645,7 +1645,7 @@ void RasterizerSceneGLES3::_setup_lights(const RenderDataGLES3 *p_render_data, b light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION); float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE); - light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle)); + light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle)); light_data.specular_amount = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 2.0; diff --git a/drivers/gles3/shaders/canvas.glsl b/drivers/gles3/shaders/canvas.glsl index 4df818cd4c..5ec25327be 100644 --- a/drivers/gles3/shaders/canvas.glsl +++ b/drivers/gles3/shaders/canvas.glsl @@ -473,7 +473,13 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - + } else if (bool(draw_data[draw_data_instance].flags & FLAGS_USE_LCD)) { + vec4 lcd_sample = texture(color_texture, uv); + if (lcd_sample.a == 1.0) { + color.rgb = lcd_sample.rgb * color.a; + } else { + color = vec4(0.0, 0.0, 0.0, 0.0); + } } else { #else { diff --git a/drivers/gles3/shaders/canvas_uniforms_inc.glsl b/drivers/gles3/shaders/canvas_uniforms_inc.glsl index 852dccf415..6b61fe9375 100644 --- a/drivers/gles3/shaders/canvas_uniforms_inc.glsl +++ b/drivers/gles3/shaders/canvas_uniforms_inc.glsl @@ -25,6 +25,7 @@ #define FLAGS_DEFAULT_SPECULAR_MAP_USED uint(1 << 27) #define FLAGS_USE_MSDF uint(1 << 28) +#define FLAGS_USE_LCD uint(1 << 29) // must be always 128 bytes long struct DrawData { diff --git a/drivers/gles3/storage/light_storage.cpp b/drivers/gles3/storage/light_storage.cpp index 2e4bfdc15b..e2781bfbc0 100644 --- a/drivers/gles3/storage/light_storage.cpp +++ b/drivers/gles3/storage/light_storage.cpp @@ -318,7 +318,7 @@ AABB LightStorage::light_get_aabb(RID p_light) const { switch (light->type) { case RS::LIGHT_SPOT: { float len = light->param[RS::LIGHT_PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; + float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); }; case RS::LIGHT_OMNI: { diff --git a/drivers/gles3/storage/material_storage.h b/drivers/gles3/storage/material_storage.h index d135357f6a..a2a7554821 100644 --- a/drivers/gles3/storage/material_storage.h +++ b/drivers/gles3/storage/material_storage.h @@ -142,6 +142,7 @@ struct CanvasShaderData : public ShaderData { BLEND_MODE_MUL, BLEND_MODE_PMALPHA, BLEND_MODE_DISABLED, + BLEND_MODE_LCD, }; bool valid; diff --git a/drivers/vulkan/rendering_device_vulkan.cpp b/drivers/vulkan/rendering_device_vulkan.cpp index 2debba1b83..f2d78636d7 100644 --- a/drivers/vulkan/rendering_device_vulkan.cpp +++ b/drivers/vulkan/rendering_device_vulkan.cpp @@ -7543,6 +7543,16 @@ RenderingDeviceVulkan::DrawList *RenderingDeviceVulkan::_get_draw_list_ptr(DrawL } } +void RenderingDeviceVulkan::draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) { + DrawList *dl = _get_draw_list_ptr(p_list); + ERR_FAIL_COND(!dl); +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_MSG(!dl->validation.active, "Submitted Draw Lists can no longer be modified."); +#endif + + vkCmdSetBlendConstants(dl->command_buffer, p_color.components); +} + void RenderingDeviceVulkan::draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) { DrawList *dl = _get_draw_list_ptr(p_list); ERR_FAIL_COND(!dl); diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 6572de7c52..6007e1ab4d 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -1155,6 +1155,7 @@ public: virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()); + virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color); virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline); virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index); virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array); diff --git a/editor/action_map_editor.cpp b/editor/action_map_editor.cpp index 648e950fd4..c8ab98a80f 100644 --- a/editor/action_map_editor.cpp +++ b/editor/action_map_editor.cpp @@ -577,7 +577,6 @@ String InputEventConfigurationDialog::_get_device_string(int p_device) const { void InputEventConfigurationDialog::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { input_list_search->set_right_icon(input_list_search->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); @@ -732,9 +731,9 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() { store_command_checkbox->set_pressed(true); store_command_checkbox->set_text(TTR("Store Command")); #ifdef APPLE_STYLE_KEYS - store_command_checkbox->set_tooltip(TTR("Toggles between serializing 'command' and 'meta'. Used for compatibility with Windows/Linux style keyboard.")); + store_command_checkbox->set_tooltip_text(TTR("Toggles between serializing 'command' and 'meta'. Used for compatibility with Windows/Linux style keyboard.")); #else - store_command_checkbox->set_tooltip(TTR("Toggles between serializing 'command' and 'control'. Used for compatibility with Apple Style keyboards.")); + store_command_checkbox->set_tooltip_text(TTR("Toggles between serializing 'command' and 'control'. Used for compatibility with Apple Style keyboards.")); #endif mod_container->add_child(store_command_checkbox); @@ -745,7 +744,7 @@ InputEventConfigurationDialog::InputEventConfigurationDialog() { physical_key_checkbox = memnew(CheckBox); physical_key_checkbox->set_text(TTR("Use Physical Keycode")); - physical_key_checkbox->set_tooltip(TTR("Stores the physical position of the key on the keyboard rather than the key's value. Used for compatibility with non-latin layouts.\nThis should generally be enabled for most game shortcuts, but not in non-game applications.")); + physical_key_checkbox->set_tooltip_text(TTR("Stores the physical position of the key on the keyboard rather than the key's value. Used for compatibility with non-latin layouts.\nThis should generally be enabled for most game shortcuts, but not in non-game applications.")); physical_key_checkbox->connect("toggled", callable_mp(this, &InputEventConfigurationDialog::_physical_keycode_toggled)); physical_key_checkbox->hide(); additional_options_container->add_child(physical_key_checkbox); @@ -805,7 +804,7 @@ String ActionMapEditor::_check_new_action_name(const String &p_name) { void ActionMapEditor::_add_edit_text_changed(const String &p_name) { String error = _check_new_action_name(p_name); - add_button->set_tooltip(error); + add_button->set_tooltip_text(error); add_button->set_disabled(!error.is_empty()); } @@ -1058,7 +1057,6 @@ void ActionMapEditor::drop_data_fw(const Point2 &p_point, const Variant &p_data, void ActionMapEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { action_list_search->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); if (!actions_cache.is_empty()) { diff --git a/editor/animation_bezier_editor.cpp b/editor/animation_bezier_editor.cpp index 9af8b907c4..c121ab42d3 100644 --- a/editor/animation_bezier_editor.cpp +++ b/editor/animation_bezier_editor.cpp @@ -216,8 +216,8 @@ void AnimationBezierTrackEdit::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/animation_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { bezier_icon = get_theme_icon(SNAME("KeyBezierPoint"), SNAME("EditorIcons")); bezier_handle_icon = get_theme_icon(SNAME("KeyBezierHandle"), SNAME("EditorIcons")); diff --git a/editor/animation_track_editor.cpp b/editor/animation_track_editor.cpp index 5df413f0a7..379e2cb510 100644 --- a/editor/animation_track_editor.cpp +++ b/editor/animation_track_editor.cpp @@ -1489,7 +1489,6 @@ int AnimationTimelineEdit::get_name_limit() const { void AnimationTimelineEdit::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/animation_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); add_track->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); @@ -1751,13 +1750,13 @@ void AnimationTimelineEdit::update_values() { if (use_fps && animation->get_step() > 0) { length->set_value(animation->get_length() / animation->get_step()); length->set_step(1); - length->set_tooltip(TTR("Animation length (frames)")); - time_icon->set_tooltip(TTR("Animation length (frames)")); + length->set_tooltip_text(TTR("Animation length (frames)")); + time_icon->set_tooltip_text(TTR("Animation length (frames)")); } else { length->set_value(animation->get_length()); length->set_step(0.001); - length->set_tooltip(TTR("Animation length (seconds)")); - time_icon->set_tooltip(TTR("Animation length (seconds)")); + length->set_tooltip_text(TTR("Animation length (seconds)")); + time_icon->set_tooltip_text(TTR("Animation length (seconds)")); } switch (animation->get_loop_mode()) { @@ -1942,7 +1941,7 @@ AnimationTimelineEdit::AnimationTimelineEdit() { len_hb->add_child(expander); time_icon = memnew(TextureRect); time_icon->set_v_size_flags(SIZE_SHRINK_CENTER); - time_icon->set_tooltip(TTR("Animation length (seconds)")); + time_icon->set_tooltip_text(TTR("Animation length (seconds)")); len_hb->add_child(time_icon); length = memnew(EditorSpinSlider); length->set_min(0.001); @@ -1951,12 +1950,12 @@ AnimationTimelineEdit::AnimationTimelineEdit() { length->set_allow_greater(true); length->set_custom_minimum_size(Vector2(70 * EDSCALE, 0)); length->set_hide_slider(true); - length->set_tooltip(TTR("Animation length (seconds)")); + length->set_tooltip_text(TTR("Animation length (seconds)")); length->connect("value_changed", callable_mp(this, &AnimationTimelineEdit::_anim_length_changed)); len_hb->add_child(length); loop = memnew(Button); loop->set_flat(true); - loop->set_tooltip(TTR("Animation Looping")); + loop->set_tooltip_text(TTR("Animation Looping")); loop->connect("pressed", callable_mp(this, &AnimationTimelineEdit::_anim_loop_pressed)); loop->set_toggle_mode(true); len_hb->add_child(loop); @@ -2122,11 +2121,12 @@ void AnimationTrackEdit::_notification(int p_what) { get_theme_icon(SNAME("InterpWrapClamp"), SNAME("EditorIcons")), get_theme_icon(SNAME("InterpWrapLoop"), SNAME("EditorIcons")), }; - Ref<Texture2D> interp_icon[4] = { + Ref<Texture2D> interp_icon[5] = { get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), - get_theme_icon(SNAME("InterpCubicInTime"), SNAME("EditorIcons")) + get_theme_icon(SNAME("InterpLinearAngle"), SNAME("EditorIcons")), + get_theme_icon(SNAME("InterpCubicAngle"), SNAME("EditorIcons")), }; Ref<Texture2D> cont_icon[4] = { get_theme_icon(SNAME("TrackContinuous"), SNAME("EditorIcons")), @@ -2849,7 +2849,23 @@ void AnimationTrackEdit::gui_input(const Ref<InputEvent> &p_event) { menu->add_icon_item(get_theme_icon(SNAME("InterpRaw"), SNAME("EditorIcons")), TTR("Nearest"), MENU_INTERPOLATION_NEAREST); menu->add_icon_item(get_theme_icon(SNAME("InterpLinear"), SNAME("EditorIcons")), TTR("Linear"), MENU_INTERPOLATION_LINEAR); menu->add_icon_item(get_theme_icon(SNAME("InterpCubic"), SNAME("EditorIcons")), TTR("Cubic"), MENU_INTERPOLATION_CUBIC); - menu->add_icon_item(get_theme_icon(SNAME("InterpCubicInTime"), SNAME("EditorIcons")), TTR("CubicInTime"), MENU_INTERPOLATION_CUBIC_IN_TIME); + // Check is angle property. + AnimationPlayerEditor *ape = AnimationPlayerEditor::get_singleton(); + if (ape) { + AnimationPlayer *ap = ape->get_player(); + if (ap) { + NodePath path = animation->track_get_path(track); + Node *nd = ap->get_node(ap->get_root())->get_node(NodePath(path.get_concatenated_names())); + StringName prop = path.get_concatenated_subnames(); + PropertyInfo prop_info; + ClassDB::get_property_info(nd->get_class(), prop, &prop_info); + bool is_angle = prop_info.type == Variant::FLOAT && prop_info.hint_string.find("radians") != -1; + if (is_angle) { + menu->add_icon_item(get_theme_icon(SNAME("InterpLinearAngle"), SNAME("EditorIcons")), TTR("Linear Angle"), MENU_INTERPOLATION_LINEAR_ANGLE); + menu->add_icon_item(get_theme_icon(SNAME("InterpCubicAngle"), SNAME("EditorIcons")), TTR("Cubic Angle"), MENU_INTERPOLATION_CUBIC_ANGLE); + } + } + } menu->reset_size(); Vector2 popup_pos = get_screen_position() + interp_mode_rect.position + Vector2(0, interp_mode_rect.size.height); @@ -3191,7 +3207,8 @@ void AnimationTrackEdit::_menu_selected(int p_index) { case MENU_INTERPOLATION_NEAREST: case MENU_INTERPOLATION_LINEAR: case MENU_INTERPOLATION_CUBIC: - case MENU_INTERPOLATION_CUBIC_IN_TIME: { + case MENU_INTERPOLATION_LINEAR_ANGLE: + case MENU_INTERPOLATION_CUBIC_ANGLE: { Animation::InterpolationType interp_mode = Animation::InterpolationType(p_index - MENU_INTERPOLATION_NEAREST); undo_redo->create_action(TTR("Change Animation Interpolation Mode")); undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", track, interp_mode); @@ -4582,7 +4599,7 @@ void AnimationTrackEditor::_update_tracks() { g->set_type_and_name(icon, name, animation->track_get_path(i)); g->set_root(root); - g->set_tooltip(tooltip); + g->set_tooltip_text(tooltip); g->set_timeline(timeline); groups.push_back(g); VBoxContainer *vb = memnew(VBoxContainer); @@ -4741,8 +4758,8 @@ void AnimationTrackEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { panner->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/animation_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { zoom_icon->set_texture(get_theme_icon(SNAME("Zoom"), SNAME("EditorIcons"))); bezier_edit_icon->set_icon(get_theme_icon(SNAME("EditBezier"), SNAME("EditorIcons"))); @@ -6045,6 +6062,9 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { Vector<int> keys = E->value; int len = keys.size() - 1; + // Special case for angle interpolation. + bool is_using_angle = animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_LINEAR_ANGLE || animation->track_get_interpolation_type(track) == Animation::INTERPOLATION_CUBIC_ANGLE; + // Make insert queue. Vector<Pair<double, Variant>> insert_queue; for (int i = 0; i < len; i++) { @@ -6054,6 +6074,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { double to_t = animation->track_get_key_time(track, keys[i + 1]); Variant from_v = animation->track_get_key_value(track, keys[i]); Variant to_v = animation->track_get_key_value(track, keys[i + 1]); + if (is_using_angle) { + real_t a = from_v; + real_t b = to_v; + real_t to_diff = fmod(b - a, Math_TAU); + to_v = a + fmod(2.0 * to_diff, Math_TAU) - to_diff; + } Variant delta_v; Variant::sub(to_v, from_v, delta_v); double duration = to_t - from_t; @@ -6169,15 +6195,12 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { case EDIT_GOTO_PREV_STEP: { goto_prev_step(false); } break; - case EDIT_APPLY_RESET: { - AnimationPlayerEditor::get_singleton()->get_player()->apply_reset(true); - } break; - case EDIT_BAKE_ANIMATION: { + case EDIT_BAKE_TRACK: { bake_dialog->popup_centered(Size2(200, 100) * EDSCALE); } break; - case EDIT_BAKE_ANIMATION_CONFIRM: { - undo_redo->create_action(TTR("Bake Animation as Linear keys.")); + case EDIT_BAKE_TRACK_CONFIRM: { + undo_redo->create_action(TTR("Bake Track as Linear keys.")); int track_len = animation->get_track_count(); bool b_trs = bake_trs->is_pressed(); @@ -6195,10 +6218,14 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { do_bake |= b_bs && type == Animation::TYPE_BLEND_SHAPE; do_bake |= b_v && type == Animation::TYPE_VALUE; if (do_bake && !animation->track_is_compressed(i)) { - if (animation->track_get_interpolation_type(i) == Animation::INTERPOLATION_NEAREST) { - continue; // Nearest interpolation cannot be baked. + Animation::InterpolationType it = animation->track_get_interpolation_type(i); + if (it == Animation::INTERPOLATION_NEAREST) { + continue; // Nearest and Angle interpolation cannot be baked. } + // Special case for angle interpolation. + bool is_using_angle = it == Animation::INTERPOLATION_LINEAR_ANGLE || it == Animation::INTERPOLATION_CUBIC_ANGLE; + // Make insert queue. Vector<Pair<double, Variant>> insert_queue; @@ -6262,7 +6289,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } // Insert keys. - undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", i, Animation::INTERPOLATION_LINEAR); + undo_redo->add_do_method(animation.ptr(), "track_set_interpolation_type", i, is_using_angle ? Animation::INTERPOLATION_LINEAR_ANGLE : Animation::INTERPOLATION_LINEAR); for (int j = insert_queue.size() - 1; j >= 0; j--) { undo_redo->add_do_method(animation.ptr(), "track_insert_key", i, insert_queue[j].first, insert_queue[j].second); undo_redo->add_undo_method(animation.ptr(), "track_remove_key", i, j); @@ -6280,6 +6307,10 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { } break; + case EDIT_APPLY_RESET: { + AnimationPlayerEditor::get_singleton()->get_player()->apply_reset(true); + } break; + case EDIT_OPTIMIZE_ANIMATION: { optimize_dialog->popup_centered(Size2(250, 180) * EDSCALE); @@ -6288,6 +6319,7 @@ void AnimationTrackEditor::_edit_menu_pressed(int p_option) { animation->optimize(optimize_velocity_error->get_value(), optimize_angular_error->get_value(), optimize_precision_error->get_value()); _update_tracks(); undo_redo->clear_history(true, undo_redo->get_history_for_object(animation.ptr()).id); + undo_redo->clear_history(true, undo_redo->get_history_for_object(this).id); } break; case EDIT_CLEAN_UP_ANIMATION: { @@ -6356,6 +6388,7 @@ void AnimationTrackEditor::_cleanup_animation(Ref<Animation> p_animation) { } undo_redo->clear_history(true, undo_redo->get_history_for_object(animation.ptr()).id); + undo_redo->clear_history(true, undo_redo->get_history_for_object(this).id); _update_tracks(); } @@ -6604,7 +6637,7 @@ AnimationTrackEditor::AnimationTrackEditor() { imported_anim_warning = memnew(Button); imported_anim_warning->hide(); imported_anim_warning->set_text(TTR("Imported Scene")); - imported_anim_warning->set_tooltip(TTR("Warning: Editing imported animation")); + imported_anim_warning->set_tooltip_text(TTR("Warning: Editing imported animation")); imported_anim_warning->connect("pressed", callable_mp(this, &AnimationTrackEditor::_show_imported_anim_warning)); bottom_hb->add_child(imported_anim_warning); @@ -6615,7 +6648,7 @@ AnimationTrackEditor::AnimationTrackEditor() { bezier_edit_icon->set_disabled(true); bezier_edit_icon->set_toggle_mode(true); bezier_edit_icon->connect("pressed", callable_mp(this, &AnimationTrackEditor::_toggle_bezier_edit)); - bezier_edit_icon->set_tooltip(TTR("Toggle between the bezier curve editor and track editor.")); + bezier_edit_icon->set_tooltip_text(TTR("Toggle between the bezier curve editor and track editor.")); bottom_hb->add_child(bezier_edit_icon); @@ -6623,7 +6656,7 @@ AnimationTrackEditor::AnimationTrackEditor() { selected_filter->set_flat(true); selected_filter->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); // Same function works the same. selected_filter->set_toggle_mode(true); - selected_filter->set_tooltip(TTR("Only show tracks from nodes selected in tree.")); + selected_filter->set_tooltip_text(TTR("Only show tracks from nodes selected in tree.")); bottom_hb->add_child(selected_filter); @@ -6631,7 +6664,7 @@ AnimationTrackEditor::AnimationTrackEditor() { view_group->set_flat(true); view_group->connect("pressed", callable_mp(this, &AnimationTrackEditor::_view_group_toggle)); view_group->set_toggle_mode(true); - view_group->set_tooltip(TTR("Group tracks by node or display them as plain list.")); + view_group->set_tooltip_text(TTR("Group tracks by node or display them as plain list.")); bottom_hb->add_child(view_group); bottom_hb->add_child(memnew(VSeparator)); @@ -6650,7 +6683,7 @@ AnimationTrackEditor::AnimationTrackEditor() { step->set_step(0.001); step->set_hide_slider(true); step->set_custom_minimum_size(Size2(100, 0) * EDSCALE); - step->set_tooltip(TTR("Animation step value.")); + step->set_tooltip_text(TTR("Animation step value.")); bottom_hb->add_child(step); step->connect("value_changed", callable_mp(this, &AnimationTrackEditor::_update_step)); step->set_read_only(true); @@ -6682,7 +6715,7 @@ AnimationTrackEditor::AnimationTrackEditor() { edit->set_text(TTR("Edit")); edit->set_flat(false); edit->set_disabled(true); - edit->set_tooltip(TTR("Animation properties.")); + edit->set_tooltip_text(TTR("Animation properties.")); edit->get_popup()->add_item(TTR("Copy Tracks"), EDIT_COPY_TRACKS); edit->get_popup()->add_item(TTR("Paste Tracks"), EDIT_PASTE_TRACKS); edit->get_popup()->add_separator(); @@ -6701,11 +6734,12 @@ AnimationTrackEditor::AnimationTrackEditor() { edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_next_step", TTR("Go to Next Step"), KeyModifierMask::CMD | Key::RIGHT), EDIT_GOTO_NEXT_STEP); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/goto_prev_step", TTR("Go to Previous Step"), KeyModifierMask::CMD | Key::LEFT), EDIT_GOTO_PREV_STEP); edit->get_popup()->add_separator(); + edit->get_popup()->add_item(TTR("Bake Track"), EDIT_BAKE_TRACK); + edit->get_popup()->add_separator(); edit->get_popup()->add_shortcut(ED_SHORTCUT("animation_editor/apply_reset", TTR("Apply Reset")), EDIT_APPLY_RESET); edit->get_popup()->add_separator(); - edit->get_popup()->add_item(TTR("Bake Animation"), EDIT_BAKE_ANIMATION); - edit->get_popup()->add_item(TTR("Optimize Animation"), EDIT_OPTIMIZE_ANIMATION); - edit->get_popup()->add_item(TTR("Clean-Up Animation"), EDIT_CLEAN_UP_ANIMATION); + edit->get_popup()->add_item(TTR("Optimize Animation (no undo)"), EDIT_OPTIMIZE_ANIMATION); + edit->get_popup()->add_item(TTR("Clean-Up Animation (no undo)"), EDIT_CLEAN_UP_ANIMATION); edit->get_popup()->connect("id_pressed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed)); edit->get_popup()->connect("about_to_popup", callable_mp(this, &AnimationTrackEditor::_edit_menu_about_to_popup)); @@ -6873,8 +6907,8 @@ AnimationTrackEditor::AnimationTrackEditor() { // bake_dialog = memnew(ConfirmationDialog); - bake_dialog->set_title(TTR("Anim. Baker")); - bake_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_BAKE_ANIMATION_CONFIRM)); + bake_dialog->set_title(TTR("Track Baker")); + bake_dialog->connect("confirmed", callable_mp(this, &AnimationTrackEditor::_edit_menu_pressed).bind(EDIT_BAKE_TRACK_CONFIRM)); add_child(bake_dialog); GridContainer *bake_grid = memnew(GridContainer); bake_grid->set_columns(2); diff --git a/editor/animation_track_editor.h b/editor/animation_track_editor.h index 9cf3269fd0..a17ee65eab 100644 --- a/editor/animation_track_editor.h +++ b/editor/animation_track_editor.h @@ -144,7 +144,8 @@ class AnimationTrackEdit : public Control { MENU_INTERPOLATION_NEAREST, MENU_INTERPOLATION_LINEAR, MENU_INTERPOLATION_CUBIC, - MENU_INTERPOLATION_CUBIC_IN_TIME, + MENU_INTERPOLATION_LINEAR_ANGLE, + MENU_INTERPOLATION_CUBIC_ANGLE, MENU_LOOP_WRAP, MENU_LOOP_CLAMP, MENU_KEY_INSERT, @@ -501,7 +502,7 @@ class AnimationTrackEditor : public VBoxContainer { NodePath full_path; NodePath base_path; Animation::TrackType track_type = Animation::TYPE_ANIMATION; - Animation::InterpolationType interp_type = Animation::INTERPOLATION_CUBIC_IN_TIME; + Animation::InterpolationType interp_type = Animation::INTERPOLATION_CUBIC_ANGLE; Animation::UpdateMode update_mode = Animation::UPDATE_CAPTURE; Animation::LoopMode loop_mode = Animation::LOOP_PINGPONG; bool loop_wrap = false; @@ -544,9 +545,9 @@ public: EDIT_GOTO_NEXT_STEP, EDIT_GOTO_NEXT_STEP_TIMELINE_ONLY, // Next step without updating animation. EDIT_GOTO_PREV_STEP, + EDIT_BAKE_TRACK, + EDIT_BAKE_TRACK_CONFIRM, EDIT_APPLY_RESET, - EDIT_BAKE_ANIMATION, - EDIT_BAKE_ANIMATION_CONFIRM, EDIT_OPTIMIZE_ANIMATION, EDIT_OPTIMIZE_ANIMATION_CONFIRM, EDIT_CLEAN_UP_ANIMATION, diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index bdd30dc653..9dddcbbeba 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -1740,10 +1740,6 @@ void CodeTextEditor::_update_status_bar_theme() { void CodeTextEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - _update_status_bar_theme(); - } break; - case NOTIFICATION_THEME_CHANGED: { _update_status_bar_theme(); if (toggle_scripts_button->is_visible()) { @@ -1862,7 +1858,7 @@ void CodeTextEditor::update_toggle_scripts_button() { } else { toggle_scripts_button->set_icon(get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"), SNAME("EditorIcons"))); } - toggle_scripts_button->set_tooltip(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); + toggle_scripts_button->set_tooltip_text(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); } CodeTextEditor::CodeTextEditor() { @@ -1955,7 +1951,7 @@ CodeTextEditor::CodeTextEditor() { error_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); error_button->set_default_cursor_shape(CURSOR_POINTING_HAND); error_button->connect("pressed", callable_mp(this, &CodeTextEditor::_error_button_pressed)); - error_button->set_tooltip(TTR("Errors")); + error_button->set_tooltip_text(TTR("Errors")); set_error_count(0); // Warnings @@ -1965,14 +1961,14 @@ CodeTextEditor::CodeTextEditor() { warning_button->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); warning_button->set_default_cursor_shape(CURSOR_POINTING_HAND); warning_button->connect("pressed", callable_mp(this, &CodeTextEditor::_warning_button_pressed)); - warning_button->set_tooltip(TTR("Warnings")); + warning_button->set_tooltip_text(TTR("Warnings")); set_warning_count(0); // Line and column line_and_col_txt = memnew(Label); status_bar->add_child(line_and_col_txt); line_and_col_txt->set_v_size_flags(SIZE_EXPAND | SIZE_SHRINK_CENTER); - line_and_col_txt->set_tooltip(TTR("Line and column numbers.")); + line_and_col_txt->set_tooltip_text(TTR("Line and column numbers.")); line_and_col_txt->set_mouse_filter(MOUSE_FILTER_STOP); text_editor->connect("gui_input", callable_mp(this, &CodeTextEditor::_text_editor_gui_input)); diff --git a/editor/connections_dialog.cpp b/editor/connections_dialog.cpp index dc8a64d904..bfa9081af2 100644 --- a/editor/connections_dialog.cpp +++ b/editor/connections_dialog.cpp @@ -230,9 +230,8 @@ void ConnectDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { bind_editor->edit(cdbinds); + } break; - [[fallthrough]]; - } case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < type_list->get_item_count(); i++) { String type_name = Variant::get_type_name((Variant::Type)type_list->get_item_id(i)); @@ -460,7 +459,7 @@ ConnectDialog::ConnectDialog() { vbc_right->add_margin_child(TTR("Extra Call Arguments:"), bind_editor, true); unbind_count = memnew(SpinBox); - unbind_count->set_tooltip(TTR("Allows to drop arguments sent by signal emitter.")); + unbind_count->set_tooltip_text(TTR("Allows to drop arguments sent by signal emitter.")); unbind_count->connect("value_changed", callable_mp(this, &ConnectDialog::_unbind_count_changed)); vbc_right->add_margin_child(TTR("Unbind Signal Arguments:"), unbind_count); @@ -481,13 +480,13 @@ ConnectDialog::ConnectDialog() { deferred = memnew(CheckBox); deferred->set_h_size_flags(0); deferred->set_text(TTR("Deferred")); - deferred->set_tooltip(TTR("Defers the signal, storing it in a queue and only firing it at idle time.")); + deferred->set_tooltip_text(TTR("Defers the signal, storing it in a queue and only firing it at idle time.")); vbc_right->add_child(deferred); oneshot = memnew(CheckBox); oneshot->set_h_size_flags(0); oneshot->set_text(TTR("Oneshot")); - oneshot->set_tooltip(TTR("Disconnects the signal after its first emission.")); + oneshot->set_tooltip_text(TTR("Disconnects the signal after its first emission.")); vbc_right->add_child(oneshot); cdbinds = memnew(ConnectDialogBinds); @@ -913,7 +912,6 @@ void ConnectionsDock::_connect_pressed() { void ConnectionsDock::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); } break; diff --git a/editor/create_dialog.cpp b/editor/create_dialog.cpp index c84e8ec48f..02ce081c02 100644 --- a/editor/create_dialog.cpp +++ b/editor/create_dialog.cpp @@ -423,16 +423,10 @@ void CreateDialog::_sbox_input(const Ref<InputEvent> &p_ie) { } } -void CreateDialog::_update_theme() { - search_box->set_right_icon(search_options->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - favorite->set_icon(search_options->get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons"))); -} - void CreateDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { connect("confirmed", callable_mp(this, &CreateDialog::_confirmed)); - _update_theme(); } break; case NOTIFICATION_EXIT_TREE: { @@ -449,7 +443,8 @@ void CreateDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + search_box->set_right_icon(search_options->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + favorite->set_icon(search_options->get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons"))); } break; } } @@ -780,7 +775,7 @@ CreateDialog::CreateDialog() { favorite = memnew(Button); favorite->set_toggle_mode(true); - favorite->set_tooltip(TTR("(Un)favorite selected item.")); + favorite->set_tooltip_text(TTR("(Un)favorite selected item.")); favorite->connect("pressed", callable_mp(this, &CreateDialog::_favorite_toggled)); search_hb->add_child(favorite); vbc->add_margin_child(TTR("Search:"), search_hb); diff --git a/editor/create_dialog.h b/editor/create_dialog.h index f7731d2726..9a17993e11 100644 --- a/editor/create_dialog.h +++ b/editor/create_dialog.h @@ -101,8 +101,6 @@ class CreateDialog : public ConfirmationDialog { bool _is_class_disabled_by_feature_profile(const StringName &p_class) const; void _load_favorites_and_history(); - void _update_theme(); - protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/debugger/editor_network_profiler.cpp b/editor/debugger/editor_network_profiler.cpp index 8c18eba71d..185553cac0 100644 --- a/editor/debugger/editor_network_profiler.cpp +++ b/editor/debugger/editor_network_profiler.cpp @@ -40,7 +40,6 @@ void EditorNetworkProfiler::_bind_methods() { void EditorNetworkProfiler::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); diff --git a/editor/debugger/editor_profiler.cpp b/editor/debugger/editor_profiler.cpp index 28b5d4be15..30197e6d8b 100644 --- a/editor/debugger/editor_profiler.cpp +++ b/editor/debugger/editor_profiler.cpp @@ -394,10 +394,9 @@ void EditorProfiler::_clear_pressed() { void EditorProfiler::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_TRANSLATION_CHANGED: { + case NOTIFICATION_TRANSLATION_CHANGED: + case NOTIFICATION_THEME_CHANGED: { activate->set_icon(get_theme_icon(SNAME("Play"), SNAME("EditorIcons"))); clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); } break; @@ -607,7 +606,7 @@ EditorProfiler::EditorProfiler() { display_time = memnew(OptionButton); display_time->add_item(TTR("Inclusive")); display_time->add_item(TTR("Self")); - display_time->set_tooltip(TTR("Inclusive: Includes time from other functions called by this function.\nUse this to spot bottlenecks.\n\nSelf: Only count the time spent in the function itself, not in other functions called by that function.\nUse this to find individual functions to optimize.")); + display_time->set_tooltip_text(TTR("Inclusive: Includes time from other functions called by this function.\nUse this to spot bottlenecks.\n\nSelf: Only count the time spent in the function itself, not in other functions called by that function.\nUse this to find individual functions to optimize.")); display_time->connect("item_selected", callable_mp(this, &EditorProfiler::_combo_changed)); hb->add_child(display_time); diff --git a/editor/debugger/editor_visual_profiler.cpp b/editor/debugger/editor_visual_profiler.cpp index 6f3dd1793c..df1a59cc99 100644 --- a/editor/debugger/editor_visual_profiler.cpp +++ b/editor/debugger/editor_visual_profiler.cpp @@ -424,10 +424,9 @@ void EditorVisualProfiler::_clear_pressed() { void EditorVisualProfiler::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_TRANSLATION_CHANGED: { + case NOTIFICATION_TRANSLATION_CHANGED: + case NOTIFICATION_THEME_CHANGED: { if (is_layout_rtl()) { activate->set_icon(get_theme_icon(SNAME("PlayBackwards"), SNAME("EditorIcons"))); } else { diff --git a/editor/debugger/script_editor_debugger.cpp b/editor/debugger/script_editor_debugger.cpp index 1bee0513ca..1036561a47 100644 --- a/editor/debugger/script_editor_debugger.cpp +++ b/editor/debugger/script_editor_debugger.cpp @@ -369,7 +369,7 @@ void ScriptEditorDebugger::_parse_message(const String &p_msg, const Array &p_da } } - vmem_total->set_tooltip(TTR("Bytes:") + " " + itos(total)); + vmem_total->set_tooltip_text(TTR("Bytes:") + " " + itos(total)); vmem_total->set_text(String::humanize_size(total)); } else if (p_msg == "stack_dump") { @@ -776,7 +776,7 @@ void ScriptEditorDebugger::_set_reason_text(const String &p_reason, MessageType reason->add_theme_color_override("font_color", get_theme_color(SNAME("success_color"), SNAME("Editor"))); } reason->set_text(p_reason); - reason->set_tooltip(p_reason.word_wrap(80)); + reason->set_tooltip_text(p_reason.word_wrap(80)); } void ScriptEditorDebugger::_notification(int p_what) { @@ -787,8 +787,8 @@ void ScriptEditorDebugger::_notification(int p_what) { error_tree->connect("item_selected", callable_mp(this, &ScriptEditorDebugger::_error_selected)); error_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_error_activated)); breakpoints_tree->connect("item_activated", callable_mp(this, &ScriptEditorDebugger::_breakpoint_tree_clicked)); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { skip_breakpoints->set_icon(get_theme_icon(skip_breakpoints_value ? SNAME("DebugSkipBreakpointsOn") : SNAME("DebugSkipBreakpointsOff"), SNAME("EditorIcons"))); copy->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); @@ -964,7 +964,7 @@ void ScriptEditorDebugger::stop() { peer->close(); peer.unref(); reason->set_text(""); - reason->set_tooltip(""); + reason->set_tooltip_text(""); } node_path_cache.clear(); @@ -1706,7 +1706,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() { skip_breakpoints = memnew(Button); skip_breakpoints->set_flat(true); hbc->add_child(skip_breakpoints); - skip_breakpoints->set_tooltip(TTR("Skip Breakpoints")); + skip_breakpoints->set_tooltip_text(TTR("Skip Breakpoints")); skip_breakpoints->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_skip_breakpoints)); hbc->add_child(memnew(VSeparator)); @@ -1714,7 +1714,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() { copy = memnew(Button); copy->set_flat(true); hbc->add_child(copy); - copy->set_tooltip(TTR("Copy Error")); + copy->set_tooltip_text(TTR("Copy Error")); copy->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_copy)); hbc->add_child(memnew(VSeparator)); @@ -1722,14 +1722,14 @@ ScriptEditorDebugger::ScriptEditorDebugger() { step = memnew(Button); step->set_flat(true); hbc->add_child(step); - step->set_tooltip(TTR("Step Into")); + step->set_tooltip_text(TTR("Step Into")); step->set_shortcut(ED_GET_SHORTCUT("debugger/step_into")); step->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_step)); next = memnew(Button); next->set_flat(true); hbc->add_child(next); - next->set_tooltip(TTR("Step Over")); + next->set_tooltip_text(TTR("Step Over")); next->set_shortcut(ED_GET_SHORTCUT("debugger/step_over")); next->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_next)); @@ -1738,14 +1738,14 @@ ScriptEditorDebugger::ScriptEditorDebugger() { dobreak = memnew(Button); dobreak->set_flat(true); hbc->add_child(dobreak); - dobreak->set_tooltip(TTR("Break")); + dobreak->set_tooltip_text(TTR("Break")); dobreak->set_shortcut(ED_GET_SHORTCUT("debugger/break")); dobreak->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_break)); docontinue = memnew(Button); docontinue->set_flat(true); hbc->add_child(docontinue); - docontinue->set_tooltip(TTR("Continue")); + docontinue->set_tooltip_text(TTR("Continue")); docontinue->set_shortcut(ED_GET_SHORTCUT("debugger/continue")); docontinue->connect("pressed", callable_mp(this, &ScriptEditorDebugger::debug_continue)); @@ -1917,7 +1917,7 @@ ScriptEditorDebugger::ScriptEditorDebugger() { vmem_hb->add_child(vmem_refresh); vmem_export = memnew(Button); vmem_export->set_flat(true); - vmem_export->set_tooltip(TTR("Export list to a CSV file")); + vmem_export->set_tooltip_text(TTR("Export list to a CSV file")); vmem_hb->add_child(vmem_export); vmem_vb->add_child(vmem_hb); vmem_refresh->connect("pressed", callable_mp(this, &ScriptEditorDebugger::_video_mem_request)); diff --git a/editor/editor_about.cpp b/editor/editor_about.cpp index 17aa67cd45..cdf300e288 100644 --- a/editor/editor_about.cpp +++ b/editor/editor_about.cpp @@ -38,22 +38,18 @@ // The metadata key used to store and retrieve the version text to copy to the clipboard. static const String META_TEXT_TO_COPY = "text_to_copy"; -void EditorAbout::_theme_changed() { - const Ref<Font> font = get_theme_font(SNAME("source"), SNAME("EditorFonts")); - const int font_size = get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")); - _tpl_text->add_theme_font_override("normal_font", font); - _tpl_text->add_theme_font_size_override("normal_font_size", font_size); - _tpl_text->add_theme_constant_override("line_separation", 4 * EDSCALE); - _license_text->add_theme_font_override("normal_font", font); - _license_text->add_theme_font_size_override("normal_font_size", font_size); - _license_text->add_theme_constant_override("line_separation", 4 * EDSCALE); - _logo->set_texture(get_theme_icon(SNAME("Logo"), SNAME("EditorIcons"))); -} - void EditorAbout::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: { - _theme_changed(); + case NOTIFICATION_THEME_CHANGED: { + const Ref<Font> font = get_theme_font(SNAME("source"), SNAME("EditorFonts")); + const int font_size = get_theme_font_size(SNAME("source_size"), SNAME("EditorFonts")); + _tpl_text->add_theme_font_override("normal_font", font); + _tpl_text->add_theme_font_size_override("normal_font_size", font_size); + _tpl_text->add_theme_constant_override("line_separation", 4 * EDSCALE); + _license_text->add_theme_font_override("normal_font", font); + _license_text->add_theme_font_size_override("normal_font_size", font_size); + _license_text->add_theme_constant_override("line_separation", 4 * EDSCALE); + _logo->set_texture(get_theme_icon(SNAME("Logo"), SNAME("EditorIcons"))); } break; } } @@ -120,7 +116,6 @@ EditorAbout::EditorAbout() { set_hide_on_ok(true); VBoxContainer *vbc = memnew(VBoxContainer); - vbc->connect("theme_changed", callable_mp(this, &EditorAbout::_theme_changed)); HBoxContainer *hbc = memnew(HBoxContainer); hbc->set_h_size_flags(Control::SIZE_EXPAND_FILL); hbc->set_alignment(BoxContainer::ALIGNMENT_CENTER); @@ -147,7 +142,7 @@ EditorAbout::EditorAbout() { // Set the text to copy in metadata as it slightly differs from the button's text. version_btn->set_meta(META_TEXT_TO_COPY, "v" VERSION_FULL_BUILD + hash); version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); - version_btn->set_tooltip(TTR("Click to copy.")); + version_btn->set_tooltip_text(TTR("Click to copy.")); version_btn->connect("pressed", callable_mp(this, &EditorAbout::_version_button_pressed)); version_info_vbc->add_child(version_btn); diff --git a/editor/editor_about.h b/editor/editor_about.h index 971843f6d2..b152f1b4d3 100644 --- a/editor/editor_about.h +++ b/editor/editor_about.h @@ -62,8 +62,6 @@ private: RichTextLabel *_tpl_text = nullptr; TextureRect *_logo = nullptr; - void _theme_changed(); - protected: void _notification(int p_what); static void _bind_methods(); diff --git a/editor/editor_audio_buses.cpp b/editor/editor_audio_buses.cpp index f1add65b7c..cc65cddfb2 100644 --- a/editor/editor_audio_buses.cpp +++ b/editor/editor_audio_buses.cpp @@ -66,7 +66,6 @@ void EditorAudioBus::_update_visible_channels() { void EditorAudioBus::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < CHANNELS_MAX; i++) { channel[i].vu_l->set_under_texture(get_theme_icon(SNAME("BusVuEmpty"), SNAME("EditorIcons"))); @@ -395,7 +394,7 @@ void EditorAudioBus::_show_value(float slider_value) { // Also set the preview text as a standard Control tooltip. // This way, it can be seen when the slider is merely hovered (instead of dragged). - slider->set_tooltip(text); + slider->set_tooltip_text(text); audio_value_preview_label->set_text(text); const Vector2 slider_size = slider->get_size(); const Vector2 slider_position = slider->get_global_position(); @@ -779,7 +778,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { buses = p_buses; is_master = p_is_master; - set_tooltip(TTR("Drag & drop to rearrange.")); + set_tooltip_text(TTR("Drag & drop to rearrange.")); VBoxContainer *vb = memnew(VBoxContainer); add_child(vb); @@ -796,21 +795,21 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { solo = memnew(Button); solo->set_flat(true); solo->set_toggle_mode(true); - solo->set_tooltip(TTR("Solo")); + solo->set_tooltip_text(TTR("Solo")); solo->set_focus_mode(FOCUS_NONE); solo->connect("pressed", callable_mp(this, &EditorAudioBus::_solo_toggled)); hbc->add_child(solo); mute = memnew(Button); mute->set_flat(true); mute->set_toggle_mode(true); - mute->set_tooltip(TTR("Mute")); + mute->set_tooltip_text(TTR("Mute")); mute->set_focus_mode(FOCUS_NONE); mute->connect("pressed", callable_mp(this, &EditorAudioBus::_mute_toggled)); hbc->add_child(mute); bypass = memnew(Button); bypass->set_flat(true); bypass->set_toggle_mode(true); - bypass->set_tooltip(TTR("Bypass")); + bypass->set_tooltip_text(TTR("Bypass")); bypass->set_focus_mode(FOCUS_NONE); bypass->connect("pressed", callable_mp(this, &EditorAudioBus::_bypass_toggled)); hbc->add_child(bypass); @@ -936,7 +935,7 @@ EditorAudioBus::EditorAudioBus(EditorAudioBuses *p_buses, bool p_is_master) { bus_options->set_shortcut_context(this); bus_options->set_h_size_flags(SIZE_SHRINK_END); bus_options->set_anchor(SIDE_RIGHT, 0.0); - bus_options->set_tooltip(TTR("Bus Options")); + bus_options->set_tooltip_text(TTR("Bus Options")); hbc->add_child(bus_options); bus_popup = bus_options->get_popup(); @@ -1025,7 +1024,6 @@ EditorAudioBuses *EditorAudioBuses::register_editor() { void EditorAudioBuses::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { bus_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } break; @@ -1282,7 +1280,7 @@ EditorAudioBuses::EditorAudioBuses() { add = memnew(Button); top_hb->add_child(add); add->set_text(TTR("Add Bus")); - add->set_tooltip(TTR("Add a new Audio Bus to this layout.")); + add->set_tooltip_text(TTR("Add a new Audio Bus to this layout.")); add->connect("pressed", callable_mp(this, &EditorAudioBuses::_add_bus)); VSeparator *separator = memnew(VSeparator); @@ -1290,25 +1288,25 @@ EditorAudioBuses::EditorAudioBuses() { load = memnew(Button); load->set_text(TTR("Load")); - load->set_tooltip(TTR("Load an existing Bus Layout.")); + load->set_tooltip_text(TTR("Load an existing Bus Layout.")); top_hb->add_child(load); load->connect("pressed", callable_mp(this, &EditorAudioBuses::_load_layout)); save_as = memnew(Button); save_as->set_text(TTR("Save As")); - save_as->set_tooltip(TTR("Save this Bus Layout to a file.")); + save_as->set_tooltip_text(TTR("Save this Bus Layout to a file.")); top_hb->add_child(save_as); save_as->connect("pressed", callable_mp(this, &EditorAudioBuses::_save_as_layout)); _default = memnew(Button); _default->set_text(TTR("Load Default")); - _default->set_tooltip(TTR("Load the default Bus Layout.")); + _default->set_tooltip_text(TTR("Load the default Bus Layout.")); top_hb->add_child(_default); _default->connect("pressed", callable_mp(this, &EditorAudioBuses::_load_default_layout)); _new = memnew(Button); _new->set_text(TTR("Create")); - _new->set_tooltip(TTR("Create a new Bus Layout.")); + _new->set_tooltip_text(TTR("Create a new Bus Layout.")); top_hb->add_child(_new); _new->connect("pressed", callable_mp(this, &EditorAudioBuses::_new_layout)); diff --git a/editor/editor_autoload_settings.cpp b/editor/editor_autoload_settings.cpp index 120ac5b984..7dff0d54f7 100644 --- a/editor/editor_autoload_settings.cpp +++ b/editor/editor_autoload_settings.cpp @@ -59,7 +59,6 @@ void EditorAutoloadSettings::_notification(int p_what) { get_tree()->get_root()->call_deferred(SNAME("add_child"), info.node); } } - browse_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } break; case NOTIFICATION_THEME_CHANGED: { diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp index 2f1134e8ef..cc0f60fee5 100644 --- a/editor/editor_file_dialog.cpp +++ b/editor/editor_file_dialog.cpp @@ -70,7 +70,6 @@ VBoxContainer *EditorFileDialog::get_vbox() { void EditorFileDialog::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY: case NOTIFICATION_THEME_CHANGED: case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_TRANSLATION_CHANGED: { @@ -1625,13 +1624,13 @@ EditorFileDialog::EditorFileDialog() { dir_prev = memnew(Button); dir_prev->set_flat(true); - dir_prev->set_tooltip(TTR("Go to previous folder.")); + dir_prev->set_tooltip_text(TTR("Go to previous folder.")); dir_next = memnew(Button); dir_next->set_flat(true); - dir_next->set_tooltip(TTR("Go to next folder.")); + dir_next->set_tooltip_text(TTR("Go to next folder.")); dir_up = memnew(Button); dir_up->set_flat(true); - dir_up->set_tooltip(TTR("Go to parent folder.")); + dir_up->set_tooltip_text(TTR("Go to parent folder.")); pathhb->add_child(dir_prev); pathhb->add_child(dir_next); @@ -1655,14 +1654,14 @@ EditorFileDialog::EditorFileDialog() { refresh = memnew(Button); refresh->set_flat(true); - refresh->set_tooltip(TTR("Refresh files.")); + refresh->set_tooltip_text(TTR("Refresh files.")); refresh->connect("pressed", callable_mp(this, &EditorFileDialog::update_file_list)); pathhb->add_child(refresh); favorite = memnew(Button); favorite->set_flat(true); favorite->set_toggle_mode(true); - favorite->set_tooltip(TTR("(Un)favorite current folder.")); + favorite->set_tooltip_text(TTR("(Un)favorite current folder.")); favorite->connect("pressed", callable_mp(this, &EditorFileDialog::_favorite_pressed)); pathhb->add_child(favorite); @@ -1670,7 +1669,7 @@ EditorFileDialog::EditorFileDialog() { show_hidden->set_flat(true); show_hidden->set_toggle_mode(true); show_hidden->set_pressed(is_showing_hidden_files()); - show_hidden->set_tooltip(TTR("Toggle the visibility of hidden files.")); + show_hidden->set_tooltip_text(TTR("Toggle the visibility of hidden files.")); show_hidden->connect("toggled", callable_mp(this, &EditorFileDialog::set_show_hidden_files)); pathhb->add_child(show_hidden); @@ -1685,7 +1684,7 @@ EditorFileDialog::EditorFileDialog() { mode_thumbnails->set_toggle_mode(true); mode_thumbnails->set_pressed(display_mode == DISPLAY_THUMBNAILS); mode_thumbnails->set_button_group(view_mode_group); - mode_thumbnails->set_tooltip(TTR("View items as a grid of thumbnails.")); + mode_thumbnails->set_tooltip_text(TTR("View items as a grid of thumbnails.")); pathhb->add_child(mode_thumbnails); mode_list = memnew(Button); @@ -1694,7 +1693,7 @@ EditorFileDialog::EditorFileDialog() { mode_list->set_toggle_mode(true); mode_list->set_pressed(display_mode == DISPLAY_LIST); mode_list->set_button_group(view_mode_group); - mode_list->set_tooltip(TTR("View items as a list.")); + mode_list->set_tooltip_text(TTR("View items as a list.")); pathhb->add_child(mode_list); shortcuts_container = memnew(HBoxContainer); diff --git a/editor/editor_fonts.cpp b/editor/editor_fonts.cpp index a02051c8ee..fffe77f1c4 100644 --- a/editor/editor_fonts.cpp +++ b/editor/editor_fonts.cpp @@ -37,7 +37,7 @@ #include "scene/resources/default_theme/default_theme.h" #include "scene/resources/font.h" -Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { +Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { Ref<FontFile> font; font.instantiate(); @@ -45,7 +45,7 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin font->set_data(data); font->set_multichannel_signed_distance_field(p_msdf); - font->set_antialiased(p_aa); + font->set_antialiasing(p_aa); font->set_hinting(p_hinting); font->set_force_autohinter(p_autohint); font->set_subpixel_positioning(p_font_subpixel_positioning); @@ -57,13 +57,13 @@ Ref<FontFile> load_external_font(const String &p_path, TextServer::Hinting p_hin return font; } -Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, bool p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { +Ref<FontFile> load_internal_font(const uint8_t *p_data, size_t p_size, TextServer::Hinting p_hinting, TextServer::FontAntialiasing p_aa, bool p_autohint, TextServer::SubpixelPositioning p_font_subpixel_positioning, bool p_msdf = false, TypedArray<Font> *r_fallbacks = nullptr) { Ref<FontFile> font; font.instantiate(); font->set_data_ptr(p_data, p_size); font->set_multichannel_signed_distance_field(p_msdf); - font->set_antialiased(p_aa); + font->set_antialiasing(p_aa); font->set_hinting(p_hinting); font->set_force_autohinter(p_autohint); font->set_subpixel_positioning(p_font_subpixel_positioning); @@ -91,7 +91,7 @@ Ref<FontVariation> make_bold_font(const Ref<Font> &p_font, double p_embolden, Ty void editor_register_fonts(Ref<Theme> p_theme) { Ref<DirAccess> dir = DirAccess::create(DirAccess::ACCESS_FILESYSTEM); - bool font_antialiased = (bool)EditorSettings::get_singleton()->get("interface/editor/font_antialiased"); + TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)EditorSettings::get_singleton()->get("interface/editor/font_antialiasing"); int font_hinting_setting = (int)EditorSettings::get_singleton()->get("interface/editor/font_hinting"); TextServer::SubpixelPositioning font_subpixel_positioning = (TextServer::SubpixelPositioning)(int)EditorSettings::get_singleton()->get("interface/editor/font_subpixel_positioning"); @@ -123,47 +123,47 @@ void editor_register_fonts(Ref<Theme> p_theme) { const int default_font_size = int(EDITOR_GET("interface/editor/main_font_size")) * EDSCALE; const float embolden_strength = 0.6; - Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false); - Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); + Ref<Font> default_font = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); + Ref<Font> default_font_msdf = load_internal_font(_font_NotoSans_Regular, _font_NotoSans_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true); TypedArray<Font> fallbacks; - Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); - Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> arabic_font = load_internal_font(_font_NotoNaskhArabicUI_Regular, _font_NotoNaskhArabicUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> bengali_font = load_internal_font(_font_NotoSansBengaliUI_Regular, _font_NotoSansBengaliUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> devanagari_font = load_internal_font(_font_NotoSansDevanagariUI_Regular, _font_NotoSansDevanagariUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> georgian_font = load_internal_font(_font_NotoSansGeorgian_Regular, _font_NotoSansGeorgian_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> hebrew_font = load_internal_font(_font_NotoSansHebrew_Regular, _font_NotoSansHebrew_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> malayalam_font = load_internal_font(_font_NotoSansMalayalamUI_Regular, _font_NotoSansMalayalamUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> oriya_font = load_internal_font(_font_NotoSansOriyaUI_Regular, _font_NotoSansOriyaUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> sinhala_font = load_internal_font(_font_NotoSansSinhalaUI_Regular, _font_NotoSansSinhalaUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> tamil_font = load_internal_font(_font_NotoSansTamilUI_Regular, _font_NotoSansTamilUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> telugu_font = load_internal_font(_font_NotoSansTeluguUI_Regular, _font_NotoSansTeluguUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> thai_font = load_internal_font(_font_NotoSansThaiUI_Regular, _font_NotoSansThaiUI_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> fallback_font = load_internal_font(_font_DroidSansFallback, _font_DroidSansFallback_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); + Ref<FontFile> japanese_font = load_internal_font(_font_DroidSansJapanese, _font_DroidSansJapanese_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks); default_font->set_fallbacks(fallbacks); default_font_msdf->set_fallbacks(fallbacks); - Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false); - Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, true); + Ref<FontFile> default_font_bold = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false); + Ref<FontFile> default_font_bold_msdf = load_internal_font(_font_NotoSans_Bold, _font_NotoSans_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, true); TypedArray<Font> fallbacks_bold; - Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); - Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiased, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> arabic_font_bold = load_internal_font(_font_NotoNaskhArabicUI_Bold, _font_NotoNaskhArabicUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> bengali_font_bold = load_internal_font(_font_NotoSansBengaliUI_Bold, _font_NotoSansBengaliUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> devanagari_font_bold = load_internal_font(_font_NotoSansDevanagariUI_Bold, _font_NotoSansDevanagariUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> georgian_font_bold = load_internal_font(_font_NotoSansGeorgian_Bold, _font_NotoSansGeorgian_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> hebrew_font_bold = load_internal_font(_font_NotoSansHebrew_Bold, _font_NotoSansHebrew_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> malayalam_font_bold = load_internal_font(_font_NotoSansMalayalamUI_Bold, _font_NotoSansMalayalamUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> oriya_font_bold = load_internal_font(_font_NotoSansOriyaUI_Bold, _font_NotoSansOriyaUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> sinhala_font_bold = load_internal_font(_font_NotoSansSinhalaUI_Bold, _font_NotoSansSinhalaUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> tamil_font_bold = load_internal_font(_font_NotoSansTamilUI_Bold, _font_NotoSansTamilUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> telugu_font_bold = load_internal_font(_font_NotoSansTeluguUI_Bold, _font_NotoSansTeluguUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); + Ref<FontFile> thai_font_bold = load_internal_font(_font_NotoSansThaiUI_Bold, _font_NotoSansThaiUI_Bold_size, font_hinting, font_antialiasing, true, font_subpixel_positioning, false, &fallbacks_bold); Ref<FontVariation> fallback_font_bold = make_bold_font(fallback_font, embolden_strength, &fallbacks_bold); Ref<FontVariation> japanese_font_bold = make_bold_font(japanese_font, embolden_strength, &fallbacks_bold); default_font_bold->set_fallbacks(fallbacks_bold); default_font_bold_msdf->set_fallbacks(fallbacks_bold); - Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> default_font_mono = load_internal_font(_font_JetBrainsMono_Regular, _font_JetBrainsMono_Regular_size, font_hinting, font_antialiasing, true, font_subpixel_positioning); default_font_mono->set_fallbacks(fallbacks); // Init base font configs and load custom fonts. @@ -174,7 +174,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> default_fc; default_fc.instantiate(); if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font); @@ -191,7 +191,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> default_fc_msdf; default_fc_msdf.instantiate(); if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_msdf); @@ -208,7 +208,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> bold_fc; bold_fc.instantiate(); if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold); @@ -216,7 +216,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { } bold_fc->set_base_font(custom_font); } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold); @@ -234,7 +234,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> bold_fc_msdf; bold_fc_msdf.instantiate(); if (custom_font_path_bold.length() > 0 && dir->file_exists(custom_font_path_bold)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path_bold, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold_msdf); @@ -242,7 +242,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { } bold_fc_msdf->set_base_font(custom_font); } else if (custom_font_path.length() > 0 && dir->file_exists(custom_font_path)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_bold_msdf); @@ -260,7 +260,7 @@ void editor_register_fonts(Ref<Theme> p_theme) { Ref<FontVariation> mono_fc; mono_fc.instantiate(); if (custom_font_path_source.length() > 0 && dir->file_exists(custom_font_path_source)) { - Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiased, true, font_subpixel_positioning); + Ref<FontFile> custom_font = load_external_font(custom_font_path_source, font_hinting, font_antialiasing, true, font_subpixel_positioning); { TypedArray<Font> fallback_custom; fallback_custom.push_back(default_font_mono); diff --git a/editor/editor_help.cpp b/editor/editor_help.cpp index 7fa4303145..29a0781e96 100644 --- a/editor/editor_help.cpp +++ b/editor/editor_help.cpp @@ -44,29 +44,6 @@ DocTools *EditorHelp::doc = nullptr; -void EditorHelp::_update_theme() { - text_color = get_theme_color(SNAME("text_color"), SNAME("EditorHelp")); - title_color = get_theme_color(SNAME("title_color"), SNAME("EditorHelp")); - headline_color = get_theme_color(SNAME("headline_color"), SNAME("EditorHelp")); - comment_color = get_theme_color(SNAME("comment_color"), SNAME("EditorHelp")); - symbol_color = get_theme_color(SNAME("symbol_color"), SNAME("EditorHelp")); - value_color = get_theme_color(SNAME("value_color"), SNAME("EditorHelp")); - qualifier_color = get_theme_color(SNAME("qualifier_color"), SNAME("EditorHelp")); - type_color = get_theme_color(SNAME("type_color"), SNAME("EditorHelp")); - - class_desc->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp"))); - class_desc->add_theme_constant_override("line_separation", get_theme_constant(SNAME("line_separation"), SNAME("EditorHelp"))); - class_desc->add_theme_constant_override("table_h_separation", get_theme_constant(SNAME("table_h_separation"), SNAME("EditorHelp"))); - class_desc->add_theme_constant_override("table_v_separation", get_theme_constant(SNAME("table_v_separation"), SNAME("EditorHelp"))); - - doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts")); - doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); - doc_title_font = get_theme_font(SNAME("doc_title"), SNAME("EditorFonts")); - doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); - - doc_title_font_size = get_theme_font_size(SNAME("doc_title_size"), SNAME("EditorFonts")); -} - void EditorHelp::_search(bool p_search_previous) { if (p_search_previous) { find_bar->search_prev(); @@ -239,6 +216,27 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) { class_desc->pop(); } +void EditorHelp::_add_type_icon(const String &p_type, int p_size) { + Ref<Texture2D> icon; + if (has_theme_icon(p_type, SNAME("EditorIcons"))) { + icon = get_theme_icon(p_type, SNAME("EditorIcons")); + } else if (ClassDB::class_exists(p_type) && ClassDB::is_parent_class(p_type, "Object")) { + icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons")); + } else { + icon = get_theme_icon(SNAME("ArrowRight"), SNAME("EditorIcons")); + } + + Vector2i size = Vector2i(icon->get_width(), icon->get_height()); + if (p_size > 0) { + // Ensures icon scales proportionally on both axis, based on icon height. + float ratio = p_size / float(size.height); + size.width *= ratio; + size.height *= ratio; + } + + class_desc->add_image(icon, size.width, size.height); +} + String EditorHelp::_fix_constant(const String &p_constant) const { if (p_constant.strip_edges() == "4294967295") { return "0xFFFFFFFF"; @@ -525,27 +523,17 @@ void EditorHelp::_update_doc() { method_line.clear(); section_line.clear(); - _update_theme(); String link_color_text = title_color.to_html(false); DocData::ClassDoc cd = doc->class_list[edited_class]; // Make a copy, so we can sort without worrying. - Ref<Texture2D> icon; - if (has_theme_icon(edited_class, SNAME("EditorIcons"))) { - icon = get_theme_icon(edited_class, SNAME("EditorIcons")); - } else if (ClassDB::class_exists(edited_class) && ClassDB::is_parent_class(edited_class, "Object")) { - icon = get_theme_icon(SNAME("Object"), SNAME("EditorIcons")); - } else { - icon = get_theme_icon(SNAME("ArrowRight"), SNAME("EditorIcons")); - } - // Class name section_line.push_back(Pair<String, int>(TTR("Top"), 0)); class_desc->push_font(doc_title_font); class_desc->push_font_size(doc_title_font_size); class_desc->push_color(title_color); class_desc->add_text(TTR("Class:") + " "); - class_desc->add_image(icon, icon->get_width(), icon->get_height()); + _add_type_icon(edited_class, doc_title_font_size); class_desc->add_text(" "); class_desc->push_color(headline_color); _add_text(edited_class); @@ -566,6 +554,8 @@ void EditorHelp::_update_doc() { String inherits = cd.inherits; while (!inherits.is_empty()) { + _add_type_icon(inherits); + class_desc->add_text(" "); // Extra space, otherwise icon borrows hyperlink from _add_type(). _add_type(inherits); inherits = doc->class_list[inherits].inherits; @@ -597,7 +587,8 @@ void EditorHelp::_update_doc() { if (prev) { class_desc->add_text(" , "); } - + _add_type_icon(E.value.name); + class_desc->add_text(" "); // Extra space, otherwise icon borrows hyperlink from _add_type(). _add_type(E.value.name); prev = true; } @@ -1994,10 +1985,29 @@ void EditorHelp::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - if (is_inside_tree()) { - _class_desc_resized(true); - } + _class_desc_resized(true); update_toggle_scripts_button(); + + text_color = get_theme_color(SNAME("text_color"), SNAME("EditorHelp")); + title_color = get_theme_color(SNAME("title_color"), SNAME("EditorHelp")); + headline_color = get_theme_color(SNAME("headline_color"), SNAME("EditorHelp")); + comment_color = get_theme_color(SNAME("comment_color"), SNAME("EditorHelp")); + symbol_color = get_theme_color(SNAME("symbol_color"), SNAME("EditorHelp")); + value_color = get_theme_color(SNAME("value_color"), SNAME("EditorHelp")); + qualifier_color = get_theme_color(SNAME("qualifier_color"), SNAME("EditorHelp")); + type_color = get_theme_color(SNAME("type_color"), SNAME("EditorHelp")); + + class_desc->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp"))); + class_desc->add_theme_constant_override("line_separation", get_theme_constant(SNAME("line_separation"), SNAME("EditorHelp"))); + class_desc->add_theme_constant_override("table_h_separation", get_theme_constant(SNAME("table_h_separation"), SNAME("EditorHelp"))); + class_desc->add_theme_constant_override("table_v_separation", get_theme_constant(SNAME("table_v_separation"), SNAME("EditorHelp"))); + + doc_font = get_theme_font(SNAME("doc"), SNAME("EditorFonts")); + doc_bold_font = get_theme_font(SNAME("doc_bold"), SNAME("EditorFonts")); + doc_title_font = get_theme_font(SNAME("doc_title"), SNAME("EditorFonts")); + doc_code_font = get_theme_font(SNAME("doc_source"), SNAME("EditorFonts")); + + doc_title_font_size = get_theme_font_size(SNAME("doc_title_size"), SNAME("EditorFonts")); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -2078,7 +2088,7 @@ void EditorHelp::update_toggle_scripts_button() { } else { toggle_scripts_button->set_icon(get_theme_icon(ScriptEditor::get_singleton()->is_scripts_panel_toggled() ? SNAME("Back") : SNAME("Forward"), SNAME("EditorIcons"))); } - toggle_scripts_button->set_tooltip(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); + toggle_scripts_button->set_tooltip_text(vformat("%s (%s)", TTR("Toggle Scripts Panel"), ED_GET_SHORTCUT("script_editor/toggle_scripts_panel")->get_as_text())); } void EditorHelp::_bind_methods() { @@ -2175,7 +2185,6 @@ void EditorHelpBit::_bind_methods() { void EditorHelpBit::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { rich_text->add_theme_color_override("selection_color", get_theme_color(SNAME("selection_color"), SNAME("EditorHelp"))); rich_text->clear(); @@ -2257,7 +2266,6 @@ void FindBar::popup_search() { void FindBar::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { find_prev->set_icon(get_theme_icon(SNAME("MoveUp"), SNAME("EditorIcons"))); find_next->set_icon(get_theme_icon(SNAME("MoveDown"), SNAME("EditorIcons"))); diff --git a/editor/editor_help.h b/editor/editor_help.h index 9f8da938f1..20eb7f78fc 100644 --- a/editor/editor_help.h +++ b/editor/editor_help.h @@ -145,7 +145,6 @@ class EditorHelp : public VBoxContainer { int scroll_to = -1; - void _update_theme(); void _help_callback(const String &p_topic); void _add_text(const String &p_bbcode); @@ -153,6 +152,7 @@ class EditorHelp : public VBoxContainer { //void _button_pressed(int p_idx); void _add_type(const String &p_type, const String &p_enum = String()); + void _add_type_icon(const String &p_type, int p_size = 0); void _add_method(const DocData::MethodDoc &p_method, bool p_overview = true); void _add_bulletpoint(); diff --git a/editor/editor_help_search.cpp b/editor/editor_help_search.cpp index 297d1226e3..b4678d8363 100644 --- a/editor/editor_help_search.cpp +++ b/editor/editor_help_search.cpp @@ -206,7 +206,7 @@ EditorHelpSearch::EditorHelpSearch() { case_sensitive_button = memnew(Button); case_sensitive_button->set_flat(true); - case_sensitive_button->set_tooltip(TTR("Case Sensitive")); + case_sensitive_button->set_tooltip_text(TTR("Case Sensitive")); case_sensitive_button->connect("pressed", callable_mp(this, &EditorHelpSearch::_update_results)); case_sensitive_button->set_toggle_mode(true); case_sensitive_button->set_focus_mode(Control::FOCUS_NONE); @@ -214,7 +214,7 @@ EditorHelpSearch::EditorHelpSearch() { hierarchy_button = memnew(Button); hierarchy_button->set_flat(true); - hierarchy_button->set_tooltip(TTR("Show Hierarchy")); + hierarchy_button->set_tooltip_text(TTR("Show Hierarchy")); hierarchy_button->connect("pressed", callable_mp(this, &EditorHelpSearch::_update_results)); hierarchy_button->set_toggle_mode(true); hierarchy_button->set_pressed(true); diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 122e6ad021..21dbb5ab97 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -896,14 +896,9 @@ static Control *make_help_bit(const String &p_text, bool p_property) { } Control *EditorProperty::make_custom_tooltip(const String &p_text) const { - tooltip_text = p_text; return make_help_bit(p_text, true); } -String EditorProperty::get_tooltip_text() const { - return tooltip_text; -} - void EditorProperty::menu_option(int p_option) { switch (p_option) { case MENU_COPY_PROPERTY: { @@ -951,7 +946,6 @@ void EditorProperty::_bind_methods() { ClassDB::bind_method(D_METHOD("get_edited_property"), &EditorProperty::get_edited_property); ClassDB::bind_method(D_METHOD("get_edited_object"), &EditorProperty::get_edited_object); - ClassDB::bind_method(D_METHOD("get_tooltip_text"), &EditorProperty::get_tooltip_text); ClassDB::bind_method(D_METHOD("update_property"), &EditorProperty::update_property); ClassDB::bind_method(D_METHOD("add_focusable", "control"), &EditorProperty::add_focusable); @@ -1129,7 +1123,6 @@ void EditorInspectorCategory::_notification(int p_what) { } Control *EditorInspectorCategory::make_custom_tooltip(const String &p_text) const { - tooltip_text = p_text; return make_help_bit(p_text, false); } @@ -1148,14 +1141,6 @@ Size2 EditorInspectorCategory::get_minimum_size() const { return ms; } -void EditorInspectorCategory::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_tooltip_text"), &EditorInspectorCategory::get_tooltip_text); -} - -String EditorInspectorCategory::get_tooltip_text() const { - return tooltip_text; -} - EditorInspectorCategory::EditorInspectorCategory() { } @@ -2066,7 +2051,7 @@ void EditorInspectorArray::_setup() { ae.panel->set_mouse_filter(MOUSE_FILTER_PASS); ae.panel->set_drag_forwarding(this); ae.panel->set_meta("index", begin_array_index + i); - ae.panel->set_tooltip(vformat(TTR("Element %d: %s%d*"), i, array_element_prefix, i)); + ae.panel->set_tooltip_text(vformat(TTR("Element %d: %s%d*"), i, array_element_prefix, i)); ae.panel->connect("focus_entered", callable_mp((CanvasItem *)ae.panel, &PanelContainer::update)); ae.panel->connect("focus_exited", callable_mp((CanvasItem *)ae.panel, &PanelContainer::update)); ae.panel->connect("draw", callable_mp(this, &EditorInspectorArray::_panel_draw).bind(i)); @@ -2190,7 +2175,6 @@ bool EditorInspectorArray::can_drop_data_fw(const Point2 &p_point, const Variant void EditorInspectorArray::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { Color color = get_theme_color(SNAME("dark_color_1"), SNAME("Editor")); odd_style->set_bg_color(color.darkened(-0.08)); @@ -2384,7 +2368,6 @@ void EditorPaginator::update(int p_page, int p_max_page) { void EditorPaginator::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { first_page_button->set_icon(get_theme_icon(SNAME("PageFirst"), SNAME("EditorIcons"))); prev_page_button->set_icon(get_theme_icon(SNAME("PagePrevious"), SNAME("EditorIcons"))); @@ -2803,7 +2786,7 @@ void EditorInspector::update_tree() { class_descr_cache[doc_name] = descr; } - category->set_tooltip(p.name + "::" + (class_descr_cache[doc_name].is_empty() ? "" : class_descr_cache[doc_name])); + category->set_tooltip_text(p.name + "::" + (class_descr_cache[doc_name].is_empty() ? "" : class_descr_cache[doc_name])); } // Add editors at the start of a category. @@ -2996,7 +2979,7 @@ void EditorInspector::update_tree() { Color c = sscolor; c.a /= level; section->setup(acc_path, label, object, c, use_folding, section_depth); - section->set_tooltip(tooltip); + section->set_tooltip_text(tooltip); // Add editors at the start of a group. for (Ref<EditorInspectorPlugin> &ped : valid_plugins) { @@ -3240,9 +3223,9 @@ void EditorInspector::update_tree() { ep->connect("resource_selected", callable_mp(this, &EditorInspector::_resource_selected), CONNECT_DEFERRED); ep->connect("object_id_selected", callable_mp(this, &EditorInspector::_object_id_selected), CONNECT_DEFERRED); if (!doc_info.description.is_empty()) { - ep->set_tooltip(property_prefix + p.name + "::" + doc_info.description); + ep->set_tooltip_text(property_prefix + p.name + "::" + doc_info.description); } else { - ep->set_tooltip(property_prefix + p.name); + ep->set_tooltip_text(property_prefix + p.name); } ep->set_doc_path(doc_info.path); ep->update_property(); diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h index 905e13b3a9..474078853a 100644 --- a/editor/editor_inspector.h +++ b/editor/editor_inspector.h @@ -117,8 +117,6 @@ private: Control *bottom_editor = nullptr; PopupMenu *menu = nullptr; - mutable String tooltip_text; - HashMap<StringName, Variant> cache; GDVIRTUAL0(_update_property) @@ -199,8 +197,6 @@ public: void set_object_and_property(Object *p_object, const StringName &p_property); virtual Control *make_custom_tooltip(const String &p_text) const override; - String get_tooltip_text() const; - void set_draw_top_bg(bool p_draw) { draw_top_bg = p_draw; } bool can_revert_to_default() const { return can_revert; } @@ -254,18 +250,13 @@ class EditorInspectorCategory : public Control { Ref<Texture2D> icon; String label; - mutable String tooltip_text; - protected: void _notification(int p_what); - static void _bind_methods(); public: virtual Size2 get_minimum_size() const override; virtual Control *make_custom_tooltip(const String &p_text) const override; - String get_tooltip_text() const; - EditorInspectorCategory(); }; diff --git a/editor/editor_locale_dialog.cpp b/editor/editor_locale_dialog.cpp index 0cf7f7df2a..87da67fb05 100644 --- a/editor/editor_locale_dialog.cpp +++ b/editor/editor_locale_dialog.cpp @@ -493,7 +493,7 @@ EditorLocaleDialog::EditorLocaleDialog() { { lang_code = memnew(LineEdit); lang_code->set_max_length(3); - lang_code->set_tooltip("Language"); + lang_code->set_tooltip_text("Language"); vb_language->add_child(lang_code); } hb_locale->add_child(vb_language); @@ -509,7 +509,7 @@ EditorLocaleDialog::EditorLocaleDialog() { { script_code = memnew(LineEdit); script_code->set_max_length(4); - script_code->set_tooltip("Script"); + script_code->set_tooltip_text("Script"); vb_script->add_child(script_code); } hb_locale->add_child(vb_script); @@ -525,7 +525,7 @@ EditorLocaleDialog::EditorLocaleDialog() { { country_code = memnew(LineEdit); country_code->set_max_length(2); - country_code->set_tooltip("Country"); + country_code->set_tooltip_text("Country"); vb_country->add_child(country_code); } hb_locale->add_child(vb_country); @@ -542,7 +542,7 @@ EditorLocaleDialog::EditorLocaleDialog() { variant_code = memnew(LineEdit); variant_code->set_h_size_flags(Control::SIZE_EXPAND_FILL); variant_code->set_placeholder("Variant"); - variant_code->set_tooltip("Variant"); + variant_code->set_tooltip_text("Variant"); vb_variant->add_child(variant_code); } hb_locale->add_child(vb_variant); diff --git a/editor/editor_log.cpp b/editor/editor_log.cpp index dc03a1f270..dbb6706cb3 100644 --- a/editor/editor_log.cpp +++ b/editor/editor_log.cpp @@ -64,52 +64,48 @@ void EditorLog::_error_handler(void *p_self, const char *p_func, const char *p_f } } -void EditorLog::_update_theme() { - Ref<Font> normal_font = get_theme_font(SNAME("output_source"), SNAME("EditorFonts")); - if (normal_font.is_valid()) { - log->add_theme_font_override("normal_font", normal_font); - } - - log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts"))); - log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4)); - - Ref<Font> bold_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts")); - if (bold_font.is_valid()) { - log->add_theme_font_override("bold_font", bold_font); - } - - type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_theme_icon(SNAME("Popup"), SNAME("EditorIcons"))); - type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons"))); - type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); - type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); - - type_filter_map[MSG_TYPE_STD]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); - type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); - type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); - type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); - - clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); - copy_button->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); - collapse_button->set_icon(get_theme_icon(SNAME("CombineLines"), SNAME("EditorIcons"))); - show_search_button->set_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - - theme_cache.error_color = get_theme_color(SNAME("error_color"), SNAME("Editor")); - theme_cache.error_icon = get_theme_icon(SNAME("Error"), SNAME("EditorIcons")); - theme_cache.warning_color = get_theme_color(SNAME("warning_color"), SNAME("Editor")); - theme_cache.warning_icon = get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")); - theme_cache.message_color = get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.6); -} - void EditorLog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - _update_theme(); _load_state(); } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + Ref<Font> normal_font = get_theme_font(SNAME("output_source"), SNAME("EditorFonts")); + if (normal_font.is_valid()) { + log->add_theme_font_override("normal_font", normal_font); + } + + log->add_theme_font_size_override("normal_font_size", get_theme_font_size(SNAME("output_source_size"), SNAME("EditorFonts"))); + log->add_theme_color_override("selection_color", get_theme_color(SNAME("accent_color"), SNAME("Editor")) * Color(1, 1, 1, 0.4)); + + Ref<Font> bold_font = get_theme_font(SNAME("bold"), SNAME("EditorFonts")); + if (bold_font.is_valid()) { + log->add_theme_font_override("bold_font", bold_font); + } + + type_filter_map[MSG_TYPE_STD]->toggle_button->set_icon(get_theme_icon(SNAME("Popup"), SNAME("EditorIcons"))); + type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_icon(get_theme_icon(SNAME("StatusError"), SNAME("EditorIcons"))); + type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_icon(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); + type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); + + type_filter_map[MSG_TYPE_STD]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + type_filter_map[MSG_TYPE_ERROR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + type_filter_map[MSG_TYPE_WARNING]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + type_filter_map[MSG_TYPE_EDITOR]->toggle_button->set_theme_type_variation("EditorLogFilterButton"); + + clear_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); + copy_button->set_icon(get_theme_icon(SNAME("ActionCopy"), SNAME("EditorIcons"))); + collapse_button->set_icon(get_theme_icon(SNAME("CombineLines"), SNAME("EditorIcons"))); + show_search_button->set_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + + theme_cache.error_color = get_theme_color(SNAME("error_color"), SNAME("Editor")); + theme_cache.error_icon = get_theme_icon(SNAME("Error"), SNAME("EditorIcons")); + theme_cache.warning_color = get_theme_color(SNAME("warning_color"), SNAME("Editor")); + theme_cache.warning_icon = get_theme_icon(SNAME("Warning"), SNAME("EditorIcons")); + theme_cache.message_color = get_theme_color(SNAME("font_color"), SNAME("Editor")) * Color(1, 1, 1, 0.6); + _rebuild_log(); } break; } @@ -252,6 +248,11 @@ void EditorLog::_rebuild_log() { } void EditorLog::_add_log_line(LogMessage &p_message, bool p_replace_previous) { + if (!is_inside_tree()) { + // The log will be built all at once when it enters the tree and has its theme items. + return; + } + // Only add the message to the log if it passes the filters. bool filter_active = type_filter_map[p_message.type]->is_active(); String search_text = search_box->get_text(); @@ -414,7 +415,7 @@ EditorLog::EditorLog() { collapse_button = memnew(Button); collapse_button->set_flat(true); collapse_button->set_focus_mode(FOCUS_NONE); - collapse_button->set_tooltip(TTR("Collapse duplicate messages into one log entry. Shows number of occurrences.")); + collapse_button->set_tooltip_text(TTR("Collapse duplicate messages into one log entry. Shows number of occurrences.")); collapse_button->set_toggle_mode(true); collapse_button->set_pressed(false); collapse_button->connect("toggled", callable_mp(this, &EditorLog::_set_collapse)); diff --git a/editor/editor_log.h b/editor/editor_log.h index 3bdfd936c1..0e17eb7949 100644 --- a/editor/editor_log.h +++ b/editor/editor_log.h @@ -95,7 +95,7 @@ private: toggle_button->set_toggle_mode(true); toggle_button->set_pressed(true); toggle_button->set_text(itos(message_count)); - toggle_button->set_tooltip(TTR(p_tooltip)); + toggle_button->set_tooltip_text(TTR(p_tooltip)); // Don't tint the icon even when in "pressed" state. toggle_button->add_theme_color_override("icon_color_pressed", Color(1, 1, 1, 1)); toggle_button->set_focus_mode(FOCUS_NONE); @@ -175,8 +175,6 @@ private: void _save_state(); void _load_state(); - void _update_theme(); - protected: static void _bind_methods(); void _notification(int p_what); diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 4aedd98bd3..9a188bbe38 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -845,7 +845,7 @@ void EditorNode::_update_update_spinner() { update_popup->set_item_checked(update_popup->get_item_index(SETTINGS_UPDATE_WHEN_CHANGED), !update_continuously); if (update_continuously) { - update_spinner->set_tooltip(TTR("Spins when the editor window redraws.\nUpdate Continuously is enabled, which can increase power usage. Click to disable it.")); + update_spinner->set_tooltip_text(TTR("Spins when the editor window redraws.\nUpdate Continuously is enabled, which can increase power usage. Click to disable it.")); // Use a different color for the update spinner when Update Continuously is enabled, // as this feature should only be enabled for troubleshooting purposes. @@ -855,7 +855,7 @@ void EditorNode::_update_update_spinner() { update_spinner->set_self_modulate( gui_base->get_theme_color(SNAME("error_color"), SNAME("Editor")) * (dark_theme ? Color(1.1, 1.1, 1.1) : Color(4.25, 4.25, 4.25))); } else { - update_spinner->set_tooltip(TTR("Spins when the editor window redraws.")); + update_spinner->set_tooltip_text(TTR("Spins when the editor window redraws.")); update_spinner->set_self_modulate(Color(1, 1, 1)); } @@ -2432,7 +2432,7 @@ void EditorNode::_run(bool p_current, const String &p_custom) { String run_filename; - if (p_current || (editor_data.get_edited_scene_root() && !p_custom.is_empty() && p_custom == editor_data.get_edited_scene_root()->get_scene_file_path())) { + if ((p_current && p_custom.is_empty()) || (editor_data.get_edited_scene_root() && !p_custom.is_empty() && p_custom == editor_data.get_edited_scene_root()->get_scene_file_path())) { Node *scene = editor_data.get_edited_scene_root(); if (!scene) { @@ -2494,15 +2494,19 @@ void EditorNode::_run(bool p_current, const String &p_custom) { emit_signal(SNAME("play_pressed")); if (p_current) { + run_current_filename = run_filename; play_scene_button->set_pressed(true); play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); + play_scene_button->set_tooltip_text(TTR("Reload the played scene.")); } else if (!p_custom.is_empty()) { run_custom_filename = p_custom; play_custom_scene_button->set_pressed(true); play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); + play_custom_scene_button->set_tooltip_text(TTR("Reload the played scene.")); } else { play_button->set_pressed(true); play_button->set_icon(gui_base->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); + play_button->set_tooltip_text(TTR("Reload the played scene.")); } stop_button->set_disabled(false); @@ -2527,9 +2531,22 @@ void EditorNode::_run_native(const Ref<EditorExportPreset> &p_preset) { } } +void EditorNode::_reset_play_buttons() { + play_button->set_pressed(false); + play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); + play_button->set_tooltip_text(TTR("Play the project.")); + play_scene_button->set_pressed(false); + play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); + play_scene_button->set_tooltip_text(TTR("Play the edited scene.")); + play_custom_scene_button->set_pressed(false); + play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); + play_custom_scene_button->set_tooltip_text(TTR("Play a custom scene.")); +} + void EditorNode::_android_build_source_selected(const String &p_file) { export_template_manager->install_android_template_from_file(p_file); } + void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (!p_confirmed) { // FIXME: this may be a hack. current_menu_option = (MenuOptions)p_option; @@ -2821,7 +2838,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { quick_run->set_title(TTR("Quick Run Scene...")); play_custom_scene_button->set_pressed(false); } else { - String last_custom_scene = run_custom_filename; + String last_custom_scene = run_custom_filename; // This is necessary to have a copy of the string. run_play_custom(last_custom_scene); } @@ -2833,13 +2850,9 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { editor_run.stop(); run_custom_filename.clear(); - play_button->set_pressed(false); - play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); - play_scene_button->set_pressed(false); - play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); - play_custom_scene_button->set_pressed(false); - play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); + run_current_filename.clear(); stop_button->set_disabled(true); + _reset_play_buttons(); if (bool(EDITOR_GET("run/output/always_close_output_on_stop"))) { for (int i = 0; i < bottom_panel_items.size(); i++) { @@ -2862,7 +2875,12 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { } break; case RUN_PLAY_SCENE: { - run_play_current(); + if (run_current_filename.is_empty() || editor_run.get_status() == EditorRun::STATUS_STOP) { + run_play_current(); + } else { + String last_current_scene = run_current_filename; // This is necessary to have a copy of the string. + run_play_custom(last_current_scene); + } } break; case RUN_SETTINGS: { @@ -3684,6 +3702,18 @@ void EditorNode::fix_dependencies(const String &p_for_file) { int EditorNode::new_scene() { int idx = editor_data.add_edited_scene(-1); + // Remove placeholder empty scene. + if (editor_data.get_edited_scene_count() > 1) { + for (int i = 0; i < editor_data.get_edited_scene_count() - 1; i++) { + bool unsaved = get_undo_redo()->is_history_unsaved(editor_data.get_scene_history_id(i)); + if (!unsaved && editor_data.get_scene_path(i).is_empty()) { + editor_data.remove_scene(i); + idx--; + } + } + } + idx = MAX(idx, 0); + _scene_tab_changed(idx); editor_data.clear_editor_states(); _update_scene_tabs(); @@ -5066,8 +5096,9 @@ void EditorNode::run_play_current() { } void EditorNode::run_play_custom(const String &p_custom) { + bool is_current = !run_current_filename.is_empty(); _menu_option_confirm(RUN_STOP, true); - _run(false, p_custom); + _run(is_current, p_custom); } void EditorNode::run_stop() { @@ -6295,7 +6326,7 @@ EditorNode::EditorNode() { main_vbox->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT, Control::PRESET_MODE_MINSIZE, 8); main_vbox->add_theme_constant_override("separation", 8 * EDSCALE); - menu_hb = memnew(HBoxContainer); + menu_hb = memnew(EditorTitleBar); main_vbox->add_child(menu_hb); left_l_hsplit = memnew(HSplitContainer); @@ -6484,7 +6515,7 @@ EditorNode::EditorNode() { scene_tab_add = memnew(Button); scene_tab_add->set_flat(true); - scene_tab_add->set_tooltip(TTR("Add a new scene.")); + scene_tab_add->set_tooltip_text(TTR("Add a new scene.")); scene_tab_add->set_icon(gui_base->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); scene_tab_add->add_theme_color_override("icon_normal_color", Color(0.6f, 0.6f, 0.6f, 0.8f)); scene_tabs->add_child(scene_tab_add); @@ -6500,7 +6531,7 @@ EditorNode::EditorNode() { ED_SHORTCUT_AND_COMMAND("editor/distraction_free_mode", TTR("Distraction Free Mode"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F11); ED_SHORTCUT_OVERRIDE("editor/distraction_free_mode", "macos", KeyModifierMask::CMD | KeyModifierMask::CTRL | Key::D); distraction_free->set_shortcut(ED_GET_SHORTCUT("editor/distraction_free_mode")); - distraction_free->set_tooltip(TTR("Toggle distraction-free mode.")); + distraction_free->set_tooltip_text(TTR("Toggle distraction-free mode.")); distraction_free->connect("pressed", callable_mp(this, &EditorNode::_toggle_distraction_free_mode)); distraction_free->set_icon(gui_base->get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons"))); distraction_free->set_toggle_mode(true); @@ -6526,6 +6557,15 @@ EditorNode::EditorNode() { scene_root_parent->add_child(main_control); bool global_menu = !bool(EDITOR_GET("interface/editor/use_embedded_menu")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU); + bool can_expand = bool(EDITOR_GET("interface/editor/expand_to_title")) && DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_EXTEND_TO_TITLE); + + if (can_expand) { + // Add spacer to avoid other controls under window minimize/maximize/close buttons (left side). + Control *menu_spacer = memnew(Control); + menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_spacer->set_custom_minimum_size(Size2(DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID).x, 0)); + menu_hb->add_child(menu_spacer); + } main_menu = memnew(MenuBar); menu_hb->add_child(main_menu); @@ -6543,7 +6583,7 @@ EditorNode::EditorNode() { prev_scene = memnew(Button); prev_scene->set_flat(true); prev_scene->set_icon(gui_base->get_theme_icon(SNAME("PrevScene"), SNAME("EditorIcons"))); - prev_scene->set_tooltip(TTR("Go to previously opened scene.")); + prev_scene->set_tooltip_text(TTR("Go to previously opened scene.")); prev_scene->set_disabled(true); prev_scene->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(FILE_OPEN_PREV)); gui_base->add_child(prev_scene); @@ -6695,6 +6735,11 @@ EditorNode::EditorNode() { ED_SHORTCUT_OVERRIDE("editor/quit_to_project_list", "macos", KeyModifierMask::SHIFT + KeyModifierMask::ALT + Key::Q); project_menu->add_shortcut(ED_GET_SHORTCUT("editor/quit_to_project_list"), RUN_PROJECT_MANAGER, true); + // Spacer to center 2D / 3D / Script buttons. + Control *left_spacer = memnew(Control); + left_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_hb->add_child(left_spacer); + menu_hb->add_spacer(); main_editor_button_vb = memnew(HBoxContainer); @@ -6772,7 +6817,9 @@ EditorNode::EditorNode() { } help_menu->add_icon_shortcut(gui_base->get_theme_icon(SNAME("Heart"), SNAME("EditorIcons")), ED_SHORTCUT_AND_COMMAND("editor/support_development", TTR("Support Godot Development")), HELP_SUPPORT_GODOT_DEVELOPMENT); + // Spacer to center 2D / 3D / Script buttons. Control *right_spacer = memnew(Control); + right_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); menu_hb->add_child(right_spacer); HBoxContainer *play_hb = memnew(HBoxContainer); @@ -6782,10 +6829,8 @@ EditorNode::EditorNode() { play_button->set_flat(true); play_hb->add_child(play_button); play_button->set_toggle_mode(true); - play_button->set_icon(gui_base->get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); play_button->set_focus_mode(Control::FOCUS_NONE); play_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY)); - play_button->set_tooltip(TTR("Play the project.")); ED_SHORTCUT_AND_COMMAND("editor/play", TTR("Play"), Key::F5); ED_SHORTCUT_OVERRIDE("editor/play", "macos", KeyModifierMask::CMD | Key::B); @@ -6796,7 +6841,7 @@ EditorNode::EditorNode() { pause_button->set_toggle_mode(true); pause_button->set_icon(gui_base->get_theme_icon(SNAME("Pause"), SNAME("EditorIcons"))); pause_button->set_focus_mode(Control::FOCUS_NONE); - pause_button->set_tooltip(TTR("Pause the scene execution for debugging.")); + pause_button->set_tooltip_text(TTR("Pause the scene execution for debugging.")); pause_button->set_disabled(true); play_hb->add_child(pause_button); @@ -6810,7 +6855,7 @@ EditorNode::EditorNode() { stop_button->set_focus_mode(Control::FOCUS_NONE); stop_button->set_icon(gui_base->get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); stop_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_STOP)); - stop_button->set_tooltip(TTR("Stop the scene.")); + stop_button->set_tooltip_text(TTR("Stop the scene.")); stop_button->set_disabled(true); ED_SHORTCUT("editor/stop", TTR("Stop"), Key::F8); @@ -6826,9 +6871,7 @@ EditorNode::EditorNode() { play_hb->add_child(play_scene_button); play_scene_button->set_toggle_mode(true); play_scene_button->set_focus_mode(Control::FOCUS_NONE); - play_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayScene"), SNAME("EditorIcons"))); play_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_SCENE)); - play_scene_button->set_tooltip(TTR("Play the edited scene.")); ED_SHORTCUT_AND_COMMAND("editor/play_scene", TTR("Play Scene"), Key::F6); ED_SHORTCUT_OVERRIDE("editor/play_scene", "macos", KeyModifierMask::CMD | Key::R); @@ -6839,9 +6882,9 @@ EditorNode::EditorNode() { play_hb->add_child(play_custom_scene_button); play_custom_scene_button->set_toggle_mode(true); play_custom_scene_button->set_focus_mode(Control::FOCUS_NONE); - play_custom_scene_button->set_icon(gui_base->get_theme_icon(SNAME("PlayCustom"), SNAME("EditorIcons"))); play_custom_scene_button->connect("pressed", callable_mp(this, &EditorNode::_menu_option).bind(RUN_PLAY_CUSTOM_SCENE)); - play_custom_scene_button->set_tooltip(TTR("Play custom scene")); + + _reset_play_buttons(); ED_SHORTCUT_AND_COMMAND("editor/play_custom_scene", TTR("Play Custom Scene"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::F5); ED_SHORTCUT_OVERRIDE("editor/play_custom_scene", "macos", KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::R); @@ -6854,7 +6897,7 @@ EditorNode::EditorNode() { write_movie_button->set_pressed(false); write_movie_button->set_icon(gui_base->get_theme_icon(SNAME("MainMovieWrite"), SNAME("EditorIcons"))); write_movie_button->set_focus_mode(Control::FOCUS_NONE); - write_movie_button->set_tooltip(TTR("Enable Movie Maker mode.\nThe project will run at stable FPS and the visual and audio output will be recorded to a video file.")); + write_movie_button->set_tooltip_text(TTR("Enable Movie Maker mode.\nThe project will run at stable FPS and the visual and audio output will be recorded to a video file.")); // This button behaves differently, so color it as such. write_movie_button->add_theme_color_override("icon_normal_color", Color(1, 1, 1, 0.7)); @@ -6878,6 +6921,14 @@ EditorNode::EditorNode() { right_menu_hb->add_child(rendering_driver); + if (can_expand) { + // Add spacer to avoid other controls under the window minimize/maximize/close buttons (right side). + Control *menu_spacer = memnew(Control); + menu_spacer->set_mouse_filter(Control::MOUSE_FILTER_PASS); + menu_spacer->set_custom_minimum_size(Size2(DisplayServer::get_singleton()->window_get_safe_title_margins(DisplayServer::MAIN_WINDOW_ID).y, 0)); + menu_hb->add_child(menu_spacer); + } + // Only display the render drivers that are available for this display driver. int display_driver_idx = OS::get_singleton()->get_display_driver_id(); Vector<String> render_drivers = DisplayServer::get_create_function_rendering_drivers(display_driver_idx); @@ -7033,7 +7084,7 @@ EditorNode::EditorNode() { // Fade out the version label to be less prominent, but still readable. version_btn->set_self_modulate(Color(1, 1, 1, 0.65)); version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); - version_btn->set_tooltip(TTR("Click to copy.")); + version_btn->set_tooltip_text(TTR("Click to copy.")); version_btn->connect("pressed", callable_mp(this, &EditorNode::_version_button_pressed)); version_info_vbc->add_child(version_btn); @@ -7294,7 +7345,7 @@ EditorNode::EditorNode() { canvas_item_mat_convert.instantiate(); resource_conversion_plugins.push_back(canvas_item_mat_convert); - Ref<ParticlesMaterialConversionPlugin> particles_mat_convert; + Ref<ParticleProcessMaterialConversionPlugin> particles_mat_convert; particles_mat_convert.instantiate(); resource_conversion_plugins.push_back(particles_mat_convert); @@ -7434,8 +7485,16 @@ EditorNode::EditorNode() { add_child(screenshot_timer); screenshot_timer->set_owner(get_owner()); - main_menu->set_custom_minimum_size(Size2(MAX(main_menu->get_minimum_size().x, play_hb->get_minimum_size().x + right_menu_hb->get_minimum_size().x), 0)); - right_spacer->set_custom_minimum_size(Size2(MAX(0, main_menu->get_minimum_size().x - play_hb->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + // Adjust spacers to center 2D / 3D / Script buttons. + int max_w = MAX(play_hb->get_minimum_size().x + right_menu_hb->get_minimum_size().x, main_menu->get_minimum_size().x); + left_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - main_menu->get_minimum_size().x), 0)); + right_spacer->set_custom_minimum_size(Size2(MAX(0, max_w - play_hb->get_minimum_size().x - right_menu_hb->get_minimum_size().x), 0)); + + // Extend menu bar to window title. + if (can_expand) { + DisplayServer::get_singleton()->window_set_flag(DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE, true, DisplayServer::MAIN_WINDOW_ID); + menu_hb->set_can_move_window(true); + } String exec = OS::get_singleton()->get_executable_path(); // Save editor executable path for third-party tools. diff --git a/editor/editor_node.h b/editor/editor_node.h index 91c753e480..792d2fc879 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -35,6 +35,7 @@ #include "editor/editor_folding.h" #include "editor/editor_native_shader_source_visualizer.h" #include "editor/editor_run.h" +#include "editor/editor_title_bar.h" #include "editor/export/editor_export.h" #include "editor/inspector_dock.h" @@ -322,7 +323,7 @@ private: HBoxContainer *bottom_hb = nullptr; Control *vp_base = nullptr; - HBoxContainer *menu_hb = nullptr; + EditorTitleBar *menu_hb = nullptr; Control *main_control = nullptr; MenuBar *main_menu = nullptr; PopupMenu *file_menu = nullptr; @@ -470,7 +471,9 @@ private: String _tmp_import_path; String external_file; String open_navigate; + String run_custom_filename; + String run_current_filename; DynamicFontImportSettings *fontdata_import_settings = nullptr; SceneImportSettings *scene_import_settings = nullptr; @@ -580,6 +583,7 @@ private: void _run(bool p_current = false, const String &p_custom = ""); void _run_native(const Ref<EditorExportPreset> &p_preset); + void _reset_play_buttons(); void _add_to_recent_scenes(const String &p_scene); void _update_recent_scenes(); diff --git a/editor/editor_path.cpp b/editor/editor_path.cpp index 87ebd3e1c1..b8b6d57c08 100644 --- a/editor/editor_path.cpp +++ b/editor/editor_path.cpp @@ -80,6 +80,11 @@ void EditorPath::_add_children_to_popup(Object *p_obj, int p_depth) { } void EditorPath::_show_popup() { + if (sub_objects_menu->is_visible()) { + sub_objects_menu->hide(); + return; + } + sub_objects_menu->clear(); Size2 size = get_size(); @@ -145,14 +150,14 @@ void EditorPath::update_path() { } current_object_label->set_text(" " + name); // An extra space so the text is not too close of the icon. - set_tooltip(obj->get_class()); + set_tooltip_text(obj->get_class()); } } } void EditorPath::clear_path() { set_disabled(true); - set_tooltip(""); + set_tooltip_text(""); current_object_label->set_text(""); current_object_icon->set_texture(nullptr); @@ -177,7 +182,6 @@ void EditorPath::_id_pressed(int p_idx) { void EditorPath::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { update_path(); @@ -226,5 +230,5 @@ EditorPath::EditorPath(EditorSelectionHistory *p_history) { sub_objects_menu->connect("about_to_popup", callable_mp(this, &EditorPath::_about_to_show)); sub_objects_menu->connect("id_pressed", callable_mp(this, &EditorPath::_id_pressed)); - set_tooltip(TTR("Open a list of sub-resources.")); + set_tooltip_text(TTR("Open a list of sub-resources.")); } diff --git a/editor/editor_properties.cpp b/editor/editor_properties.cpp index 84c4c9c877..c3fd46c511 100644 --- a/editor/editor_properties.cpp +++ b/editor/editor_properties.cpp @@ -99,6 +99,10 @@ void EditorPropertyText::set_string_name(bool p_enabled) { string_name = p_enabled; } +void EditorPropertyText::set_secret(bool p_enabled) { + text->set_secret(p_enabled); +} + void EditorPropertyText::set_placeholder(const String &p_string) { text->set_placeholder(p_string); } @@ -163,8 +167,7 @@ void EditorPropertyMultilineText::update_property() { void EditorPropertyMultilineText::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_THEME_CHANGED: { Ref<Texture2D> df = get_theme_icon(SNAME("DistractionFree"), SNAME("EditorIcons")); open_big_text->set_icon(df); @@ -318,7 +321,6 @@ void EditorPropertyTextEnum::_bind_methods() { void EditorPropertyTextEnum::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { edit_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); accept_button->set_icon(get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons"))); @@ -392,7 +394,7 @@ void EditorPropertyLocale::_locale_pressed() { void EditorPropertyLocale::update_property() { String locale_code = get_edited_object()->get(get_edited_property()); locale->set_text(locale_code); - locale->set_tooltip(locale_code); + locale->set_tooltip_text(locale_code); } void EditorPropertyLocale::setup(const String &p_hint_text) { @@ -400,7 +402,6 @@ void EditorPropertyLocale::setup(const String &p_hint_text) { void EditorPropertyLocale::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { locale_edit->set_icon(get_theme_icon(SNAME("Translation"), SNAME("EditorIcons"))); } break; @@ -481,7 +482,7 @@ void EditorPropertyPath::_path_pressed() { void EditorPropertyPath::update_property() { String full_path = get_edited_object()->get(get_edited_property()); path->set_text(full_path); - path->set_tooltip(full_path); + path->set_tooltip_text(full_path); } void EditorPropertyPath::setup(const Vector<String> &p_extensions, bool p_folder, bool p_global) { @@ -496,7 +497,6 @@ void EditorPropertyPath::set_save_mode() { void EditorPropertyPath::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { path_edit->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } break; @@ -1149,7 +1149,6 @@ void EditorPropertyLayersGrid::_bind_methods() { void EditorPropertyLayers::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { button->set_normal_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); button->set_pressed_texture(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); @@ -1458,7 +1457,7 @@ void EditorPropertyFloat::_value_changed(double val) { } if (angle_in_radians) { - val = Math::deg2rad(val); + val = Math::deg_to_rad(val); } emit_changed(get_edited_property(), val); } @@ -1466,7 +1465,7 @@ void EditorPropertyFloat::_value_changed(double val) { void EditorPropertyFloat::update_property() { double val = get_edited_object()->get(get_edited_property()); if (angle_in_radians) { - val = Math::rad2deg(val); + val = Math::rad_to_deg(val); } setting = true; spin->set_value(val); @@ -1673,8 +1672,7 @@ void EditorPropertyEasing::setup(bool p_positive_only, bool p_flip) { void EditorPropertyEasing::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_THEME_CHANGED: { preset->clear(); preset->add_icon_item(get_theme_icon(SNAME("CurveLinear"), SNAME("EditorIcons")), "Linear", EASING_LINEAR); preset->add_icon_item(get_theme_icon(SNAME("CurveIn"), SNAME("EditorIcons")), "Ease In", EASING_IN); @@ -1771,7 +1769,6 @@ void EditorPropertyVector2::_update_ratio() { void EditorPropertyVector2::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); @@ -1881,7 +1878,6 @@ void EditorPropertyRect2::update_property() { void EditorPropertyRect2::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { @@ -1988,9 +1984,9 @@ void EditorPropertyVector3::_value_changed(double val, const String &p_name) { v3.y = spin[1]->get_value(); v3.z = spin[2]->get_value(); if (angle_in_radians) { - v3.x = Math::deg2rad(v3.x); - v3.y = Math::deg2rad(v3.y); - v3.z = Math::deg2rad(v3.z); + v3.x = Math::deg_to_rad(v3.x); + v3.y = Math::deg_to_rad(v3.y); + v3.z = Math::deg_to_rad(v3.z); } emit_changed(get_edited_property(), v3, p_name); } @@ -2022,9 +2018,9 @@ void EditorPropertyVector3::_update_ratio() { void EditorPropertyVector3::update_using_vector(Vector3 p_vector) { if (angle_in_radians) { - p_vector.x = Math::rad2deg(p_vector.x); - p_vector.y = Math::rad2deg(p_vector.y); - p_vector.z = Math::rad2deg(p_vector.z); + p_vector.x = Math::rad_to_deg(p_vector.x); + p_vector.y = Math::rad_to_deg(p_vector.y); + p_vector.z = Math::rad_to_deg(p_vector.z); } setting = true; spin[0]->set_value(p_vector.x); @@ -2039,9 +2035,9 @@ Vector3 EditorPropertyVector3::get_vector() { v3.y = spin[1]->get_value(); v3.z = spin[2]->get_value(); if (angle_in_radians) { - v3.x = Math::deg2rad(v3.x); - v3.y = Math::deg2rad(v3.y); - v3.z = Math::deg2rad(v3.z); + v3.x = Math::deg_to_rad(v3.x); + v3.y = Math::deg_to_rad(v3.y); + v3.z = Math::deg_to_rad(v3.z); } return v3; @@ -2049,7 +2045,6 @@ Vector3 EditorPropertyVector3::get_vector() { void EditorPropertyVector3::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); @@ -2184,7 +2179,6 @@ void EditorPropertyVector2i::_update_ratio() { void EditorPropertyVector2i::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); @@ -2294,7 +2288,6 @@ void EditorPropertyRect2i::update_property() { void EditorPropertyRect2i::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { @@ -2435,7 +2428,6 @@ void EditorPropertyVector3i::_update_ratio() { void EditorPropertyVector3i::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { linked->set_normal_texture(get_theme_icon(SNAME("Unlinked"), SNAME("EditorIcons"))); linked->set_pressed_texture(get_theme_icon(SNAME("Instance"), SNAME("EditorIcons"))); @@ -2547,7 +2539,6 @@ void EditorPropertyPlane::update_property() { void EditorPropertyPlane::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { @@ -2643,9 +2634,9 @@ void EditorPropertyQuaternion::_custom_value_changed(double val) { edit_euler.z = euler[2]->get_value(); Vector3 v; - v.x = Math::deg2rad(edit_euler.x); - v.y = Math::deg2rad(edit_euler.y); - v.z = Math::deg2rad(edit_euler.z); + v.x = Math::deg_to_rad(edit_euler.x); + v.y = Math::deg_to_rad(edit_euler.y); + v.z = Math::deg_to_rad(edit_euler.z); Quaternion temp_q = Quaternion(v); spin[0]->set_value(temp_q.x); @@ -2685,9 +2676,9 @@ void EditorPropertyQuaternion::update_property() { spin[3]->set_value(val.w); if (!is_grabbing_euler()) { Vector3 v = val.normalized().get_euler_yxz(); - edit_euler.x = Math::rad2deg(v.x); - edit_euler.y = Math::rad2deg(v.y); - edit_euler.z = Math::rad2deg(v.z); + edit_euler.x = Math::rad_to_deg(v.x); + edit_euler.y = Math::rad_to_deg(v.y); + edit_euler.z = Math::rad_to_deg(v.z); euler[0]->set_value(edit_euler.x); euler[1]->set_value(edit_euler.y); euler[2]->set_value(edit_euler.z); @@ -2701,7 +2692,6 @@ void EditorPropertyQuaternion::_warning_pressed() { void EditorPropertyQuaternion::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { @@ -2856,7 +2846,6 @@ void EditorPropertyVector4::update_property() { void EditorPropertyVector4::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { @@ -2948,7 +2937,6 @@ void EditorPropertyVector4i::update_property() { void EditorPropertyVector4i::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 4; i++) { @@ -3043,7 +3031,6 @@ void EditorPropertyAABB::update_property() { void EditorPropertyAABB::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 6; i++) { @@ -3126,7 +3113,6 @@ void EditorPropertyTransform2D::update_property() { void EditorPropertyTransform2D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 6; i++) { @@ -3223,7 +3209,6 @@ void EditorPropertyBasis::update_property() { void EditorPropertyBasis::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 9; i++) { @@ -3321,7 +3306,6 @@ void EditorPropertyTransform3D::update_using_transform(Transform3D p_transform) void EditorPropertyTransform3D::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 12; i++) { @@ -3427,7 +3411,6 @@ void EditorPropertyProjection::update_using_transform(Projection p_transform) { void EditorPropertyProjection::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { const Color *colors = _get_property_colors(); for (int i = 0; i < 16; i++) { @@ -3498,7 +3481,6 @@ void EditorPropertyColor::_picker_opening() { void EditorPropertyColor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { picker->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); } break; @@ -3511,14 +3493,14 @@ void EditorPropertyColor::update_property() { // Add a tooltip to display each channel's values without having to click the ColorPickerButton if (picker->is_editing_alpha()) { - picker->set_tooltip(vformat( + picker->set_tooltip_text(vformat( "R: %s\nG: %s\nB: %s\nA: %s", rtos(color.r).pad_decimals(2), rtos(color.g).pad_decimals(2), rtos(color.b).pad_decimals(2), rtos(color.a).pad_decimals(2))); } else { - picker->set_tooltip(vformat( + picker->set_tooltip_text(vformat( "R: %s\nG: %s\nB: %s", rtos(color.r).pad_decimals(2), rtos(color.g).pad_decimals(2), @@ -3676,7 +3658,7 @@ void EditorPropertyNodePath::update_property() { p = get_edited_object()->get(get_edited_property()); } - assign->set_tooltip(p); + assign->set_tooltip_text(p); if (p == NodePath()) { assign->set_icon(Ref<Texture2D>()); assign->set_text(TTR("Assign...")); @@ -3722,7 +3704,6 @@ void EditorPropertyNodePath::setup(const NodePath &p_base_hint, Vector<StringNam void EditorPropertyNodePath::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { Ref<Texture2D> t = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")); clear->set_icon(t); @@ -4134,7 +4115,6 @@ void EditorPropertyResource::set_use_sub_inspector(bool p_enable) { void EditorPropertyResource::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (!updating_theme) { _update_property_bg(); @@ -4408,6 +4388,9 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyText *editor = memnew(EditorPropertyText); if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) { editor->set_placeholder(p_hint_text); + } else if (p_hint == PROPERTY_HINT_PASSWORD) { + editor->set_secret(true); + editor->set_placeholder(p_hint_text); } return editor; } @@ -4532,6 +4515,9 @@ EditorProperty *EditorInspectorDefaultPlugin::get_editor_for_property(Object *p_ EditorPropertyText *editor = memnew(EditorPropertyText); if (p_hint == PROPERTY_HINT_PLACEHOLDER_TEXT) { editor->set_placeholder(p_hint_text); + } else if (p_hint == PROPERTY_HINT_PASSWORD) { + editor->set_secret(true); + editor->set_placeholder(p_hint_text); } editor->set_string_name(true); return editor; diff --git a/editor/editor_properties.h b/editor/editor_properties.h index 6ac3973303..d6c9510634 100644 --- a/editor/editor_properties.h +++ b/editor/editor_properties.h @@ -67,6 +67,7 @@ public: void set_string_name(bool p_enabled); virtual void update_property() override; void set_placeholder(const String &p_string); + void set_secret(bool p_enabled); EditorPropertyText(); }; diff --git a/editor/editor_properties_array_dict.cpp b/editor/editor_properties_array_dict.cpp index 9a83082d1e..fa7e5cf4a9 100644 --- a/editor/editor_properties_array_dict.cpp +++ b/editor/editor_properties_array_dict.cpp @@ -485,8 +485,7 @@ void EditorPropertyArray::drop_data_fw(const Point2 &p_point, const Variant &p_d void EditorPropertyArray::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_THEME_CHANGED: { change_type->clear(); for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (i == Variant::CALLABLE || i == Variant::SIGNAL || i == Variant::RID) { @@ -1111,7 +1110,7 @@ void EditorPropertyDictionary::update_property() { if (i < amount) { String cs = key.get_construct_string(); prop->set_label(key.get_construct_string()); - prop->set_tooltip(cs); + prop->set_tooltip_text(cs); change_index = i + offset; } else if (i == amount) { prop->set_label(TTR("New Key:")); @@ -1166,8 +1165,7 @@ void EditorPropertyDictionary::_object_id_selected(const StringName &p_property, void EditorPropertyDictionary::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_THEME_CHANGED: { change_type->clear(); for (int i = 0; i < Variant::VARIANT_MAX; i++) { if (i == Variant::CALLABLE || i == Variant::SIGNAL || i == Variant::RID) { @@ -1361,7 +1359,7 @@ void EditorPropertyLocalizableString::update_property() { String cs = key.get_construct_string(); prop->set_label(cs); - prop->set_tooltip(cs); + prop->set_tooltip_text(cs); remove_index = i + offset; prop->set_selectable(false); @@ -1405,8 +1403,7 @@ void EditorPropertyLocalizableString::_object_id_selected(const StringName &p_pr void EditorPropertyLocalizableString::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_THEME_CHANGED: { if (Object::cast_to<Button>(button_add_item)) { button_add_item->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); } diff --git a/editor/editor_property_name_processor.cpp b/editor/editor_property_name_processor.cpp index 6c713de94a..a2dfa4f80e 100644 --- a/editor/editor_property_name_processor.cpp +++ b/editor/editor_property_name_processor.cpp @@ -106,6 +106,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["aabb"] = "AABB"; capitalize_string_remaps["adb"] = "ADB"; capitalize_string_remaps["ao"] = "AO"; + capitalize_string_remaps["api"] = "API"; capitalize_string_remaps["apk"] = "APK"; capitalize_string_remaps["arm64-v8a"] = "arm64-v8a"; capitalize_string_remaps["armeabi-v7a"] = "armeabi-v7a"; @@ -172,6 +173,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["k1"] = "K1"; capitalize_string_remaps["k2"] = "K2"; capitalize_string_remaps["kb"] = "(KB)"; // Unit. + capitalize_string_remaps["lcd"] = "LCD"; capitalize_string_remaps["ldr"] = "LDR"; capitalize_string_remaps["lod"] = "LOD"; capitalize_string_remaps["lowpass"] = "Low-pass"; @@ -190,11 +192,14 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["opengl"] = "OpenGL"; capitalize_string_remaps["opentype"] = "OpenType"; capitalize_string_remaps["openxr"] = "OpenXR"; + capitalize_string_remaps["osslsigncode"] = "osslsigncode"; capitalize_string_remaps["pck"] = "PCK"; capitalize_string_remaps["png"] = "PNG"; capitalize_string_remaps["po2"] = "(Power of 2)"; // Unit. capitalize_string_remaps["pvrtc"] = "PVRTC"; capitalize_string_remaps["pvs"] = "PVS"; + capitalize_string_remaps["rcedit"] = "rcedit"; + capitalize_string_remaps["rcodesign"] = "rcodesign"; capitalize_string_remaps["rgb"] = "RGB"; capitalize_string_remaps["rid"] = "RID"; capitalize_string_remaps["rmb"] = "RMB"; @@ -204,6 +209,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["sdfgi"] = "SDFGI"; capitalize_string_remaps["sdk"] = "SDK"; capitalize_string_remaps["sec"] = "(sec)"; // Unit. + capitalize_string_remaps["signtool"] = "signtool"; capitalize_string_remaps["sms"] = "SMS"; capitalize_string_remaps["srgb"] = "sRGB"; capitalize_string_remaps["ssao"] = "SSAO"; @@ -236,6 +242,7 @@ EditorPropertyNameProcessor::EditorPropertyNameProcessor() { capitalize_string_remaps["webp"] = "WebP"; capitalize_string_remaps["webrtc"] = "WebRTC"; capitalize_string_remaps["websocket"] = "WebSocket"; + capitalize_string_remaps["wine"] = "wine"; capitalize_string_remaps["wifi"] = "Wi-Fi"; capitalize_string_remaps["x86"] = "x86"; capitalize_string_remaps["xr"] = "XR"; diff --git a/editor/editor_resource_picker.cpp b/editor/editor_resource_picker.cpp index 7e42c45b01..78ed71400c 100644 --- a/editor/editor_resource_picker.cpp +++ b/editor/editor_resource_picker.cpp @@ -62,7 +62,7 @@ void EditorResourcePicker::_update_resource() { if (edited_resource == Ref<Resource>()) { assign_button->set_icon(Ref<Texture2D>()); assign_button->set_text(TTR("[empty]")); - assign_button->set_tooltip(""); + assign_button->set_tooltip_text(""); } else { assign_button->set_icon(EditorNode::get_singleton()->get_object_icon(edited_resource.operator->(), "Object")); @@ -73,13 +73,13 @@ void EditorResourcePicker::_update_resource() { } else { assign_button->set_text(edited_resource->get_class()); } - assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class()); + assign_button->set_tooltip_text(resource_path + TTR("Type:") + " " + edited_resource->get_class()); // Preview will override the above, so called at the end. EditorResourcePreview::get_singleton()->queue_edited_resource_preview(edited_resource, this, "_update_resource_preview", edited_resource->get_instance_id()); } } else if (edited_resource.is_valid()) { - assign_button->set_tooltip(resource_path + TTR("Type:") + " " + edited_resource->get_class()); + assign_button->set_tooltip_text(resource_path + TTR("Type:") + " " + edited_resource->get_class()); } assign_button->set_disabled(!editable && !edited_resource.is_valid()); @@ -108,7 +108,7 @@ void EditorResourcePicker::_update_resource_preview(const String &p_path, const preview_rect->set_stretch_mode(TextureRect::STRETCH_KEEP_ASPECT_CENTERED); int thumbnail_size = EditorSettings::get_singleton()->get("filesystem/file_dialog/thumbnail_size"); thumbnail_size *= EDSCALE; - assign_button->set_custom_minimum_size(Size2(MIN(1, assign_button_min_size.x), MIN(thumbnail_size, assign_button_min_size.y))); + assign_button->set_custom_minimum_size(Size2(MAX(1, assign_button_min_size.x), MAX(thumbnail_size, assign_button_min_size.y))); } preview_rect->set_texture(p_preview); @@ -762,8 +762,8 @@ void EditorResourcePicker::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { _update_resource(); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { edit_button->set_icon(get_theme_icon(SNAME("select_arrow"), SNAME("Tree"))); } break; @@ -1038,7 +1038,6 @@ EditorShaderPicker::EditorShaderPicker() { void EditorAudioStreamPicker::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_READY: case NOTIFICATION_THEME_CHANGED: { _update_resource(); } break; diff --git a/editor/editor_run_native.cpp b/editor/editor_run_native.cpp index d8b738be17..3e8f17085d 100644 --- a/editor/editor_run_native.cpp +++ b/editor/editor_run_native.cpp @@ -77,9 +77,9 @@ void EditorRunNative::_notification(int p_what) { mb->get_popup()->clear(); mb->show(); if (dc == 1) { - mb->set_tooltip(eep->get_option_tooltip(0)); + mb->set_tooltip_text(eep->get_option_tooltip(0)); } else { - mb->set_tooltip(eep->get_options_tooltip()); + mb->set_tooltip_text(eep->get_options_tooltip()); for (int i = 0; i < dc; i++) { mb->get_popup()->add_icon_item(eep->get_option_icon(i), eep->get_option_label(i)); mb->get_popup()->set_item_tooltip(-1, eep->get_option_tooltip(i)); diff --git a/editor/editor_settings.cpp b/editor/editor_settings.cpp index 4437b1b166..f5d3b4842d 100644 --- a/editor/editor_settings.cpp +++ b/editor/editor_settings.cpp @@ -407,6 +407,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { set_restart_if_changed("interface/editor/debug/enable_pseudolocalization", true); // Use pseudolocalization in editor. EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/use_embedded_menu", false, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) + EDITOR_SETTING_USAGE(Variant::BOOL, PROPERTY_HINT_NONE, "interface/editor/expand_to_title", true, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING_USAGE(Variant::FLOAT, PROPERTY_HINT_RANGE, "interface/editor/custom_display_scale", 1.0, "0.5,3,0.01", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED) EDITOR_SETTING(Variant::INT, PROPERTY_HINT_RANGE, "interface/editor/main_font_size", 14, "8,48,1") @@ -414,7 +415,7 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) { EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/code_font_contextual_ligatures", 0, "Default,Disable Contextual Alternates (Coding Ligatures),Use Custom OpenType Feature Set") _initial_set("interface/editor/code_font_custom_opentype_features", ""); _initial_set("interface/editor/code_font_custom_variations", ""); - _initial_set("interface/editor/font_antialiased", true); + EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_antialiasing", 1, "None,Grayscale,LCD sub-pixel") #ifdef MACOS_ENABLED EDITOR_SETTING(Variant::INT, PROPERTY_HINT_ENUM, "interface/editor/font_hinting", 0, "Auto (None),None,Light,Normal") #else @@ -1476,8 +1477,11 @@ void ED_SHORTCUT_OVERRIDE_ARRAY(const String &p_path, const String &p_feature, c } } - // Directly override the existing shortcut. - sc->set_events(events); + // Override the existing shortcut only if it wasn't customized by the user (i.e. still "original"). + if (Shortcut::is_event_array_equal(sc->get_events(), sc->get_meta("original"))) { + sc->set_events(events); + } + sc->set_meta("original", events.duplicate(true)); } diff --git a/editor/editor_spin_slider.cpp b/editor/editor_spin_slider.cpp index 5b98460e8e..128d90cd62 100644 --- a/editor/editor_spin_slider.cpp +++ b/editor/editor_spin_slider.cpp @@ -149,6 +149,10 @@ void EditorSpinSlider::gui_input(const Ref<InputEvent> &p_event) { } void EditorSpinSlider::_grabber_gui_input(const Ref<InputEvent> &p_event) { + if (read_only) { + return; + } + Ref<InputEventMouseButton> mb = p_event; if (grabbing_grabber) { @@ -427,7 +431,6 @@ void EditorSpinSlider::_draw_spin_slider() { void EditorSpinSlider::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { _update_value_input_stylebox(); } break; diff --git a/editor/editor_title_bar.cpp b/editor/editor_title_bar.cpp new file mode 100644 index 0000000000..06dcea1f8a --- /dev/null +++ b/editor/editor_title_bar.cpp @@ -0,0 +1,86 @@ +/*************************************************************************/ +/* editor_title_bar.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 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 SOFTWARE. */ +/*************************************************************************/ + +#include "editor/editor_title_bar.h" + +void EditorTitleBar::input(const Ref<InputEvent> &p_event) { + if (!can_move) { + return; + } + + Ref<InputEventMouseMotion> mm = p_event; + if (mm.is_valid() && moving) { + if ((mm->get_button_mask() & MouseButton::LEFT) == MouseButton::LEFT) { + Window *w = Object::cast_to<Window>(get_viewport()); + if (w) { + Point2 mouse = DisplayServer::get_singleton()->mouse_get_position(); + w->set_position(mouse - click_pos); + } + } else { + moving = false; + } + } + + Ref<InputEventMouseButton> mb = p_event; + if (mb.is_valid() && has_point(mb->get_position())) { + Window *w = Object::cast_to<Window>(get_viewport()); + if (w) { + if (mb->get_button_index() == MouseButton::LEFT) { + if (mb->is_pressed()) { + click_pos = DisplayServer::get_singleton()->mouse_get_position() - w->get_position(); + moving = true; + } else { + moving = false; + } + } + if (mb->get_button_index() == MouseButton::LEFT && mb->is_double_click() && mb->is_pressed()) { + if (DisplayServer::get_singleton()->window_maximize_on_title_dbl_click()) { + if (w->get_mode() == Window::MODE_WINDOWED) { + w->set_mode(Window::MODE_MAXIMIZED); + } else if (w->get_mode() == Window::MODE_MAXIMIZED) { + w->set_mode(Window::MODE_WINDOWED); + } + } else if (DisplayServer::get_singleton()->window_minimize_on_title_dbl_click()) { + w->set_mode(Window::MODE_MINIMIZED); + } + moving = false; + } + } + } +} + +void EditorTitleBar::set_can_move_window(bool p_enabled) { + can_move = p_enabled; + set_process_input(can_move); +} + +bool EditorTitleBar::get_can_move_window() const { + return can_move; +} diff --git a/editor/editor_title_bar.h b/editor/editor_title_bar.h new file mode 100644 index 0000000000..ad6ec37ac9 --- /dev/null +++ b/editor/editor_title_bar.h @@ -0,0 +1,53 @@ +/*************************************************************************/ +/* editor_title_bar.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* 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 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 SOFTWARE. */ +/*************************************************************************/ + +#ifndef EDITOR_TITLE_BAR_H +#define EDITOR_TITLE_BAR_H + +#include "scene/gui/box_container.h" +#include "scene/main/window.h" + +class EditorTitleBar : public HBoxContainer { + GDCLASS(EditorTitleBar, HBoxContainer); + + Point2i click_pos; + bool moving = false; + bool can_move = false; + +protected: + virtual void input(const Ref<InputEvent> &p_event) override; + static void _bind_methods(){}; + +public: + void set_can_move_window(bool p_enabled); + bool get_can_move_window() const; +}; + +#endif // EDITOR_TITLE_BAR_H diff --git a/editor/editor_toaster.cpp b/editor/editor_toaster.cpp index 050cde6069..15a4464298 100644 --- a/editor/editor_toaster.cpp +++ b/editor/editor_toaster.cpp @@ -105,7 +105,6 @@ void EditorToaster::_notification(int p_what) { } } break; - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (vbox_container->is_visible()) { main_button->set_icon(get_theme_icon(SNAME("Notification"), SNAME("EditorIcons"))); @@ -236,11 +235,11 @@ void EditorToaster::_auto_hide_or_free_toasts() { } if (toasts.is_empty()) { - main_button->set_tooltip(TTR("No notifications.")); + main_button->set_tooltip_text(TTR("No notifications.")); main_button->set_modulate(Color(0.5, 0.5, 0.5)); main_button->set_disabled(true); } else { - main_button->set_tooltip(TTR("Show notifications.")); + main_button->set_tooltip_text(TTR("Show notifications.")); main_button->set_modulate(Color(1, 1, 1)); main_button->set_disabled(false); } @@ -341,7 +340,7 @@ void EditorToaster::_repop_old() { Control *EditorToaster::popup(Control *p_control, Severity p_severity, double p_time, String p_tooltip) { // Create the panel according to the severity. PanelContainer *panel = memnew(PanelContainer); - panel->set_tooltip(p_tooltip); + panel->set_tooltip_text(p_tooltip); switch (p_severity) { case SEVERITY_INFO: panel->add_theme_style_override("panel", info_panel_style_background); @@ -518,7 +517,7 @@ EditorToaster::EditorToaster() { // Main button. main_button = memnew(Button); - main_button->set_tooltip(TTR("No notifications.")); + main_button->set_tooltip_text(TTR("No notifications.")); main_button->set_modulate(Color(0.5, 0.5, 0.5)); main_button->set_disabled(true); main_button->set_flat(true); @@ -534,7 +533,7 @@ EditorToaster::EditorToaster() { add_child(disable_notifications_panel); disable_notifications_button = memnew(Button); - disable_notifications_button->set_tooltip(TTR("Silence the notifications.")); + disable_notifications_button->set_tooltip_text(TTR("Silence the notifications.")); disable_notifications_button->set_flat(true); disable_notifications_button->connect("pressed", callable_mp(this, &EditorToaster::_set_notifications_enabled).bind(false)); disable_notifications_panel->add_child(disable_notifications_button); diff --git a/editor/editor_zoom_widget.cpp b/editor/editor_zoom_widget.cpp index e4beea5e5f..512fa1c86c 100644 --- a/editor/editor_zoom_widget.cpp +++ b/editor/editor_zoom_widget.cpp @@ -143,7 +143,6 @@ void EditorZoomWidget::set_zoom_by_increments(int p_increment_count, bool p_inte void EditorZoomWidget::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { zoom_minus->set_icon(get_theme_icon(SNAME("ZoomLess"), SNAME("EditorIcons"))); zoom_plus->set_icon(get_theme_icon(SNAME("ZoomMore"), SNAME("EditorIcons"))); diff --git a/editor/export/editor_export.cpp b/editor/export/editor_export.cpp index 31f408eedb..d291040bd2 100644 --- a/editor/export/editor_export.cpp +++ b/editor/export/editor_export.cpp @@ -312,12 +312,14 @@ void EditorExport::update_export_presets() { // Clear the preset properties and values prior to reloading preset->properties.clear(); preset->values.clear(); + preset->update_visibility.clear(); for (const EditorExportPlatform::ExportOption &E : options) { preset->properties.push_back(E.option); StringName option_name = E.option.name; preset->values[option_name] = previous_values.has(option_name) ? previous_values[option_name] : E.default_value; + preset->update_visibility[option_name] = E.update_visibility; } } } diff --git a/editor/export/editor_export_platform.cpp b/editor/export/editor_export_platform.cpp index ab1586cb77..8283c24e61 100644 --- a/editor/export/editor_export_platform.cpp +++ b/editor/export/editor_export_platform.cpp @@ -323,6 +323,7 @@ Ref<EditorExportPreset> EditorExportPlatform::create_preset() { for (const ExportOption &E : options) { preset->properties.push_back(E.option); preset->values[E.option.name] = E.default_value; + preset->update_visibility[E.option.name] = E.update_visibility; } return preset; diff --git a/editor/export/editor_export_platform.h b/editor/export/editor_export_platform.h index c870ee66aa..bbdb47e041 100644 --- a/editor/export/editor_export_platform.h +++ b/editor/export/editor_export_platform.h @@ -117,10 +117,12 @@ public: struct ExportOption { PropertyInfo option; Variant default_value; + bool update_visibility = false; - ExportOption(const PropertyInfo &p_info, const Variant &p_default) : + ExportOption(const PropertyInfo &p_info, const Variant &p_default, bool p_update_visibility = false) : option(p_info), - default_value(p_default) { + default_value(p_default), + update_visibility(p_update_visibility) { } ExportOption() {} }; @@ -136,13 +138,13 @@ public: messages.push_back(msg); switch (p_type) { case EXPORT_MESSAGE_INFO: { - print_line(vformat("%s: %s\n", msg.category, msg.text)); + print_line(vformat("%s: %s", msg.category, msg.text)); } break; case EXPORT_MESSAGE_WARNING: { - WARN_PRINT(vformat("%s: %s\n", msg.category, msg.text)); + WARN_PRINT(vformat("%s: %s", msg.category, msg.text)); } break; case EXPORT_MESSAGE_ERROR: { - ERR_PRINT(vformat("%s: %s\n", msg.category, msg.text)); + ERR_PRINT(vformat("%s: %s", msg.category, msg.text)); } break; default: break; @@ -170,7 +172,7 @@ public: virtual void get_export_options(List<ExportOption> *r_options) = 0; virtual bool should_update_export_options() { return false; } - virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } + virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const { return true; } virtual String get_os_name() const = 0; virtual String get_name() const = 0; diff --git a/editor/export/editor_export_preset.cpp b/editor/export/editor_export_preset.cpp index cdf69e727d..4411ad11bc 100644 --- a/editor/export/editor_export_preset.cpp +++ b/editor/export/editor_export_preset.cpp @@ -34,6 +34,9 @@ bool EditorExportPreset::_set(const StringName &p_name, const Variant &p_value) if (values.has(p_name)) { values[p_name] = p_value; EditorExport::singleton->save_presets(); + if (update_visibility[p_name]) { + notify_property_list_changed(); + } return true; } @@ -51,7 +54,7 @@ bool EditorExportPreset::_get(const StringName &p_name, Variant &r_ret) const { void EditorExportPreset::_get_property_list(List<PropertyInfo> *p_list) const { for (const PropertyInfo &E : properties) { - if (platform->get_export_option_visibility(E.name, values)) { + if (platform->get_export_option_visibility(this, E.name, values)) { p_list->push_back(E); } } diff --git a/editor/export/editor_export_preset.h b/editor/export/editor_export_preset.h index 00109396b0..0c780c45cd 100644 --- a/editor/export/editor_export_preset.h +++ b/editor/export/editor_export_preset.h @@ -67,6 +67,7 @@ private: List<PropertyInfo> properties; HashMap<StringName, Variant> values; + HashMap<StringName, bool> update_visibility; String name; diff --git a/editor/export/export_template_manager.cpp b/editor/export/export_template_manager.cpp index a7d9d7f068..ebcf60508a 100644 --- a/editor/export/export_template_manager.cpp +++ b/editor/export/export_template_manager.cpp @@ -754,7 +754,6 @@ Error ExportTemplateManager::install_android_template_from_file(const String &p_ void ExportTemplateManager::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { current_value->add_theme_font_override("font", get_theme_font(SNAME("main"), SNAME("EditorFonts"))); current_missing_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); @@ -868,13 +867,13 @@ ExportTemplateManager::ExportTemplateManager() { current_open_button = memnew(Button); current_open_button->set_text(TTR("Open Folder")); - current_open_button->set_tooltip(TTR("Open the folder containing installed templates for the current version.")); + current_open_button->set_tooltip_text(TTR("Open the folder containing installed templates for the current version.")); current_installed_hb->add_child(current_open_button); current_open_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_open_template_folder).bind(VERSION_FULL_CONFIG)); current_uninstall_button = memnew(Button); current_uninstall_button->set_text(TTR("Uninstall")); - current_uninstall_button->set_tooltip(TTR("Uninstall templates for the current version.")); + current_uninstall_button->set_tooltip_text(TTR("Uninstall templates for the current version.")); current_installed_hb->add_child(current_uninstall_button); current_uninstall_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_uninstall_template).bind(VERSION_FULL_CONFIG)); @@ -915,14 +914,14 @@ ExportTemplateManager::ExportTemplateManager() { Button *download_current_button = memnew(Button); download_current_button->set_text(TTR("Download and Install")); - download_current_button->set_tooltip(TTR("Download and install templates for the current version from the best possible mirror.")); + download_current_button->set_tooltip_text(TTR("Download and install templates for the current version from the best possible mirror.")); download_install_hb->add_child(download_current_button); download_current_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_download_current)); // Update downloads buttons to prevent unsupported downloads. if (!downloads_available) { download_current_button->set_disabled(true); - download_current_button->set_tooltip(TTR("Official export templates aren't available for development builds.")); + download_current_button->set_tooltip_text(TTR("Official export templates aren't available for development builds.")); } HBoxContainer *install_file_hb = memnew(HBoxContainer); @@ -931,7 +930,7 @@ ExportTemplateManager::ExportTemplateManager() { install_file_button = memnew(Button); install_file_button->set_text(TTR("Install from File")); - install_file_button->set_tooltip(TTR("Install templates from a local file.")); + install_file_button->set_tooltip_text(TTR("Install templates from a local file.")); install_file_hb->add_child(install_file_button); install_file_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_install_file)); @@ -956,7 +955,7 @@ ExportTemplateManager::ExportTemplateManager() { Button *download_cancel_button = memnew(Button); download_cancel_button->set_text(TTR("Cancel")); - download_cancel_button->set_tooltip(TTR("Cancel the download of the templates.")); + download_cancel_button->set_tooltip_text(TTR("Cancel the download of the templates.")); download_progress_hb->add_child(download_cancel_button); download_cancel_button->connect("pressed", callable_mp(this, &ExportTemplateManager::_cancel_template_download)); diff --git a/editor/export/project_export.cpp b/editor/export/project_export.cpp index 76493d330f..00a0e08d3a 100644 --- a/editor/export/project_export.cpp +++ b/editor/export/project_export.cpp @@ -185,9 +185,9 @@ void ProjectExportDialog::_update_export_all() { export_all_button->set_disabled(!can_export); if (can_export) { - export_all_button->set_tooltip(TTR("Export the project for all the presets defined.")); + export_all_button->set_tooltip_text(TTR("Export the project for all the presets defined.")); } else { - export_all_button->set_tooltip(TTR("All presets must have an export path defined for Export All to work.")); + export_all_button->set_tooltip_text(TTR("All presets must have an export path defined for Export All to work.")); } } @@ -1020,12 +1020,12 @@ ProjectExportDialog::ProjectExportDialog() { mc->add_child(presets); presets->connect("item_selected", callable_mp(this, &ProjectExportDialog::_edit_preset)); duplicate_preset = memnew(Button); - duplicate_preset->set_tooltip(TTR("Duplicate")); + duplicate_preset->set_tooltip_text(TTR("Duplicate")); duplicate_preset->set_flat(true); preset_hb->add_child(duplicate_preset); duplicate_preset->connect("pressed", callable_mp(this, &ProjectExportDialog::_duplicate_preset)); delete_preset = memnew(Button); - delete_preset->set_tooltip(TTR("Delete")); + delete_preset->set_tooltip_text(TTR("Delete")); delete_preset->set_flat(true); preset_hb->add_child(delete_preset); delete_preset->connect("pressed", callable_mp(this, &ProjectExportDialog::_delete_preset)); @@ -1041,7 +1041,7 @@ ProjectExportDialog::ProjectExportDialog() { name->connect("text_changed", callable_mp(this, &ProjectExportDialog::_name_changed)); runnable = memnew(CheckButton); runnable->set_text(TTR("Runnable")); - runnable->set_tooltip(TTR("If checked, the preset will be available for use in one-click deploy.\nOnly one preset per platform may be marked as runnable.")); + runnable->set_tooltip_text(TTR("If checked, the preset will be available for use in one-click deploy.\nOnly one preset per platform may be marked as runnable.")); runnable->connect("pressed", callable_mp(this, &ProjectExportDialog::_runnable_pressed)); settings_vb->add_child(runnable); diff --git a/editor/filesystem_dock.cpp b/editor/filesystem_dock.cpp index b823db68f0..a42433caee 100644 --- a/editor/filesystem_dock.cpp +++ b/editor/filesystem_dock.cpp @@ -614,11 +614,11 @@ void FileSystemDock::_set_file_display(bool p_active) { if (p_active) { file_list_display_mode = FILE_LIST_DISPLAY_LIST; button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons"))); - button_file_list_display_mode->set_tooltip(TTR("View items as a grid of thumbnails.")); + button_file_list_display_mode->set_tooltip_text(TTR("View items as a grid of thumbnails.")); } else { file_list_display_mode = FILE_LIST_DISPLAY_THUMBNAILS; button_file_list_display_mode->set_icon(get_theme_icon(SNAME("FileList"), SNAME("EditorIcons"))); - button_file_list_display_mode->set_tooltip(TTR("View items as a list.")); + button_file_list_display_mode->set_tooltip_text(TTR("View items as a list.")); } _update_file_list(true); @@ -2977,7 +2977,7 @@ void FileSystemDock::_file_sort_popup(int p_id) { MenuButton *FileSystemDock::_create_file_menu_button() { MenuButton *button = memnew(MenuButton); button->set_flat(true); - button->set_tooltip(TTR("Sort files")); + button->set_tooltip_text(TTR("Sort files")); PopupMenu *p = button->get_popup(); p->connect("id_pressed", callable_mp(this, &FileSystemDock::_file_sort_popup)); @@ -3040,14 +3040,14 @@ FileSystemDock::FileSystemDock() { button_hist_prev->set_flat(true); button_hist_prev->set_disabled(true); button_hist_prev->set_focus_mode(FOCUS_NONE); - button_hist_prev->set_tooltip(TTR("Previous Folder/File")); + button_hist_prev->set_tooltip_text(TTR("Previous Folder/File")); toolbar_hbc->add_child(button_hist_prev); button_hist_next = memnew(Button); button_hist_next->set_flat(true); button_hist_next->set_disabled(true); button_hist_next->set_focus_mode(FOCUS_NONE); - button_hist_next->set_tooltip(TTR("Next Folder/File")); + button_hist_next->set_tooltip_text(TTR("Next Folder/File")); toolbar_hbc->add_child(button_hist_next); current_path = memnew(LineEdit); @@ -3059,7 +3059,7 @@ FileSystemDock::FileSystemDock() { button_reload = memnew(Button); button_reload->connect("pressed", callable_mp(this, &FileSystemDock::_rescan)); button_reload->set_focus_mode(FOCUS_NONE); - button_reload->set_tooltip(TTR("Re-Scan Filesystem")); + button_reload->set_tooltip_text(TTR("Re-Scan Filesystem")); button_reload->hide(); toolbar_hbc->add_child(button_reload); @@ -3067,7 +3067,7 @@ FileSystemDock::FileSystemDock() { button_toggle_display_mode->set_toggle_mode(true); button_toggle_display_mode->connect("toggled", callable_mp(this, &FileSystemDock::_toggle_split_mode)); button_toggle_display_mode->set_focus_mode(FOCUS_NONE); - button_toggle_display_mode->set_tooltip(TTR("Toggle Split Mode")); + button_toggle_display_mode->set_tooltip_text(TTR("Toggle Split Mode")); button_toggle_display_mode->set_flat(true); toolbar_hbc->add_child(button_toggle_display_mode); diff --git a/editor/find_in_files.cpp b/editor/find_in_files.cpp index 81b71b5609..56387e87f5 100644 --- a/editor/find_in_files.cpp +++ b/editor/find_in_files.cpp @@ -373,7 +373,7 @@ FindInFilesDialog::FindInFilesDialog() { Label *filter_label = memnew(Label); filter_label->set_text(TTR("Filters:")); - filter_label->set_tooltip(TTR("Include the files with the following extensions. Add or remove them in ProjectSettings.")); + filter_label->set_tooltip_text(TTR("Include the files with the following extensions. Add or remove them in ProjectSettings.")); gc->add_child(filter_label); _filters_container = memnew(HBoxContainer); diff --git a/editor/groups_editor.cpp b/editor/groups_editor.cpp index 15add50fd4..87721a2bbf 100644 --- a/editor/groups_editor.cpp +++ b/editor/groups_editor.cpp @@ -380,7 +380,6 @@ void GroupDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_TRANSLATION_CHANGED: case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED: - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (is_layout_rtl()) { add_button->set_icon(groups->get_theme_icon(SNAME("Back"), SNAME("EditorIcons"))); diff --git a/editor/icons/InterpCubicAngle.svg b/editor/icons/InterpCubicAngle.svg new file mode 100644 index 0000000000..e302d556dc --- /dev/null +++ b/editor/icons/InterpCubicAngle.svg @@ -0,0 +1 @@ +<svg enable-background="new 0 0 16 8" height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#5fff95" stroke-linecap="round"><path d="m2 6c5 0 3-4 6-4s1 4 6 4" stroke-width="2"/><circle cx="14" cy="2" r="1.5" stroke-linejoin="round"/></g></svg> diff --git a/editor/icons/InterpCubicInTime.svg b/editor/icons/InterpCubicInTime.svg deleted file mode 100644 index 81027f798a..0000000000 --- a/editor/icons/InterpCubicInTime.svg +++ /dev/null @@ -1 +0,0 @@ -<svg enable-background="new -595.5 420.5 16 8" height="8" viewBox="-595.5 420.5 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m-593.5 426.5c1-4 3.5-5.5 6-2s5 2 6-2" fill="none" stroke="#ff92cb" stroke-linecap="round" stroke-width="2"/></svg> diff --git a/editor/icons/InterpLinearAngle.svg b/editor/icons/InterpLinearAngle.svg new file mode 100644 index 0000000000..af4e87a6cb --- /dev/null +++ b/editor/icons/InterpLinearAngle.svg @@ -0,0 +1 @@ +<svg enable-background="new 0 0 16 8" height="8" viewBox="0 0 16 8" width="16" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fd995f" stroke-linecap="round" stroke-linejoin="round"><path d="m2 6 6-4 6 4" stroke-width="2"/><circle cx="14" cy="2" r="1.5"/></g></svg> diff --git a/editor/icons/ParticlesMaterial.svg b/editor/icons/ParticleProcessMaterial.svg index 33598980a5..33598980a5 100644 --- a/editor/icons/ParticlesMaterial.svg +++ b/editor/icons/ParticleProcessMaterial.svg diff --git a/editor/icons/RigidDynamicBody2D.svg b/editor/icons/RigidBody2D.svg index 5d08e991ae..5d08e991ae 100644 --- a/editor/icons/RigidDynamicBody2D.svg +++ b/editor/icons/RigidBody2D.svg diff --git a/editor/icons/RigidDynamicBody3D.svg b/editor/icons/RigidBody3D.svg index 7f5db4ce88..7f5db4ce88 100644 --- a/editor/icons/RigidDynamicBody3D.svg +++ b/editor/icons/RigidBody3D.svg diff --git a/editor/icons/SoftDynamicBody3D.svg b/editor/icons/SoftBody3D.svg index 7bc9a22c22..7bc9a22c22 100644 --- a/editor/icons/SoftDynamicBody3D.svg +++ b/editor/icons/SoftBody3D.svg diff --git a/editor/import/audio_stream_import_settings.cpp b/editor/import/audio_stream_import_settings.cpp index f3709efab6..843c076642 100644 --- a/editor/import/audio_stream_import_settings.cpp +++ b/editor/import/audio_stream_import_settings.cpp @@ -42,8 +42,7 @@ void AudioStreamImportSettings::_notification(int p_what) { connect("confirmed", callable_mp(this, &AudioStreamImportSettings::_reimport)); } break; - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_THEME_CHANGED: { _play_button->set_icon(get_theme_icon(SNAME("MainPlay"), SNAME("EditorIcons"))); _stop_button->set_icon(get_theme_icon(SNAME("Stop"), SNAME("EditorIcons"))); _preview->set_color(get_theme_color(SNAME("dark_color_2"), SNAME("Editor"))); @@ -526,7 +525,7 @@ AudioStreamImportSettings::AudioStreamImportSettings() { loop_hb->add_theme_constant_override("separation", 4 * EDSCALE); loop = memnew(CheckBox); loop->set_text(TTR("Enable")); - loop->set_tooltip(TTR("Enable looping.")); + loop->set_tooltip_text(TTR("Enable looping.")); loop->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); loop_hb->add_child(loop); loop_hb->add_spacer(); @@ -535,7 +534,7 @@ AudioStreamImportSettings::AudioStreamImportSettings() { loop_offset->set_max(10000); loop_offset->set_step(0.001); loop_offset->set_suffix("sec"); - loop_offset->set_tooltip(TTR("Loop offset (from beginning). Note that if BPM is set, this setting will be ignored.")); + loop_offset->set_tooltip_text(TTR("Loop offset (from beginning). Note that if BPM is set, this setting will be ignored.")); loop_offset->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); loop_hb->add_child(loop_offset); main_vbox->add_margin_child(TTR("Loop:"), loop_hb); @@ -549,14 +548,14 @@ AudioStreamImportSettings::AudioStreamImportSettings() { bpm_edit = memnew(SpinBox); bpm_edit->set_max(400); bpm_edit->set_step(0.01); - bpm_edit->set_tooltip(TTR("Configure the Beats Per Measure (tempo) used for the interactive streams.\nThis is required in order to configure beat information.")); + bpm_edit->set_tooltip_text(TTR("Configure the Beats Per Measure (tempo) used for the interactive streams.\nThis is required in order to configure beat information.")); bpm_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); interactive_hb->add_child(bpm_edit); interactive_hb->add_spacer(); bar_beats_label = memnew(Label(TTR("Beats/Bar:"))); interactive_hb->add_child(bar_beats_label); bar_beats_edit = memnew(SpinBox); - bar_beats_edit->set_tooltip(TTR("Configure the Beats Per Bar. This used for music-aware transitions between AudioStreams.")); + bar_beats_edit->set_tooltip_text(TTR("Configure the Beats Per Bar. This used for music-aware transitions between AudioStreams.")); bar_beats_edit->set_min(2); bar_beats_edit->set_max(32); bar_beats_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); @@ -567,7 +566,7 @@ AudioStreamImportSettings::AudioStreamImportSettings() { beats_enabled->connect("toggled", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); interactive_hb->add_child(beats_enabled); beats_edit = memnew(SpinBox); - beats_edit->set_tooltip(TTR("Configure the amount of Beats used for music-aware looping. If zero, it will be autodetected from the length.\nIt is recommended to set this value (either manually or by clicking on a beat number in the preview) to ensure looping works properly.")); + beats_edit->set_tooltip_text(TTR("Configure the amount of Beats used for music-aware looping. If zero, it will be autodetected from the length.\nIt is recommended to set this value (either manually or by clicking on a beat number in the preview) to ensure looping works properly.")); beats_edit->set_max(99999); beats_edit->connect("value_changed", callable_mp(this, &AudioStreamImportSettings::_settings_changed).unbind(1)); interactive_hb->add_child(beats_edit); diff --git a/editor/import/collada.cpp b/editor/import/collada.cpp index f4d19fe8b6..5b9ed2c1d2 100644 --- a/editor/import/collada.cpp +++ b/editor/import/collada.cpp @@ -131,7 +131,7 @@ Transform3D Collada::Node::compute_transform(const Collada &state) const { switch (xf.op) { case XForm::OP_ROTATE: { if (xf.data.size() >= 4) { - xform_step.rotate(Vector3(xf.data[0], xf.data[1], xf.data[2]), Math::deg2rad(xf.data[3])); + xform_step.rotate(Vector3(xf.data[0], xf.data[1], xf.data[2]), Math::deg_to_rad(xf.data[3])); } } break; case XForm::OP_SCALE: { diff --git a/editor/import/dynamic_font_import_settings.cpp b/editor/import/dynamic_font_import_settings.cpp index 043681aa87..ad80ac1ca9 100644 --- a/editor/import/dynamic_font_import_settings.cpp +++ b/editor/import/dynamic_font_import_settings.cpp @@ -449,8 +449,8 @@ void DynamicFontImportSettings::_main_prop_changed(const String &p_edited_proper // Update font preview. if (font_preview.is_valid()) { - if (p_edited_property == "antialiased") { - font_preview->set_antialiased(import_settings_data->get("antialiased")); + if (p_edited_property == "antialiasing") { + font_preview->set_antialiasing((TextServer::FontAntialiasing)import_settings_data->get("antialiasing").operator int()); } else if (p_edited_property == "generate_mipmaps") { font_preview->set_generate_mipmaps(import_settings_data->get("generate_mipmaps")); } else if (p_edited_property == "multichannel_signed_distance_field") { @@ -574,6 +574,12 @@ void DynamicFontImportSettings::_variations_validate() { } } } + if ((TextServer::FontAntialiasing)(int)import_settings_data->get("antialiasing") == TextServer::FONT_ANTIALIASING_LCD) { + warn += "\n" + TTR("Note: LCD sub-pixel anti-aliasing is selected, each of the glyphs will be pre-rendered for all supported sub-pixel layouts (5x)."); + } + if ((TextServer::SubpixelPositioning)(int)import_settings_data->get("subpixel_positioning") != TextServer::SUBPIXEL_POSITIONING_DISABLED) { + warn += "\n" + TTR("Note: Sub-pixel positioning is selected, each of the glyphs might be pre-rendered for multiple sub-pixel offsets (up to 4x)."); + } if (warn.is_empty()) { label_warn->set_text(""); label_warn->hide(); @@ -870,7 +876,6 @@ void DynamicFontImportSettings::_notification(int p_what) { connect("confirmed", callable_mp(this, &DynamicFontImportSettings::_re_import)); } break; - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { add_var->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); } break; @@ -881,7 +886,7 @@ void DynamicFontImportSettings::_re_import() { HashMap<StringName, Variant> main_settings; main_settings["face_index"] = import_settings_data->get("face_index"); - main_settings["antialiased"] = import_settings_data->get("antialiased"); + main_settings["antialiasing"] = import_settings_data->get("antialiasing"); main_settings["generate_mipmaps"] = import_settings_data->get("generate_mipmaps"); main_settings["multichannel_signed_distance_field"] = import_settings_data->get("multichannel_signed_distance_field"); main_settings["msdf_pixel_range"] = import_settings_data->get("msdf_pixel_range"); @@ -1079,7 +1084,7 @@ void DynamicFontImportSettings::open_settings(const String &p_path) { import_settings_data->notify_property_list_changed(); if (font_preview.is_valid()) { - font_preview->set_antialiased(import_settings_data->get("antialiased")); + font_preview->set_antialiasing((TextServer::FontAntialiasing)import_settings_data->get("antialiasing").operator int()); font_preview->set_multichannel_signed_distance_field(import_settings_data->get("multichannel_signed_distance_field")); font_preview->set_msdf_pixel_range(import_settings_data->get("msdf_pixel_range")); font_preview->set_msdf_size(import_settings_data->get("msdf_size")); @@ -1108,7 +1113,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); - options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); + options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), true)); options_general.push_back(ResourceImporter::ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); @@ -1233,7 +1238,7 @@ DynamicFontImportSettings::DynamicFontImportSettings() { add_var = memnew(Button); page2_hb_vars->add_child(add_var); - add_var->set_tooltip(TTR("Add configuration")); + add_var->set_tooltip_text(TTR("Add configuration")); add_var->set_icon(add_var->get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); add_var->connect("pressed", callable_mp(this, &DynamicFontImportSettings::_variation_add)); diff --git a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp index 685cb16eb1..6f775c7ea8 100644 --- a/editor/import/post_import_plugin_skeleton_rest_fixer.cpp +++ b/editor/import/post_import_plugin_skeleton_rest_fixer.cpp @@ -324,7 +324,7 @@ void PostImportPluginSkeletonRestFixer::internal_process(InternalImportCategory Vector3 src_dir = src_tail - src_head; // Rotate rest. - if (Math::abs(Math::rad2deg(src_dir.angle_to(prof_dir))) > float(p_options["retarget/rest_fixer/fix_silhouette/threshold"])) { + if (Math::abs(Math::rad_to_deg(src_dir.angle_to(prof_dir))) > float(p_options["retarget/rest_fixer/fix_silhouette/threshold"])) { // Get rotation difference. Vector3 up_vec; // Need to rotate other than roll axis. switch (Vector3(abs(src_dir.x), abs(src_dir.y), abs(src_dir.z)).min_axis_index()) { diff --git a/editor/import/resource_importer_dynamic_font.cpp b/editor/import/resource_importer_dynamic_font.cpp index 32fd94b093..c822cd0fec 100644 --- a/editor/import/resource_importer_dynamic_font.cpp +++ b/editor/import/resource_importer_dynamic_font.cpp @@ -105,7 +105,7 @@ void ResourceImporterDynamicFont::get_import_options(const String &p_path, List< r_options->push_back(ImportOption(PropertyInfo(Variant::NIL, "Rendering", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_GROUP), Variant())); - r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "antialiased"), true)); + r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel"), 1)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "generate_mipmaps"), false)); r_options->push_back(ImportOption(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED), (msdf) ? true : false)); r_options->push_back(ImportOption(PropertyInfo(Variant::INT, "msdf_pixel_range", PROPERTY_HINT_RANGE, "1,100,1"), 8)); @@ -139,7 +139,7 @@ void ResourceImporterDynamicFont::show_advanced_options(const String &p_path) { Error ResourceImporterDynamicFont::import(const String &p_source_file, const String &p_save_path, const HashMap<StringName, Variant> &p_options, List<String> *r_platform_variants, List<String> *r_gen_files, Variant *r_metadata) { print_verbose("Importing dynamic font from: " + p_source_file); - bool antialiased = p_options["antialiased"]; + int antialiasing = p_options["antialiasing"]; bool generate_mipmaps = p_options["generate_mipmaps"]; bool msdf = p_options["multichannel_signed_distance_field"]; int px_range = p_options["msdf_pixel_range"]; @@ -159,7 +159,7 @@ Error ResourceImporterDynamicFont::import(const String &p_source_file, const Str Ref<FontFile> font; font.instantiate(); font->set_data(data); - font->set_antialiased(antialiased); + font->set_antialiasing((TextServer::FontAntialiasing)antialiasing); font->set_generate_mipmaps(generate_mipmaps); font->set_multichannel_signed_distance_field(msdf); font->set_msdf_pixel_range(px_range); diff --git a/editor/import/resource_importer_imagefont.cpp b/editor/import/resource_importer_imagefont.cpp index 374cbe7ce2..58c2061051 100644 --- a/editor/import/resource_importer_imagefont.cpp +++ b/editor/import/resource_importer_imagefont.cpp @@ -99,7 +99,7 @@ Error ResourceImporterImageFont::import(const String &p_source_file, const Strin Ref<FontFile> font; font.instantiate(); - font->set_antialiased(false); + font->set_antialiasing(TextServer::FONT_ANTIALIASING_NONE); font->set_generate_mipmaps(false); font->set_multichannel_signed_distance_field(false); font->set_fixed_size(base_size); diff --git a/editor/import/resource_importer_scene.cpp b/editor/import/resource_importer_scene.cpp index 85dda24f8e..62cb6e4167 100644 --- a/editor/import/resource_importer_scene.cpp +++ b/editor/import/resource_importer_scene.cpp @@ -565,7 +565,7 @@ Node *ResourceImporterScene::_pre_fix_node(Node *p_node, Node *p_root, HashMap<R _pre_gen_shape_list(mesh, shapes, true); } - RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); + RigidBody3D *rigid_body = memnew(RigidBody3D); rigid_body->set_name(_fixstr(name, "rigid_body")); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform()); @@ -1060,7 +1060,7 @@ Node *ResourceImporterScene::_post_fix_node(Node *p_node, Node *p_root, HashMap< base = col; } break; case MESH_PHYSICS_RIGID_BODY_AND_MESH: { - RigidDynamicBody3D *rigid_body = memnew(RigidDynamicBody3D); + RigidBody3D *rigid_body = memnew(RigidBody3D); rigid_body->set_name(p_node->get_name()); p_node->replace_by(rigid_body); rigid_body->set_transform(mi->get_transform() * get_collision_shapes_transform(node_settings)); diff --git a/editor/import/resource_importer_wav.cpp b/editor/import/resource_importer_wav.cpp index a1e00f7d30..1dcae2841b 100644 --- a/editor/import/resource_importer_wav.cpp +++ b/editor/import/resource_importer_wav.cpp @@ -390,7 +390,7 @@ Error ResourceImporterWAV::import(const String &p_source_file, const String &p_s int first = 0; int last = (frames / format_channels) - 1; bool found = false; - float limit = Math::db2linear(TRIM_DB_LIMIT); + float limit = Math::db_to_linear(TRIM_DB_LIMIT); for (int i = 0; i < data.size() / format_channels; i++) { float ampChannelSum = 0; diff --git a/editor/import_dock.cpp b/editor/import_dock.cpp index 087ef48b56..02270e163f 100644 --- a/editor/import_dock.cpp +++ b/editor/import_dock.cpp @@ -584,12 +584,12 @@ void ImportDock::_set_dirty(bool p_dirty) { // Add a dirty marker to notify the user that they should reimport the selected resource to see changes. import->set_text(TTR("Reimport") + " (*)"); import->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); - import->set_tooltip(TTR("You have pending changes that haven't been applied yet. Click Reimport to apply changes made to the import options.\nSelecting another resource in the FileSystem dock without clicking Reimport first will discard changes made in the Import dock.")); + import->set_tooltip_text(TTR("You have pending changes that haven't been applied yet. Click Reimport to apply changes made to the import options.\nSelecting another resource in the FileSystem dock without clicking Reimport first will discard changes made in the Import dock.")); } else { // Remove the dirty marker on the Reimport button. import->set_text(TTR("Reimport")); import->remove_theme_color_override("font_color"); - import->set_tooltip(""); + import->set_tooltip_text(""); } } diff --git a/editor/inspector_dock.cpp b/editor/inspector_dock.cpp index b0ff678a3e..7af04e17c1 100644 --- a/editor/inspector_dock.cpp +++ b/editor/inspector_dock.cpp @@ -633,20 +633,20 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { resource_new_button = memnew(Button); resource_new_button->set_flat(true); - resource_new_button->set_tooltip(TTR("Create a new resource in memory and edit it.")); + resource_new_button->set_tooltip_text(TTR("Create a new resource in memory and edit it.")); general_options_hb->add_child(resource_new_button); resource_new_button->connect("pressed", callable_mp(this, &InspectorDock::_new_resource)); resource_new_button->set_focus_mode(Control::FOCUS_NONE); resource_load_button = memnew(Button); resource_load_button->set_flat(true); - resource_load_button->set_tooltip(TTR("Load an existing resource from disk and edit it.")); + resource_load_button->set_tooltip_text(TTR("Load an existing resource from disk and edit it.")); general_options_hb->add_child(resource_load_button); resource_load_button->connect("pressed", callable_mp(this, &InspectorDock::_open_resource_selector)); resource_load_button->set_focus_mode(Control::FOCUS_NONE); resource_save_button = memnew(MenuButton); - resource_save_button->set_tooltip(TTR("Save the currently edited resource.")); + resource_save_button->set_tooltip_text(TTR("Save the currently edited resource.")); general_options_hb->add_child(resource_save_button); resource_save_button->get_popup()->add_item(TTR("Save"), RESOURCE_SAVE); resource_save_button->get_popup()->add_item(TTR("Save As..."), RESOURCE_SAVE_AS); @@ -655,7 +655,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { resource_save_button->set_disabled(true); resource_extra_button = memnew(MenuButton); - resource_extra_button->set_tooltip(TTR("Extra resource options.")); + resource_extra_button->set_tooltip_text(TTR("Extra resource options.")); general_options_hb->add_child(resource_extra_button); resource_extra_button->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_resource_extra_popup)); resource_extra_button->get_popup()->add_icon_shortcut(get_theme_icon(SNAME("ActionPaste"), SNAME("EditorIcons")), ED_SHORTCUT("property_editor/paste_resource", TTR("Edit Resource from Clipboard")), RESOURCE_EDIT_CLIPBOARD); @@ -671,19 +671,19 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { backward_button = memnew(Button); backward_button->set_flat(true); general_options_hb->add_child(backward_button); - backward_button->set_tooltip(TTR("Go to the previous edited object in history.")); + backward_button->set_tooltip_text(TTR("Go to the previous edited object in history.")); backward_button->set_disabled(true); backward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_back)); forward_button = memnew(Button); forward_button->set_flat(true); general_options_hb->add_child(forward_button); - forward_button->set_tooltip(TTR("Go to the next edited object in history.")); + forward_button->set_tooltip_text(TTR("Go to the next edited object in history.")); forward_button->set_disabled(true); forward_button->connect("pressed", callable_mp(this, &InspectorDock::_edit_forward)); history_menu = memnew(MenuButton); - history_menu->set_tooltip(TTR("History of recently edited objects.")); + history_menu->set_tooltip_text(TTR("History of recently edited objects.")); general_options_hb->add_child(history_menu); history_menu->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_history)); history_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_select_history)); @@ -697,7 +697,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { open_docs_button = memnew(Button); open_docs_button->set_flat(true); open_docs_button->set_disabled(true); - open_docs_button->set_tooltip(TTR("Open documentation for this object.")); + open_docs_button->set_tooltip_text(TTR("Open documentation for this object.")); open_docs_button->set_shortcut(ED_SHORTCUT("property_editor/open_help", TTR("Open Documentation"))); subresource_hb->add_child(open_docs_button); open_docs_button->connect("pressed", callable_mp(this, &InspectorDock::_menu_option).bind(OBJECT_REQUEST_HELP)); @@ -719,7 +719,7 @@ InspectorDock::InspectorDock(EditorData &p_editor_data) { object_menu = memnew(MenuButton); object_menu->set_shortcut_context(this); property_tools_hb->add_child(object_menu); - object_menu->set_tooltip(TTR("Manage object properties.")); + object_menu->set_tooltip_text(TTR("Manage object properties.")); object_menu->get_popup()->connect("about_to_popup", callable_mp(this, &InspectorDock::_prepare_menu)); object_menu->get_popup()->connect("id_pressed", callable_mp(this, &InspectorDock::_menu_option)); diff --git a/editor/node_dock.cpp b/editor/node_dock.cpp index 55fa2f22dd..e366f3ce3c 100644 --- a/editor/node_dock.cpp +++ b/editor/node_dock.cpp @@ -53,7 +53,6 @@ void NodeDock::_bind_methods() { void NodeDock::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { connections_button->set_icon(get_theme_icon(SNAME("Signals"), SNAME("EditorIcons"))); groups_button->set_icon(get_theme_icon(SNAME("Groups"), SNAME("EditorIcons"))); diff --git a/editor/plugin_config_dialog.cpp b/editor/plugin_config_dialog.cpp index 6d323572e6..88aa6354e4 100644 --- a/editor/plugin_config_dialog.cpp +++ b/editor/plugin_config_dialog.cpp @@ -111,32 +111,32 @@ void PluginConfigDialog::_on_required_text_changed(const String &) { name_validation->set_texture(valid_icon); subfolder_validation->set_texture(valid_icon); script_validation->set_texture(valid_icon); - name_validation->set_tooltip(""); - subfolder_validation->set_tooltip(""); - script_validation->set_tooltip(""); + name_validation->set_tooltip_text(""); + subfolder_validation->set_tooltip_text(""); + script_validation->set_tooltip_text(""); // Change valid status to invalid depending on conditions. Vector<String> errors; if (name_edit->get_text().is_empty()) { is_valid = false; name_validation->set_texture(invalid_icon); - name_validation->set_tooltip(TTR("Plugin name cannot be blank.")); + name_validation->set_tooltip_text(TTR("Plugin name cannot be blank.")); } if ((!script_edit->get_text().get_extension().is_empty() && script_edit->get_text().get_extension() != ext) || script_edit->get_text().ends_with(".")) { is_valid = false; script_validation->set_texture(invalid_icon); - script_validation->set_tooltip(vformat(TTR("Script extension must match chosen language extension (.%s)."), ext)); + script_validation->set_tooltip_text(vformat(TTR("Script extension must match chosen language extension (.%s)."), ext)); } if (!subfolder_edit->get_text().is_empty() && !subfolder_edit->get_text().is_valid_filename()) { is_valid = false; subfolder_validation->set_texture(invalid_icon); - subfolder_validation->set_tooltip(TTR("Subfolder name is not a valid folder name.")); + subfolder_validation->set_tooltip_text(TTR("Subfolder name is not a valid folder name.")); } else { String path = "res://addons/" + _get_subfolder(); if (!_edit_mode && DirAccess::exists(path)) { // Only show this error if in "create" mode. is_valid = false; subfolder_validation->set_texture(invalid_icon); - subfolder_validation->set_tooltip(TTR("Subfolder cannot be one which already exists.")); + subfolder_validation->set_tooltip_text(TTR("Subfolder cannot be one which already exists.")); } } diff --git a/editor/plugins/abstract_polygon_2d_editor.cpp b/editor/plugins/abstract_polygon_2d_editor.cpp index 275859f528..d17b88c2ce 100644 --- a/editor/plugins/abstract_polygon_2d_editor.cpp +++ b/editor/plugins/abstract_polygon_2d_editor.cpp @@ -151,7 +151,6 @@ void AbstractPolygon2DEditor::_menu_option(int p_option) { void AbstractPolygon2DEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { button_create->set_icon(get_theme_icon(SNAME("CurveCreate"), SNAME("EditorIcons"))); button_edit->set_icon(get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons"))); @@ -235,13 +234,13 @@ void AbstractPolygon2DEditor::disable_polygon_editing(bool p_disable, String p_r button_delete->set_disabled(p_disable); if (p_disable) { - button_create->set_tooltip(p_reason); - button_edit->set_tooltip(p_reason); - button_delete->set_tooltip(p_reason); + button_create->set_tooltip_text(p_reason); + button_edit->set_tooltip_text(p_reason); + button_delete->set_tooltip_text(p_reason); } else { - button_create->set_tooltip(TTR("Create points.")); - button_edit->set_tooltip(TTR("Edit points.\nLMB: Move Point\nRMB: Erase Point")); - button_delete->set_tooltip(TTR("Erase points.")); + button_create->set_tooltip_text(TTR("Create points.")); + button_edit->set_tooltip_text(TTR("Edit points.\nLMB: Move Point\nRMB: Erase Point")); + button_delete->set_tooltip_text(TTR("Erase points.")); } } diff --git a/editor/plugins/animation_blend_space_1d_editor.cpp b/editor/plugins/animation_blend_space_1d_editor.cpp index 2578099a9f..b8a1d2cb69 100644 --- a/editor/plugins/animation_blend_space_1d_editor.cpp +++ b/editor/plugins/animation_blend_space_1d_editor.cpp @@ -48,7 +48,9 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) { if (selected_point != -1) { - _erase_selected(); + if (!read_only) { + _erase_selected(); + } accept_event(); } } @@ -56,62 +58,64 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (mb->get_button_index() == MouseButton::LEFT && tool_create->is_pressed()))) { - menu->clear(); - animations_menu->clear(); - animations_to_add.clear(); + if (!read_only) { + menu->clear(); + animations_menu->clear(); + animations_to_add.clear(); - List<StringName> classes; - ClassDB::get_inheriters_from_class("AnimationRootNode", &classes); - classes.sort_custom<StringName::AlphCompare>(); + List<StringName> classes; + ClassDB::get_inheriters_from_class("AnimationRootNode", &classes); + classes.sort_custom<StringName::AlphCompare>(); - menu->add_submenu_item(TTR("Add Animation"), "animations"); + menu->add_submenu_item(TTR("Add Animation"), "animations"); - AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree(); - ERR_FAIL_COND(!gp); + AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree(); + ERR_FAIL_COND(!gp); - if (gp->has_node(gp->get_animation_player())) { - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player())); + if (gp->has_node(gp->get_animation_player())) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player())); - if (ap) { - List<StringName> names; - ap->get_animation_list(&names); + if (ap) { + List<StringName> names; + ap->get_animation_list(&names); - for (const StringName &E : names) { - animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E); - animations_to_add.push_back(E); + for (const StringName &E : names) { + animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E); + animations_to_add.push_back(E); + } } } - } - for (const StringName &E : classes) { - String name = String(E).replace_first("AnimationNode", ""); - if (name == "Animation" || name == "StartState" || name == "EndState") { - continue; - } + for (const StringName &E : classes) { + String name = String(E).replace_first("AnimationNode", ""); + if (name == "Animation" || name == "StartState" || name == "EndState") { + continue; + } - int idx = menu->get_item_count(); - menu->add_item(vformat(TTR("Add %s"), name), idx); - menu->set_item_metadata(idx, E); - } + int idx = menu->get_item_count(); + menu->add_item(vformat(TTR("Add %s"), name), idx); + menu->set_item_metadata(idx, E); + } - Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard(); - if (clipb.is_valid()) { + Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard(); + if (clipb.is_valid()) { + menu->add_separator(); + menu->add_item(TTR("Paste"), MENU_PASTE); + } menu->add_separator(); - menu->add_item(TTR("Paste"), MENU_PASTE); - } - menu->add_separator(); - menu->add_item(TTR("Load..."), MENU_LOAD_FILE); + menu->add_item(TTR("Load..."), MENU_LOAD_FILE); - menu->set_position(blend_space_draw->get_screen_position() + mb->get_position()); - menu->reset_size(); - menu->popup(); + menu->set_position(blend_space_draw->get_screen_position() + mb->get_position()); + menu->reset_size(); + menu->popup(); - add_point_pos = (mb->get_position() / blend_space_draw->get_size()).x; - add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); - add_point_pos += blend_space->get_min_space(); + add_point_pos = (mb->get_position() / blend_space_draw->get_size()).x; + add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); + add_point_pos += blend_space->get_min_space(); - if (snap->is_pressed()) { - add_point_pos = Math::snapped(add_point_pos, blend_space->get_snap()); + if (snap->is_pressed()) { + add_point_pos = Math::snapped(add_point_pos, blend_space->get_snap()); + } } } @@ -138,31 +142,33 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_gui_input(const Ref<InputEven } if (mb.is_valid() && !mb->is_pressed() && dragging_selected_attempt && mb->get_button_index() == MouseButton::LEFT) { - if (dragging_selected) { - // move - float point = blend_space->get_blend_point_position(selected_point); - point += drag_ofs.x; + if (!read_only) { + if (dragging_selected) { + // move + float point = blend_space->get_blend_point_position(selected_point); + point += drag_ofs.x; + + if (snap->is_pressed()) { + point = Math::snapped(point, blend_space->get_snap()); + } - if (snap->is_pressed()) { - point = Math::snapped(point, blend_space->get_snap()); + updating = true; + undo_redo->create_action(TTR("Move Node Point")); + undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point); + undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); + undo_redo->add_do_method(this, "_update_space"); + undo_redo->add_undo_method(this, "_update_space"); + undo_redo->add_do_method(this, "_update_edited_point_pos"); + undo_redo->add_undo_method(this, "_update_edited_point_pos"); + undo_redo->commit_action(); + updating = false; + _update_edited_point_pos(); } - updating = true; - undo_redo->create_action(TTR("Move Node Point")); - undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point); - undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); - undo_redo->add_do_method(this, "_update_space"); - undo_redo->add_undo_method(this, "_update_space"); - undo_redo->add_do_method(this, "_update_edited_point_pos"); - undo_redo->add_undo_method(this, "_update_edited_point_pos"); - undo_redo->commit_action(); - updating = false; - _update_edited_point_pos(); + dragging_selected_attempt = false; + dragging_selected = false; + blend_space_draw->update(); } - - dragging_selected_attempt = false; - dragging_selected = false; - blend_space_draw->update(); } // *set* the blend @@ -255,10 +261,12 @@ void AnimationNodeBlendSpace1DEditor::_blend_space_draw() { for (int i = 0; i < blend_space->get_blend_point_count(); i++) { float point = blend_space->get_blend_point_position(i); - if (dragging_selected && selected_point == i) { - point += drag_ofs.x; - if (snap->is_pressed()) { - point = Math::snapped(point, blend_space->get_snap()); + if (!read_only) { + if (dragging_selected && selected_point == i) { + point += drag_ofs.x; + if (snap->is_pressed()) { + point = Math::snapped(point, blend_space->get_snap()); + } } } @@ -475,7 +483,7 @@ void AnimationNodeBlendSpace1DEditor::_update_edited_point_pos() { void AnimationNodeBlendSpace1DEditor::_update_tool_erase() { bool point_valid = selected_point >= 0 && selected_point < blend_space->get_blend_point_count(); - tool_erase->set_disabled(!point_valid); + tool_erase->set_disabled(!point_valid || read_only); if (point_valid) { Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point); @@ -486,7 +494,11 @@ void AnimationNodeBlendSpace1DEditor::_update_tool_erase() { open_editor->hide(); } - edit_hb->show(); + if (!read_only) { + edit_hb->show(); + } else { + edit_hb->hide(); + } } else { edit_hb->hide(); } @@ -538,7 +550,6 @@ void AnimationNodeBlendSpace1DEditor::_open_editor() { void AnimationNodeBlendSpace1DEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); @@ -590,10 +601,20 @@ bool AnimationNodeBlendSpace1DEditor::can_edit(const Ref<AnimationNode> &p_node) void AnimationNodeBlendSpace1DEditor::edit(const Ref<AnimationNode> &p_node) { blend_space = p_node; + read_only = false; if (!blend_space.is_null()) { + read_only = EditorNode::get_singleton()->is_resource_read_only(blend_space); + _update_space(); } + + tool_create->set_disabled(read_only); + edit_value->set_editable(!read_only); + label_value->set_editable(!read_only); + min_value->set_editable(!read_only); + max_value->set_editable(!read_only); + sync->set_disabled(read_only); } AnimationNodeBlendSpace1DEditor *AnimationNodeBlendSpace1DEditor::singleton = nullptr; @@ -613,7 +634,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_blend->set_button_group(bg); top_hb->add_child(tool_blend); tool_blend->set_pressed(true); - tool_blend->set_tooltip(TTR("Set the blending position within the space")); + tool_blend->set_tooltip_text(TTR("Set the blending position within the space")); tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(3)); tool_select = memnew(Button); @@ -621,7 +642,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); top_hb->add_child(tool_select); - tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); + tool_select->set_tooltip_text(TTR("Select and move points, create points with RMB.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(0)); tool_create = memnew(Button); @@ -629,7 +650,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); top_hb->add_child(tool_create); - tool_create->set_tooltip(TTR("Create points.")); + tool_create->set_tooltip_text(TTR("Create points.")); tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_tool_switch).bind(1)); tool_erase_sep = memnew(VSeparator); @@ -637,7 +658,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { tool_erase = memnew(Button); tool_erase->set_flat(true); top_hb->add_child(tool_erase); - tool_erase->set_tooltip(TTR("Erase points.")); + tool_erase->set_tooltip_text(TTR("Erase points.")); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_erase_selected)); top_hb->add_child(memnew(VSeparator)); @@ -647,7 +668,7 @@ AnimationNodeBlendSpace1DEditor::AnimationNodeBlendSpace1DEditor() { snap->set_toggle_mode(true); top_hb->add_child(snap); snap->set_pressed(true); - snap->set_tooltip(TTR("Enable snap and show grid.")); + snap->set_tooltip_text(TTR("Enable snap and show grid.")); snap->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace1DEditor::_snap_toggled)); snap_value = memnew(SpinBox); diff --git a/editor/plugins/animation_blend_space_1d_editor.h b/editor/plugins/animation_blend_space_1d_editor.h index 125a3382fa..c8b01cb54b 100644 --- a/editor/plugins/animation_blend_space_1d_editor.h +++ b/editor/plugins/animation_blend_space_1d_editor.h @@ -46,6 +46,7 @@ class AnimationNodeBlendSpace1DEditor : public AnimationTreeNodeEditorPlugin { GDCLASS(AnimationNodeBlendSpace1DEditor, AnimationTreeNodeEditorPlugin); Ref<AnimationNodeBlendSpace1D> blend_space; + bool read_only = false; HBoxContainer *goto_parent_hb = nullptr; Button *goto_parent = nullptr; diff --git a/editor/plugins/animation_blend_space_2d_editor.cpp b/editor/plugins/animation_blend_space_2d_editor.cpp index c0723cef87..918fca0e1c 100644 --- a/editor/plugins/animation_blend_space_2d_editor.cpp +++ b/editor/plugins/animation_blend_space_2d_editor.cpp @@ -60,11 +60,29 @@ void AnimationNodeBlendSpace2DEditor::edit(const Ref<AnimationNode> &p_node) { blend_space->disconnect("triangles_updated", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_blend_space_changed)); } blend_space = p_node; + read_only = false; if (!blend_space.is_null()) { + read_only = EditorNode::get_singleton()->is_resource_read_only(blend_space); + blend_space->connect("triangles_updated", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_blend_space_changed)); _update_space(); } + + tool_create->set_disabled(read_only); + interpolation->set_disabled(read_only); + max_x_value->set_editable(!read_only); + min_x_value->set_editable(!read_only); + max_y_value->set_editable(!read_only); + min_y_value->set_editable(!read_only); + label_x->set_editable(!read_only); + label_y->set_editable(!read_only); + edit_x->set_editable(!read_only); + edit_y->set_editable(!read_only); + tool_triangle->set_disabled(read_only); + auto_triangles->set_disabled(read_only); + sync->set_disabled(read_only); + interpolation->set_disabled(read_only); } StringName AnimationNodeBlendSpace2DEditor::get_blend_position_path() const { @@ -76,7 +94,9 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven Ref<InputEventKey> k = p_event; if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) { if (selected_point != -1 || selected_triangle != -1) { - _erase_selected(); + if (!read_only) { + _erase_selected(); + } accept_event(); } } @@ -84,57 +104,59 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid() && mb->is_pressed() && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (mb->get_button_index() == MouseButton::LEFT && tool_create->is_pressed()))) { - menu->clear(); - animations_menu->clear(); - animations_to_add.clear(); - List<StringName> classes; - classes.sort_custom<StringName::AlphCompare>(); - - ClassDB::get_inheriters_from_class("AnimationRootNode", &classes); - menu->add_submenu_item(TTR("Add Animation"), "animations"); - - AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree(); - ERR_FAIL_COND(!gp); - if (gp && gp->has_node(gp->get_animation_player())) { - AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player())); - if (ap) { - List<StringName> names; - ap->get_animation_list(&names); - for (const StringName &E : names) { - animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E); - animations_to_add.push_back(E); + if (!read_only) { + menu->clear(); + animations_menu->clear(); + animations_to_add.clear(); + List<StringName> classes; + classes.sort_custom<StringName::AlphCompare>(); + + ClassDB::get_inheriters_from_class("AnimationRootNode", &classes); + menu->add_submenu_item(TTR("Add Animation"), "animations"); + + AnimationTree *gp = AnimationTreeEditor::get_singleton()->get_tree(); + ERR_FAIL_COND(!gp); + if (gp && gp->has_node(gp->get_animation_player())) { + AnimationPlayer *ap = Object::cast_to<AnimationPlayer>(gp->get_node(gp->get_animation_player())); + if (ap) { + List<StringName> names; + ap->get_animation_list(&names); + for (const StringName &E : names) { + animations_menu->add_icon_item(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons")), E); + animations_to_add.push_back(E); + } } } - } - for (const StringName &E : classes) { - String name = String(E).replace_first("AnimationNode", ""); - if (name == "Animation" || name == "StartState" || name == "EndState") { - continue; // nope + for (const StringName &E : classes) { + String name = String(E).replace_first("AnimationNode", ""); + if (name == "Animation" || name == "StartState" || name == "EndState") { + continue; // nope + } + int idx = menu->get_item_count(); + menu->add_item(vformat(TTR("Add %s"), name), idx); + menu->set_item_metadata(idx, E); } - int idx = menu->get_item_count(); - menu->add_item(vformat(TTR("Add %s"), name), idx); - menu->set_item_metadata(idx, E); - } - Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard(); - if (clipb.is_valid()) { + Ref<AnimationNode> clipb = EditorSettings::get_singleton()->get_resource_clipboard(); + if (clipb.is_valid()) { + menu->add_separator(); + menu->add_item(TTR("Paste"), MENU_PASTE); + } menu->add_separator(); - menu->add_item(TTR("Paste"), MENU_PASTE); - } - menu->add_separator(); - menu->add_item(TTR("Load..."), MENU_LOAD_FILE); - - menu->set_position(blend_space_draw->get_screen_position() + mb->get_position()); - menu->reset_size(); - menu->popup(); - add_point_pos = (mb->get_position() / blend_space_draw->get_size()); - add_point_pos.y = 1.0 - add_point_pos.y; - add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); - add_point_pos += blend_space->get_min_space(); - - if (snap->is_pressed()) { - add_point_pos = add_point_pos.snapped(blend_space->get_snap()); + menu->add_item(TTR("Load..."), MENU_LOAD_FILE); + + menu->set_position(blend_space_draw->get_screen_position() + mb->get_position()); + menu->reset_size(); + menu->popup(); + add_point_pos = (mb->get_position() / blend_space_draw->get_size()); + add_point_pos.y = 1.0 - add_point_pos.y; + add_point_pos *= (blend_space->get_max_space() - blend_space->get_min_space()); + add_point_pos += blend_space->get_min_space(); + + if (snap->is_pressed()) { + add_point_pos = add_point_pos.snapped(blend_space->get_snap()); + } } } @@ -222,17 +244,19 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven point = point.snapped(blend_space->get_snap()); } - updating = true; - undo_redo->create_action(TTR("Move Node Point")); - undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point); - undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); - undo_redo->add_do_method(this, "_update_space"); - undo_redo->add_undo_method(this, "_update_space"); - undo_redo->add_do_method(this, "_update_edited_point_pos"); - undo_redo->add_undo_method(this, "_update_edited_point_pos"); - undo_redo->commit_action(); - updating = false; - _update_edited_point_pos(); + if (!read_only) { + updating = true; + undo_redo->create_action(TTR("Move Node Point")); + undo_redo->add_do_method(blend_space.ptr(), "set_blend_point_position", selected_point, point); + undo_redo->add_undo_method(blend_space.ptr(), "set_blend_point_position", selected_point, blend_space->get_blend_point_position(selected_point)); + undo_redo->add_do_method(this, "_update_space"); + undo_redo->add_undo_method(this, "_update_space"); + undo_redo->add_do_method(this, "_update_edited_point_pos"); + undo_redo->add_undo_method(this, "_update_edited_point_pos"); + undo_redo->commit_action(); + updating = false; + _update_edited_point_pos(); + } } dragging_selected_attempt = false; dragging_selected = false; @@ -259,7 +283,9 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_gui_input(const Ref<InputEven if (mm.is_valid() && dragging_selected_attempt) { dragging_selected = true; - drag_ofs = ((mm->get_position() - drag_from) / blend_space_draw->get_size()) * (blend_space->get_max_space() - blend_space->get_min_space()) * Vector2(1, -1); + if (!read_only) { + drag_ofs = ((mm->get_position() - drag_from) / blend_space_draw->get_size()) * (blend_space->get_max_space() - blend_space->get_min_space()) * Vector2(1, -1); + } blend_space_draw->update(); _update_edited_point_pos(); } @@ -355,7 +381,10 @@ void AnimationNodeBlendSpace2DEditor::_add_animation_type(int p_index) { } void AnimationNodeBlendSpace2DEditor::_update_tool_erase() { - tool_erase->set_disabled(!(selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) && !(selected_triangle >= 0 && selected_triangle < blend_space->get_triangle_count())); + tool_erase->set_disabled( + (!(selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) && !(selected_triangle >= 0 && selected_triangle < blend_space->get_triangle_count())) || + read_only); + if (selected_point >= 0 && selected_point < blend_space->get_blend_point_count()) { Ref<AnimationNode> an = blend_space->get_blend_point_node(selected_point); if (AnimationTreeEditor::get_singleton()->can_edit(an)) { @@ -363,7 +392,11 @@ void AnimationNodeBlendSpace2DEditor::_update_tool_erase() { } else { open_editor->hide(); } - edit_hb->show(); + if (!read_only) { + edit_hb->show(); + } else { + edit_hb->hide(); + } } else { edit_hb->hide(); } @@ -503,10 +536,12 @@ void AnimationNodeBlendSpace2DEditor::_blend_space_draw() { points.clear(); for (int i = 0; i < blend_space->get_blend_point_count(); i++) { Vector2 point = blend_space->get_blend_point_position(i); - if (dragging_selected && selected_point == i) { - point += drag_ofs; - if (snap->is_pressed()) { - point = point.snapped(blend_space->get_snap()); + if (!read_only) { + if (dragging_selected && selected_point == i) { + point += drag_ofs; + if (snap->is_pressed()) { + point = point.snapped(blend_space->get_snap()); + } } } point = (point - blend_space->get_min_space()) / (blend_space->get_max_space() - blend_space->get_min_space()); @@ -737,7 +772,6 @@ void AnimationNodeBlendSpace2DEditor::_edit_point_pos(double) { void AnimationNodeBlendSpace2DEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); @@ -833,7 +867,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_blend->set_button_group(bg); top_hb->add_child(tool_blend); tool_blend->set_pressed(true); - tool_blend->set_tooltip(TTR("Set the blending position within the space")); + tool_blend->set_tooltip_text(TTR("Set the blending position within the space")); tool_blend->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(3)); tool_select = memnew(Button); @@ -841,7 +875,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); top_hb->add_child(tool_select); - tool_select->set_tooltip(TTR("Select and move points, create points with RMB.")); + tool_select->set_tooltip_text(TTR("Select and move points, create points with RMB.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(0)); tool_create = memnew(Button); @@ -849,7 +883,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); top_hb->add_child(tool_create); - tool_create->set_tooltip(TTR("Create points.")); + tool_create->set_tooltip_text(TTR("Create points.")); tool_create->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(1)); tool_triangle = memnew(Button); @@ -857,7 +891,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_triangle->set_toggle_mode(true); tool_triangle->set_button_group(bg); top_hb->add_child(tool_triangle); - tool_triangle->set_tooltip(TTR("Create triangles by connecting points.")); + tool_triangle->set_tooltip_text(TTR("Create triangles by connecting points.")); tool_triangle->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_tool_switch).bind(2)); tool_erase_sep = memnew(VSeparator); @@ -865,7 +899,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { tool_erase = memnew(Button); tool_erase->set_flat(true); top_hb->add_child(tool_erase); - tool_erase->set_tooltip(TTR("Erase points and triangles.")); + tool_erase->set_tooltip_text(TTR("Erase points and triangles.")); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_erase_selected)); tool_erase->set_disabled(true); @@ -876,7 +910,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { top_hb->add_child(auto_triangles); auto_triangles->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_auto_triangles_toggled)); auto_triangles->set_toggle_mode(true); - auto_triangles->set_tooltip(TTR("Generate blend triangles automatically (instead of manually)")); + auto_triangles->set_tooltip_text(TTR("Generate blend triangles automatically (instead of manually)")); top_hb->add_child(memnew(VSeparator)); @@ -885,7 +919,7 @@ AnimationNodeBlendSpace2DEditor::AnimationNodeBlendSpace2DEditor() { snap->set_toggle_mode(true); top_hb->add_child(snap); snap->set_pressed(true); - snap->set_tooltip(TTR("Enable snap and show grid.")); + snap->set_tooltip_text(TTR("Enable snap and show grid.")); snap->connect("pressed", callable_mp(this, &AnimationNodeBlendSpace2DEditor::_snap_toggled)); snap_x = memnew(SpinBox); diff --git a/editor/plugins/animation_blend_space_2d_editor.h b/editor/plugins/animation_blend_space_2d_editor.h index df2bcf254d..1f015a1804 100644 --- a/editor/plugins/animation_blend_space_2d_editor.h +++ b/editor/plugins/animation_blend_space_2d_editor.h @@ -46,6 +46,7 @@ class AnimationNodeBlendSpace2DEditor : public AnimationTreeNodeEditorPlugin { GDCLASS(AnimationNodeBlendSpace2DEditor, AnimationTreeNodeEditorPlugin); Ref<AnimationNodeBlendSpace2D> blend_space; + bool read_only = false; PanelContainer *panel = nullptr; Button *tool_blend = nullptr; diff --git a/editor/plugins/animation_blend_tree_editor_plugin.cpp b/editor/plugins/animation_blend_tree_editor_plugin.cpp index e4f5576d66..11054ee11e 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.cpp +++ b/editor/plugins/animation_blend_tree_editor_plugin.cpp @@ -134,6 +134,8 @@ void AnimationNodeBlendTreeEditor::_update_graph() { GraphNode *node = memnew(GraphNode); graph->add_child(node); + node->set_draggable(!read_only); + Ref<AnimationNode> agnode = blend_tree->get_node(E); ERR_CONTINUE(!agnode.is_valid()); @@ -146,9 +148,10 @@ void AnimationNodeBlendTreeEditor::_update_graph() { if (String(E) != "output") { LineEdit *name = memnew(LineEdit); name->set_text(E); + name->set_editable(!read_only); name->set_expand_to_text_length_enabled(true); node->add_child(name); - node->set_slot(0, false, 0, Color(), true, 0, get_theme_color(SNAME("font_color"), SNAME("Label"))); + node->set_slot(0, false, 0, Color(), true, read_only ? -1 : 0, get_theme_color(SNAME("font_color"), SNAME("Label"))); name->connect("text_submitted", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed).bind(agnode), CONNECT_DEFERRED); name->connect("focus_exited", callable_mp(this, &AnimationNodeBlendTreeEditor::_node_renamed_focus_out).bind(name, agnode), CONNECT_DEFERRED); base = 1; @@ -160,7 +163,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { Label *in_name = memnew(Label); node->add_child(in_name); in_name->set_text(agnode->get_input_name(i)); - node->set_slot(base + i, true, 0, get_theme_color(SNAME("font_color"), SNAME("Label")), false, 0, Color()); + node->set_slot(base + i, true, read_only ? -1 : 0, get_theme_color(SNAME("font_color"), SNAME("Label")), false, 0, Color()); } List<PropertyInfo> pinfo; @@ -172,6 +175,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { String base_path = AnimationTreeEditor::get_singleton()->get_base_path() + String(E) + "/" + F.name; EditorProperty *prop = EditorInspector::instantiate_property_editor(AnimationTreeEditor::get_singleton()->get_tree(), F.type, base_path, F.hint, F.hint_string, F.usage); if (prop) { + prop->set_read_only(read_only); prop->set_object_and_property(AnimationTreeEditor::get_singleton()->get_tree(), base_path); prop->update_property(); prop->set_name_split_ratio(0); @@ -195,12 +199,16 @@ void AnimationNodeBlendTreeEditor::_update_graph() { if (agnode->has_filter()) { node->add_child(memnew(HSeparator)); - Button *edit_filters = memnew(Button); - edit_filters->set_text(TTR("Edit Filters")); - edit_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons"))); - node->add_child(edit_filters); - edit_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_edit_filters).bind(E), CONNECT_DEFERRED); - edit_filters->set_h_size_flags(SIZE_SHRINK_CENTER); + Button *inspect_filters = memnew(Button); + if (read_only) { + inspect_filters->set_text(TTR("Inspect Filters")); + } else { + inspect_filters->set_text(TTR("Edit Filters")); + } + inspect_filters->set_icon(get_theme_icon(SNAME("AnimationFilter"), SNAME("EditorIcons"))); + node->add_child(inspect_filters); + inspect_filters->connect("pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_inspect_filters).bind(E), CONNECT_DEFERRED); + inspect_filters->set_h_size_flags(SIZE_SHRINK_CENTER); } Ref<AnimationNodeAnimation> anim = agnode; @@ -208,6 +216,7 @@ void AnimationNodeBlendTreeEditor::_update_graph() { MenuButton *mb = memnew(MenuButton); mb->set_text(anim->get_animation()); mb->set_icon(get_theme_icon(SNAME("Animation"), SNAME("EditorIcons"))); + mb->set_disabled(read_only); Array options; node->add_child(memnew(HSeparator)); @@ -370,10 +379,18 @@ void AnimationNodeBlendTreeEditor::_popup(bool p_has_input_ports, const Vector2 } void AnimationNodeBlendTreeEditor::_popup_request(const Vector2 &p_position) { + if (read_only) { + return; + } + _popup(false, graph->get_screen_position() + graph->get_local_mouse_position(), p_position); } void AnimationNodeBlendTreeEditor::_connection_to_empty(const String &p_from, int p_from_slot, const Vector2 &p_release_position) { + if (read_only) { + return; + } + Ref<AnimationNode> node = blend_tree->get_node(p_from); if (node.is_valid()) { from_node = p_from; @@ -382,6 +399,10 @@ void AnimationNodeBlendTreeEditor::_connection_to_empty(const String &p_from, in } void AnimationNodeBlendTreeEditor::_connection_from_empty(const String &p_to, int p_to_slot, const Vector2 &p_release_position) { + if (read_only) { + return; + } + Ref<AnimationNode> node = blend_tree->get_node(p_to); if (node.is_valid()) { to_node = p_to; @@ -402,6 +423,10 @@ void AnimationNodeBlendTreeEditor::_node_dragged(const Vector2 &p_from, const Ve } void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) { + if (read_only) { + return; + } + AnimationNodeBlendTree::ConnectionError err = blend_tree->can_connect_node(p_to, p_to_index, p_from); if (err != AnimationNodeBlendTree::CONNECTION_OK) { @@ -418,6 +443,10 @@ void AnimationNodeBlendTreeEditor::_connection_request(const String &p_from, int } void AnimationNodeBlendTreeEditor::_disconnection_request(const String &p_from, int p_from_index, const String &p_to, int p_to_index) { + if (read_only) { + return; + } + graph->disconnect_node(p_from, p_from_index, p_to, p_to_index); updating = true; @@ -445,6 +474,10 @@ void AnimationNodeBlendTreeEditor::_anim_selected(int p_index, Array p_options, } void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) { + if (read_only) { + return; + } + undo_redo->create_action(TTR("Delete Node")); undo_redo->add_do_method(blend_tree.ptr(), "remove_node", p_which); undo_redo->add_undo_method(blend_tree.ptr(), "add_node", p_which, blend_tree->get_node(p_which), blend_tree.ptr()->get_node_position(p_which)); @@ -464,6 +497,10 @@ void AnimationNodeBlendTreeEditor::_delete_request(const String &p_which) { } void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray<StringName> &p_nodes) { + if (read_only) { + return; + } + List<StringName> to_erase; if (p_nodes.is_empty()) { @@ -495,6 +532,10 @@ void AnimationNodeBlendTreeEditor::_delete_nodes_request(const TypedArray<String } void AnimationNodeBlendTreeEditor::_node_selected(Object *p_node) { + if (read_only) { + return; + } + GraphNode *gn = Object::cast_to<GraphNode>(p_node); ERR_FAIL_COND(!gn); @@ -679,7 +720,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano } } - ti->set_editable(0, true); + ti->set_editable(0, !read_only); ti->set_selectable(0, true); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); @@ -692,7 +733,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano ti = filters->create_item(ti); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, concat); - ti->set_editable(0, true); + ti->set_editable(0, !read_only); ti->set_selectable(0, true); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_metadata(0, path); @@ -714,7 +755,7 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano ti = filters->create_item(ti); ti->set_cell_mode(0, TreeItem::CELL_MODE_CHECK); ti->set_text(0, types_text); - ti->set_editable(0, true); + ti->set_editable(0, !read_only); ti->set_selectable(0, true); ti->set_checked(0, anode->is_path_filtered(path)); ti->set_metadata(0, path); @@ -727,7 +768,15 @@ bool AnimationNodeBlendTreeEditor::_update_filters(const Ref<AnimationNode> &ano return true; } -void AnimationNodeBlendTreeEditor::_edit_filters(const String &p_which) { +void AnimationNodeBlendTreeEditor::_inspect_filters(const String &p_which) { + if (read_only) { + filter_dialog->set_title(TTR("Inspect Filtered Tracks:")); + } else { + filter_dialog->set_title(TTR("Edit Filtered Tracks:")); + } + + filter_enabled->set_disabled(read_only); + Ref<AnimationNode> anode = blend_tree->get_node(p_which); ERR_FAIL_COND(!anode.is_valid()); @@ -750,16 +799,10 @@ void AnimationNodeBlendTreeEditor::_update_editor_settings() { graph->set_warped_panning(bool(EditorSettings::get_singleton()->get("editors/panning/warped_mouse_panning"))); } -void AnimationNodeBlendTreeEditor::_update_theme() { - error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); - error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); -} - void AnimationNodeBlendTreeEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { _update_editor_settings(); - _update_theme(); } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { @@ -767,7 +810,8 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); if (is_visible_in_tree()) { _update_graph(); @@ -838,6 +882,10 @@ void AnimationNodeBlendTreeEditor::_notification(int p_what) { } void AnimationNodeBlendTreeEditor::_scroll_changed(const Vector2 &p_scroll) { + if (read_only) { + return; + } + if (updating) { return; } @@ -944,13 +992,20 @@ void AnimationNodeBlendTreeEditor::edit(const Ref<AnimationNode> &p_node) { blend_tree = p_node; + read_only = false; + if (blend_tree.is_null()) { hide(); } else { + read_only = EditorNode::get_singleton()->is_resource_read_only(blend_tree); + blend_tree->connect("removed_from_graph", callable_mp(this, &AnimationNodeBlendTreeEditor::_removed_from_graph)); _update_graph(); } + + add_node->set_disabled(read_only); + graph->set_arrange_nodes_button_hidden(read_only); } AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { @@ -986,6 +1041,7 @@ AnimationNodeBlendTreeEditor::AnimationNodeBlendTreeEditor() { graph->get_zoom_hbox()->move_child(add_node, 0); add_node->get_popup()->connect("id_pressed", callable_mp(this, &AnimationNodeBlendTreeEditor::_add_node)); add_node->connect("about_to_popup", callable_mp(this, &AnimationNodeBlendTreeEditor::_update_options_menu).bind(false)); + add_node->set_disabled(read_only); add_options.push_back(AddOption("Animation", "AnimationNodeAnimation")); add_options.push_back(AddOption("OneShot", "AnimationNodeOneShot", 2)); diff --git a/editor/plugins/animation_blend_tree_editor_plugin.h b/editor/plugins/animation_blend_tree_editor_plugin.h index af43da6197..cdbf2975f2 100644 --- a/editor/plugins/animation_blend_tree_editor_plugin.h +++ b/editor/plugins/animation_blend_tree_editor_plugin.h @@ -47,6 +47,9 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { GDCLASS(AnimationNodeBlendTreeEditor, AnimationTreeNodeEditorPlugin); Ref<AnimationNodeBlendTree> blend_tree; + + bool read_only = false; + GraphEdit *graph = nullptr; MenuButton *add_node = nullptr; Vector2 position_from_popup_menu; @@ -106,7 +109,7 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _delete_nodes_request(const TypedArray<StringName> &p_nodes); bool _update_filters(const Ref<AnimationNode> &anode); - void _edit_filters(const String &p_which); + void _inspect_filters(const String &p_which); void _filter_edited(); void _filter_toggled(); Ref<AnimationNode> _filter_edit; @@ -120,7 +123,6 @@ class AnimationNodeBlendTreeEditor : public AnimationTreeNodeEditorPlugin { void _removed_from_graph(); void _update_editor_settings(); - void _update_theme(); EditorFileDialog *open_file = nullptr; Ref<AnimationNode> file_loaded; diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index f374f48fb2..e47c5b1e4b 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -1646,28 +1646,28 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug play_bw_from = memnew(Button); play_bw_from->set_flat(true); - play_bw_from->set_tooltip(TTR("Play selected animation backwards from current pos. (A)")); + play_bw_from->set_tooltip_text(TTR("Play selected animation backwards from current pos. (A)")); hb->add_child(play_bw_from); play_bw = memnew(Button); play_bw->set_flat(true); - play_bw->set_tooltip(TTR("Play selected animation backwards from end. (Shift+A)")); + play_bw->set_tooltip_text(TTR("Play selected animation backwards from end. (Shift+A)")); hb->add_child(play_bw); stop = memnew(Button); stop->set_flat(true); stop->set_toggle_mode(true); hb->add_child(stop); - stop->set_tooltip(TTR("Stop animation playback. (S)")); + stop->set_tooltip_text(TTR("Stop animation playback. (S)")); play = memnew(Button); play->set_flat(true); - play->set_tooltip(TTR("Play selected animation from start. (Shift+D)")); + play->set_tooltip_text(TTR("Play selected animation from start. (Shift+D)")); hb->add_child(play); play_from = memnew(Button); play_from->set_flat(true); - play_from->set_tooltip(TTR("Play selected animation from current pos. (D)")); + play_from->set_tooltip_text(TTR("Play selected animation from current pos. (D)")); hb->add_child(play_from); frame = memnew(SpinBox); @@ -1675,7 +1675,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug frame->set_custom_minimum_size(Size2(80, 0) * EDSCALE); frame->set_stretch_ratio(2); frame->set_step(0.0001); - frame->set_tooltip(TTR("Animation position (in seconds).")); + frame->set_tooltip_text(TTR("Animation position (in seconds).")); hb->add_child(memnew(VSeparator)); @@ -1683,7 +1683,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug hb->add_child(scale); scale->set_h_size_flags(SIZE_EXPAND_FILL); scale->set_stretch_ratio(1); - scale->set_tooltip(TTR("Scale animation playback globally for the node.")); + scale->set_tooltip_text(TTR("Scale animation playback globally for the node.")); scale->hide(); delete_dialog = memnew(ConfirmationDialog); @@ -1693,7 +1693,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug tool_anim = memnew(MenuButton); tool_anim->set_shortcut_context(this); tool_anim->set_flat(false); - tool_anim->set_tooltip(TTR("Animation Tools")); + tool_anim->set_tooltip_text(TTR("Animation Tools")); tool_anim->set_text(TTR("Animation")); tool_anim->get_popup()->add_shortcut(ED_SHORTCUT("animation_player_editor/new_animation", TTR("New")), TOOL_NEW_ANIM); tool_anim->get_popup()->add_separator(); @@ -1712,13 +1712,13 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug animation = memnew(OptionButton); hb->add_child(animation); animation->set_h_size_flags(SIZE_EXPAND_FILL); - animation->set_tooltip(TTR("Display list of animations in player.")); + animation->set_tooltip_text(TTR("Display list of animations in player.")); animation->set_clip_text(true); autoplay = memnew(Button); autoplay->set_flat(true); hb->add_child(autoplay); - autoplay->set_tooltip(TTR("Autoplay on Load")); + autoplay->set_tooltip_text(TTR("Autoplay on Load")); hb->add_child(memnew(VSeparator)); @@ -1731,12 +1731,12 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug onion_toggle = memnew(Button); onion_toggle->set_flat(true); onion_toggle->set_toggle_mode(true); - onion_toggle->set_tooltip(TTR("Enable Onion Skinning")); + onion_toggle->set_tooltip_text(TTR("Enable Onion Skinning")); onion_toggle->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_onion_skinning_menu).bind(ONION_SKINNING_ENABLE)); hb->add_child(onion_toggle); onion_skinning = memnew(MenuButton); - onion_skinning->set_tooltip(TTR("Onion Skinning Options")); + onion_skinning->set_tooltip_text(TTR("Onion Skinning Options")); onion_skinning->get_popup()->add_separator(TTR("Directions")); // TRANSLATORS: Opposite of "Future", refers to a direction in animation onion skinning. onion_skinning->get_popup()->add_check_item(TTR("Past"), ONION_SKINNING_PAST); @@ -1759,7 +1759,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug pin = memnew(Button); pin->set_flat(true); pin->set_toggle_mode(true); - pin->set_tooltip(TTR("Pin AnimationPlayer")); + pin->set_tooltip_text(TTR("Pin AnimationPlayer")); hb->add_child(pin); pin->connect("pressed", callable_mp(this, &AnimationPlayerEditor::_pin_pressed)); diff --git a/editor/plugins/animation_state_machine_editor.cpp b/editor/plugins/animation_state_machine_editor.cpp index ef4ae3dca4..07d132229d 100644 --- a/editor/plugins/animation_state_machine_editor.cpp +++ b/editor/plugins/animation_state_machine_editor.cpp @@ -56,7 +56,11 @@ bool AnimationNodeStateMachineEditor::can_edit(const Ref<AnimationNode> &p_node) void AnimationNodeStateMachineEditor::edit(const Ref<AnimationNode> &p_node) { state_machine = p_node; + read_only = false; + if (state_machine.is_valid()) { + read_only = EditorNode::get_singleton()->is_resource_read_only(state_machine); + selected_transition_from = StringName(); selected_transition_to = StringName(); selected_transition_index = -1; @@ -66,6 +70,9 @@ void AnimationNodeStateMachineEditor::edit(const Ref<AnimationNode> &p_node) { _update_mode(); _update_graph(); } + + tool_create->set_disabled(read_only); + tool_connect->set_disabled(read_only); } void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEvent> &p_event) { @@ -77,7 +84,9 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv Ref<InputEventKey> k = p_event; if (tool_select->is_pressed() && k.is_valid() && k->is_pressed() && k->get_keycode() == Key::KEY_DELETE && !k->is_echo()) { if (selected_node != StringName() || !selected_nodes.is_empty() || selected_transition_to != StringName() || selected_transition_from != StringName()) { - _erase_selected(); + if (!read_only) { + _erase_selected(); + } accept_event(); } } @@ -95,9 +104,11 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv Ref<InputEventMouseButton> mb = p_event; // Add new node - if (mb.is_valid() && mb->is_pressed() && !box_selecting && !connecting && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MouseButton::LEFT))) { - connecting_from = StringName(); - _open_menu(mb->get_position()); + if (!read_only) { + if (mb.is_valid() && mb->is_pressed() && !box_selecting && !connecting && ((tool_select->is_pressed() && mb->get_button_index() == MouseButton::RIGHT) || (tool_create->is_pressed() && mb->get_button_index() == MouseButton::LEFT))) { + connecting_from = StringName(); + _open_menu(mb->get_position()); + } } // Select node or push a field inside @@ -121,22 +132,24 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv return; } - if (node_rects[i].name.has_point(mb->get_position()) && state_machine->can_edit_node(node_rects[i].node_name)) { // edit name - Ref<StyleBox> line_sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")); + if (!read_only) { + if (node_rects[i].name.has_point(mb->get_position()) && state_machine->can_edit_node(node_rects[i].node_name)) { // edit name + Ref<StyleBox> line_sb = get_theme_stylebox(SNAME("normal"), SNAME("LineEdit")); - Rect2 edit_rect = node_rects[i].name; - edit_rect.position -= line_sb->get_offset(); - edit_rect.size += line_sb->get_minimum_size(); + Rect2 edit_rect = node_rects[i].name; + edit_rect.position -= line_sb->get_offset(); + edit_rect.size += line_sb->get_minimum_size(); - name_edit_popup->set_position(state_machine_draw->get_screen_position() + edit_rect.position); - name_edit_popup->set_size(edit_rect.size); - name_edit->set_text(node_rects[i].node_name); - name_edit_popup->popup(); - name_edit->grab_focus(); - name_edit->select_all(); + name_edit_popup->set_position(state_machine_draw->get_screen_position() + edit_rect.position); + name_edit_popup->set_size(edit_rect.size); + name_edit->set_text(node_rects[i].node_name); + name_edit_popup->popup(); + name_edit->grab_focus(); + name_edit->select_all(); - prev_name = node_rects[i].node_name; - return; + prev_name = node_rects[i].node_name; + return; + } } if (node_rects[i].edit.has_point(mb->get_position())) { //edit name @@ -319,7 +332,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } // Move mouse while connecting - if (mm.is_valid() && connecting) { + if (mm.is_valid() && connecting && !read_only) { connecting_to = mm->get_position(); connecting_to_node = StringName(); state_machine_draw->update(); @@ -333,7 +346,7 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } // Move mouse while moving a node - if (mm.is_valid() && dragging_selected_attempt) { + if (mm.is_valid() && dragging_selected_attempt && !read_only) { dragging_selected = true; drag_ofs = mm->get_position() - drag_from; snap_x = StringName(); @@ -463,9 +476,9 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv to = String(transition_lines[closest].multi_transitions[i].to_node); tooltip += "\n" + from + " -> " + to; } - state_machine_draw->set_tooltip(tooltip); + state_machine_draw->set_tooltip_text(tooltip); } else { - state_machine_draw->set_tooltip(""); + state_machine_draw->set_tooltip_text(""); } } } @@ -478,17 +491,21 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv } Control::CursorShape AnimationNodeStateMachineEditor::get_cursor_shape(const Point2 &p_pos) const { - // Put ibeam (text cursor) over names to make it clearer that they are editable. - Transform2D xform = panel->get_transform() * state_machine_draw->get_transform(); - Point2 pos = xform.xform_inv(p_pos); Control::CursorShape cursor_shape = get_default_cursor_shape(); - - for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order. - if (node_rects[i].node.has_point(pos)) { - if (node_rects[i].name.has_point(pos)) { - cursor_shape = Control::CURSOR_IBEAM; + if (!read_only) { + // Put ibeam (text cursor) over names to make it clearer that they are editable. + Transform2D xform = panel->get_transform() * state_machine_draw->get_transform(); + Point2 pos = xform.xform_inv(p_pos); + + for (int i = node_rects.size() - 1; i >= 0; i--) { // Inverse to draw order. + if (node_rects[i].node.has_point(pos)) { + if (node_rects[i].name.has_point(pos)) { + if (state_machine->can_edit_node(node_rects[i].node_name)) { + cursor_shape = Control::CURSOR_IBEAM; + } + } + break; } - break; } } return cursor_shape; @@ -1527,10 +1544,9 @@ void AnimationNodeStateMachineEditor::_update_graph() { void AnimationNodeStateMachineEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: - case NOTIFICATION_TRANSLATION_CHANGED: { + case NOTIFICATION_TRANSLATION_CHANGED: + case NOTIFICATION_THEME_CHANGED: { error_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); error_label->add_theme_color_override("font_color", get_theme_color(SNAME("error_color"), SNAME("Editor"))); panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); @@ -1848,9 +1864,9 @@ void AnimationNodeStateMachineEditor::_update_mode() { tool_erase_hb->show(); bool nothing_selected = selected_nodes.is_empty() && selected_transition_from == StringName() && selected_transition_to == StringName(); bool start_end_selected = selected_nodes.size() == 1 && (*selected_nodes.begin() == state_machine->start_node || *selected_nodes.begin() == state_machine->end_node); - tool_erase->set_disabled(nothing_selected || start_end_selected); + tool_erase->set_disabled(nothing_selected || start_end_selected || read_only); - if (selected_nodes.is_empty() || start_end_selected) { + if (selected_nodes.is_empty() || start_end_selected || read_only) { tool_group->set_disabled(true); tool_group->set_visible(true); tool_ungroup->set_visible(false); @@ -1900,7 +1916,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_select->set_toggle_mode(true); tool_select->set_button_group(bg); tool_select->set_pressed(true); - tool_select->set_tooltip(TTR("Select and move nodes.\nRMB: Add node at position clicked.\nShift+LMB+Drag: Connects the selected node with another node or creates a new node if you select an area without nodes.")); + tool_select->set_tooltip_text(TTR("Select and move nodes.\nRMB: Add node at position clicked.\nShift+LMB+Drag: Connects the selected node with another node or creates a new node if you select an area without nodes.")); tool_select->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED); tool_create = memnew(Button); @@ -1908,7 +1924,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { top_hb->add_child(tool_create); tool_create->set_toggle_mode(true); tool_create->set_button_group(bg); - tool_create->set_tooltip(TTR("Create new nodes.")); + tool_create->set_tooltip_text(TTR("Create new nodes.")); tool_create->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED); tool_connect = memnew(Button); @@ -1916,7 +1932,7 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { top_hb->add_child(tool_connect); tool_connect->set_toggle_mode(true); tool_connect->set_button_group(bg); - tool_connect->set_tooltip(TTR("Connect nodes.")); + tool_connect->set_tooltip_text(TTR("Connect nodes.")); tool_connect->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_update_mode), CONNECT_DEFERRED); tool_erase_hb = memnew(HBoxContainer); @@ -1925,21 +1941,21 @@ AnimationNodeStateMachineEditor::AnimationNodeStateMachineEditor() { tool_group = memnew(Button); tool_group->set_flat(true); - tool_group->set_tooltip(TTR("Group Selected Node(s)") + " (Ctrl+G)"); + tool_group->set_tooltip_text(TTR("Group Selected Node(s)") + " (Ctrl+G)"); tool_group->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_group_selected_nodes)); tool_group->set_disabled(true); tool_erase_hb->add_child(tool_group); tool_ungroup = memnew(Button); tool_ungroup->set_flat(true); - tool_ungroup->set_tooltip(TTR("Ungroup Selected Node") + " (Ctrl+Shift+G)"); + tool_ungroup->set_tooltip_text(TTR("Ungroup Selected Node") + " (Ctrl+Shift+G)"); tool_ungroup->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_ungroup_selected_nodes)); tool_ungroup->set_visible(false); tool_erase_hb->add_child(tool_ungroup); tool_erase = memnew(Button); tool_erase->set_flat(true); - tool_erase->set_tooltip(TTR("Remove selected node or transition.")); + tool_erase->set_tooltip_text(TTR("Remove selected node or transition.")); tool_erase->connect("pressed", callable_mp(this, &AnimationNodeStateMachineEditor::_erase_selected).bind(false)); tool_erase->set_disabled(true); tool_erase_hb->add_child(tool_erase); diff --git a/editor/plugins/animation_state_machine_editor.h b/editor/plugins/animation_state_machine_editor.h index fdd1af0f6d..3a59e94a5f 100644 --- a/editor/plugins/animation_state_machine_editor.h +++ b/editor/plugins/animation_state_machine_editor.h @@ -47,6 +47,8 @@ class AnimationNodeStateMachineEditor : public AnimationTreeNodeEditorPlugin { Ref<AnimationNodeStateMachine> state_machine; + bool read_only = false; + Button *tool_select = nullptr; Button *tool_create = nullptr; Button *tool_connect = nullptr; diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp index 8ee162d085..3c12d17c57 100644 --- a/editor/plugins/asset_library_editor_plugin.cpp +++ b/editor/plugins/asset_library_editor_plugin.cpp @@ -193,7 +193,6 @@ void EditorAssetLibraryItemDescription::set_image(int p_type, int p_index, const void EditorAssetLibraryItemDescription::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { previews_bg->add_theme_style_override("panel", previews->get_theme_stylebox(SNAME("normal"), SNAME("TextEdit"))); } break; @@ -401,7 +400,6 @@ void EditorAssetLibraryItemDownload::configure(const String &p_title, int p_asse void EditorAssetLibraryItemDownload::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("AssetLib"))); status->add_theme_color_override("font_color", get_theme_color(SNAME("status_color"), SNAME("AssetLib"))); @@ -580,7 +578,6 @@ void EditorAssetLibrary::_notification(int p_what) { error_label->raise(); } break; - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { error_tr->set_texture(get_theme_icon(SNAME("Error"), SNAME("EditorIcons"))); filter->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); diff --git a/editor/plugins/bone_map_editor_plugin.cpp b/editor/plugins/bone_map_editor_plugin.cpp index 5db9249af1..c16dca00a3 100644 --- a/editor/plugins/bone_map_editor_plugin.cpp +++ b/editor/plugins/bone_map_editor_plugin.cpp @@ -294,7 +294,7 @@ void BoneMapper::create_editor() { clear_mapping_button = memnew(Button); clear_mapping_button->set_icon(get_theme_icon(SNAME("Clear"), SNAME("EditorIcons"))); - clear_mapping_button->set_tooltip(TTR("Clear mappings in current group.")); + clear_mapping_button->set_tooltip_text(TTR("Clear mappings in current group.")); clear_mapping_button->connect("pressed", callable_mp(this, &BoneMapper::_clear_mapping_current_group)); group_hbox->add_child(clear_mapping_button); diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index 2e83e2041f..1ed37876f0 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -223,8 +223,8 @@ public: grid_step_x->set_value(p_grid_step.x); grid_step_y->set_value(p_grid_step.y); primary_grid_steps->set_value(p_primary_grid_steps); - rotation_offset->set_value(Math::rad2deg(p_rotation_offset)); - rotation_step->set_value(Math::rad2deg(p_rotation_step)); + rotation_offset->set_value(Math::rad_to_deg(p_rotation_offset)); + rotation_step->set_value(Math::rad_to_deg(p_rotation_step)); scale_step->set_value(p_scale_step); } @@ -232,8 +232,8 @@ public: p_grid_offset = Point2(grid_offset_x->get_value(), grid_offset_y->get_value()); p_grid_step = Point2(grid_step_x->get_value(), grid_step_y->get_value()); p_primary_grid_steps = int(primary_grid_steps->get_value()); - p_rotation_offset = Math::deg2rad(rotation_offset->get_value()); - p_rotation_step = Math::deg2rad(rotation_step->get_value()); + p_rotation_offset = Math::deg_to_rad(rotation_offset->get_value()); + p_rotation_step = Math::deg_to_rad(rotation_step->get_value()); p_scale_step = scale_step->get_value(); } }; @@ -1447,7 +1447,7 @@ bool CanvasItemEditor::_gui_input_rotate(const Ref<InputEvent> &p_event) { drag_selection, vformat(TTR("Rotate CanvasItem \"%s\" to %d degrees"), drag_selection[0]->get_name(), - Math::rad2deg(drag_selection[0]->_edit_get_rotation())), + Math::rad_to_deg(drag_selection[0]->_edit_get_rotation())), true); } @@ -3676,7 +3676,7 @@ void CanvasItemEditor::_draw_transform_message() { } break; case DRAG_ROTATE: { - real_t delta = Math::rad2deg(current_transform.get_rotation() - original_transform.get_rotation()); + real_t delta = Math::rad_to_deg(current_transform.get_rotation() - original_transform.get_rotation()); transform_message = TTR("Rotating:") + " " + FORMAT(delta) + String::utf8(" °"); } break; @@ -4261,11 +4261,11 @@ void CanvasItemEditor::_insert_animation_keys(bool p_location, bool p_rotation, void CanvasItemEditor::_update_override_camera_button(bool p_game_running) { if (p_game_running) { override_camera_button->set_disabled(false); - override_camera_button->set_tooltip(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera.")); + override_camera_button->set_tooltip_text(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera.")); } else { override_camera_button->set_disabled(true); override_camera_button->set_pressed(false); - override_camera_button->set_tooltip(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature.")); + override_camera_button->set_tooltip_text(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature.")); } } @@ -5104,7 +5104,7 @@ CanvasItemEditor::CanvasItemEditor() { select_button->set_pressed(true); select_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/select_mode", TTR("Select Mode"), Key::Q)); select_button->set_shortcut_context(this); - select_button->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked.")); + select_button->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+Drag: Move selected node.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Alt+Drag: Scale selected node.") + "\n" + TTR("V: Set selected node's pivot position.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("RMB: Add node at position clicked.")); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5115,7 +5115,7 @@ CanvasItemEditor::CanvasItemEditor() { move_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_MOVE)); move_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/move_mode", TTR("Move Mode"), Key::W)); move_button->set_shortcut_context(this); - move_button->set_tooltip(TTR("Move Mode")); + move_button->set_tooltip_text(TTR("Move Mode")); rotate_button = memnew(Button); rotate_button->set_flat(true); @@ -5124,7 +5124,7 @@ CanvasItemEditor::CanvasItemEditor() { rotate_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_ROTATE)); rotate_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/rotate_mode", TTR("Rotate Mode"), Key::E)); rotate_button->set_shortcut_context(this); - rotate_button->set_tooltip(TTR("Rotate Mode")); + rotate_button->set_tooltip_text(TTR("Rotate Mode")); scale_button = memnew(Button); scale_button->set_flat(true); @@ -5133,7 +5133,7 @@ CanvasItemEditor::CanvasItemEditor() { scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_SCALE)); scale_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/scale_mode", TTR("Scale Mode"), Key::S)); scale_button->set_shortcut_context(this); - scale_button->set_tooltip(TTR("Shift: Scale proportionally.")); + scale_button->set_tooltip_text(TTR("Shift: Scale proportionally.")); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5142,14 +5142,14 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(list_select_button); list_select_button->set_toggle_mode(true); list_select_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_LIST_SELECT)); - list_select_button->set_tooltip(TTR("Show list of selectable nodes at position clicked.")); + list_select_button->set_tooltip_text(TTR("Show list of selectable nodes at position clicked.")); pivot_button = memnew(Button); pivot_button->set_flat(true); main_menu_hbox->add_child(pivot_button); pivot_button->set_toggle_mode(true); pivot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_EDIT_PIVOT)); - pivot_button->set_tooltip(TTR("Click to change object's rotation pivot.")); + pivot_button->set_tooltip_text(TTR("Click to change object's rotation pivot.")); pan_button = memnew(Button); pan_button->set_flat(true); @@ -5158,7 +5158,7 @@ CanvasItemEditor::CanvasItemEditor() { pan_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_PAN)); pan_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/pan_mode", TTR("Pan Mode"), Key::G)); pan_button->set_shortcut_context(this); - pan_button->set_tooltip(TTR("You can also use Pan View shortcut (Space by default) to pan in any mode.")); + pan_button->set_tooltip_text(TTR("You can also use Pan View shortcut (Space by default) to pan in any mode.")); ruler_button = memnew(Button); ruler_button->set_flat(true); @@ -5167,7 +5167,7 @@ CanvasItemEditor::CanvasItemEditor() { ruler_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_button_tool_select).bind(TOOL_RULER)); ruler_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/ruler_mode", TTR("Ruler Mode"), Key::R)); ruler_button->set_shortcut_context(this); - ruler_button->set_tooltip(TTR("Ruler Mode")); + ruler_button->set_tooltip_text(TTR("Ruler Mode")); main_menu_hbox->add_child(memnew(VSeparator)); @@ -5176,7 +5176,7 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(smart_snap_button); smart_snap_button->set_toggle_mode(true); smart_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_smart_snap)); - smart_snap_button->set_tooltip(TTR("Toggle smart snapping.")); + smart_snap_button->set_tooltip_text(TTR("Toggle smart snapping.")); smart_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_smart_snap", TTR("Use Smart Snap"), KeyModifierMask::SHIFT | Key::S)); smart_snap_button->set_shortcut_context(this); @@ -5185,7 +5185,7 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(grid_snap_button); grid_snap_button->set_toggle_mode(true); grid_snap_button->connect("toggled", callable_mp(this, &CanvasItemEditor::_button_toggle_grid_snap)); - grid_snap_button->set_tooltip(TTR("Toggle grid snapping.")); + grid_snap_button->set_tooltip_text(TTR("Toggle grid snapping.")); grid_snap_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/use_grid_snap", TTR("Use Grid Snap"), KeyModifierMask::SHIFT | Key::G)); grid_snap_button->set_shortcut_context(this); @@ -5193,7 +5193,7 @@ CanvasItemEditor::CanvasItemEditor() { snap_config_menu->set_shortcut_context(this); main_menu_hbox->add_child(snap_config_menu); snap_config_menu->set_h_size_flags(SIZE_SHRINK_END); - snap_config_menu->set_tooltip(TTR("Snapping Options")); + snap_config_menu->set_tooltip_text(TTR("Snapping Options")); snap_config_menu->set_switch_on_hover(true); PopupMenu *p = snap_config_menu->get_popup(); @@ -5227,7 +5227,7 @@ CanvasItemEditor::CanvasItemEditor() { main_menu_hbox->add_child(lock_button); lock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(LOCK_SELECTED)); - lock_button->set_tooltip(TTR("Lock selected node, preventing selection and movement.")); + lock_button->set_tooltip_text(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. lock_button->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); @@ -5235,7 +5235,7 @@ CanvasItemEditor::CanvasItemEditor() { unlock_button->set_flat(true); main_menu_hbox->add_child(unlock_button); unlock_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNLOCK_SELECTED)); - unlock_button->set_tooltip(TTR("Unlock selected node, allowing selection and movement.")); + unlock_button->set_tooltip_text(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. unlock_button->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); @@ -5243,7 +5243,7 @@ CanvasItemEditor::CanvasItemEditor() { group_button->set_flat(true); main_menu_hbox->add_child(group_button); group_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(GROUP_SELECTED)); - group_button->set_tooltip(TTR("Make selected node's children not selectable.")); + group_button->set_tooltip_text(TTR("Make selected node's children not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. group_button->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); @@ -5251,7 +5251,7 @@ CanvasItemEditor::CanvasItemEditor() { ungroup_button->set_flat(true); main_menu_hbox->add_child(ungroup_button); ungroup_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(UNGROUP_SELECTED)); - ungroup_button->set_tooltip(TTR("Make selected node's children selectable.")); + ungroup_button->set_tooltip_text(TTR("Make selected node's children selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. ungroup_button->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); @@ -5260,7 +5260,7 @@ CanvasItemEditor::CanvasItemEditor() { skeleton_menu = memnew(MenuButton); skeleton_menu->set_shortcut_context(this); main_menu_hbox->add_child(skeleton_menu); - skeleton_menu->set_tooltip(TTR("Skeleton Options")); + skeleton_menu->set_tooltip_text(TTR("Skeleton Options")); skeleton_menu->set_switch_on_hover(true); p = skeleton_menu->get_popup(); @@ -5340,7 +5340,7 @@ CanvasItemEditor::CanvasItemEditor() { key_loc_button->set_pressed(true); key_loc_button->set_focus_mode(FOCUS_NONE); key_loc_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_POS)); - key_loc_button->set_tooltip(TTR("Translation mask for inserting keys.")); + key_loc_button->set_tooltip_text(TTR("Translation mask for inserting keys.")); animation_hb->add_child(key_loc_button); key_rot_button = memnew(Button); @@ -5349,7 +5349,7 @@ CanvasItemEditor::CanvasItemEditor() { key_rot_button->set_pressed(true); key_rot_button->set_focus_mode(FOCUS_NONE); key_rot_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_ROT)); - key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys.")); + key_rot_button->set_tooltip_text(TTR("Rotation mask for inserting keys.")); animation_hb->add_child(key_rot_button); key_scale_button = memnew(Button); @@ -5357,14 +5357,14 @@ CanvasItemEditor::CanvasItemEditor() { key_scale_button->set_toggle_mode(true); key_scale_button->set_focus_mode(FOCUS_NONE); key_scale_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_SCALE)); - key_scale_button->set_tooltip(TTR("Scale mask for inserting keys.")); + key_scale_button->set_tooltip_text(TTR("Scale mask for inserting keys.")); animation_hb->add_child(key_scale_button); key_insert_button = memnew(Button); key_insert_button->set_flat(true); key_insert_button->set_focus_mode(FOCUS_NONE); key_insert_button->connect("pressed", callable_mp(this, &CanvasItemEditor::_popup_callback).bind(ANIM_INSERT_KEY)); - key_insert_button->set_tooltip(TTR("Insert keys (based on mask).")); + key_insert_button->set_tooltip_text(TTR("Insert keys (based on mask).")); key_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_insert_key", TTR("Insert Key"), Key::INSERT)); key_insert_button->set_shortcut_context(this); animation_hb->add_child(key_insert_button); @@ -5373,14 +5373,14 @@ CanvasItemEditor::CanvasItemEditor() { key_auto_insert_button->set_flat(true); key_auto_insert_button->set_toggle_mode(true); key_auto_insert_button->set_focus_mode(FOCUS_NONE); - key_auto_insert_button->set_tooltip(TTR("Auto insert keys when objects are translated, rotated or scaled (based on mask).\nKeys are only added to existing tracks, no new tracks will be created.\nKeys must be inserted manually for the first time.")); + key_auto_insert_button->set_tooltip_text(TTR("Auto insert keys when objects are translated, rotated or scaled (based on mask).\nKeys are only added to existing tracks, no new tracks will be created.\nKeys must be inserted manually for the first time.")); key_auto_insert_button->set_shortcut(ED_SHORTCUT("canvas_item_editor/anim_auto_insert_key", TTR("Auto Insert Key"))); key_auto_insert_button->set_shortcut_context(this); animation_hb->add_child(key_auto_insert_button); animation_menu = memnew(MenuButton); animation_menu->set_shortcut_context(this); - animation_menu->set_tooltip(TTR("Animation Key and Pose Options")); + animation_menu->set_tooltip_text(TTR("Animation Key and Pose Options")); animation_hb->add_child(animation_menu); animation_menu->get_popup()->connect("id_pressed", callable_mp(this, &CanvasItemEditor::_popup_callback)); animation_menu->set_switch_on_hover(true); @@ -5563,19 +5563,7 @@ bool CanvasItemEditorViewport::_cyclical_dependency_exists(const String &p_targe void CanvasItemEditorViewport::_create_nodes(Node *parent, Node *child, String &path, const Point2 &p_point) { // Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others. String name = path.get_file().get_basename(); - switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) { - case NAME_CASING_PASCAL_CASE: - name = name.capitalize().replace(" ", ""); - break; - case NAME_CASING_CAMEL_CASE: - name = name.capitalize().replace(" ", ""); - name[0] = name.to_lower()[0]; - break; - case NAME_CASING_SNAKE_CASE: - name = name.capitalize().replace(" ", "_").to_lower(); - break; - } - child->set_name(name); + child->set_name(Node::adjust_name_casing(name)); Ref<Texture2D> texture = ResourceCache::get_ref(path); @@ -5868,26 +5856,21 @@ Node *CanvasItemEditorViewport::_make_texture_node_type(String texture_node_type return node; } -void CanvasItemEditorViewport::_update_theme() { - List<BaseButton *> btn_list; - button_group->get_buttons(&btn_list); - - for (int i = 0; i < btn_list.size(); i++) { - CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]); - check->set_icon(get_theme_icon(check->get_text(), SNAME("EditorIcons"))); - } - - label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); -} - void CanvasItemEditorViewport::_notification(int p_what) { switch (p_what) { case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + List<BaseButton *> btn_list; + button_group->get_buttons(&btn_list); + + for (int i = 0; i < btn_list.size(); i++) { + CheckBox *check = Object::cast_to<CheckBox>(btn_list[i]); + check->set_icon(get_theme_icon(check->get_text(), SNAME("EditorIcons"))); + } + + label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); } break; case NOTIFICATION_ENTER_TREE: { - _update_theme(); connect("mouse_exited", callable_mp(this, &CanvasItemEditorViewport::_on_mouse_exit)); } break; diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h index 2ca495e5d6..a4107c009e 100644 --- a/editor/plugins/canvas_item_editor_plugin.h +++ b/editor/plugins/canvas_item_editor_plugin.h @@ -215,7 +215,7 @@ private: int primary_grid_steps = 8; int grid_step_multiplier = 0; - real_t snap_rotation_step = Math::deg2rad(15.0); + real_t snap_rotation_step = Math::deg_to_rad(15.0); real_t snap_rotation_offset = 0.0; real_t snap_scale_step = 0.1f; bool smart_snap_active = false; @@ -616,7 +616,6 @@ class CanvasItemEditorViewport : public Control { bool _create_instance(Node *parent, String &path, const Point2 &p_point); void _perform_drop_data(); void _show_resource_type_selector(); - void _update_theme(); static void _bind_methods(); diff --git a/editor/plugins/control_editor_plugin.cpp b/editor/plugins/control_editor_plugin.cpp index 2a12dc0e89..cee09edcc6 100644 --- a/editor/plugins/control_editor_plugin.cpp +++ b/editor/plugins/control_editor_plugin.cpp @@ -69,14 +69,14 @@ void ControlPositioningWarning::_update_toggler() { Ref<Texture2D> arrow; if (hint_label->is_visible()) { arrow = get_theme_icon(SNAME("arrow"), SNAME("Tree")); - set_tooltip(TTR("Collapse positioning hint.")); + set_tooltip_text(TTR("Collapse positioning hint.")); } else { if (is_layout_rtl()) { arrow = get_theme_icon(SNAME("arrow_collapsed"), SNAME("Tree")); } else { arrow = get_theme_icon(SNAME("arrow_collapsed_mirrored"), SNAME("Tree")); } - set_tooltip(TTR("Expand positioning hint.")); + set_tooltip_text(TTR("Expand positioning hint.")); } hint_icon->set_texture(arrow); @@ -102,7 +102,6 @@ void ControlPositioningWarning::gui_input(const Ref<InputEvent> &p_event) { void ControlPositioningWarning::_notification(int p_notification) { switch (p_notification) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: _update_warning(); _update_toggler(); @@ -492,7 +491,6 @@ void ControlEditorPopupButton::_popup_visibility_changed(bool p_visible) { void ControlEditorPopupButton::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { arrow_icon = get_theme_icon("select_arrow", "Tree"); } break; @@ -538,7 +536,7 @@ void ControlEditorPresetPicker::_add_row_button(HBoxContainer *p_row, const int Button *b = memnew(Button); b->set_custom_minimum_size(Size2i(36, 36) * EDSCALE); b->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER); - b->set_tooltip(p_name); + b->set_tooltip_text(p_name); b->set_flat(true); p_row->add_child(b); b->connect("pressed", callable_mp(this, &ControlEditorPresetPicker::_preset_button_pressed).bind(p_preset)); @@ -558,7 +556,6 @@ void AnchorPresetPicker::_preset_button_pressed(const int p_preset) { void AnchorPresetPicker::_notification(int p_notification) { switch (p_notification) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { preset_buttons[PRESET_TOP_LEFT]->set_icon(get_theme_icon(SNAME("ControlAlignTopLeft"), SNAME("EditorIcons"))); preset_buttons[PRESET_CENTER_TOP]->set_icon(get_theme_icon(SNAME("ControlAlignCenterTop"), SNAME("EditorIcons"))); @@ -658,16 +655,15 @@ void SizeFlagPresetPicker::set_allowed_flags(Vector<SizeFlags> &p_flags) { expand_button->set_disabled(!p_flags.has(SIZE_EXPAND)); if (p_flags.has(SIZE_EXPAND)) { - expand_button->set_tooltip(TTR("Enable to also set the Expand flag.\nDisable to only set Shrink/Fill flags.")); + expand_button->set_tooltip_text(TTR("Enable to also set the Expand flag.\nDisable to only set Shrink/Fill flags.")); } else { expand_button->set_pressed(false); - expand_button->set_tooltip(TTR("Some parents of the selected nodes do not support the Expand flag.")); + expand_button->set_tooltip_text(TTR("Some parents of the selected nodes do not support the Expand flag.")); } } void SizeFlagPresetPicker::_notification(int p_notification) { switch (p_notification) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (vertical) { preset_buttons[SIZE_SHRINK_BEGIN]->set_icon(get_theme_icon(SNAME("ControlAlignCenterTop"), SNAME("EditorIcons"))); @@ -710,7 +706,7 @@ SizeFlagPresetPicker::SizeFlagPresetPicker(bool p_vertical) { expand_button = memnew(CheckBox); expand_button->set_flat(true); expand_button->set_text(TTR("Align with Expand")); - expand_button->set_tooltip(TTR("Enable to also set the Expand flag.\nDisable to only set Shrink/Fill flags.")); + expand_button->set_tooltip_text(TTR("Enable to also set the Expand flag.\nDisable to only set Shrink/Fill flags.")); main_vb->add_child(expand_button); } @@ -974,7 +970,6 @@ void ControlEditorToolbar::_selection_changed() { void ControlEditorToolbar::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { anchors_button->set_icon(get_theme_icon(SNAME("ControlLayout"), SNAME("EditorIcons"))); anchor_mode_button->set_icon(get_theme_icon(SNAME("Anchor"), SNAME("EditorIcons"))); @@ -988,7 +983,7 @@ ControlEditorToolbar::ControlEditorToolbar() { // Anchor and offset tools. anchors_button = memnew(ControlEditorPopupButton); - anchors_button->set_tooltip(TTR("Presets for the anchor and offset values of a Control node.")); + anchors_button->set_tooltip_text(TTR("Presets for the anchor and offset values of a Control node.")); add_child(anchors_button); Label *anchors_label = memnew(Label); @@ -1004,20 +999,20 @@ ControlEditorToolbar::ControlEditorToolbar() { Button *keep_ratio_button = memnew(Button); keep_ratio_button->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT); keep_ratio_button->set_text(TTR("Set to Current Ratio")); - keep_ratio_button->set_tooltip(TTR("Adjust anchors and offsets to match the current rect size.")); + keep_ratio_button->set_tooltip_text(TTR("Adjust anchors and offsets to match the current rect size.")); anchors_button->get_popup_hbox()->add_child(keep_ratio_button); keep_ratio_button->connect("pressed", callable_mp(this, &ControlEditorToolbar::_anchors_to_current_ratio)); anchor_mode_button = memnew(Button); anchor_mode_button->set_flat(true); anchor_mode_button->set_toggle_mode(true); - anchor_mode_button->set_tooltip(TTR("When active, moving Control nodes changes their anchors instead of their offsets.")); + anchor_mode_button->set_tooltip_text(TTR("When active, moving Control nodes changes their anchors instead of their offsets.")); add_child(anchor_mode_button); anchor_mode_button->connect("toggled", callable_mp(this, &ControlEditorToolbar::_anchor_mode_toggled)); // Container tools. containers_button = memnew(ControlEditorPopupButton); - containers_button->set_tooltip(TTR("Sizing settings for children of a Container node.")); + containers_button->set_tooltip_text(TTR("Sizing settings for children of a Container node.")); add_child(containers_button); Label *container_h_label = memnew(Label); diff --git a/editor/plugins/cpu_particles_2d_editor_plugin.cpp b/editor/plugins/cpu_particles_2d_editor_plugin.cpp index e20d298195..e56fd5dfe3 100644 --- a/editor/plugins/cpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/cpu_particles_2d_editor_plugin.cpp @@ -37,7 +37,7 @@ #include "editor/editor_undo_redo_manager.h" #include "scene/2d/cpu_particles_2d.h" #include "scene/gui/separator.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" void CPUParticles2DEditorPlugin::edit(Object *p_object) { particles = Object::cast_to<CPUParticles2D>(p_object); diff --git a/editor/plugins/font_config_plugin.cpp b/editor/plugins/font_config_plugin.cpp index c7d3e92802..9b03b3ae09 100644 --- a/editor/plugins/font_config_plugin.cpp +++ b/editor/plugins/font_config_plugin.cpp @@ -152,7 +152,6 @@ bool EditorPropertyFontOTObject::_property_get_revert(const StringName &p_name, void EditorPropertyFontMetaOverride::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (Object::cast_to<Button>(button_add)) { button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); @@ -290,7 +289,7 @@ void EditorPropertyFontMetaOverride::update_property() { } else { prop->set_label(TranslationServer::get_singleton()->get_locale_name(name)); } - prop->set_tooltip(name); + prop->set_tooltip_text(name); prop->set_selectable(false); prop->connect("property_changed", callable_mp(this, &EditorPropertyFontMetaOverride::_property_changed)); @@ -380,14 +379,6 @@ EditorPropertyFontMetaOverride::EditorPropertyFontMetaOverride(bool p_script) { /* EditorPropertyOTVariation */ /*************************************************************************/ -void EditorPropertyOTVariation::_notification(int p_what) { - switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: { - } break; - } -} - void EditorPropertyOTVariation::_property_changed(const String &p_property, Variant p_value, const String &p_name, bool p_changing) { if (p_property.begins_with("keys")) { Dictionary dict = object->get_dict(); @@ -487,7 +478,7 @@ void EditorPropertyOTVariation::update_property() { String name = TS->tag_to_name(name_tag); prop->set_label(name.capitalize()); - prop->set_tooltip(name); + prop->set_tooltip_text(name); prop->set_selectable(false); prop->connect("property_changed", callable_mp(this, &EditorPropertyOTVariation::_property_changed)); @@ -547,7 +538,6 @@ EditorPropertyOTVariation::EditorPropertyOTVariation() { void EditorPropertyOTFeatures::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { if (Object::cast_to<Button>(button_add)) { button_add->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); @@ -766,7 +756,7 @@ void EditorPropertyOTFeatures::update_property() { disp_name = vformat("%s (%s)", disp_name, info["label"].operator String()); } prop->set_label(disp_name); - prop->set_tooltip(name); + prop->set_tooltip_text(name); prop->set_selectable(false); prop->connect("property_changed", callable_mp(this, &EditorPropertyOTFeatures::_property_changed)); diff --git a/editor/plugins/font_config_plugin.h b/editor/plugins/font_config_plugin.h index 41dde3cc59..ae138bab8f 100644 --- a/editor/plugins/font_config_plugin.h +++ b/editor/plugins/font_config_plugin.h @@ -139,7 +139,6 @@ class EditorPropertyOTVariation : public EditorProperty { EditorPaginator *paginator = nullptr; protected: - void _notification(int p_what); static void _bind_methods(){}; void _edit_pressed(); diff --git a/editor/plugins/gpu_particles_2d_editor_plugin.cpp b/editor/plugins/gpu_particles_2d_editor_plugin.cpp index 1487f8b7bc..e2d19c34e6 100644 --- a/editor/plugins/gpu_particles_2d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_2d_editor_plugin.cpp @@ -38,7 +38,7 @@ #include "editor/scene_tree_dock.h" #include "scene/2d/cpu_particles_2d.h" #include "scene/gui/separator.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" void GPUParticles2DEditorPlugin::edit(Object *p_object) { particles = Object::cast_to<GPUParticles2D>(p_object); @@ -167,9 +167,9 @@ void GPUParticles2DEditorPlugin::_generate_visibility_rect() { } void GPUParticles2DEditorPlugin::_generate_emission_mask() { - Ref<ParticlesMaterial> pm = particles->get_process_material(); + Ref<ParticleProcessMaterial> pm = particles->get_process_material(); if (!pm.is_valid()) { - EditorNode::get_singleton()->show_warning(TTR("Can only set point into a ParticlesMaterial process material")); + EditorNode::get_singleton()->show_warning(TTR("Can only set point into a ParticleProcessMaterial process material")); return; } @@ -320,7 +320,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { } if (valid_normals.size()) { - pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS); + pm->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_DIRECTED_POINTS); Vector<uint8_t> normdata; normdata.resize(w * h * 2 * sizeof(float)); //use RG texture @@ -339,7 +339,7 @@ void GPUParticles2DEditorPlugin::_generate_emission_mask() { pm->set_emission_normal_texture(ImageTexture::create_from_image(img)); } else { - pm->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS); + pm->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_POINTS); } } diff --git a/editor/plugins/gpu_particles_3d_editor_plugin.cpp b/editor/plugins/gpu_particles_3d_editor_plugin.cpp index 335efd6949..ebc92bf531 100644 --- a/editor/plugins/gpu_particles_3d_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_3d_editor_plugin.cpp @@ -36,7 +36,7 @@ #include "editor/plugins/node_3d_editor_plugin.h" #include "editor/scene_tree_dock.h" #include "scene/3d/cpu_particles_3d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" bool GPUParticles3DEditorBase::_generate(Vector<Vector3> &points, Vector<Vector3> &normals) { bool use_normals = emission_fill->get_selected() == 1; @@ -255,9 +255,9 @@ void GPUParticles3DEditor::_menu_option(int p_option) { } } break; case MENU_OPTION_CREATE_EMISSION_VOLUME_FROM_NODE: { - Ref<ParticlesMaterial> material = node->get_process_material(); + Ref<ParticleProcessMaterial> material = node->get_process_material(); if (material.is_null()) { - EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticlesMaterial' is required.")); + EditorNode::get_singleton()->show_warning(TTR("A processor material of type 'ParticleProcessMaterial' is required.")); return; } @@ -366,11 +366,11 @@ void GPUParticles3DEditor::_generate_emission_points() { Ref<Image> image = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img)); Ref<ImageTexture> tex = ImageTexture::create_from_image(image); - Ref<ParticlesMaterial> material = node->get_process_material(); + Ref<ParticleProcessMaterial> material = node->get_process_material(); ERR_FAIL_COND(material.is_null()); if (normals.size() > 0) { - material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_DIRECTED_POINTS); + material->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_DIRECTED_POINTS); material->set_emission_point_count(point_count); material->set_emission_point_texture(tex); @@ -392,7 +392,7 @@ void GPUParticles3DEditor::_generate_emission_points() { Ref<Image> image2 = memnew(Image(w, h, false, Image::FORMAT_RGBF, point_img2)); material->set_emission_normal_texture(ImageTexture::create_from_image(image2)); } else { - material->set_emission_shape(ParticlesMaterial::EMISSION_SHAPE_POINTS); + material->set_emission_shape(ParticleProcessMaterial::EMISSION_SHAPE_POINTS); material->set_emission_point_count(point_count); material->set_emission_point_texture(tex); } diff --git a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp index b54cb515e4..59d665342f 100644 --- a/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp +++ b/editor/plugins/gpu_particles_collision_sdf_editor_plugin.cpp @@ -101,7 +101,7 @@ void GPUParticlesCollisionSDF3DEditorPlugin::_notification(int p_what) { return; } - bake->set_tooltip(text); + bake->set_tooltip_text(text); } break; } } diff --git a/editor/plugins/gradient_editor_plugin.cpp b/editor/plugins/gradient_editor_plugin.cpp index 460178490e..f368d5bea1 100644 --- a/editor/plugins/gradient_editor_plugin.cpp +++ b/editor/plugins/gradient_editor_plugin.cpp @@ -135,7 +135,7 @@ void EditorInspectorPluginGradient::parse_begin(Object *p_object) { add_custom_control(gradient_tools_hbox); reverse_btn->connect("pressed", callable_mp(this, &EditorInspectorPluginGradient::_reverse_button_pressed)); - reverse_btn->set_tooltip(TTR("Reverse/mirror gradient.")); + reverse_btn->set_tooltip_text(TTR("Reverse/mirror gradient.")); } void EditorInspectorPluginGradient::_reverse_button_pressed() { diff --git a/editor/plugins/gradient_texture_2d_editor_plugin.cpp b/editor/plugins/gradient_texture_2d_editor_plugin.cpp index 6c463f71cf..9ebca9fb31 100644 --- a/editor/plugins/gradient_texture_2d_editor_plugin.cpp +++ b/editor/plugins/gradient_texture_2d_editor_plugin.cpp @@ -104,7 +104,6 @@ void GradientTexture2DEditorRect::set_snap_size(float p_snap_size) { void GradientTexture2DEditorRect::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { checkerboard->set_texture(get_theme_icon(SNAME("GuiMiniCheckerboard"), SNAME("EditorIcons"))); } break; @@ -214,7 +213,6 @@ void GradientTexture2DEditor::set_texture(Ref<GradientTexture2D> &p_texture) { void GradientTexture2DEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { reverse_button->set_icon(get_theme_icon(SNAME("ReverseGradient"), SNAME("EditorIcons"))); snap_button->set_icon(get_theme_icon(SNAME("SnapGrid"), SNAME("EditorIcons"))); @@ -229,14 +227,14 @@ GradientTexture2DEditor::GradientTexture2DEditor() { add_child(toolbar); reverse_button = memnew(Button); - reverse_button->set_tooltip(TTR("Swap Gradient Fill Points")); + reverse_button->set_tooltip_text(TTR("Swap Gradient Fill Points")); toolbar->add_child(reverse_button); reverse_button->connect("pressed", callable_mp(this, &GradientTexture2DEditor::_reverse_button_pressed)); toolbar->add_child(memnew(VSeparator)); snap_button = memnew(Button); - snap_button->set_tooltip(TTR("Toggle Grid Snap")); + snap_button->set_tooltip_text(TTR("Toggle Grid Snap")); snap_button->set_toggle_mode(true); toolbar->add_child(snap_button); snap_button->connect("toggled", callable_mp(this, &GradientTexture2DEditor::_set_snap_enabled)); diff --git a/editor/plugins/input_event_editor_plugin.cpp b/editor/plugins/input_event_editor_plugin.cpp index 153eab32d2..6b323e0e57 100644 --- a/editor/plugins/input_event_editor_plugin.cpp +++ b/editor/plugins/input_event_editor_plugin.cpp @@ -35,7 +35,6 @@ void InputEventConfigContainer::_bind_methods() { void InputEventConfigContainer::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { open_config_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); } break; diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 5d59f62f05..74a6e90a6d 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -36,7 +36,7 @@ #include "editor/editor_undo_redo_manager.h" #include "scene/gui/subviewport_container.h" #include "scene/resources/fog_material.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" #include "scene/resources/sky_material.h" void MaterialEditor::_notification(int p_what) { @@ -179,8 +179,8 @@ MaterialEditor::MaterialEditor() { viewport->add_child(box_instance); Transform3D box_xform; - box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg2rad(25.0)); - box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg2rad(-25.0)); + box_xform.basis.rotate(Vector3(1, 0, 0), Math::deg_to_rad(25.0)); + box_xform.basis = box_xform.basis * Basis().rotated(Vector3(0, 1, 0), Math::deg_to_rad(-25.0)); box_xform.basis.scale(Vector3(0.7, 0.7, 0.7)); box_xform.origin.y = 0.05; box_instance->set_transform(box_xform); @@ -405,17 +405,17 @@ Ref<Resource> ORMMaterial3DConversionPlugin::convert(const Ref<Resource> &p_reso return smat; } -String ParticlesMaterialConversionPlugin::converts_to() const { +String ParticleProcessMaterialConversionPlugin::converts_to() const { return "ShaderMaterial"; } -bool ParticlesMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const { - Ref<ParticlesMaterial> mat = p_resource; +bool ParticleProcessMaterialConversionPlugin::handles(const Ref<Resource> &p_resource) const { + Ref<ParticleProcessMaterial> mat = p_resource; return mat.is_valid(); } -Ref<Resource> ParticlesMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const { - Ref<ParticlesMaterial> mat = p_resource; +Ref<Resource> ParticleProcessMaterialConversionPlugin::convert(const Ref<Resource> &p_resource) const { + Ref<ParticleProcessMaterial> mat = p_resource; ERR_FAIL_COND_V(!mat.is_valid(), Ref<Resource>()); Ref<ShaderMaterial> smat; diff --git a/editor/plugins/material_editor_plugin.h b/editor/plugins/material_editor_plugin.h index fc3da5fd9f..06ae43e6d7 100644 --- a/editor/plugins/material_editor_plugin.h +++ b/editor/plugins/material_editor_plugin.h @@ -122,8 +122,8 @@ public: virtual Ref<Resource> convert(const Ref<Resource> &p_resource) const override; }; -class ParticlesMaterialConversionPlugin : public EditorResourceConversionPlugin { - GDCLASS(ParticlesMaterialConversionPlugin, EditorResourceConversionPlugin); +class ParticleProcessMaterialConversionPlugin : public EditorResourceConversionPlugin { + GDCLASS(ParticleProcessMaterialConversionPlugin, EditorResourceConversionPlugin); public: virtual String converts_to() const override; diff --git a/editor/plugins/mesh_editor_plugin.cpp b/editor/plugins/mesh_editor_plugin.cpp index 31c9f1e387..980d2974a0 100644 --- a/editor/plugins/mesh_editor_plugin.cpp +++ b/editor/plugins/mesh_editor_plugin.cpp @@ -77,8 +77,8 @@ void MeshEditor::edit(Ref<Mesh> p_mesh) { mesh = p_mesh; mesh_instance->set_mesh(mesh); - rot_x = Math::deg2rad(-15.0); - rot_y = Math::deg2rad(30.0); + rot_x = Math::deg_to_rad(-15.0); + rot_y = Math::deg_to_rad(30.0); _update_rotation(); AABB aabb = mesh->get_aabb(); diff --git a/editor/plugins/node_3d_editor_gizmos.cpp b/editor/plugins/node_3d_editor_gizmos.cpp index 043848080f..878f8c9a95 100644 --- a/editor/plugins/node_3d_editor_gizmos.cpp +++ b/editor/plugins/node_3d_editor_gizmos.cpp @@ -59,7 +59,7 @@ #include "scene/3d/ray_cast_3d.h" #include "scene/3d/reflection_probe.h" #include "scene/3d/shape_cast_3d.h" -#include "scene/3d/soft_dynamic_body_3d.h" +#include "scene/3d/soft_body_3d.h" #include "scene/3d/spring_arm_3d.h" #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body_3d.h" @@ -1295,7 +1295,7 @@ static float _find_closest_angle_to_half_pi_arc(const Vector3 &p_from, const Vec //min_p = p_arc_xform.affine_inverse().xform(min_p); float a = (Math_PI * 0.5) - Vector2(min_p.x, -min_p.z).angle(); - return Math::rad2deg(a); + return Math::rad_to_deg(a); } void Light3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, Camera3D *p_camera, const Point2 &p_point) { @@ -1421,8 +1421,8 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int i = 0; i < 120; i++) { // Create a circle - const float ra = Math::deg2rad((float)(i * 3)); - const float rb = Math::deg2rad((float)((i + 1) * 3)); + const float ra = Math::deg_to_rad((float)(i * 3)); + const float rb = Math::deg_to_rad((float)((i + 1) * 3)); const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -1458,13 +1458,13 @@ void Light3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { SpotLight3D *sl = Object::cast_to<SpotLight3D>(light); float r = sl->get_param(Light3D::PARAM_RANGE); - float w = r * Math::sin(Math::deg2rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); - float d = r * Math::cos(Math::deg2rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); + float w = r * Math::sin(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); + float d = r * Math::cos(Math::deg_to_rad(sl->get_param(Light3D::PARAM_SPOT_ANGLE))); for (int i = 0; i < 120; i++) { // Draw a circle - const float ra = Math::deg2rad((float)(i * 3)); - const float rb = Math::deg2rad((float)((i + 1) * 3)); + const float ra = Math::deg_to_rad((float)(i * 3)); + const float rb = Math::deg_to_rad((float)((i + 1) * 3)); const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w; const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w; @@ -1545,8 +1545,8 @@ void AudioStreamPlayer3DGizmoPlugin::set_handle(const EditorNode3DGizmo *p_gizmo float closest_angle = 1e20; for (int i = 0; i < 180; i++) { - float a = Math::deg2rad((float)i); - float an = Math::deg2rad((float)(i + 1)); + float a = Math::deg_to_rad((float)i); + float an = Math::deg_to_rad((float)(i + 1)); Vector3 from(Math::sin(a), 0, -Math::cos(a)); Vector3 to(Math::sin(an), 0, -Math::cos(an)); @@ -1628,8 +1628,8 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { for (int i = 0; i < 120; i++) { // Create a circle. - const float ra = Math::deg2rad((float)(i * 3)); - const float rb = Math::deg2rad((float)((i + 1) * 3)); + const float ra = Math::deg_to_rad((float)(i * 3)); + const float rb = Math::deg_to_rad((float)((i + 1) * 3)); const Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; const Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -1671,8 +1671,8 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { if (player->is_emission_angle_enabled()) { const float pc = player->get_emission_angle(); - const float ofs = -Math::cos(Math::deg2rad(pc)); - const float radius = Math::sin(Math::deg2rad(pc)); + const float ofs = -Math::cos(Math::deg_to_rad(pc)); + const float radius = Math::sin(Math::deg_to_rad(pc)); Vector<Vector3> points_primary; points_primary.resize(200); @@ -1707,7 +1707,7 @@ void AudioStreamPlayer3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_lines(points_secondary, material_secondary); Vector<Vector3> handles; - const float ha = Math::deg2rad(player->get_emission_angle()); + const float ha = Math::deg_to_rad(player->get_emission_angle()); handles.push_back(Vector3(Math::sin(ha), 0, -Math::cos(ha))); p_gizmo->add_handles(handles, get_material("handles")); } @@ -1872,7 +1872,7 @@ void Camera3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { // The real FOV is halved for accurate representation float fov = camera->get_fov() / 2.0; - Vector3 side = Vector3(Math::sin(Math::deg2rad(fov)), 0, -Math::cos(Math::deg2rad(fov))); + Vector3 side = Vector3(Math::sin(Math::deg_to_rad(fov)), 0, -Math::cos(Math::deg_to_rad(fov))); Vector3 nside = side; nside.x = -nside.x; Vector3 up = Vector3(0, side.x, 0); @@ -1944,7 +1944,7 @@ MeshInstance3DGizmoPlugin::MeshInstance3DGizmoPlugin() { } bool MeshInstance3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to<MeshInstance3D>(p_spatial) != nullptr && Object::cast_to<SoftDynamicBody3D>(p_spatial) == nullptr; + return Object::cast_to<MeshInstance3D>(p_spatial) != nullptr && Object::cast_to<SoftBody3D>(p_spatial) == nullptr; } String MeshInstance3DGizmoPlugin::get_gizmo_name() const { @@ -2643,8 +2643,8 @@ void VehicleWheel3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { float r = car_wheel->get_radius(); const int skip = 10; for (int i = 0; i <= 360; i += skip) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + skip); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + skip); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -2687,30 +2687,30 @@ void VehicleWheel3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { /////////// -SoftDynamicBody3DGizmoPlugin::SoftDynamicBody3DGizmoPlugin() { +SoftBody3DGizmoPlugin::SoftBody3DGizmoPlugin() { Color gizmo_color = EDITOR_GET("editors/3d_gizmos/gizmo_colors/shape"); create_material("shape_material", gizmo_color); create_handle_material("handles"); } -bool SoftDynamicBody3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { - return Object::cast_to<SoftDynamicBody3D>(p_spatial) != nullptr; +bool SoftBody3DGizmoPlugin::has_gizmo(Node3D *p_spatial) { + return Object::cast_to<SoftBody3D>(p_spatial) != nullptr; } -String SoftDynamicBody3DGizmoPlugin::get_gizmo_name() const { - return "SoftDynamicBody3D"; +String SoftBody3DGizmoPlugin::get_gizmo_name() const { + return "SoftBody3D"; } -int SoftDynamicBody3DGizmoPlugin::get_priority() const { +int SoftBody3DGizmoPlugin::get_priority() const { return -1; } -bool SoftDynamicBody3DGizmoPlugin::is_selectable_when_hidden() const { +bool SoftBody3DGizmoPlugin::is_selectable_when_hidden() const { return true; } -void SoftDynamicBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +void SoftBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); p_gizmo->clear(); @@ -2746,22 +2746,22 @@ void SoftDynamicBody3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { p_gizmo->add_collision_triangles(tm); } -String SoftDynamicBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - return "SoftDynamicBody3D pin point"; +String SoftBody3DGizmoPlugin::get_handle_name(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { + return "SoftBody3D pin point"; } -Variant SoftDynamicBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +Variant SoftBody3DGizmoPlugin::get_handle_value(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); return Variant(soft_body->is_point_pinned(p_id)); } -void SoftDynamicBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +void SoftBody3DGizmoPlugin::commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel) { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); soft_body->pin_point_toggle(p_id); } -bool SoftDynamicBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { - SoftDynamicBody3D *soft_body = Object::cast_to<SoftDynamicBody3D>(p_gizmo->get_spatial_node()); +bool SoftBody3DGizmoPlugin::is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const { + SoftBody3D *soft_body = Object::cast_to<SoftBody3D>(p_gizmo->get_spatial_node()); return soft_body->is_point_pinned(p_id); } @@ -3272,8 +3272,8 @@ void GPUParticlesCollision3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> points; for (int i = 0; i <= 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -4517,8 +4517,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector<Vector3> points; for (int i = 0; i <= 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; @@ -4589,8 +4589,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3 d(0, height * 0.5 - radius, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; @@ -4660,8 +4660,8 @@ void CollisionShape3DGizmoPlugin::redraw(EditorNode3DGizmo *p_gizmo) { Vector3 d(0, height * 0.5, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; @@ -5203,8 +5203,8 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba //swing for (int i = 0; i < 360; i += 10) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 10); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 10); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * w; @@ -5221,12 +5221,12 @@ void JointGizmosDrawer::draw_cone(const Transform3D &p_offset, const Basis &p_ba r_points.push_back(p_offset.translated_local(p_base.xform(Vector3(1, 0, 0))).origin); /// Twist - float ts = Math::rad2deg(p_twist); + float ts = Math::rad_to_deg(p_twist); ts = MIN(ts, 720); for (int i = 0; i < int(ts); i += 5) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 5); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 5); float c = i / 720.0; float cn = (i + 5) / 720.0; Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * w * c; diff --git a/editor/plugins/node_3d_editor_gizmos.h b/editor/plugins/node_3d_editor_gizmos.h index 7dac1bd360..1b6485ac4e 100644 --- a/editor/plugins/node_3d_editor_gizmos.h +++ b/editor/plugins/node_3d_editor_gizmos.h @@ -409,8 +409,8 @@ public: VehicleWheel3DGizmoPlugin(); }; -class SoftDynamicBody3DGizmoPlugin : public EditorNode3DGizmoPlugin { - GDCLASS(SoftDynamicBody3DGizmoPlugin, EditorNode3DGizmoPlugin); +class SoftBody3DGizmoPlugin : public EditorNode3DGizmoPlugin { + GDCLASS(SoftBody3DGizmoPlugin, EditorNode3DGizmoPlugin); public: bool has_gizmo(Node3D *p_spatial) override; @@ -424,7 +424,7 @@ public: void commit_handle(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary, const Variant &p_restore, bool p_cancel = false) override; bool is_handle_highlighted(const EditorNode3DGizmo *p_gizmo, int p_id, bool p_secondary) const override; - SoftDynamicBody3DGizmoPlugin(); + SoftBody3DGizmoPlugin(); }; class VisibleOnScreenNotifier3DGizmoPlugin : public EditorNode3DGizmoPlugin { diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 6add9e2e1e..cc592e532c 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -342,7 +342,7 @@ void Node3DEditorViewport::_update_camera(real_t p_interp_delta) { camera->set_global_transform(to_camera_transform(camera_cursor)); if (orthogonal) { - float half_fov = Math::deg2rad(get_fov()) / 2.0; + float half_fov = Math::deg_to_rad(get_fov()) / 2.0; float height = 2.0 * cursor.distance * Math::tan(half_fov); camera->set_orthogonal(height, get_znear(), get_zfar()); } else { @@ -2144,7 +2144,7 @@ void Node3DEditorViewport::_nav_orbit(Ref<InputEventWithModifiers> p_event, cons } const real_t degrees_per_pixel = EditorSettings::get_singleton()->get("editors/3d/navigation_feel/orbit_sensitivity"); - const real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + const real_t radians_per_pixel = Math::deg_to_rad(degrees_per_pixel); const bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); const bool invert_x_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_x_axis"); @@ -2177,7 +2177,7 @@ void Node3DEditorViewport::_nav_look(Ref<InputEventWithModifiers> p_event, const // Scale mouse sensitivity with camera FOV scale when zoomed in to make it easier to point at things. const real_t degrees_per_pixel = real_t(EditorSettings::get_singleton()->get("editors/3d/freelook/freelook_sensitivity")) * MIN(1.0, cursor.fov_scale); - const real_t radians_per_pixel = Math::deg2rad(degrees_per_pixel); + const real_t radians_per_pixel = Math::deg_to_rad(degrees_per_pixel); const bool invert_y_axis = EditorSettings::get_singleton()->get("editors/3d/navigation/invert_y_axis"); // Note: do NOT assume the camera has the "current" transform, because it is interpolated and may have "lag". @@ -3981,19 +3981,7 @@ bool Node3DEditorViewport::_create_instance(Node *parent, String &path, const Po // Adjust casing according to project setting. The file name is expected to be in snake_case, but will work for others. String name = path.get_file().get_basename(); - switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) { - case NAME_CASING_PASCAL_CASE: - name = name.capitalize().replace(" ", ""); - break; - case NAME_CASING_CAMEL_CASE: - name = name.capitalize().replace(" ", ""); - name[0] = name.to_lower()[0]; - break; - case NAME_CASING_SNAKE_CASE: - name = name.capitalize().replace(" ", "_").to_lower(); - break; - } - mesh_instance->set_name(name); + mesh_instance->set_name(Node::adjust_name_casing(name)); instantiated_scene = mesh_instance; } else { @@ -4546,7 +4534,7 @@ void Node3DEditorViewport::update_transform(Point2 p_mousepos, bool p_shift) { break; } - static const float orthogonal_threshold = Math::cos(Math::deg2rad(87.0f)); + static const float orthogonal_threshold = Math::cos(Math::deg_to_rad(87.0f)); bool axis_is_orthogonal = ABS(plane.normal.dot(global_axis)) < orthogonal_threshold; double angle = 0.0f; @@ -4566,10 +4554,10 @@ void Node3DEditorViewport::update_transform(Point2 p_mousepos, bool p_shift) { if (_edit.snap || spatial_editor->is_snap_enabled()) { snap = spatial_editor->get_rotate_snap(); } - angle = Math::rad2deg(angle) + snap * 0.5; //else it won't reach +180 + angle = Math::rad_to_deg(angle) + snap * 0.5; //else it won't reach +180 angle -= Math::fmod(angle, snap); set_message(vformat(TTR("Rotating %s degrees."), String::num(angle, snap_step_decimals))); - angle = Math::deg2rad(angle); + angle = Math::deg_to_rad(angle); bool local_coords = (spatial_editor->are_local_coords_enabled() && _edit.plane != TRANSFORM_VIEW); // Disable local transformation for TRANSFORM_VIEW @@ -5737,7 +5725,7 @@ void Node3DEditor::_xform_dialog_action() { for (int i = 0; i < 3; i++) { translate[i] = xform_translate[i]->get_text().to_float(); - rotate[i] = Math::deg2rad(xform_rotate[i]->get_text().to_float()); + rotate[i] = Math::deg_to_rad(xform_rotate[i]->get_text().to_float()); scale[i] = xform_scale[i]->get_text().to_float(); } @@ -5830,11 +5818,11 @@ void Node3DEditor::_update_camera_override_button(bool p_game_running) { if (p_game_running) { button->set_disabled(false); - button->set_tooltip(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera.")); + button->set_tooltip_text(TTR("Project Camera Override\nOverrides the running project's camera with the editor viewport camera.")); } else { button->set_disabled(true); button->set_pressed(false); - button->set_tooltip(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature.")); + button->set_tooltip_text(TTR("Project Camera Override\nNo project instance running. Run the project from the editor to use this feature.")); } } @@ -7146,42 +7134,6 @@ void Node3DEditor::_add_environment_to_scene(bool p_already_added_sun) { undo_redo->commit_action(); } -void Node3DEditor::_update_theme() { - tool_button[TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); - tool_button[TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons"))); - tool_button[TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons"))); - tool_button[TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons"))); - tool_button[TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons"))); - tool_button[TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons"))); - tool_button[TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons"))); - tool_button[TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons"))); - tool_button[TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons"))); - - tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons"))); - tool_option_button[TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); - tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons"))); - - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons"))); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons"))); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels2Alt"), SNAME("EditorIcons"))); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon(SNAME("Panels3"), SNAME("EditorIcons"))); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons"))); - view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons"))); - - sun_button->set_icon(get_theme_icon(SNAME("DirectionalLight3D"), SNAME("EditorIcons"))); - environ_button->set_icon(get_theme_icon(SNAME("WorldEnvironment"), SNAME("EditorIcons"))); - sun_environ_settings->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); - - sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window"))); - environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window"))); - - sun_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); - environ_sky_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); - environ_ground_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); - - context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles"))); -} - void Node3DEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { @@ -7204,7 +7156,6 @@ void Node3DEditor::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: { - _update_theme(); _register_all_gizmos(); _update_gizmos_menu(); _init_indicators(); @@ -7216,7 +7167,40 @@ void Node3DEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + tool_button[TOOL_MODE_SELECT]->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_MOVE]->set_icon(get_theme_icon(SNAME("ToolMove"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_ROTATE]->set_icon(get_theme_icon(SNAME("ToolRotate"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_SCALE]->set_icon(get_theme_icon(SNAME("ToolScale"), SNAME("EditorIcons"))); + tool_button[TOOL_MODE_LIST_SELECT]->set_icon(get_theme_icon(SNAME("ListSelect"), SNAME("EditorIcons"))); + tool_button[TOOL_LOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Lock"), SNAME("EditorIcons"))); + tool_button[TOOL_UNLOCK_SELECTED]->set_icon(get_theme_icon(SNAME("Unlock"), SNAME("EditorIcons"))); + tool_button[TOOL_GROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Group"), SNAME("EditorIcons"))); + tool_button[TOOL_UNGROUP_SELECTED]->set_icon(get_theme_icon(SNAME("Ungroup"), SNAME("EditorIcons"))); + + tool_option_button[TOOL_OPT_LOCAL_COORDS]->set_icon(get_theme_icon(SNAME("Object"), SNAME("EditorIcons"))); + tool_option_button[TOOL_OPT_USE_SNAP]->set_icon(get_theme_icon(SNAME("Snap"), SNAME("EditorIcons"))); + tool_option_button[TOOL_OPT_OVERRIDE_CAMERA]->set_icon(get_theme_icon(SNAME("Camera3D"), SNAME("EditorIcons"))); + + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_1_VIEWPORT), get_theme_icon(SNAME("Panels1"), SNAME("EditorIcons"))); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS), get_theme_icon(SNAME("Panels2"), SNAME("EditorIcons"))); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_2_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels2Alt"), SNAME("EditorIcons"))); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS), get_theme_icon(SNAME("Panels3"), SNAME("EditorIcons"))); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_3_VIEWPORTS_ALT), get_theme_icon(SNAME("Panels3Alt"), SNAME("EditorIcons"))); + view_menu->get_popup()->set_item_icon(view_menu->get_popup()->get_item_index(MENU_VIEW_USE_4_VIEWPORTS), get_theme_icon(SNAME("Panels4"), SNAME("EditorIcons"))); + + sun_button->set_icon(get_theme_icon(SNAME("DirectionalLight3D"), SNAME("EditorIcons"))); + environ_button->set_icon(get_theme_icon(SNAME("WorldEnvironment"), SNAME("EditorIcons"))); + sun_environ_settings->set_icon(get_theme_icon(SNAME("GuiTabMenuHl"), SNAME("EditorIcons"))); + + sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window"))); + environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window"))); + + sun_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); + environ_sky_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); + environ_ground_color->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); + + context_menu_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("ContextualToolbar"), SNAME("EditorStyles"))); + _update_gizmos_menu_theme(); sun_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window"))); environ_title->add_theme_font_override("font", get_theme_font(SNAME("title_font"), SNAME("Window"))); @@ -7512,7 +7496,7 @@ void Node3DEditor::_register_all_gizmos() { add_gizmo_plugin(Ref<AudioListener3DGizmoPlugin>(memnew(AudioListener3DGizmoPlugin))); add_gizmo_plugin(Ref<MeshInstance3DGizmoPlugin>(memnew(MeshInstance3DGizmoPlugin))); add_gizmo_plugin(Ref<OccluderInstance3DGizmoPlugin>(memnew(OccluderInstance3DGizmoPlugin))); - add_gizmo_plugin(Ref<SoftDynamicBody3DGizmoPlugin>(memnew(SoftDynamicBody3DGizmoPlugin))); + add_gizmo_plugin(Ref<SoftBody3DGizmoPlugin>(memnew(SoftBody3DGizmoPlugin))); add_gizmo_plugin(Ref<Sprite3DGizmoPlugin>(memnew(Sprite3DGizmoPlugin))); add_gizmo_plugin(Ref<Label3DGizmoPlugin>(memnew(Label3DGizmoPlugin))); add_gizmo_plugin(Ref<Marker3DGizmoPlugin>(memnew(Marker3DGizmoPlugin))); @@ -7623,10 +7607,10 @@ void Node3DEditor::_load_default_preview_settings() { // On any not-tidally-locked planet, a sun would have an angular altitude // of 60 degrees as the average of all points on the sphere at noon. // The azimuth choice is arbitrary, but ideally shouldn't be on an axis. - sun_rotation = Vector2(-Math::deg2rad(60.0), Math::deg2rad(150.0)); + sun_rotation = Vector2(-Math::deg_to_rad(60.0), Math::deg_to_rad(150.0)); - sun_angle_altitude->set_value(-Math::rad2deg(sun_rotation.x)); - sun_angle_azimuth->set_value(180.0 - Math::rad2deg(sun_rotation.y)); + sun_angle_altitude->set_value(-Math::rad_to_deg(sun_rotation.x)); + sun_angle_azimuth->set_value(180.0 - Math::rad_to_deg(sun_rotation.y)); sun_direction->update(); environ_sky_color->set_pick_color(Color(0.385, 0.454, 0.55)); environ_ground_color->set_pick_color(Color(0.2, 0.169, 0.133)); @@ -7669,8 +7653,8 @@ void Node3DEditor::_update_preview_environment() { } } - sun_angle_altitude->set_value(-Math::rad2deg(sun_rotation.x)); - sun_angle_azimuth->set_value(180.0 - Math::rad2deg(sun_rotation.y)); + sun_angle_altitude->set_value(-Math::rad_to_deg(sun_rotation.x)); + sun_angle_azimuth->set_value(180.0 - Math::rad_to_deg(sun_rotation.y)); bool disable_env = world_env_count > 0 || environ_button->is_pressed(); @@ -7703,15 +7687,15 @@ void Node3DEditor::_sun_direction_input(const Ref<InputEvent> &p_event) { sun_rotation.x += mm->get_relative().y * (0.02 * EDSCALE); sun_rotation.y -= mm->get_relative().x * (0.02 * EDSCALE); sun_rotation.x = CLAMP(sun_rotation.x, -Math_TAU / 4, Math_TAU / 4); - sun_angle_altitude->set_value(-Math::rad2deg(sun_rotation.x)); - sun_angle_azimuth->set_value(180.0 - Math::rad2deg(sun_rotation.y)); + sun_angle_altitude->set_value(-Math::rad_to_deg(sun_rotation.x)); + sun_angle_azimuth->set_value(180.0 - Math::rad_to_deg(sun_rotation.y)); _preview_settings_changed(); } } void Node3DEditor::_sun_direction_angle_set() { - sun_rotation.x = Math::deg2rad(-sun_angle_altitude->get_value()); - sun_rotation.y = Math::deg2rad(180.0 - sun_angle_azimuth->get_value()); + sun_rotation.x = Math::deg_to_rad(-sun_angle_altitude->get_value()); + sun_rotation.y = Math::deg_to_rad(180.0 - sun_angle_azimuth->get_value()); _preview_settings_changed(); } @@ -7759,7 +7743,7 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_MODE_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_SELECT)); tool_button[TOOL_MODE_SELECT]->set_shortcut(ED_SHORTCUT("spatial_editor/tool_select", TTR("Select Mode"), Key::Q)); tool_button[TOOL_MODE_SELECT]->set_shortcut_context(this); - tool_button[TOOL_MODE_SELECT]->set_tooltip(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); + tool_button[TOOL_MODE_SELECT]->set_tooltip_text(keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Drag: Rotate selected node around pivot.") + "\n" + TTR("Alt+RMB: Show list of all nodes at position clicked, including locked.")); main_menu_hbox->add_child(memnew(VSeparator)); tool_button[TOOL_MODE_MOVE] = memnew(Button); @@ -7794,13 +7778,13 @@ Node3DEditor::Node3DEditor() { tool_button[TOOL_MODE_LIST_SELECT]->set_toggle_mode(true); tool_button[TOOL_MODE_LIST_SELECT]->set_flat(true); tool_button[TOOL_MODE_LIST_SELECT]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_TOOL_LIST_SELECT)); - tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip(TTR("Show list of selectable nodes at position clicked.")); + tool_button[TOOL_MODE_LIST_SELECT]->set_tooltip_text(TTR("Show list of selectable nodes at position clicked.")); tool_button[TOOL_LOCK_SELECTED] = memnew(Button); main_menu_hbox->add_child(tool_button[TOOL_LOCK_SELECTED]); tool_button[TOOL_LOCK_SELECTED]->set_flat(true); tool_button[TOOL_LOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_LOCK_SELECTED)); - tool_button[TOOL_LOCK_SELECTED]->set_tooltip(TTR("Lock selected node, preventing selection and movement.")); + tool_button[TOOL_LOCK_SELECTED]->set_tooltip_text(TTR("Lock selected node, preventing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_LOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/lock_selected_nodes", TTR("Lock Selected Node(s)"), KeyModifierMask::CMD | Key::L)); @@ -7808,7 +7792,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(tool_button[TOOL_UNLOCK_SELECTED]); tool_button[TOOL_UNLOCK_SELECTED]->set_flat(true); tool_button[TOOL_UNLOCK_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNLOCK_SELECTED)); - tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip(TTR("Unlock selected node, allowing selection and movement.")); + tool_button[TOOL_UNLOCK_SELECTED]->set_tooltip_text(TTR("Unlock selected node, allowing selection and movement.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_UNLOCK_SELECTED]->set_shortcut(ED_SHORTCUT("editor/unlock_selected_nodes", TTR("Unlock Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::L)); @@ -7816,7 +7800,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(tool_button[TOOL_GROUP_SELECTED]); tool_button[TOOL_GROUP_SELECTED]->set_flat(true); tool_button[TOOL_GROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_GROUP_SELECTED)); - tool_button[TOOL_GROUP_SELECTED]->set_tooltip(TTR("Make selected node's children not selectable.")); + tool_button[TOOL_GROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children not selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_GROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/group_selected_nodes", TTR("Group Selected Node(s)"), KeyModifierMask::CMD | Key::G)); @@ -7824,7 +7808,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(tool_button[TOOL_UNGROUP_SELECTED]); tool_button[TOOL_UNGROUP_SELECTED]->set_flat(true); tool_button[TOOL_UNGROUP_SELECTED]->connect("pressed", callable_mp(this, &Node3DEditor::_menu_item_pressed).bind(MENU_UNGROUP_SELECTED)); - tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip(TTR("Make selected node's children selectable.")); + tool_button[TOOL_UNGROUP_SELECTED]->set_tooltip_text(TTR("Make selected node's children selectable.")); // Define the shortcut globally (without a context) so that it works if the Scene tree dock is currently focused. tool_button[TOOL_UNGROUP_SELECTED]->set_shortcut(ED_SHORTCUT("editor/ungroup_selected_nodes", TTR("Ungroup Selected Node(s)"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::G)); @@ -7858,7 +7842,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(memnew(VSeparator)); sun_button = memnew(Button); - sun_button->set_tooltip(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled.")); + sun_button->set_tooltip_text(TTR("Toggle preview sunlight.\nIf a DirectionalLight3D node is added to the scene, preview sunlight is disabled.")); sun_button->set_toggle_mode(true); sun_button->set_flat(true); sun_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED); @@ -7867,7 +7851,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(sun_button); environ_button = memnew(Button); - environ_button->set_tooltip(TTR("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled.")); + environ_button->set_tooltip_text(TTR("Toggle preview environment.\nIf a WorldEnvironment node is added to the scene, preview environment is disabled.")); environ_button->set_toggle_mode(true); environ_button->set_flat(true); environ_button->connect("pressed", callable_mp(this, &Node3DEditor::_update_preview_environment), CONNECT_DEFERRED); @@ -7876,7 +7860,7 @@ Node3DEditor::Node3DEditor() { main_menu_hbox->add_child(environ_button); sun_environ_settings = memnew(Button); - sun_environ_settings->set_tooltip(TTR("Edit Sun and Environment settings.")); + sun_environ_settings->set_tooltip_text(TTR("Edit Sun and Environment settings.")); sun_environ_settings->set_flat(true); sun_environ_settings->connect("pressed", callable_mp(this, &Node3DEditor::_sun_environ_settings_pressed)); @@ -8234,7 +8218,7 @@ void fragment() { sun_add_to_scene = memnew(Button); sun_add_to_scene->set_text(TTR("Add Sun to Scene")); - sun_add_to_scene->set_tooltip(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene.")); + sun_add_to_scene->set_tooltip_text(TTR("Adds a DirectionalLight3D node matching the preview sun settings to the current scene.\nHold Shift while clicking to also add the preview environment to the current scene.")); sun_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_sun_to_scene).bind(false)); sun_vb->add_spacer(); sun_vb->add_child(sun_add_to_scene); @@ -8303,7 +8287,7 @@ void fragment() { environ_add_to_scene = memnew(Button); environ_add_to_scene->set_text(TTR("Add Environment to Scene")); - environ_add_to_scene->set_tooltip(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene.")); + environ_add_to_scene->set_tooltip_text(TTR("Adds a WorldEnvironment node matching the preview environment settings to the current scene.\nHold Shift while clicking to also add the preview sun to the current scene.")); environ_add_to_scene->connect("pressed", callable_mp(this, &Node3DEditor::_add_environment_to_scene).bind(false)); environ_vb->add_spacer(); environ_vb->add_child(environ_add_to_scene); diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index e0298ebd5f..e07374dd49 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -778,8 +778,6 @@ private: void _add_sun_to_scene(bool p_already_added_environment = false); void _add_environment_to_scene(bool p_already_added_sun = false); - void _update_theme(); - protected: void _notification(int p_what); //void _gui_input(InputEvent p_event); diff --git a/editor/plugins/packed_scene_translation_parser_plugin.cpp b/editor/plugins/packed_scene_translation_parser_plugin.cpp index 8d083d28b2..2f4ae734d1 100644 --- a/editor/plugins/packed_scene_translation_parser_plugin.cpp +++ b/editor/plugins/packed_scene_translation_parser_plugin.cpp @@ -123,7 +123,7 @@ Error PackedSceneEditorTranslationParserPlugin::parse_file(const String &p_path, PackedSceneEditorTranslationParserPlugin::PackedSceneEditorTranslationParserPlugin() { // Scene Node's properties containing strings that will be fetched for translation. lookup_properties.insert("text"); - lookup_properties.insert("hint_tooltip"); + lookup_properties.insert("tooltip_text"); lookup_properties.insert("placeholder_text"); lookup_properties.insert("items"); lookup_properties.insert("title"); diff --git a/editor/plugins/path_2d_editor_plugin.cpp b/editor/plugins/path_2d_editor_plugin.cpp index 1d8a3f5c81..00b0a0b100 100644 --- a/editor/plugins/path_2d_editor_plugin.cpp +++ b/editor/plugins/path_2d_editor_plugin.cpp @@ -40,7 +40,6 @@ void Path2DEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { curve_edit->set_icon(get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons"))); curve_edit_curve->set_icon(get_theme_icon(SNAME("CurveCurve"), SNAME("EditorIcons"))); @@ -537,7 +536,7 @@ Path2DEditor::Path2DEditor() { curve_edit->set_flat(true); curve_edit->set_toggle_mode(true); curve_edit->set_focus_mode(Control::FOCUS_NONE); - curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); + curve_edit->set_tooltip_text(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Left Click: Split Segment (in curve)") + "\n" + TTR("Right Click: Delete Point")); curve_edit->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_EDIT)); base_hb->add_child(curve_edit); @@ -545,7 +544,7 @@ Path2DEditor::Path2DEditor() { curve_edit_curve->set_flat(true); curve_edit_curve->set_toggle_mode(true); curve_edit_curve->set_focus_mode(Control::FOCUS_NONE); - curve_edit_curve->set_tooltip(TTR("Select Control Points (Shift+Drag)")); + curve_edit_curve->set_tooltip_text(TTR("Select Control Points (Shift+Drag)")); curve_edit_curve->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_EDIT_CURVE)); base_hb->add_child(curve_edit_curve); @@ -553,7 +552,7 @@ Path2DEditor::Path2DEditor() { curve_create->set_flat(true); curve_create->set_toggle_mode(true); curve_create->set_focus_mode(Control::FOCUS_NONE); - curve_create->set_tooltip(TTR("Add Point (in empty space)")); + curve_create->set_tooltip_text(TTR("Add Point (in empty space)")); curve_create->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_CREATE)); base_hb->add_child(curve_create); @@ -561,14 +560,14 @@ Path2DEditor::Path2DEditor() { curve_del->set_flat(true); curve_del->set_toggle_mode(true); curve_del->set_focus_mode(Control::FOCUS_NONE); - curve_del->set_tooltip(TTR("Delete Point")); + curve_del->set_tooltip_text(TTR("Delete Point")); curve_del->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(MODE_DELETE)); base_hb->add_child(curve_del); curve_close = memnew(Button); curve_close->set_flat(true); curve_close->set_focus_mode(Control::FOCUS_NONE); - curve_close->set_tooltip(TTR("Close Curve")); + curve_close->set_tooltip_text(TTR("Close Curve")); curve_close->connect("pressed", callable_mp(this, &Path2DEditor::_mode_selected).bind(ACTION_CLOSE)); base_hb->add_child(curve_close); diff --git a/editor/plugins/path_3d_editor_plugin.cpp b/editor/plugins/path_3d_editor_plugin.cpp index 084c0c2bb0..d5dbd24eac 100644 --- a/editor/plugins/path_3d_editor_plugin.cpp +++ b/editor/plugins/path_3d_editor_plugin.cpp @@ -563,8 +563,6 @@ void Path3DEditorPlugin::_notification(int p_what) { curve_edit->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(1)); curve_del->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_mode_changed).bind(2)); curve_close->connect("pressed", callable_mp(this, &Path3DEditorPlugin::_close_curve)); - - _update_theme(); } break; case NOTIFICATION_READY: { @@ -597,7 +595,7 @@ Path3DEditorPlugin::Path3DEditorPlugin() { curve_edit->set_toggle_mode(true); curve_edit->hide(); curve_edit->set_focus_mode(Control::FOCUS_NONE); - curve_edit->set_tooltip(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); + curve_edit->set_tooltip_text(TTR("Select Points") + "\n" + TTR("Shift+Drag: Select Control Points") + "\n" + keycode_get_string((Key)KeyModifierMask::CMD) + TTR("Click: Add Point") + "\n" + TTR("Right Click: Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_edit); curve_create = memnew(Button); @@ -605,7 +603,7 @@ Path3DEditorPlugin::Path3DEditorPlugin() { curve_create->set_toggle_mode(true); curve_create->hide(); curve_create->set_focus_mode(Control::FOCUS_NONE); - curve_create->set_tooltip(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)")); + curve_create->set_tooltip_text(TTR("Add Point (in empty space)") + "\n" + TTR("Split Segment (in curve)")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_create); curve_del = memnew(Button); @@ -613,14 +611,14 @@ Path3DEditorPlugin::Path3DEditorPlugin() { curve_del->set_toggle_mode(true); curve_del->hide(); curve_del->set_focus_mode(Control::FOCUS_NONE); - curve_del->set_tooltip(TTR("Delete Point")); + curve_del->set_tooltip_text(TTR("Delete Point")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_del); curve_close = memnew(Button); curve_close->set_flat(true); curve_close->hide(); curve_close->set_focus_mode(Control::FOCUS_NONE); - curve_close->set_tooltip(TTR("Close Curve")); + curve_close->set_tooltip_text(TTR("Close Curve")); Node3DEditor::get_singleton()->add_control_to_menu_panel(curve_close); PopupMenu *menu; diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 4f46c99a04..d414ff5143 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -91,8 +91,8 @@ void Polygon2DEditor::_notification(int p_what) { uv_vscroll->set_anchors_and_offsets_preset(PRESET_RIGHT_WIDE); uv_hscroll->set_anchors_and_offsets_preset(PRESET_BOTTOM_WIDE); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { uv_edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); bone_scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); @@ -1237,7 +1237,7 @@ Polygon2DEditor::Polygon2DEditor() { button_uv = memnew(Button); button_uv->set_flat(true); add_child(button_uv); - button_uv->set_tooltip(TTR("Open Polygon 2D UV editor.")); + button_uv->set_tooltip_text(TTR("Open Polygon 2D UV editor.")); button_uv->connect("pressed", callable_mp(this, &Polygon2DEditor::_menu_option).bind(MODE_EDIT_UV)); uv_mode = UV_MODE_EDIT_POINT; @@ -1293,17 +1293,17 @@ Polygon2DEditor::Polygon2DEditor() { uv_button[i]->set_focus_mode(FOCUS_NONE); } - uv_button[UV_MODE_CREATE]->set_tooltip(TTR("Create Polygon")); - uv_button[UV_MODE_CREATE_INTERNAL]->set_tooltip(TTR("Create Internal Vertex")); - uv_button[UV_MODE_REMOVE_INTERNAL]->set_tooltip(TTR("Remove Internal Vertex")); - uv_button[UV_MODE_EDIT_POINT]->set_tooltip(TTR("Move Points") + "\n" + TTR("Ctrl: Rotate") + "\n" + TTR("Shift: Move All") + "\n" + TTR("Shift+Ctrl: Scale")); - uv_button[UV_MODE_MOVE]->set_tooltip(TTR("Move Polygon")); - uv_button[UV_MODE_ROTATE]->set_tooltip(TTR("Rotate Polygon")); - uv_button[UV_MODE_SCALE]->set_tooltip(TTR("Scale Polygon")); - uv_button[UV_MODE_ADD_POLYGON]->set_tooltip(TTR("Create a custom polygon. Enables custom polygon rendering.")); - uv_button[UV_MODE_REMOVE_POLYGON]->set_tooltip(TTR("Remove a custom polygon. If none remain, custom polygon rendering is disabled.")); - uv_button[UV_MODE_PAINT_WEIGHT]->set_tooltip(TTR("Paint weights with specified intensity.")); - uv_button[UV_MODE_CLEAR_WEIGHT]->set_tooltip(TTR("Unpaint weights with specified intensity.")); + uv_button[UV_MODE_CREATE]->set_tooltip_text(TTR("Create Polygon")); + uv_button[UV_MODE_CREATE_INTERNAL]->set_tooltip_text(TTR("Create Internal Vertex")); + uv_button[UV_MODE_REMOVE_INTERNAL]->set_tooltip_text(TTR("Remove Internal Vertex")); + uv_button[UV_MODE_EDIT_POINT]->set_tooltip_text(TTR("Move Points") + "\n" + TTR("Ctrl: Rotate") + "\n" + TTR("Shift: Move All") + "\n" + TTR("Shift+Ctrl: Scale")); + uv_button[UV_MODE_MOVE]->set_tooltip_text(TTR("Move Polygon")); + uv_button[UV_MODE_ROTATE]->set_tooltip_text(TTR("Rotate Polygon")); + uv_button[UV_MODE_SCALE]->set_tooltip_text(TTR("Scale Polygon")); + uv_button[UV_MODE_ADD_POLYGON]->set_tooltip_text(TTR("Create a custom polygon. Enables custom polygon rendering.")); + uv_button[UV_MODE_REMOVE_POLYGON]->set_tooltip_text(TTR("Remove a custom polygon. If none remain, custom polygon rendering is disabled.")); + uv_button[UV_MODE_PAINT_WEIGHT]->set_tooltip_text(TTR("Paint weights with specified intensity.")); + uv_button[UV_MODE_CLEAR_WEIGHT]->set_tooltip_text(TTR("Unpaint weights with specified intensity.")); uv_button[UV_MODE_CREATE]->hide(); uv_button[UV_MODE_CREATE_INTERNAL]->hide(); @@ -1368,7 +1368,7 @@ Polygon2DEditor::Polygon2DEditor() { b_snap_enable->set_focus_mode(FOCUS_NONE); b_snap_enable->set_toggle_mode(true); b_snap_enable->set_pressed(use_snap); - b_snap_enable->set_tooltip(TTR("Enable Snap")); + b_snap_enable->set_tooltip_text(TTR("Enable Snap")); b_snap_enable->connect("toggled", callable_mp(this, &Polygon2DEditor::_set_use_snap)); b_snap_grid = memnew(Button); @@ -1378,7 +1378,7 @@ Polygon2DEditor::Polygon2DEditor() { b_snap_grid->set_focus_mode(FOCUS_NONE); b_snap_grid->set_toggle_mode(true); b_snap_grid->set_pressed(snap_show_grid); - b_snap_grid->set_tooltip(TTR("Show Grid")); + b_snap_grid->set_tooltip_text(TTR("Show Grid")); b_snap_grid->connect("toggled", callable_mp(this, &Polygon2DEditor::_set_show_grid)); grid_settings = memnew(AcceptDialog); diff --git a/editor/plugins/resource_preloader_editor_plugin.cpp b/editor/plugins/resource_preloader_editor_plugin.cpp index 201a3af539..1d569b7c52 100644 --- a/editor/plugins/resource_preloader_editor_plugin.cpp +++ b/editor/plugins/resource_preloader_editor_plugin.cpp @@ -39,7 +39,6 @@ void ResourcePreloaderEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { load->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); } break; @@ -356,7 +355,7 @@ ResourcePreloaderEditor::ResourcePreloaderEditor() { vbc->add_child(hbc); load = memnew(Button); - load->set_tooltip(TTR("Load Resource")); + load->set_tooltip_text(TTR("Load Resource")); hbc->add_child(load); paste = memnew(Button); diff --git a/editor/plugins/root_motion_editor_plugin.cpp b/editor/plugins/root_motion_editor_plugin.cpp index 681dd476e3..49196d6c79 100644 --- a/editor/plugins/root_motion_editor_plugin.cpp +++ b/editor/plugins/root_motion_editor_plugin.cpp @@ -198,7 +198,7 @@ void EditorPropertyRootMotion::_node_clear() { void EditorPropertyRootMotion::update_property() { NodePath p = get_edited_object()->get(get_edited_property()); - assign->set_tooltip(p); + assign->set_tooltip_text(p); if (p == NodePath()) { assign->set_icon(Ref<Texture2D>()); assign->set_text(TTR("Assign...")); @@ -234,7 +234,6 @@ void EditorPropertyRootMotion::setup(const NodePath &p_base_hint) { void EditorPropertyRootMotion::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { Ref<Texture2D> t = get_theme_icon(SNAME("Clear"), SNAME("EditorIcons")); clear->set_icon(t); diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index a0c9ddb14b..1a692cffcc 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -352,9 +352,9 @@ void ScriptEditorQuickOpen::_notification(int p_what) { connect("confirmed", callable_mp(this, &ScriptEditorQuickOpen::_confirmed)); search_box->set_clear_button_enabled(true); - [[fallthrough]]; - } - case NOTIFICATION_VISIBILITY_CHANGED: { + } break; + + case NOTIFICATION_THEME_CHANGED: { search_box->set_right_icon(search_options->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); } break; @@ -1613,8 +1613,8 @@ void ScriptEditor::_notification(int p_what) { EditorSettings::get_singleton()->connect("settings_changed", callable_mp(this, &ScriptEditor::_editor_settings_changed)); EditorFileSystem::get_singleton()->connect("filesystem_changed", callable_mp(this, &ScriptEditor::_filesystem_changed)); _editor_settings_changed(); - [[fallthrough]]; - } + } break; + case NOTIFICATION_TRANSLATION_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: case NOTIFICATION_THEME_CHANGED: { @@ -3712,7 +3712,7 @@ ScriptEditor::ScriptEditor() { members_overview_alphabeta_sort_button = memnew(Button); members_overview_alphabeta_sort_button->set_flat(true); - members_overview_alphabeta_sort_button->set_tooltip(TTR("Toggle alphabetical sorting of the method list.")); + members_overview_alphabeta_sort_button->set_tooltip_text(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/script_list/sort_members_outline_alphabetically")); members_overview_alphabeta_sort_button->connect("toggled", callable_mp(this, &ScriptEditor::_toggle_members_overview_alpha_sort)); @@ -3858,14 +3858,14 @@ ScriptEditor::ScriptEditor() { site_search->set_text(TTR("Online Docs")); site_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option).bind(SEARCH_WEBSITE)); menu_hb->add_child(site_search); - site_search->set_tooltip(TTR("Open Godot online documentation.")); + site_search->set_tooltip_text(TTR("Open Godot online documentation.")); help_search = memnew(Button); help_search->set_flat(true); help_search->set_text(TTR("Search Help")); help_search->connect("pressed", callable_mp(this, &ScriptEditor::_menu_option).bind(SEARCH_HELP)); menu_hb->add_child(help_search); - help_search->set_tooltip(TTR("Search the reference documentation.")); + help_search->set_tooltip_text(TTR("Search the reference documentation.")); menu_hb->add_child(memnew(VSeparator)); @@ -3874,14 +3874,14 @@ ScriptEditor::ScriptEditor() { script_back->connect("pressed", callable_mp(this, &ScriptEditor::_history_back)); menu_hb->add_child(script_back); script_back->set_disabled(true); - script_back->set_tooltip(TTR("Go to previous edited document.")); + script_back->set_tooltip_text(TTR("Go to previous edited document.")); script_forward = memnew(Button); script_forward->set_flat(true); script_forward->connect("pressed", callable_mp(this, &ScriptEditor::_history_forward)); menu_hb->add_child(script_forward); script_forward->set_disabled(true); - script_forward->set_tooltip(TTR("Go to next edited document.")); + script_forward->set_tooltip_text(TTR("Go to next edited document.")); tab_container->connect("tab_changed", callable_mp(this, &ScriptEditor::_tab_changed)); diff --git a/editor/plugins/script_text_editor.cpp b/editor/plugins/script_text_editor.cpp index 5e7db17edf..421b258f49 100644 --- a/editor/plugins/script_text_editor.cpp +++ b/editor/plugins/script_text_editor.cpp @@ -1392,7 +1392,11 @@ void ScriptTextEditor::_change_syntax_highlighter(int p_idx) { void ScriptTextEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: + case NOTIFICATION_ENTER_TREE: { + code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_line_height()); + } break; + + case NOTIFICATION_THEME_CHANGED: { if (!editor_enabled) { break; } @@ -1400,9 +1404,6 @@ void ScriptTextEditor::_notification(int p_what) { _update_warnings(); _update_errors(); } - [[fallthrough]]; - case NOTIFICATION_ENTER_TREE: { - code_editor->get_text_editor()->set_gutter_width(connection_gutter, code_editor->get_text_editor()->get_line_height()); } break; } } diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 4641df3dca..b4a0216e9f 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -712,7 +712,6 @@ void ShaderEditor::_menu_option(int p_option) { void ShaderEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { PopupMenu *popup = help_menu->get_popup(); popup->set_item_icon(popup->get_item_index(HELP_DOCS), get_theme_icon(SNAME("ExternalLink"), SNAME("EditorIcons"))); @@ -1257,6 +1256,17 @@ void ShaderEditorPlugin::_update_shader_list_status() { } } +void ShaderEditorPlugin::_move_shader_tab(int p_from, int p_to) { + if (p_from == p_to) { + return; + } + EditedShader es = edited_shaders[p_from]; + edited_shaders.remove_at(p_from); + edited_shaders.insert(p_to, es); + shader_tabs->move_child(shader_tabs->get_tab_control(p_from), p_to); + _update_shader_list(); +} + void ShaderEditorPlugin::edit(Object *p_object) { EditedShader es; @@ -1451,6 +1461,109 @@ void ShaderEditorPlugin::_shader_include_created(Ref<ShaderInclude> p_shader_inc EditorNode::get_singleton()->push_item(p_shader_inc.ptr()); } +Variant ShaderEditorPlugin::get_drag_data_fw(const Point2 &p_point, Control *p_from) { + if (shader_list->get_item_count() == 0) { + return Variant(); + } + + int idx = shader_list->get_item_at_position(p_point); + if (idx < 0) { + return Variant(); + } + + HBoxContainer *drag_preview = memnew(HBoxContainer); + String preview_name = shader_list->get_item_text(idx); + Ref<Texture2D> preview_icon = shader_list->get_item_icon(idx); + + if (!preview_icon.is_null()) { + TextureRect *tf = memnew(TextureRect); + tf->set_texture(preview_icon); + tf->set_stretch_mode(TextureRect::STRETCH_KEEP_CENTERED); + drag_preview->add_child(tf); + } + Label *label = memnew(Label(preview_name)); + drag_preview->add_child(label); + main_split->set_drag_preview(drag_preview); + + Dictionary drag_data; + drag_data["type"] = "shader_list_element"; + drag_data["shader_list_element"] = idx; + + return drag_data; +} + +bool ShaderEditorPlugin::can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const { + Dictionary d = p_data; + if (!d.has("type")) { + return false; + } + + if (String(d["type"]) == "shader_list_element") { + return true; + } + + if (String(d["type"]) == "files") { + Vector<String> files = d["files"]; + + if (files.size() == 0) { + return false; + } + + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + if (ResourceLoader::exists(file, "Shader")) { + Ref<Shader> shader = ResourceLoader::load(file); + if (shader.is_valid()) { + return true; + } + } + } + return false; + } + + return false; +} + +void ShaderEditorPlugin::drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) { + if (!can_drop_data_fw(p_point, p_data, p_from)) { + return; + } + + Dictionary d = p_data; + if (!d.has("type")) { + return; + } + + if (String(d["type"]) == "shader_list_element") { + int idx = d["shader_list_element"]; + int new_idx = shader_list->get_item_at_position(p_point); + _move_shader_tab(idx, new_idx); + return; + } + + if (String(d["type"]) == "files") { + Vector<String> files = d["files"]; + + for (int i = 0; i < files.size(); i++) { + String file = files[i]; + if (!ResourceLoader::exists(file, "Shader")) { + continue; + } + + Ref<Resource> res = ResourceLoader::load(file); + if (res.is_valid()) { + edit(res.ptr()); + } + } + } +} + +void ShaderEditorPlugin::_bind_methods() { + ClassDB::bind_method(D_METHOD("_get_drag_data_fw", "point", "from"), &ShaderEditorPlugin::get_drag_data_fw); + ClassDB::bind_method(D_METHOD("_can_drop_data_fw", "point", "data", "from"), &ShaderEditorPlugin::can_drop_data_fw); + ClassDB::bind_method(D_METHOD("_drop_data_fw", "point", "data", "from"), &ShaderEditorPlugin::drop_data_fw); +} + ShaderEditorPlugin::ShaderEditorPlugin() { main_split = memnew(HSplitContainer); @@ -1483,6 +1596,7 @@ ShaderEditorPlugin::ShaderEditorPlugin() { vb->add_child(shader_list); shader_list->connect("item_selected", callable_mp(this, &ShaderEditorPlugin::_shader_selected)); shader_list->connect("item_clicked", callable_mp(this, &ShaderEditorPlugin::_shader_list_clicked)); + shader_list->set_drag_forwarding(this); main_split->add_child(vb); vb->set_custom_minimum_size(Size2(200, 300) * EDSCALE); diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 0980cc4db2..afd38ef71a 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -250,6 +250,14 @@ class ShaderEditorPlugin : public EditorPlugin { void _shader_created(Ref<Shader> p_shader); void _shader_include_created(Ref<ShaderInclude> p_shader_inc); void _update_shader_list_status(); + void _move_shader_tab(int p_from, int p_to); + + Variant get_drag_data_fw(const Point2 &p_point, Control *p_from); + bool can_drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from) const; + void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from); + +protected: + static void _bind_methods(); public: virtual void edit(Object *p_object) override; diff --git a/editor/plugins/skeleton_3d_editor_plugin.cpp b/editor/plugins/skeleton_3d_editor_plugin.cpp index c25f2bb25c..f21adabffb 100644 --- a/editor/plugins/skeleton_3d_editor_plugin.cpp +++ b/editor/plugins/skeleton_3d_editor_plugin.cpp @@ -733,7 +733,7 @@ void Skeleton3DEditor::create_editors() { edit_mode_button->set_flat(true); edit_mode_button->set_toggle_mode(true); edit_mode_button->set_focus_mode(FOCUS_NONE); - edit_mode_button->set_tooltip(TTR("Edit Mode\nShow buttons on joints.")); + edit_mode_button->set_tooltip_text(TTR("Edit Mode\nShow buttons on joints.")); edit_mode_button->connect("toggled", callable_mp(this, &Skeleton3DEditor::edit_mode_toggled)); edit_mode = false; @@ -754,7 +754,7 @@ void Skeleton3DEditor::create_editors() { key_loc_button->set_toggle_mode(true); key_loc_button->set_pressed(false); key_loc_button->set_focus_mode(FOCUS_NONE); - key_loc_button->set_tooltip(TTR("Translation mask for inserting keys.")); + key_loc_button->set_tooltip_text(TTR("Translation mask for inserting keys.")); animation_hb->add_child(key_loc_button); key_rot_button = memnew(Button); @@ -762,7 +762,7 @@ void Skeleton3DEditor::create_editors() { key_rot_button->set_toggle_mode(true); key_rot_button->set_pressed(true); key_rot_button->set_focus_mode(FOCUS_NONE); - key_rot_button->set_tooltip(TTR("Rotation mask for inserting keys.")); + key_rot_button->set_tooltip_text(TTR("Rotation mask for inserting keys.")); animation_hb->add_child(key_rot_button); key_scale_button = memnew(Button); @@ -770,14 +770,14 @@ void Skeleton3DEditor::create_editors() { key_scale_button->set_toggle_mode(true); key_scale_button->set_pressed(false); key_scale_button->set_focus_mode(FOCUS_NONE); - key_scale_button->set_tooltip(TTR("Scale mask for inserting keys.")); + key_scale_button->set_tooltip_text(TTR("Scale mask for inserting keys.")); animation_hb->add_child(key_scale_button); key_insert_button = memnew(Button); key_insert_button->set_flat(true); key_insert_button->set_focus_mode(FOCUS_NONE); key_insert_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys).bind(false)); - key_insert_button->set_tooltip(TTR("Insert key of bone poses already exist track.")); + key_insert_button->set_tooltip_text(TTR("Insert key of bone poses already exist track.")); key_insert_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_to_existing_tracks", TTR("Insert Key (Existing Tracks)"), Key::INSERT)); animation_hb->add_child(key_insert_button); @@ -785,7 +785,7 @@ void Skeleton3DEditor::create_editors() { key_insert_all_button->set_flat(true); key_insert_all_button->set_focus_mode(FOCUS_NONE); key_insert_all_button->connect("pressed", callable_mp(this, &Skeleton3DEditor::insert_keys).bind(true)); - key_insert_all_button->set_tooltip(TTR("Insert key of all bone poses.")); + key_insert_all_button->set_tooltip_text(TTR("Insert key of all bone poses.")); key_insert_all_button->set_shortcut(ED_SHORTCUT("skeleton_3d_editor/insert_key_of_all_bones", TTR("Insert Key (All Bones)"), KeyModifierMask::CMD + Key::INSERT)); animation_hb->add_child(key_insert_all_button); diff --git a/editor/plugins/sprite_2d_editor_plugin.cpp b/editor/plugins/sprite_2d_editor_plugin.cpp index e45c907e86..a493827d60 100644 --- a/editor/plugins/sprite_2d_editor_plugin.cpp +++ b/editor/plugins/sprite_2d_editor_plugin.cpp @@ -506,7 +506,6 @@ void Sprite2DEditor::_debug_uv_draw() { void Sprite2DEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { options->set_icon(get_theme_icon(SNAME("Sprite2D"), SNAME("EditorIcons"))); diff --git a/editor/plugins/sprite_frames_editor_plugin.cpp b/editor/plugins/sprite_frames_editor_plugin.cpp index 205fed48b4..56da3c986e 100644 --- a/editor/plugins/sprite_frames_editor_plugin.cpp +++ b/editor/plugins/sprite_frames_editor_plugin.cpp @@ -408,7 +408,6 @@ void SpriteFramesEditor::_prepare_sprite_sheet(const String &p_file) { void SpriteFramesEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { load->set_icon(get_theme_icon(SNAME("Load"), SNAME("EditorIcons"))); load_sheet->set_icon(get_theme_icon(SNAME("SpriteSheet"), SNAME("EditorIcons"))); @@ -1161,13 +1160,13 @@ SpriteFramesEditor::SpriteFramesEditor() { new_anim = memnew(Button); new_anim->set_flat(true); - new_anim->set_tooltip(TTR("New Animation")); + new_anim->set_tooltip_text(TTR("New Animation")); hbc_animlist->add_child(new_anim); new_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_add)); remove_anim = memnew(Button); remove_anim->set_flat(true); - remove_anim->set_tooltip(TTR("Remove Animation")); + remove_anim->set_tooltip_text(TTR("Remove Animation")); hbc_animlist->add_child(remove_anim); remove_anim->connect("pressed", callable_mp(this, &SpriteFramesEditor::_animation_remove)); @@ -1215,53 +1214,53 @@ SpriteFramesEditor::SpriteFramesEditor() { load = memnew(Button); load->set_flat(true); - load->set_tooltip(TTR("Add a Texture from File")); + load->set_tooltip_text(TTR("Add a Texture from File")); hbc->add_child(load); load_sheet = memnew(Button); load_sheet->set_flat(true); - load_sheet->set_tooltip(TTR("Add Frames from a Sprite Sheet")); + load_sheet->set_tooltip_text(TTR("Add Frames from a Sprite Sheet")); hbc->add_child(load_sheet); hbc->add_child(memnew(VSeparator)); copy = memnew(Button); copy->set_flat(true); - copy->set_tooltip(TTR("Copy")); + copy->set_tooltip_text(TTR("Copy")); hbc->add_child(copy); paste = memnew(Button); paste->set_flat(true); - paste->set_tooltip(TTR("Paste")); + paste->set_tooltip_text(TTR("Paste")); hbc->add_child(paste); hbc->add_child(memnew(VSeparator)); empty = memnew(Button); empty->set_flat(true); - empty->set_tooltip(TTR("Insert Empty (Before)")); + empty->set_tooltip_text(TTR("Insert Empty (Before)")); hbc->add_child(empty); empty2 = memnew(Button); empty2->set_flat(true); - empty2->set_tooltip(TTR("Insert Empty (After)")); + empty2->set_tooltip_text(TTR("Insert Empty (After)")); hbc->add_child(empty2); hbc->add_child(memnew(VSeparator)); move_up = memnew(Button); move_up->set_flat(true); - move_up->set_tooltip(TTR("Move (Before)")); + move_up->set_tooltip_text(TTR("Move (Before)")); hbc->add_child(move_up); move_down = memnew(Button); move_down->set_flat(true); - move_down->set_tooltip(TTR("Move (After)")); + move_down->set_tooltip_text(TTR("Move (After)")); hbc->add_child(move_down); _delete = memnew(Button); _delete->set_flat(true); - _delete->set_tooltip(TTR("Delete")); + _delete->set_tooltip_text(TTR("Delete")); hbc->add_child(_delete); hbc->add_spacer(); @@ -1269,19 +1268,19 @@ SpriteFramesEditor::SpriteFramesEditor() { zoom_out = memnew(Button); zoom_out->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_out)); zoom_out->set_flat(true); - zoom_out->set_tooltip(TTR("Zoom Out")); + zoom_out->set_tooltip_text(TTR("Zoom Out")); hbc->add_child(zoom_out); zoom_reset = memnew(Button); zoom_reset->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_reset)); zoom_reset->set_flat(true); - zoom_reset->set_tooltip(TTR("Zoom Reset")); + zoom_reset->set_tooltip_text(TTR("Zoom Reset")); hbc->add_child(zoom_reset); zoom_in = memnew(Button); zoom_in->connect("pressed", callable_mp(this, &SpriteFramesEditor::_zoom_in)); zoom_in->set_flat(true); - zoom_in->set_tooltip(TTR("Zoom In")); + zoom_in->set_tooltip_text(TTR("Zoom In")); hbc->add_child(zoom_in); file = memnew(EditorFileDialog); @@ -1434,21 +1433,21 @@ SpriteFramesEditor::SpriteFramesEditor() { split_sheet_zoom_out = memnew(Button); split_sheet_zoom_out->set_flat(true); split_sheet_zoom_out->set_focus_mode(FOCUS_NONE); - split_sheet_zoom_out->set_tooltip(TTR("Zoom Out")); + split_sheet_zoom_out->set_tooltip_text(TTR("Zoom Out")); split_sheet_zoom_out->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_out)); split_sheet_zoom_hb->add_child(split_sheet_zoom_out); split_sheet_zoom_reset = memnew(Button); split_sheet_zoom_reset->set_flat(true); split_sheet_zoom_reset->set_focus_mode(FOCUS_NONE); - split_sheet_zoom_reset->set_tooltip(TTR("Zoom Reset")); + split_sheet_zoom_reset->set_tooltip_text(TTR("Zoom Reset")); split_sheet_zoom_reset->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_reset)); split_sheet_zoom_hb->add_child(split_sheet_zoom_reset); split_sheet_zoom_in = memnew(Button); split_sheet_zoom_in->set_flat(true); split_sheet_zoom_in->set_focus_mode(FOCUS_NONE); - split_sheet_zoom_in->set_tooltip(TTR("Zoom In")); + split_sheet_zoom_in->set_tooltip_text(TTR("Zoom In")); split_sheet_zoom_in->connect("pressed", callable_mp(this, &SpriteFramesEditor::_sheet_zoom_in)); split_sheet_zoom_hb->add_child(split_sheet_zoom_in); diff --git a/editor/plugins/style_box_editor_plugin.cpp b/editor/plugins/style_box_editor_plugin.cpp index d4baff34e2..6dbba3ced2 100644 --- a/editor/plugins/style_box_editor_plugin.cpp +++ b/editor/plugins/style_box_editor_plugin.cpp @@ -71,15 +71,7 @@ void StyleBoxPreview::_sb_changed() { void StyleBoxPreview::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - if (!is_inside_tree()) { - // TODO: This is a workaround because `NOTIFICATION_THEME_CHANGED` - // is getting called for some reason when the `TexturePreview` is - // getting destroyed, which causes `get_theme_font()` to return `nullptr`. - // See https://github.com/godotengine/godot/issues/50743. - break; - } grid_preview->set_normal_texture(get_theme_icon(SNAME("StyleBoxGridInvisible"), SNAME("EditorIcons"))); grid_preview->set_pressed_texture(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons"))); grid_preview->set_hover_texture(get_theme_icon(SNAME("StyleBoxGridVisible"), SNAME("EditorIcons"))); diff --git a/editor/plugins/texture_editor_plugin.cpp b/editor/plugins/texture_editor_plugin.cpp index be382759f5..1b79527352 100644 --- a/editor/plugins/texture_editor_plugin.cpp +++ b/editor/plugins/texture_editor_plugin.cpp @@ -38,16 +38,7 @@ TextureRect *TexturePreview::get_texture_display() { void TexturePreview::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - if (!is_inside_tree()) { - // TODO: This is a workaround because `NOTIFICATION_THEME_CHANGED` - // is getting called for some reason when the `TexturePreview` is - // getting destroyed, which causes `get_theme_font()` to return `nullptr`. - // See https://github.com/godotengine/godot/issues/50743. - break; - } - if (metadata_label) { Ref<Font> metadata_label_font = get_theme_font(SNAME("expression"), SNAME("EditorFonts")); metadata_label->add_theme_font_override("font", metadata_label_font); diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 772bae6544..1d0ae4d36f 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -821,7 +821,6 @@ void TextureRegionEditor::_update_autoslice() { void TextureRegionEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { edit_draw->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } break; @@ -1110,19 +1109,19 @@ TextureRegionEditor::TextureRegionEditor() { zoom_out = memnew(Button); zoom_out->set_flat(true); - zoom_out->set_tooltip(TTR("Zoom Out")); + zoom_out->set_tooltip_text(TTR("Zoom Out")); zoom_out->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_out)); zoom_hb->add_child(zoom_out); zoom_reset = memnew(Button); zoom_reset->set_flat(true); - zoom_reset->set_tooltip(TTR("Zoom Reset")); + zoom_reset->set_tooltip_text(TTR("Zoom Reset")); zoom_reset->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_reset)); zoom_hb->add_child(zoom_reset); zoom_in = memnew(Button); zoom_in->set_flat(true); - zoom_in->set_tooltip(TTR("Zoom In")); + zoom_in->set_tooltip_text(TTR("Zoom In")); zoom_in->connect("pressed", callable_mp(this, &TextureRegionEditor::_zoom_in)); zoom_hb->add_child(zoom_in); diff --git a/editor/plugins/theme_editor_plugin.cpp b/editor/plugins/theme_editor_plugin.cpp index af3959d47c..ac67965a6c 100644 --- a/editor/plugins/theme_editor_plugin.cpp +++ b/editor/plugins/theme_editor_plugin.cpp @@ -839,7 +839,6 @@ bool ThemeItemImportTree::has_selected_items() const { void ThemeItemImportTree::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { select_icons_warning_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); select_icons_warning->add_theme_color_override("font_color", get_theme_color(SNAME("disabled_font_color"), SNAME("Editor"))); @@ -1103,15 +1102,15 @@ ThemeItemImportTree::ThemeItemImportTree() { button_set->set_alignment(BoxContainer::ALIGNMENT_END); all_set->add_child(button_set); select_all_items_button->set_flat(true); - select_all_items_button->set_tooltip(select_all_items_tooltip); + select_all_items_button->set_tooltip_text(select_all_items_tooltip); button_set->add_child(select_all_items_button); select_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_data_type_pressed).bind(i)); select_full_items_button->set_flat(true); - select_full_items_button->set_tooltip(select_full_items_tooltip); + select_full_items_button->set_tooltip_text(select_full_items_tooltip); button_set->add_child(select_full_items_button); select_full_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_data_type_pressed).bind(i)); deselect_all_items_button->set_flat(true); - deselect_all_items_button->set_tooltip(deselect_all_items_tooltip); + deselect_all_items_button->set_tooltip_text(deselect_all_items_tooltip); button_set->add_child(deselect_all_items_button); deselect_all_items_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_data_type_pressed).bind(i)); @@ -1142,12 +1141,12 @@ ThemeItemImportTree::ThemeItemImportTree() { import_collapse_types_button = memnew(Button); import_collapse_types_button->set_flat(true); - import_collapse_types_button->set_tooltip(TTR("Collapse types.")); + import_collapse_types_button->set_tooltip_text(TTR("Collapse types.")); import_buttons->add_child(import_collapse_types_button); import_collapse_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items).bind(true)); import_expand_types_button = memnew(Button); import_expand_types_button->set_flat(true); - import_expand_types_button->set_tooltip(TTR("Expand types.")); + import_expand_types_button->set_tooltip_text(TTR("Expand types.")); import_buttons->add_child(import_expand_types_button); import_expand_types_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_toggle_type_items).bind(false)); @@ -1156,19 +1155,19 @@ ThemeItemImportTree::ThemeItemImportTree() { import_select_all_button = memnew(Button); import_select_all_button->set_flat(true); import_select_all_button->set_text(TTR("Select All")); - import_select_all_button->set_tooltip(TTR("Select all Theme items.")); + import_select_all_button->set_tooltip_text(TTR("Select all Theme items.")); import_buttons->add_child(import_select_all_button); import_select_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_all_items_pressed)); import_select_full_button = memnew(Button); import_select_full_button->set_flat(true); import_select_full_button->set_text(TTR("Select With Data")); - import_select_full_button->set_tooltip(TTR("Select all Theme items with item data.")); + import_select_full_button->set_tooltip_text(TTR("Select all Theme items with item data.")); import_buttons->add_child(import_select_full_button); import_select_full_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_select_full_items_pressed)); import_deselect_all_button = memnew(Button); import_deselect_all_button->set_flat(true); import_deselect_all_button->set_text(TTR("Deselect All")); - import_deselect_all_button->set_tooltip(TTR("Deselect all Theme items.")); + import_deselect_all_button->set_tooltip_text(TTR("Deselect all Theme items.")); import_buttons->add_child(import_deselect_all_button); import_deselect_all_button->connect("pressed", callable_mp(this, &ThemeItemImportTree::_deselect_all_items_pressed)); @@ -1865,8 +1864,8 @@ void ThemeItemEditorDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { connect("about_to_popup", callable_mp(this, &ThemeItemEditorDialog::_dialog_about_to_show)); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { edit_items_add_color->set_icon(get_theme_icon(SNAME("Color"), SNAME("EditorIcons"))); edit_items_add_constant->set_icon(get_theme_icon(SNAME("MemberConstant"), SNAME("EditorIcons"))); @@ -1954,42 +1953,42 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito edit_items_toolbar->add_child(edit_items_toolbar_add_label); edit_items_add_color = memnew(Button); - edit_items_add_color->set_tooltip(TTR("Add Color Item")); + edit_items_add_color->set_tooltip_text(TTR("Add Color Item")); edit_items_add_color->set_flat(true); edit_items_add_color->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_color); edit_items_add_color->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_COLOR)); edit_items_add_constant = memnew(Button); - edit_items_add_constant->set_tooltip(TTR("Add Constant Item")); + edit_items_add_constant->set_tooltip_text(TTR("Add Constant Item")); edit_items_add_constant->set_flat(true); edit_items_add_constant->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_constant); edit_items_add_constant->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_CONSTANT)); edit_items_add_font = memnew(Button); - edit_items_add_font->set_tooltip(TTR("Add Font Item")); + edit_items_add_font->set_tooltip_text(TTR("Add Font Item")); edit_items_add_font->set_flat(true); edit_items_add_font->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_font); edit_items_add_font->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_FONT)); edit_items_add_font_size = memnew(Button); - edit_items_add_font_size->set_tooltip(TTR("Add Font Size Item")); + edit_items_add_font_size->set_tooltip_text(TTR("Add Font Size Item")); edit_items_add_font_size->set_flat(true); edit_items_add_font_size->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_font_size); edit_items_add_font_size->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_FONT_SIZE)); edit_items_add_icon = memnew(Button); - edit_items_add_icon->set_tooltip(TTR("Add Icon Item")); + edit_items_add_icon->set_tooltip_text(TTR("Add Icon Item")); edit_items_add_icon->set_flat(true); edit_items_add_icon->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_icon); edit_items_add_icon->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_open_add_theme_item_dialog).bind(Theme::DATA_TYPE_ICON)); edit_items_add_stylebox = memnew(Button); - edit_items_add_stylebox->set_tooltip(TTR("Add StyleBox Item")); + edit_items_add_stylebox->set_tooltip_text(TTR("Add StyleBox Item")); edit_items_add_stylebox->set_flat(true); edit_items_add_stylebox->set_disabled(true); edit_items_toolbar->add_child(edit_items_add_stylebox); @@ -2002,21 +2001,21 @@ ThemeItemEditorDialog::ThemeItemEditorDialog(ThemeTypeEditor *p_theme_type_edito edit_items_toolbar->add_child(edit_items_toolbar_remove_label); edit_items_remove_class = memnew(Button); - edit_items_remove_class->set_tooltip(TTR("Remove Class Items")); + edit_items_remove_class->set_tooltip_text(TTR("Remove Class Items")); edit_items_remove_class->set_flat(true); edit_items_remove_class->set_disabled(true); edit_items_toolbar->add_child(edit_items_remove_class); edit_items_remove_class->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_class_items)); edit_items_remove_custom = memnew(Button); - edit_items_remove_custom->set_tooltip(TTR("Remove Custom Items")); + edit_items_remove_custom->set_tooltip_text(TTR("Remove Custom Items")); edit_items_remove_custom->set_flat(true); edit_items_remove_custom->set_disabled(true); edit_items_toolbar->add_child(edit_items_remove_custom); edit_items_remove_custom->connect("pressed", callable_mp(this, &ThemeItemEditorDialog::_remove_custom_items)); edit_items_remove_all = memnew(Button); - edit_items_remove_all->set_tooltip(TTR("Remove All Items")); + edit_items_remove_all->set_tooltip_text(TTR("Remove All Items")); edit_items_remove_all->set_flat(true); edit_items_remove_all->set_disabled(true); edit_items_toolbar->add_child(edit_items_remove_all); @@ -2194,8 +2193,8 @@ void ThemeTypeDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { connect("about_to_popup", callable_mp(this, &ThemeTypeDialog::_dialog_about_to_show)); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { _update_add_type_options(); } break; @@ -2412,7 +2411,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ item_name->set_h_size_flags(SIZE_EXPAND_FILL); item_name->set_clip_text(true); item_name->set_text(p_item_name); - item_name->set_tooltip(p_item_name); + item_name->set_tooltip_text(p_item_name); item_name_container->add_child(item_name); if (p_editable) { @@ -2425,21 +2424,21 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ Button *item_rename_button = memnew(Button); item_rename_button->set_icon(get_theme_icon(SNAME("Edit"), SNAME("EditorIcons"))); - item_rename_button->set_tooltip(TTR("Rename Item")); + item_rename_button->set_tooltip_text(TTR("Rename Item")); item_rename_button->set_flat(true); item_name_container->add_child(item_rename_button); item_rename_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_cbk).bind(p_data_type, p_item_name, item_name_container)); Button *item_remove_button = memnew(Button); item_remove_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - item_remove_button->set_tooltip(TTR("Remove Item")); + item_remove_button->set_tooltip_text(TTR("Remove Item")); item_remove_button->set_flat(true); item_name_container->add_child(item_remove_button); item_remove_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_remove_cbk).bind(p_data_type, p_item_name)); Button *item_rename_confirm_button = memnew(Button); item_rename_confirm_button->set_icon(get_theme_icon(SNAME("ImportCheck"), SNAME("EditorIcons"))); - item_rename_confirm_button->set_tooltip(TTR("Confirm Item Rename")); + item_rename_confirm_button->set_tooltip_text(TTR("Confirm Item Rename")); item_rename_confirm_button->set_flat(true); item_name_container->add_child(item_rename_confirm_button); item_rename_confirm_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_confirmed).bind(p_data_type, p_item_name, item_name_container)); @@ -2447,7 +2446,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ Button *item_rename_cancel_button = memnew(Button); item_rename_cancel_button->set_icon(get_theme_icon(SNAME("ImportFail"), SNAME("EditorIcons"))); - item_rename_cancel_button->set_tooltip(TTR("Cancel Item Rename")); + item_rename_cancel_button->set_tooltip_text(TTR("Cancel Item Rename")); item_rename_cancel_button->set_flat(true); item_name_container->add_child(item_rename_cancel_button); item_rename_cancel_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_rename_canceled).bind(p_data_type, p_item_name, item_name_container)); @@ -2457,7 +2456,7 @@ HBoxContainer *ThemeTypeEditor::_create_property_control(Theme::DataType p_data_ Button *item_override_button = memnew(Button); item_override_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - item_override_button->set_tooltip(TTR("Override Item")); + item_override_button->set_tooltip_text(TTR("Override Item")); item_override_button->set_flat(true); item_name_container->add_child(item_override_button); item_override_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_item_override_cbk).bind(p_data_type, p_item_name)); @@ -2667,7 +2666,7 @@ void ThemeTypeEditor::_update_type_items() { pin_leader_button->set_toggle_mode(true); pin_leader_button->set_pressed(true); pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"))); - pin_leader_button->set_tooltip(TTR("Unpin this StyleBox as a main style.")); + pin_leader_button->set_tooltip_text(TTR("Unpin this StyleBox as a main style.")); item_control->add_child(pin_leader_button); pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_unpin_leader_button_pressed)); @@ -2710,7 +2709,7 @@ void ThemeTypeEditor::_update_type_items() { pin_leader_button->set_flat(true); pin_leader_button->set_toggle_mode(true); pin_leader_button->set_icon(get_theme_icon(SNAME("Pin"), SNAME("EditorIcons"))); - pin_leader_button->set_tooltip(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type.")); + pin_leader_button->set_tooltip_text(TTR("Pin this StyleBox as a main style. Editing its properties will update the same properties in all other StyleBoxes of this type.")); item_control->add_child(pin_leader_button); pin_leader_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_on_pin_leader_button_pressed).bind(item_editor, E.key)); } else { @@ -3302,7 +3301,6 @@ void ThemeTypeEditor::_add_type_dialog_selected(const String p_type_name) { void ThemeTypeEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { add_type_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); @@ -3387,7 +3385,7 @@ ThemeTypeEditor::ThemeTypeEditor() { theme_type_list->connect("item_selected", callable_mp(this, &ThemeTypeEditor::_list_type_selected)); add_type_button = memnew(Button); - add_type_button->set_tooltip(TTR("Add a type from a list of available types or create a new one.")); + add_type_button->set_tooltip_text(TTR("Add a type from a list of available types or create a new one.")); type_list_hb->add_child(add_type_button); add_type_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_button_cbk)); @@ -3397,7 +3395,7 @@ ThemeTypeEditor::ThemeTypeEditor() { show_default_items_button = memnew(CheckButton); show_default_items_button->set_h_size_flags(SIZE_EXPAND_FILL); show_default_items_button->set_text(TTR("Show Default")); - show_default_items_button->set_tooltip(TTR("Show default type items alongside items that have been overridden.")); + show_default_items_button->set_tooltip_text(TTR("Show default type items alongside items that have been overridden.")); show_default_items_button->set_pressed(true); type_controls->add_child(show_default_items_button); show_default_items_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_update_type_items)); @@ -3405,7 +3403,7 @@ ThemeTypeEditor::ThemeTypeEditor() { Button *add_default_items_button = memnew(Button); add_default_items_button->set_h_size_flags(SIZE_EXPAND_FILL); add_default_items_button->set_text(TTR("Override All")); - add_default_items_button->set_tooltip(TTR("Override all default type items.")); + add_default_items_button->set_tooltip_text(TTR("Override all default type items.")); type_controls->add_child(add_default_items_button); add_default_items_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_default_type_items)); @@ -3452,7 +3450,7 @@ ThemeTypeEditor::ThemeTypeEditor() { type_variation_edit->connect("focus_exited", callable_mp(this, &ThemeTypeEditor::_update_type_items)); type_variation_button = memnew(Button); type_variation_hb->add_child(type_variation_button); - type_variation_button->set_tooltip(TTR("Select the variation base type from a list of available types.")); + type_variation_button->set_tooltip_text(TTR("Select the variation base type from a list of available types.")); type_variation_button->connect("pressed", callable_mp(this, &ThemeTypeEditor::_add_type_variation_cbk)); type_variation_locked = memnew(Label); @@ -3595,7 +3593,6 @@ void ThemeEditor::_preview_control_picked(String p_class_name) { void ThemeEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { preview_tabs->add_theme_style_override("tab_selected", get_theme_stylebox(SNAME("ThemeEditorPreviewFG"), SNAME("EditorStyles"))); preview_tabs->add_theme_style_override("tab_unselected", get_theme_stylebox(SNAME("ThemeEditorPreviewBG"), SNAME("EditorStyles"))); @@ -3633,7 +3630,7 @@ ThemeEditor::ThemeEditor() { Button *theme_edit_button = memnew(Button); theme_edit_button->set_text(TTR("Manage Items...")); - theme_edit_button->set_tooltip(TTR("Add, remove, organize and import Theme items.")); + theme_edit_button->set_tooltip_text(TTR("Add, remove, organize and import Theme items.")); theme_edit_button->set_flat(true); theme_edit_button->connect("pressed", callable_mp(this, &ThemeEditor::_theme_edit_button_cbk)); top_menu->add_child(theme_edit_button); diff --git a/editor/plugins/theme_editor_preview.cpp b/editor/plugins/theme_editor_preview.cpp index b5c6c6d651..41b4a4c407 100644 --- a/editor/plugins/theme_editor_preview.cpp +++ b/editor/plugins/theme_editor_preview.cpp @@ -193,8 +193,8 @@ void ThemeEditorPreview::_notification(int p_what) { } connect("visibility_changed", callable_mp(this, &ThemeEditorPreview::_preview_visibility_changed)); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons"))); @@ -227,7 +227,7 @@ ThemeEditorPreview::ThemeEditorPreview() { preview_toolbar->add_child(picker_button); picker_button->set_flat(true); picker_button->set_toggle_mode(true); - picker_button->set_tooltip(TTR("Toggle the control picker, allowing to visually select control types for edit.")); + picker_button->set_tooltip_text(TTR("Toggle the control picker, allowing to visually select control types for edit.")); picker_button->connect("pressed", callable_mp(this, &ThemeEditorPreview::_picker_button_cbk)); MarginContainer *preview_body = memnew(MarginContainer); @@ -272,7 +272,6 @@ ThemeEditorPreview::ThemeEditorPreview() { void DefaultThemeEditorPreview::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { test_color_picker_button->set_custom_minimum_size(Size2(0, get_theme_constant(SNAME("color_picker_button_height"), SNAME("Editor")))); } break; @@ -475,7 +474,6 @@ void SceneThemeEditorPreview::_reload_scene() { void SceneThemeEditorPreview::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { reload_scene_button->set_icon(get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); } break; @@ -517,7 +515,7 @@ SceneThemeEditorPreview::SceneThemeEditorPreview() { reload_scene_button = memnew(Button); reload_scene_button->set_flat(true); - reload_scene_button->set_tooltip(TTR("Reload the scene to reflect its most actual state.")); + reload_scene_button->set_tooltip_text(TTR("Reload the scene to reflect its most actual state.")); preview_toolbar->add_child(reload_scene_button); reload_scene_button->connect("pressed", callable_mp(this, &SceneThemeEditorPreview::_reload_scene)); } diff --git a/editor/plugins/tiles/tile_atlas_view.cpp b/editor/plugins/tiles/tile_atlas_view.cpp index 54ba28833c..8d2b150d6d 100644 --- a/editor/plugins/tiles/tile_atlas_view.cpp +++ b/editor/plugins/tiles/tile_atlas_view.cpp @@ -160,7 +160,7 @@ void TileAtlasView::_center_view() { } void TileAtlasView::_base_tiles_root_control_gui_input(const Ref<InputEvent> &p_event) { - base_tiles_root_control->set_tooltip(""); + base_tiles_root_control->set_tooltip_text(""); Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { @@ -169,7 +169,7 @@ void TileAtlasView::_base_tiles_root_control_gui_input(const Ref<InputEvent> &p_ if (coords != TileSetSource::INVALID_ATLAS_COORDS) { coords = tile_set_atlas_source->get_tile_at_coords(coords); if (coords != TileSetSource::INVALID_ATLAS_COORDS) { - base_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: 0"), source_id, coords)); + base_tiles_root_control->set_tooltip_text(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: 0"), source_id, coords)); } } } @@ -319,7 +319,7 @@ void TileAtlasView::_draw_base_tiles_shape_grid() { } void TileAtlasView::_alternative_tiles_root_control_gui_input(const Ref<InputEvent> &p_event) { - alternative_tiles_root_control->set_tooltip(""); + alternative_tiles_root_control->set_tooltip_text(""); Ref<InputEventMouseMotion> mm = p_event; if (mm.is_valid()) { @@ -328,7 +328,7 @@ void TileAtlasView::_alternative_tiles_root_control_gui_input(const Ref<InputEve Vector2i coords = Vector2i(coords3.x, coords3.y); int alternative_id = coords3.z; if (coords != TileSetSource::INVALID_ATLAS_COORDS && alternative_id != TileSetSource::INVALID_TILE_ALTERNATIVE) { - alternative_tiles_root_control->set_tooltip(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: %d"), source_id, coords, alternative_id)); + alternative_tiles_root_control->set_tooltip_text(vformat(TTR("Source: %d\nAtlas coordinates: %s\nAlternative: %d"), source_id, coords, alternative_id)); } } } @@ -542,7 +542,7 @@ TileAtlasView::TileAtlasView() { button_center_view->connect("pressed", callable_mp(this, &TileAtlasView::_center_view)); button_center_view->set_flat(true); button_center_view->set_disabled(true); - button_center_view->set_tooltip(TTR("Center View")); + button_center_view->set_tooltip_text(TTR("Center View")); add_child(button_center_view); panner.instantiate(); diff --git a/editor/plugins/tiles/tile_data_editors.cpp b/editor/plugins/tiles/tile_data_editors.cpp index b44b6fcc53..f6001e8972 100644 --- a/editor/plugins/tiles/tile_data_editors.cpp +++ b/editor/plugins/tiles/tile_data_editors.cpp @@ -722,7 +722,6 @@ void GenericTilePolygonEditor::set_multiple_polygon_mode(bool p_multiple_polygon void GenericTilePolygonEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { button_create->set_icon(get_theme_icon(SNAME("CurveCreate"), SNAME("EditorIcons"))); button_edit->set_icon(get_theme_icon(SNAME("CurveEdit"), SNAME("EditorIcons"))); @@ -764,21 +763,21 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { button_create->set_toggle_mode(true); button_create->set_button_group(tools_button_group); button_create->set_pressed(true); - button_create->set_tooltip(TTR("Add polygon tool")); + button_create->set_tooltip_text(TTR("Add polygon tool")); toolbar->add_child(button_create); button_edit = memnew(Button); button_edit->set_flat(true); button_edit->set_toggle_mode(true); button_edit->set_button_group(tools_button_group); - button_edit->set_tooltip(TTR("Edit points tool")); + button_edit->set_tooltip_text(TTR("Edit points tool")); toolbar->add_child(button_edit); button_delete = memnew(Button); button_delete->set_flat(true); button_delete->set_toggle_mode(true); button_delete->set_button_group(tools_button_group); - button_delete->set_tooltip(TTR("Delete points tool")); + button_delete->set_tooltip_text(TTR("Delete points tool")); toolbar->add_child(button_delete); button_advanced_menu = memnew(MenuButton); @@ -801,7 +800,7 @@ GenericTilePolygonEditor::GenericTilePolygonEditor() { button_pixel_snap->set_flat(true); button_pixel_snap->set_toggle_mode(true); button_pixel_snap->set_pressed(true); - button_pixel_snap->set_tooltip(TTR("Snap to half-pixel")); + button_pixel_snap->set_tooltip_text(TTR("Snap to half-pixel")); toolbar->add_child(button_pixel_snap); Control *root = memnew(Control); @@ -1161,14 +1160,13 @@ void TileDataDefaultEditor::setup_property_editor(Variant::Type p_type, String p property_editor->set_label(p_label); } property_editor->connect("property_changed", callable_mp(this, &TileDataDefaultEditor::_property_value_changed).unbind(1)); - property_editor->set_tooltip(p_property); + property_editor->set_tooltip_text(p_property); property_editor->update_property(); add_child(property_editor); } void TileDataDefaultEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons"))); tile_bool_checked = get_theme_icon(SNAME("TileChecked"), SNAME("EditorIcons")); @@ -1371,7 +1369,7 @@ void TileDataCollisionEditor::_polygons_changed() { one_way_property_editor->set_label(one_way_property); one_way_property_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1)); one_way_property_editor->connect("selected", callable_mp(this, &TileDataCollisionEditor::_property_selected)); - one_way_property_editor->set_tooltip(one_way_property_editor->get_edited_property()); + one_way_property_editor->set_tooltip_text(one_way_property_editor->get_edited_property()); one_way_property_editor->update_property(); add_child(one_way_property_editor); property_editors[one_way_property] = one_way_property_editor; @@ -1383,7 +1381,7 @@ void TileDataCollisionEditor::_polygons_changed() { one_way_margin_property_editor->set_label(one_way_margin_property); one_way_margin_property_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1)); one_way_margin_property_editor->connect("selected", callable_mp(this, &TileDataCollisionEditor::_property_selected)); - one_way_margin_property_editor->set_tooltip(one_way_margin_property_editor->get_edited_property()); + one_way_margin_property_editor->set_tooltip_text(one_way_margin_property_editor->get_edited_property()); one_way_margin_property_editor->update_property(); add_child(one_way_margin_property_editor); property_editors[one_way_margin_property] = one_way_margin_property_editor; @@ -1544,7 +1542,7 @@ TileDataCollisionEditor::TileDataCollisionEditor() { linear_velocity_editor->set_label("linear_velocity"); linear_velocity_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1)); linear_velocity_editor->connect("selected", callable_mp(this, &TileDataCollisionEditor::_property_selected)); - linear_velocity_editor->set_tooltip(linear_velocity_editor->get_edited_property()); + linear_velocity_editor->set_tooltip_text(linear_velocity_editor->get_edited_property()); linear_velocity_editor->update_property(); add_child(linear_velocity_editor); property_editors["linear_velocity"] = linear_velocity_editor; @@ -1554,7 +1552,7 @@ TileDataCollisionEditor::TileDataCollisionEditor() { angular_velocity_editor->set_label("angular_velocity"); angular_velocity_editor->connect("property_changed", callable_mp(this, &TileDataCollisionEditor::_property_value_changed).unbind(1)); angular_velocity_editor->connect("selected", callable_mp(this, &TileDataCollisionEditor::_property_selected)); - angular_velocity_editor->set_tooltip(angular_velocity_editor->get_edited_property()); + angular_velocity_editor->set_tooltip_text(angular_velocity_editor->get_edited_property()); angular_velocity_editor->update_property(); add_child(angular_velocity_editor); property_editors["angular_velocity"] = angular_velocity_editor; @@ -2567,7 +2565,6 @@ void TileDataTerrainsEditor::draw_over_tile(CanvasItem *p_canvas_item, Transform void TileDataTerrainsEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { picker_button->set_icon(get_theme_icon(SNAME("ColorPick"), SNAME("EditorIcons"))); } break; @@ -2602,7 +2599,7 @@ TileDataTerrainsEditor::TileDataTerrainsEditor() { terrain_set_property_editor->set_object_and_property(dummy_object, "terrain_set"); terrain_set_property_editor->set_label("Terrain Set"); terrain_set_property_editor->connect("property_changed", callable_mp(this, &TileDataTerrainsEditor::_property_value_changed).unbind(1)); - terrain_set_property_editor->set_tooltip(terrain_set_property_editor->get_edited_property()); + terrain_set_property_editor->set_tooltip_text(terrain_set_property_editor->get_edited_property()); add_child(terrain_set_property_editor); terrain_property_editor = memnew(EditorPropertyEnum); diff --git a/editor/plugins/tiles/tile_map_editor.cpp b/editor/plugins/tiles/tile_map_editor.cpp index 3f355a1ed2..9e08d4cea7 100644 --- a/editor/plugins/tiles/tile_map_editor.cpp +++ b/editor/plugins/tiles/tile_map_editor.cpp @@ -2050,7 +2050,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { paint_tool_button->set_toggle_mode(true); paint_tool_button->set_button_group(tool_buttons_group); paint_tool_button->set_shortcut(ED_SHORTCUT("tiles_editor/paint_tool", "Paint", Key::D)); - paint_tool_button->set_tooltip(TTR("Shift: Draw line.") + "\n" + TTR("Shift+Ctrl: Draw rectangle.")); + paint_tool_button->set_tooltip_text(TTR("Shift: Draw line.") + "\n" + TTR("Shift+Ctrl: Draw rectangle.")); paint_tool_button->connect("pressed", callable_mp(this, &TileMapEditorTilesPlugin::_update_toolbar)); tilemap_tiles_tools_buttons->add_child(paint_tool_button); @@ -2091,7 +2091,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { picker_button->set_flat(true); picker_button->set_toggle_mode(true); picker_button->set_shortcut(ED_SHORTCUT("tiles_editor/picker", "Picker", Key::P)); - picker_button->set_tooltip(TTR("Alternatively hold Ctrl with other tools to pick tile.")); + picker_button->set_tooltip_text(TTR("Alternatively hold Ctrl with other tools to pick tile.")); picker_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(picker_button); @@ -2100,7 +2100,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { erase_button->set_flat(true); erase_button->set_toggle_mode(true); erase_button->set_shortcut(ED_SHORTCUT("tiles_editor/eraser", "Eraser", Key::E)); - erase_button->set_tooltip(TTR("Alternatively use RMB to erase tiles.")); + erase_button->set_tooltip_text(TTR("Alternatively use RMB to erase tiles.")); erase_button->connect("pressed", callable_mp(CanvasItemEditor::get_singleton(), &CanvasItemEditor::update_viewport)); tools_settings->add_child(erase_button); @@ -2119,13 +2119,13 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { random_tile_toggle = memnew(Button); random_tile_toggle->set_flat(true); random_tile_toggle->set_toggle_mode(true); - random_tile_toggle->set_tooltip(TTR("Place Random Tile")); + random_tile_toggle->set_tooltip_text(TTR("Place Random Tile")); random_tile_toggle->connect("toggled", callable_mp(this, &TileMapEditorTilesPlugin::_on_random_tile_checkbox_toggled)); tools_settings->add_child(random_tile_toggle); // Random tile scattering. scatter_label = memnew(Label); - scatter_label->set_tooltip(TTR("Defines the probability of painting nothing instead of a randomly selected tile.")); + scatter_label->set_tooltip_text(TTR("Defines the probability of painting nothing instead of a randomly selected tile.")); scatter_label->set_text(TTR("Scattering:")); tools_settings->add_child(scatter_label); @@ -2133,7 +2133,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { scatter_spinbox->set_min(0.0); scatter_spinbox->set_max(1000); scatter_spinbox->set_step(0.001); - scatter_spinbox->set_tooltip(TTR("Defines the probability of painting nothing instead of a randomly selected tile.")); + scatter_spinbox->set_tooltip_text(TTR("Defines the probability of painting nothing instead of a randomly selected tile.")); scatter_spinbox->get_line_edit()->add_theme_constant_override("minimum_character_width", 4); scatter_spinbox->connect("value_changed", callable_mp(this, &TileMapEditorTilesPlugin::_on_scattering_spinbox_changed)); tools_settings->add_child(scatter_spinbox); @@ -2146,7 +2146,6 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { // --- Bottom panel tiles --- tiles_bottom_panel = memnew(VBoxContainer); - tiles_bottom_panel->connect("tree_entered", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme)); tiles_bottom_panel->connect("theme_changed", callable_mp(this, &TileMapEditorTilesPlugin::_update_theme)); tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_stop_dragging)); tiles_bottom_panel->connect("visibility_changed", callable_mp(this, &TileMapEditorTilesPlugin::_tab_changed)); @@ -2178,7 +2177,7 @@ TileMapEditorTilesPlugin::TileMapEditorTilesPlugin() { source_sort_button = memnew(MenuButton); source_sort_button->set_flat(true); - source_sort_button->set_tooltip(TTR("Sort sources")); + source_sort_button->set_tooltip_text(TTR("Sort sources")); PopupMenu *p = source_sort_button->get_popup(); p->connect("id_pressed", callable_mp(this, &TileMapEditorTilesPlugin::_set_source_sort)); @@ -3311,7 +3310,6 @@ TileMapEditorTerrainsPlugin::TileMapEditorTerrainsPlugin() { undo_redo = EditorNode::get_undo_redo(); main_vbox_container = memnew(VBoxContainer); - main_vbox_container->connect("tree_entered", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme)); main_vbox_container->connect("theme_changed", callable_mp(this, &TileMapEditorTerrainsPlugin::_update_theme)); main_vbox_container->set_name("Terrains"); @@ -3419,7 +3417,6 @@ TileMapEditorTerrainsPlugin::~TileMapEditorTerrainsPlugin() { void TileMapEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { missing_tile_texture = get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons")); warning_pattern_texture = get_theme_icon(SNAME("WarningPattern"), SNAME("EditorIcons")); @@ -4003,7 +4000,7 @@ TileMapEditor::TileMapEditor() { layers_selection_button = memnew(OptionButton); layers_selection_button->set_custom_minimum_size(Size2(200, 0)); layers_selection_button->set_text_overrun_behavior(TextServer::OVERRUN_TRIM_ELLIPSIS); - layers_selection_button->set_tooltip(TTR("TileMap Layers")); + layers_selection_button->set_tooltip_text(TTR("TileMap Layers")); layers_selection_button->connect("item_selected", callable_mp(this, &TileMapEditor::_layers_selection_item_selected)); tile_map_toolbar->add_child(layers_selection_button); @@ -4012,7 +4009,7 @@ TileMapEditor::TileMapEditor() { toggle_highlight_selected_layer_button->set_toggle_mode(true); toggle_highlight_selected_layer_button->set_pressed(true); toggle_highlight_selected_layer_button->connect("pressed", callable_mp(this, &TileMapEditor::_update_layers_selection)); - toggle_highlight_selected_layer_button->set_tooltip(TTR("Highlight Selected TileMap Layer")); + toggle_highlight_selected_layer_button->set_tooltip_text(TTR("Highlight Selected TileMap Layer")); tile_map_toolbar->add_child(toggle_highlight_selected_layer_button); tile_map_toolbar->add_child(memnew(VSeparator)); @@ -4021,7 +4018,7 @@ TileMapEditor::TileMapEditor() { toggle_grid_button = memnew(Button); toggle_grid_button->set_flat(true); toggle_grid_button->set_toggle_mode(true); - toggle_grid_button->set_tooltip(TTR("Toggle grid visibility.")); + toggle_grid_button->set_tooltip_text(TTR("Toggle grid visibility.")); toggle_grid_button->connect("toggled", callable_mp(this, &TileMapEditor::_on_grid_toggled)); tile_map_toolbar->add_child(toggle_grid_button); diff --git a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp index 2c1fad45d9..098cf93721 100644 --- a/editor/plugins/tiles/tile_set_atlas_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_atlas_source_editor.cpp @@ -527,7 +527,7 @@ void TileSetAtlasSourceEditor::_update_tile_id_label() { if (selection.size() == 1) { TileSelection selected = selection.front()->get(); tool_tile_id_label->set_text(vformat("%d, %s, %d", tile_set_atlas_source_id, selected.tile, selected.alternative)); - tool_tile_id_label->set_tooltip(vformat(TTR("Selected tile:\nSource: %d\nAtlas coordinates: %s\nAlternative: %d"), tile_set_atlas_source_id, selected.tile, selected.alternative)); + tool_tile_id_label->set_tooltip_text(vformat(TTR("Selected tile:\nSource: %d\nAtlas coordinates: %s\nAlternative: %d"), tile_set_atlas_source_id, selected.tile, selected.alternative)); tool_tile_id_label->show(); } else { tool_tile_id_label->hide(); @@ -1888,7 +1888,7 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In alternative_tiles_control_unscaled->update(); if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { - if (Vector2(drag_start_mouse_pos).distance_to(tile_atlas_control->get_local_mouse_position()) > 5.0 * EDSCALE) { + if (Vector2(drag_start_mouse_pos).distance_to(alternative_tiles_control->get_local_mouse_position()) > 5.0 * EDSCALE) { drag_type = DRAG_TYPE_NONE; } } @@ -1896,8 +1896,6 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In Ref<InputEventMouseButton> mb = p_event; if (mb.is_valid()) { - drag_type = DRAG_TYPE_NONE; - Vector2 mouse_local_pos = alternative_tiles_control->get_local_mouse_position(); if (mb->get_button_index() == MouseButton::LEFT) { if (mb->is_pressed()) { @@ -1919,25 +1917,29 @@ void TileSetAtlasSourceEditor::_tile_alternatives_control_gui_input(const Ref<In if (mb->is_pressed()) { drag_type = DRAG_TYPE_MAY_POPUP_MENU; drag_start_mouse_pos = alternative_tiles_control->get_local_mouse_position(); - } else if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { - // Right click released and wasn't dragged too far - Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos); + } else { + if (drag_type == DRAG_TYPE_MAY_POPUP_MENU) { + // Right click released and wasn't dragged too far + Vector3 tile = tile_atlas_view->get_alternative_tile_at_pos(mouse_local_pos); - selection.clear(); - TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) }; - if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { - selection.insert(selected); - } + selection.clear(); + TileSelection selected = { Vector2i(tile.x, tile.y), int(tile.z) }; + if (selected.tile != TileSetSource::INVALID_ATLAS_COORDS) { + selection.insert(selected); + } - _update_tile_inspector(); - _update_tile_id_label(); + _update_tile_inspector(); + _update_tile_id_label(); - if (selection.size() == 1) { - selected = selection.front()->get(); - menu_option_coords = selected.tile; - menu_option_alternative = selected.alternative; - alternative_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i())); + if (selection.size() == 1) { + selected = selection.front()->get(); + menu_option_coords = selected.tile; + menu_option_alternative = selected.alternative; + alternative_tile_popup_menu->popup(Rect2i(get_global_mouse_position(), Size2i())); + } } + + drag_type = DRAG_TYPE_NONE; } } tile_atlas_control->update(); @@ -2285,7 +2287,6 @@ void TileSetAtlasSourceEditor::_auto_remove_tiles() { void TileSetAtlasSourceEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { tool_setup_atlas_source_button->set_icon(get_theme_icon(SNAME("Tools"), SNAME("EditorIcons"))); tool_select_button->set_icon(get_theme_icon(SNAME("ToolSelect"), SNAME("EditorIcons"))); @@ -2444,7 +2445,7 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tool_setup_atlas_source_button->set_toggle_mode(true); tool_setup_atlas_source_button->set_pressed(true); tool_setup_atlas_source_button->set_button_group(tools_button_group); - tool_setup_atlas_source_button->set_tooltip(TTR("Atlas setup. Add/Remove tiles tool (use the shift key to create big tiles, control for rectangle editing).")); + tool_setup_atlas_source_button->set_tooltip_text(TTR("Atlas setup. Add/Remove tiles tool (use the shift key to create big tiles, control for rectangle editing).")); toolbox->add_child(tool_setup_atlas_source_button); tool_select_button = memnew(Button); @@ -2452,14 +2453,14 @@ TileSetAtlasSourceEditor::TileSetAtlasSourceEditor() { tool_select_button->set_toggle_mode(true); tool_select_button->set_pressed(false); tool_select_button->set_button_group(tools_button_group); - tool_select_button->set_tooltip(TTR("Select tiles.")); + tool_select_button->set_tooltip_text(TTR("Select tiles.")); toolbox->add_child(tool_select_button); tool_paint_button = memnew(Button); tool_paint_button->set_flat(true); tool_paint_button->set_toggle_mode(true); tool_paint_button->set_button_group(tools_button_group); - tool_paint_button->set_tooltip(TTR("Paint properties.")); + tool_paint_button->set_tooltip_text(TTR("Paint properties.")); toolbox->add_child(tool_paint_button); // Tool settings. diff --git a/editor/plugins/tiles/tile_set_editor.cpp b/editor/plugins/tiles/tile_set_editor.cpp index 8d04dd3121..302c34d8a5 100644 --- a/editor/plugins/tiles/tile_set_editor.cpp +++ b/editor/plugins/tiles/tile_set_editor.cpp @@ -333,7 +333,6 @@ void TileSetEditor::_set_source_sort(int p_sort) { void TileSetEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { sources_delete_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); sources_add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); @@ -695,7 +694,7 @@ TileSetEditor::TileSetEditor() { source_sort_button = memnew(MenuButton); source_sort_button->set_flat(true); - source_sort_button->set_tooltip(TTR("Sort sources")); + source_sort_button->set_tooltip_text(TTR("Sort sources")); PopupMenu *p = source_sort_button->get_popup(); p->connect("id_pressed", callable_mp(this, &TileSetEditor::_set_source_sort)); diff --git a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp index 9a4b14616f..40cdb243fe 100644 --- a/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp +++ b/editor/plugins/tiles/tile_set_scenes_collection_source_editor.cpp @@ -329,7 +329,6 @@ void TileSetScenesCollectionSourceEditor::_update_scenes_list() { void TileSetScenesCollectionSourceEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { scene_tile_add_button->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); scene_tile_delete_button->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); diff --git a/editor/plugins/version_control_editor_plugin.cpp b/editor/plugins/version_control_editor_plugin.cpp index 6db499f2c7..2b55ba64c3 100644 --- a/editor/plugins/version_control_editor_plugin.cpp +++ b/editor/plugins/version_control_editor_plugin.cpp @@ -464,7 +464,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { stage_tools->add_child(staging_area_label); refresh_button = memnew(Button); - refresh_button->set_tooltip(TTR("Detect new changes")); + refresh_button->set_tooltip_text(TTR("Detect new changes")); refresh_button->set_text(TTR("Refresh")); refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); refresh_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_refresh_stage_area)); @@ -551,7 +551,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { diff_heading = memnew(Label); diff_heading->set_text(TTR("Status")); - diff_heading->set_tooltip(TTR("View file diffs before committing them to the latest version")); + diff_heading->set_tooltip_text(TTR("View file diffs before committing them to the latest version")); diff_hbc->add_child(diff_heading); diff_file_name = memnew(Label); @@ -561,7 +561,7 @@ VersionControlEditorPlugin::VersionControlEditorPlugin() { diff_hbc->add_child(diff_file_name); diff_refresh_button = memnew(Button); - diff_refresh_button->set_tooltip(TTR("Detect changes in file diff")); + diff_refresh_button->set_tooltip_text(TTR("Detect changes in file diff")); diff_refresh_button->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Reload"), SNAME("EditorIcons"))); diff_refresh_button->connect("pressed", callable_mp(this, &VersionControlEditorPlugin::_refresh_file_diff)); diff_hbc->add_child(diff_refresh_button); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index e048ee2698..579c816dd8 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -754,7 +754,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { Button *remove_btn = memnew(Button); remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left); remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_input_port).bind(p_id, i), CONNECT_DEFERRED); hb->add_child(remove_btn); } else { @@ -781,7 +781,7 @@ void VisualShaderGraphPlugin::add_node(VisualShader::Type p_type, int p_id) { if (is_group) { Button *remove_btn = memnew(Button); remove_btn->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); - remove_btn->set_tooltip(TTR("Remove") + " " + name_left); + remove_btn->set_tooltip_text(TTR("Remove") + " " + name_left); remove_btn->connect("pressed", callable_mp(editor, &VisualShaderEditor::_remove_output_port).bind(p_id, i), CONNECT_DEFERRED); hb->add_child(remove_btn); @@ -1716,7 +1716,6 @@ void VisualShaderEditor::_update_graph() { graph_plugin->clear_links(); graph_plugin->make_dirty(true); - graph_plugin->update_theme(); for (int n_i = 0; n_i < nodes.size(); n_i++) { graph_plugin->add_node(type, nodes[n_i]); @@ -3704,9 +3703,11 @@ void VisualShaderEditor::_notification(int p_what) { graph->get_panner()->setup((ViewPanner::ControlScheme)EDITOR_GET("editors/panning/sub_editors_panning_scheme").operator int(), ED_GET_SHORTCUT("canvas_item_editor/pan_view"), bool(EditorSettings::get_singleton()->get("editors/panning/simple_panning"))); graph->set_warped_panning(bool(EditorSettings::get_singleton()->get("editors/panning/warped_mouse_panning"))); - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { + graph_plugin->update_theme(); + highend_label->set_modulate(get_theme_color(SNAME("vulkan_color"), SNAME("Editor"))); node_filter->set_right_icon(Control::get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); @@ -3759,7 +3760,7 @@ void VisualShaderEditor::_notification(int p_what) { tools->set_icon(EditorNode::get_singleton()->get_gui_base()->get_theme_icon(SNAME("Tools"), SNAME("EditorIcons"))); - if (p_what == NOTIFICATION_THEME_CHANGED && is_visible_in_tree()) { + if (is_visible_in_tree()) { _update_graph(); } } break; @@ -4826,7 +4827,7 @@ VisualShaderEditor::VisualShaderEditor() { preview_shader = memnew(Button); preview_shader->set_flat(true); preview_shader->set_toggle_mode(true); - preview_shader->set_tooltip(TTR("Show generated shader code.")); + preview_shader->set_tooltip_text(TTR("Show generated shader code.")); graph->get_zoom_hbox()->add_child(preview_shader); preview_shader->connect("pressed", callable_mp(this, &VisualShaderEditor::_show_preview_text)); @@ -4896,7 +4897,7 @@ VisualShaderEditor::VisualShaderEditor() { tools = memnew(MenuButton); filter_hb->add_child(tools); - tools->set_tooltip(TTR("Options")); + tools->set_tooltip_text(TTR("Options")); tools->get_popup()->connect("id_pressed", callable_mp(this, &VisualShaderEditor::_tools_menu_option)); tools->get_popup()->add_item(TTR("Expand All"), EXPAND_ALL); tools->get_popup()->add_item(TTR("Collapse All"), COLLAPSE_ALL); @@ -4928,7 +4929,7 @@ VisualShaderEditor::VisualShaderEditor() { highend_label->set_visible(false); highend_label->set_text("Vulkan"); highend_label->set_mouse_filter(Control::MOUSE_FILTER_STOP); - highend_label->set_tooltip(TTR("High-end node")); + highend_label->set_tooltip_text(TTR("High-end node")); node_desc = memnew(RichTextLabel); members_vb->add_child(node_desc); @@ -5411,6 +5412,7 @@ VisualShaderEditor::VisualShaderEditor() { // TEXTURES add_options.push_back(AddOption("UVFunc", "Textures", "Common", "VisualShaderNodeUVFunc", TTR("Function to be applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D)); + add_options.push_back(AddOption("UVPolarCoord", "Textures", "Common", "VisualShaderNodeUVPolarCoord", TTR("Polar coordinates conversion applied on texture coordinates."), {}, VisualShaderNode::PORT_TYPE_VECTOR_2D)); cubemap_node_option_idx = add_options.size(); add_options.push_back(AddOption("CubeMap", "Textures", "Functions", "VisualShaderNodeCubemap", TTR("Perform the cubic texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); @@ -5418,6 +5420,7 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("CurveTexture", "Textures", "Functions", "VisualShaderNodeCurveTexture", TTR("Perform the curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); curve_xyz_node_option_idx = add_options.size(); add_options.push_back(AddOption("CurveXYZTexture", "Textures", "Functions", "VisualShaderNodeCurveXYZTexture", TTR("Perform the three components curve texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D)); + add_options.push_back(AddOption("LinearSceneDepth", "Textures", "Functions", "VisualShaderNodeLinearSceneDepth", TTR("Returns the depth value of the DEPTH_TEXTURE node in a linear space."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); texture2d_node_option_idx = add_options.size(); add_options.push_back(AddOption("Texture2D", "Textures", "Functions", "VisualShaderNodeTexture", TTR("Perform the 2D texture lookup."), {}, VisualShaderNode::PORT_TYPE_VECTOR_4D)); texture2d_array_node_option_idx = add_options.size(); @@ -5457,6 +5460,13 @@ VisualShaderEditor::VisualShaderEditor() { add_options.push_back(AddOption("TransformConstant", "Transform", "Variables", "VisualShaderNodeTransformConstant", TTR("Transform constant."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM)); add_options.push_back(AddOption("TransformUniform", "Transform", "Variables", "VisualShaderNodeTransformUniform", TTR("Transform uniform."), {}, VisualShaderNode::PORT_TYPE_TRANSFORM)); + // UTILITY + + add_options.push_back(AddOption("DistanceFade", "Utility", "", "VisualShaderNodeDistanceFade", TTR("The distance fade effect fades out each pixel based on its distance to another object."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("ProximityFade", "Utility", "", "VisualShaderNodeProximityFade", TTR("The proximity fade effect fades out each pixel based on its distance to another object."), {}, VisualShaderNode::PORT_TYPE_SCALAR, TYPE_FLAGS_FRAGMENT, Shader::MODE_SPATIAL)); + add_options.push_back(AddOption("RandomRange", "Utility", "", "VisualShaderNodeRandomRange", TTR("Returns a random value between the minimum and maximum input values."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); + add_options.push_back(AddOption("Remap", "Utility", "", "VisualShaderNodeRemap", TTR("Remaps a given input from the input range to the output range."), {}, VisualShaderNode::PORT_TYPE_SCALAR)); + // VECTOR add_options.push_back(AddOption("VectorFunc", "Vector", "Common", "VisualShaderNodeVectorFunc", TTR("Vector function."), {}, VisualShaderNode::PORT_TYPE_VECTOR_3D)); diff --git a/editor/plugins/voxel_gi_editor_plugin.cpp b/editor/plugins/voxel_gi_editor_plugin.cpp index e3b2be33df..713c90c075 100644 --- a/editor/plugins/voxel_gi_editor_plugin.cpp +++ b/editor/plugins/voxel_gi_editor_plugin.cpp @@ -100,7 +100,7 @@ void VoxelGIEditorPlugin::_notification(int p_what) { return; } - bake->set_tooltip(text); + bake->set_tooltip_text(text); } break; } } diff --git a/editor/project_converter_3_to_4.cpp b/editor/project_converter_3_to_4.cpp index 9e3062d3bc..cdd088f0b1 100644 --- a/editor/project_converter_3_to_4.cpp +++ b/editor/project_converter_3_to_4.cpp @@ -76,8 +76,7 @@ static const char *enum_renames[][2] = { { "ARVR_STEREO", "XR_STEREO" }, // XRInterface { "ARVR_UNKNOWN_TRACKING", "XR_UNKNOWN_TRACKING" }, // XRInterface { "BAKE_ERROR_INVALID_MESH", "BAKE_ERROR_MESHES_INVALID" }, // LightmapGI - { "BODY_MODE_CHARACTER", "BODY_MODE_DYNAMIC" }, // PhysicsServer2D - { "BODY_MODE_DYNAMIC_LOCKED", "BODY_MODE_DYNAMIC_LINEAR" }, // PhysicsServer3D + { "BODY_MODE_CHARACTER", "BODY_MODE_RIGID_LINEAR" }, // PhysicsServer { "BUTTON_LEFT", "MOUSE_BUTTON_LEFT" }, // Globals { "BUTTON_MASK_LEFT", "MOUSE_BUTTON_MASK_LEFT" }, // Globals { "BUTTON_MASK_MIDDLE", "MOUSE_BUTTON_MASK_MIDDLE" }, // Globals @@ -125,15 +124,13 @@ static const char *enum_renames[][2] = { { "MATH_RAND", "MATH_RANDF_RANGE" }, // VisualScriptBuiltinFunc { "MATH_RANDOM", "MATH_RANDI_RANGE" }, // VisualScriptBuiltinFunc { "MATH_STEPIFY", "MATH_STEP_DECIMALS" }, // VisualScriptBuiltinFunc - { "MODE_CHARACTER", "MODE_DYNAMIC_LOCKED" }, // RigidBody2D, RigidBody3D - { "MODE_KINEMATIC", "FREEZE_MODE_KINEMATIC" }, // RigidDynamicBody + { "MODE_KINEMATIC", "FREEZE_MODE_KINEMATIC" }, // RigidBody { "MODE_OPEN_ANY", "FILE_MODE_OPEN_ANY" }, // FileDialog { "MODE_OPEN_DIR", "FILE_MODE_OPEN_DIR" }, // FileDialog { "MODE_OPEN_FILE", "FILE_MODE_OPEN_FILE" }, // FileDialog { "MODE_OPEN_FILES", "FILE_MODE_OPEN_FILES" }, // FileDialog - { "MODE_RIGID", "MODE_DYNAMIC" }, // RigidBody2D, RigidBody3D { "MODE_SAVE_FILE", "FILE_MODE_SAVE_FILE" }, // FileDialog - { "MODE_STATIC", "FREEZE_MODE_STATIC" }, // RigidDynamicBody + { "MODE_STATIC", "FREEZE_MODE_STATIC" }, // RigidBody { "NOTIFICATION_APP_PAUSED", "NOTIFICATION_APPLICATION_PAUSED" }, // MainLoop { "NOTIFICATION_APP_RESUMED", "NOTIFICATION_APPLICATION_RESUMED" }, // MainLoop { "NOTIFICATION_PATH_CHANGED", "NOTIFICATION_PATH_RENAMED" }, //Node @@ -201,7 +198,7 @@ static const char *gdscript_function_renames[][2] = { // { "set_color", "surface_set_color"}, // ImmediateMesh broke Light2D, Theme, SurfaceTool // { "set_event", "set_shortcut" }, // BaseButton - Cyclic Rename // { "set_extents", "set_size"}, // BoxShape, RectangleShape broke ReflectionProbe - // { "set_flag", "set_particle_flag"}, // ParticlesMaterial broke Window, HingeJoint3D + // { "set_flag", "set_particle_flag"}, // ParticleProcessMaterial broke Window, HingeJoint3D // { "set_h_offset", "set_drag_horizontal_offset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D // { "set_margin", "set_offset" }, // Control broke Shape3D, AtlasTexture // { "set_mode", "set_mode_file_mode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap @@ -209,6 +206,7 @@ static const char *gdscript_function_renames[][2] = { // { "set_offset", "set_progress" }, // PathFollow2D, PathFollow3D - Too common // { "set_process_mode", "set_process_callback" }, // AnimationTree broke Node, Tween, Sky // { "set_refuse_new_network_connections", "set_refuse_new_connections"}, // MultiplayerAPI broke SceneTree + // { "set_tooltip", "set_tooltip_text" }, // Control, breaks TreeItem, at least for now. // { "set_uv", "surface_set_uv" }, // ImmediateMesh broke Polygon2D // { "set_v_offset", "set_drag_vertical_offset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D // {"get_points","get_points_id"},// Astar, broke Line2D, Convexpolygonshape @@ -221,16 +219,16 @@ static const char *gdscript_function_renames[][2] = { { "_update_wrap_at", "_update_wrap_at_column" }, // TextEdit { "add_animation", "add_animation_library" }, // AnimationPlayer { "add_cancel", "add_cancel_button" }, // AcceptDialog - { "add_central_force", "apply_central_force" }, //RigidDynamicBody2D + { "add_central_force", "apply_central_force" }, //RigidBody2D { "add_child_below_node", "add_sibling" }, // Node { "add_color_override", "add_theme_color_override" }, // Control { "add_constant_override", "add_theme_constant_override" }, // Control { "add_font_override", "add_theme_font_override" }, // Control - { "add_force", "apply_force" }, //RigidDynamicBody2D + { "add_force", "apply_force" }, //RigidBody2D { "add_icon_override", "add_theme_icon_override" }, // Control { "add_scene_import_plugin", "add_scene_format_importer_plugin" }, //EditorPlugin { "add_stylebox_override", "add_theme_stylebox_override" }, // Control - { "add_torque", "apply_torque" }, //RigidDynamicBody2D + { "add_torque", "apply_torque" }, //RigidBody2D { "apply_changes", "_apply_changes" }, // EditorPlugin { "bind_child_node_to_bone", "set_bone_children" }, // Skeleton3D { "body_add_force", "body_apply_force" }, // PhysicsServer2D @@ -276,8 +274,8 @@ static const char *gdscript_function_renames[][2] = { { "get_action_list", "action_get_events" }, // InputMap { "get_alt", "is_alt_pressed" }, // InputEventWithModifiers { "get_animation_process_mode", "get_process_callback" }, // AnimationPlayer - { "get_applied_force", "get_constant_force" }, //RigidDynamicBody2D - { "get_applied_torque", "get_constant_torque" }, //RigidDynamicBody2D + { "get_applied_force", "get_constant_force" }, //RigidBody2D + { "get_applied_torque", "get_constant_torque" }, //RigidBody2D { "get_audio_bus", "get_audio_bus_name" }, // Area3D { "get_bound_child_nodes_to_bone", "get_bone_children" }, // Skeleton3D { "get_camera", "get_camera_3d" }, // Viewport -> this is also convertable to get_camera_2d, broke GLTFNode @@ -569,9 +567,23 @@ static const char *gdscript_function_renames[][2] = { { "to_utf8", "to_utf8_buffer" }, // String { "to_wchar", "to_utf32_buffer" }, // String // TODO - utf32 or utf16? - // Globals + // @GlobalScope + { "bytes2var", "bytes_to_var" }, + { "bytes2var_with_objects", "bytes_to_var_with_objects" }, + { "db2linear", "db_to_linear" }, + { "deg2rad", "deg_to_rad" }, + { "linear2db", "linear_to_db" }, + { "rad2deg", "rad_to_deg" }, { "rand_range", "randf_range" }, { "stepify", "snapped" }, + { "str2var", "str_to_var" }, + { "var2str", "var_to_str" }, + { "var2bytes", "var_to_bytes" }, + { "var2bytes_with_objects", "var_to_bytes_with_objects" }, + + // @GDScript + { "dict2inst", "dict_to_inst" }, + { "inst2dict", "inst_to_dict" }, { nullptr, nullptr }, }; @@ -610,7 +622,7 @@ static const char *csharp_function_renames[][2] = { // { "SetColor", "SurfaceSetColor"}, // ImmediateMesh broke Light2D, Theme, SurfaceTool // { "SetEvent", "SetShortcut" }, // BaseButton - Cyclic Rename // { "SetExtents", "SetSize"}, // BoxShape, RectangleShape broke ReflectionProbe - // { "SetFlag", "SetParticleFlag"}, // ParticlesMaterial broke Window, HingeJoint3D + // { "SetFlag", "SetParticleFlag"}, // ParticleProcessMaterial broke Window, HingeJoint3D // { "SetHOffset", "SetDragHorizontalOffset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D // { "SetMargin", "SetOffset" }, // Control broke Shape3D, AtlasTexture // { "SetMode", "SetModeFileMode" }, // FileDialog broke Panel, Shader, CSGPolygon, Tilemap @@ -618,6 +630,7 @@ static const char *csharp_function_renames[][2] = { // { "SetOffset", "SetProgress" }, // PathFollow2D, PathFollow3D - Too common // { "SetProcessMode", "SetProcessCallback" }, // AnimationTree broke Node, Tween, Sky // { "SetRefuseNewNetworkConnections", "SetRefuseNewConnections"}, // MultiplayerAPI broke SceneTree + // { "SetTooltip", "SetTooltipText" }, // Control, breaks TreeItem, at least for now. // { "SetUv", "SurfaceSetUv" }, // ImmediateMesh broke Polygon2D // { "SetVOffset", "SetDragVerticalOffset" }, // Camera2D broke Camera3D, PathFollow3D, PathFollow2D // {"GetPoints","GetPointsId"},// Astar, broke Line2D, Convexpolygonshape @@ -631,16 +644,16 @@ static const char *csharp_function_renames[][2] = { { "_UpdateWrapAt", "_UpdateWrapAtColumn" }, // TextEdit { "AddAnimation", "AddAnimationLibrary" }, // AnimationPlayer { "AddCancel", "AddCancelButton" }, // AcceptDialog - { "AddCentralForce", "AddConstantCentralForce" }, //RigidDynamicBody2D + { "AddCentralForce", "AddConstantCentralForce" }, //RigidBody2D { "AddChildBelowNode", "AddSibling" }, // Node { "AddColorOverride", "AddThemeColorOverride" }, // Control { "AddConstantOverride", "AddThemeConstantOverride" }, // Control { "AddFontOverride", "AddThemeFontOverride" }, // Control - { "AddForce", "AddConstantForce" }, //RigidDynamicBody2D + { "AddForce", "AddConstantForce" }, //RigidBody2D { "AddIconOverride", "AddThemeIconOverride" }, // Control { "AddSceneImportPlugin", "AddSceneFormatImporterPlugin" }, //EditorPlugin { "AddStyleboxOverride", "AddThemeStyleboxOverride" }, // Control - { "AddTorque", "AddConstantTorque" }, //RigidDynamicBody2D + { "AddTorque", "AddConstantTorque" }, //RigidBody2D { "BindChildNodeToBone", "SetBoneChildren" }, // Skeleton3D { "BumpmapToNormalmap", "BumpMapToNormalMap" }, // Image { "CanBeHidden", "_CanBeHidden" }, // EditorNode3DGizmoPlugin @@ -679,8 +692,8 @@ static const char *csharp_function_renames[][2] = { { "GetActionList", "ActionGetEvents" }, // InputMap { "GetAlt", "IsAltPressed" }, // InputEventWithModifiers { "GetAnimationProcessMode", "GetProcessCallback" }, // AnimationPlayer - { "GetAppliedForce", "GetConstantForce" }, //RigidDynamicBody2D - { "GetAppliedTorque", "GetConstantTorque" }, //RigidDynamicBody2D + { "GetAppliedForce", "GetConstantForce" }, //RigidBody2D + { "GetAppliedTorque", "GetConstantTorque" }, //RigidBody2D { "GetAudioBus", "GetAudioBusName" }, // Area3D { "GetBoundChildNodesToBone", "GetBoneChildren" }, // Skeleton3D { "GetCamera", "GetCamera3d" }, // Viewport -> this is also convertable to getCamera2d, broke GLTFNode @@ -958,9 +971,23 @@ static const char *csharp_function_renames[][2] = { { "ToUtf8", "ToUtf8Buffer" }, // String { "ToWchar", "ToUtf32Buffer" }, // String // TODO - utf32 or utf16? - // Globals + // @GlobalScope + { "Bytes2Var", "BytesToVar" }, + { "Bytes2VarWithObjects", "BytesToVarWithObjects" }, + { "Db2Linear", "DbToLinear" }, + { "Deg2Rad", "DegToRad" }, + { "Linear2Db", "LinearToDb" }, + { "Rad2Deg", "RadToDeg" }, { "RandRange", "RandfRange" }, { "Stepify", "Snapped" }, + { "Str2Var", "StrToVar" }, + { "Var2Str", "VarToStr" }, + { "Var2Bytes", "VarToBytes" }, + { "Var2BytesWithObjects", "VarToBytesWithObjects" }, + + // @GDScript + { "Dict2Inst", "DictToInst" }, + { "Inst2Dict", "InstToDict" }, { nullptr, nullptr }, }; @@ -997,7 +1024,7 @@ static const char *gdscript_properties_renames[][2] = { { "close_h_ofs", "close_h_offset" }, // Theme { "close_v_ofs", "close_v_offset" }, // Theme { "commentfocus", "comment_focus" }, // Theme - { "contacts_reported", "max_contacts_reported" }, // RigidDynamicBody + { "contacts_reported", "max_contacts_reported" }, // RigidBody { "drag_margin_bottom", "drag_bottom_margin" }, // Camera2D { "drag_margin_h_enabled", "drag_horizontal_enabled" }, // Camera2D { "drag_margin_left", "drag_left_margin" }, // Camera2D @@ -1014,6 +1041,7 @@ static const char *gdscript_properties_renames[][2] = { { "global_rate_scale", "playback_speed_scale" }, // AudioServer { "gravity_distance_scale", "gravity_point_distance_scale" }, // Area2D { "gravity_vec", "gravity_direction" }, // Area2D + { "hint_tooltip", "tooltip_text" }, // Control { "hseparation", "h_separation" }, // Theme { "iterations_per_second", "physics_ticks_per_second" }, // Engine { "invert_enable", "invert_enabled" }, // Polygon2D @@ -1098,6 +1126,7 @@ static const char *csharp_properties_renames[][2] = { { "GlobalRateScale", "PlaybackSpeedScale" }, // AudioServer { "GravityDistanceScale", "GravityPointDistanceScale" }, // Area2D { "GravityVec", "GravityDirection" }, // Area2D + { "HintTooltip", "TooltipText" }, // Control { "Hseparation", "HSeparation" }, // Theme { "IterationsPerSecond", "PhysicsTicksPerSecond" }, // Engine { "InvertEnable", "InvertEnabled" }, // Polygon2D @@ -1357,6 +1386,7 @@ static const char *class_renames[][2] = { { "PanoramaSky", "Sky" }, { "Particles", "GPUParticles3D" }, // Be careful, this will be used everywhere { "Particles2D", "GPUParticles2D" }, + { "ParticlesMaterial", "ParticleProcessMaterial" }, { "Path", "Path3D" }, // Be careful, this will be used everywhere { "PathFollow", "PathFollow3D" }, { "PhysicalBone", "PhysicalBone3D" }, @@ -1384,15 +1414,14 @@ static const char *class_renames[][2] = { { "Reference", "RefCounted" }, // Be careful, this will be used everywhere { "RemoteTransform", "RemoteTransform3D" }, { "ResourceInteractiveLoader", "ResourceLoader" }, - { "RigidBody", "RigidDynamicBody3D" }, - { "RigidBody2D", "RigidDynamicBody2D" }, + { "RigidBody", "RigidBody3D" }, { "SceneTreeTween", "Tween" }, { "Shape", "Shape3D" }, // Be careful, this will be used everywhere { "ShortCut", "Shortcut" }, { "Skeleton", "Skeleton3D" }, { "SkeletonIK", "SkeletonIK3D" }, { "SliderJoint", "SliderJoint3D" }, - { "SoftBody", "SoftDynamicBody3D" }, + { "SoftBody", "SoftBody3D" }, { "Spatial", "Node3D" }, { "SpatialGizmo", "Node3DGizmo" }, { "SpatialMaterial", "StandardMaterial3D" }, diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp index cce71d9508..a17a759c17 100644 --- a/editor/project_manager.cpp +++ b/editor/project_manager.cpp @@ -1362,7 +1362,7 @@ void ProjectList::create_project_item_control(int p_index) { hb->connect("draw", callable_mp(this, &ProjectList::_panel_draw).bind(hb)); hb->connect("gui_input", callable_mp(this, &ProjectList::_panel_input).bind(hb)); hb->add_theme_constant_override("separation", 10 * EDSCALE); - hb->set_tooltip(item.description); + hb->set_tooltip_text(item.description); VBoxContainer *favorite_box = memnew(VBoxContainer); favorite_box->set_name("FavoriteBox"); @@ -1445,9 +1445,9 @@ void ProjectList::create_project_item_control(int p_index) { if (!item.missing) { show->connect("pressed", callable_mp(this, &ProjectList::_show_project).bind(item.path)); - show->set_tooltip(TTR("Show in File Manager")); + show->set_tooltip_text(TTR("Show in File Manager")); } else { - show->set_tooltip(TTR("Error: Project is missing on the filesystem.")); + show->set_tooltip_text(TTR("Error: Project is missing on the filesystem.")); } Label *fpath = memnew(Label(item.path)); @@ -2570,7 +2570,7 @@ ProjectManager::ProjectManager() { search_box = memnew(LineEdit); search_box->set_placeholder(TTR("Filter Projects")); - search_box->set_tooltip(TTR("This field filters projects by name and last path component.\nTo filter projects by name and full path, the query must contain at least one `/` character.")); + search_box->set_tooltip_text(TTR("This field filters projects by name and last path component.\nTo filter projects by name and full path, the query must contain at least one `/` character.")); search_box->connect("text_changed", callable_mp(this, &ProjectManager::_on_search_term_changed)); search_box->set_h_size_flags(Control::SIZE_EXPAND_FILL); hb->add_child(search_box); @@ -2710,7 +2710,7 @@ ProjectManager::ProjectManager() { // Fade the version label to be less prominent, but still readable. version_btn->set_self_modulate(Color(1, 1, 1, 0.6)); version_btn->set_underline_mode(LinkButton::UNDERLINE_MODE_ON_HOVER); - version_btn->set_tooltip(TTR("Click to copy.")); + version_btn->set_tooltip_text(TTR("Click to copy.")); version_btn->connect("pressed", callable_mp(this, &ProjectManager::_version_button_pressed)); spacer_vb->add_child(version_btn); diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp index 581315d512..279ed55a38 100644 --- a/editor/project_settings_editor.cpp +++ b/editor/project_settings_editor.cpp @@ -518,24 +518,6 @@ void ProjectSettingsEditor::_update_action_map_editor() { action_map_editor->update_action_list(actions); } -void ProjectSettingsEditor::_update_theme() { - search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - restart_close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); - restart_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); - restart_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); - restart_label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); - - type_box->clear(); - for (int i = 0; i < Variant::VARIANT_MAX; i++) { - if (i == Variant::NIL || i == Variant::OBJECT || i == Variant::CALLABLE || i == Variant::SIGNAL || i == Variant::RID) { - // These types can't be serialized properly, so skip them. - continue; - } - String type = Variant::get_type_name(Variant::Type(i)); - type_box->add_icon_item(get_theme_icon(type, SNAME("EditorIcons")), type, i); - } -} - void ProjectSettingsEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { @@ -547,11 +529,24 @@ void ProjectSettingsEditor::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { general_settings_inspector->edit(ps); _update_action_map_editor(); - _update_theme(); } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + restart_close_button->set_icon(get_theme_icon(SNAME("Close"), SNAME("EditorIcons"))); + restart_container->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + restart_icon->set_texture(get_theme_icon(SNAME("StatusWarning"), SNAME("EditorIcons"))); + restart_label->add_theme_color_override("font_color", get_theme_color(SNAME("warning_color"), SNAME("Editor"))); + + type_box->clear(); + for (int i = 0; i < Variant::VARIANT_MAX; i++) { + if (i == Variant::NIL || i == Variant::OBJECT || i == Variant::CALLABLE || i == Variant::SIGNAL || i == Variant::RID) { + // These types can't be serialized properly, so skip them. + continue; + } + String type = Variant::get_type_name(Variant::Type(i)); + type_box->add_icon_item(get_theme_icon(type, SNAME("EditorIcons")), type, i); + } } break; } } diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h index 040d992e40..f01f5c1836 100644 --- a/editor/project_settings_editor.h +++ b/editor/project_settings_editor.h @@ -106,7 +106,6 @@ class ProjectSettingsEditor : public AcceptDialog { void _action_renamed(const String &p_old_name, const String &p_new_name); void _action_reordered(const String &p_action_name, const String &p_relative_to, bool p_before); void _update_action_map_editor(); - void _update_theme(); protected: void _notification(int p_what); diff --git a/editor/rename_dialog.cpp b/editor/rename_dialog.cpp index 84923a94a2..7b4df696b7 100644 --- a/editor/rename_dialog.cpp +++ b/editor/rename_dialog.cpp @@ -139,7 +139,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR but_insert_name = memnew(Button); but_insert_name->set_text("NAME"); - but_insert_name->set_tooltip(String("${NAME}\n") + TTR("Node name.")); + but_insert_name->set_tooltip_text(String("${NAME}\n") + TTR("Node name.")); but_insert_name->set_focus_mode(Control::FOCUS_NONE); but_insert_name->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${NAME}")); but_insert_name->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -149,7 +149,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR but_insert_parent = memnew(Button); but_insert_parent->set_text("PARENT"); - but_insert_parent->set_tooltip(String("${PARENT}\n") + TTR("Node's parent name, if available.")); + but_insert_parent->set_tooltip_text(String("${PARENT}\n") + TTR("Node's parent name, if available.")); but_insert_parent->set_focus_mode(Control::FOCUS_NONE); but_insert_parent->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${PARENT}")); but_insert_parent->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -159,7 +159,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR but_insert_type = memnew(Button); but_insert_type->set_text("TYPE"); - but_insert_type->set_tooltip(String("${TYPE}\n") + TTR("Node type.")); + but_insert_type->set_tooltip_text(String("${TYPE}\n") + TTR("Node type.")); but_insert_type->set_focus_mode(Control::FOCUS_NONE); but_insert_type->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${TYPE}")); but_insert_type->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -169,7 +169,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR but_insert_scene = memnew(Button); but_insert_scene->set_text("SCENE"); - but_insert_scene->set_tooltip(String("${SCENE}\n") + TTR("Current scene name.")); + but_insert_scene->set_tooltip_text(String("${SCENE}\n") + TTR("Current scene name.")); but_insert_scene->set_focus_mode(Control::FOCUS_NONE); but_insert_scene->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${SCENE}")); but_insert_scene->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -179,7 +179,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR but_insert_root = memnew(Button); but_insert_root->set_text("ROOT"); - but_insert_root->set_tooltip(String("${ROOT}\n") + TTR("Root node name.")); + but_insert_root->set_tooltip_text(String("${ROOT}\n") + TTR("Root node name.")); but_insert_root->set_focus_mode(Control::FOCUS_NONE); but_insert_root->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${ROOT}")); but_insert_root->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -189,7 +189,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR but_insert_count = memnew(Button); but_insert_count->set_text("COUNTER"); - but_insert_count->set_tooltip(String("${COUNTER}\n") + TTR("Sequential integer counter.\nCompare counter options.")); + but_insert_count->set_tooltip_text(String("${COUNTER}\n") + TTR("Sequential integer counter.\nCompare counter options.")); but_insert_count->set_focus_mode(Control::FOCUS_NONE); but_insert_count->connect("pressed", callable_mp(this, &RenameDialog::_insert_text).bind("${COUNTER}")); but_insert_count->set_h_size_flags(Control::SIZE_EXPAND_FILL); @@ -197,7 +197,7 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR chk_per_level_counter = memnew(CheckBox); chk_per_level_counter->set_text(TTR("Per-level Counter")); - chk_per_level_counter->set_tooltip(TTR("If set, the counter restarts for each group of child nodes.")); + chk_per_level_counter->set_tooltip_text(TTR("If set, the counter restarts for each group of child nodes.")); vbc_substitute->add_child(chk_per_level_counter); HBoxContainer *hbc_count_options = memnew(HBoxContainer); @@ -205,32 +205,32 @@ RenameDialog::RenameDialog(SceneTreeEditor *p_scene_tree_editor, Ref<EditorUndoR Label *lbl_count_start = memnew(Label); lbl_count_start->set_text(TTR("Start")); - lbl_count_start->set_tooltip(TTR("Initial value for the counter.")); + lbl_count_start->set_tooltip_text(TTR("Initial value for the counter.")); hbc_count_options->add_child(lbl_count_start); spn_count_start = memnew(SpinBox); - spn_count_start->set_tooltip(TTR("Initial value for the counter.")); + spn_count_start->set_tooltip_text(TTR("Initial value for the counter.")); spn_count_start->set_step(1); spn_count_start->set_min(0); hbc_count_options->add_child(spn_count_start); Label *lbl_count_step = memnew(Label); lbl_count_step->set_text(TTR("Step")); - lbl_count_step->set_tooltip(TTR("Amount by which counter is incremented for each node.")); + lbl_count_step->set_tooltip_text(TTR("Amount by which counter is incremented for each node.")); hbc_count_options->add_child(lbl_count_step); spn_count_step = memnew(SpinBox); - spn_count_step->set_tooltip(TTR("Amount by which counter is incremented for each node.")); + spn_count_step->set_tooltip_text(TTR("Amount by which counter is incremented for each node.")); spn_count_step->set_step(1); hbc_count_options->add_child(spn_count_step); Label *lbl_count_padding = memnew(Label); lbl_count_padding->set_text(TTR("Padding")); - lbl_count_padding->set_tooltip(TTR("Minimum number of digits for the counter.\nMissing digits are padded with leading zeros.")); + lbl_count_padding->set_tooltip_text(TTR("Minimum number of digits for the counter.\nMissing digits are padded with leading zeros.")); hbc_count_options->add_child(lbl_count_padding); spn_count_padding = memnew(SpinBox); - spn_count_padding->set_tooltip(TTR("Minimum number of digits for the counter.\nMissing digits are padded with leading zeros.")); + spn_count_padding->set_tooltip_text(TTR("Minimum number of digits for the counter.\nMissing digits are padded with leading zeros.")); spn_count_padding->set_step(1); hbc_count_options->add_child(spn_count_padding); diff --git a/editor/scene_create_dialog.cpp b/editor/scene_create_dialog.cpp index 94a5c07709..30a41eea7a 100644 --- a/editor/scene_create_dialog.cpp +++ b/editor/scene_create_dialog.cpp @@ -46,7 +46,6 @@ void SceneCreateDialog::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { select_node_button->set_icon(get_theme_icon(SNAME("ClassList"), SNAME("EditorIcons"))); node_type_2d->set_icon(get_theme_icon(SNAME("Node2D"), SNAME("EditorIcons"))); diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 9f80119c35..c7c713fc67 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -1230,7 +1230,7 @@ void SceneTreeDock::_notification(int p_what) { node_shortcuts_toggle->set_name("NodeShortcutsToggle"); node_shortcuts_toggle->set_icon(get_theme_icon(SNAME("Favorites"), SNAME("EditorIcons"))); node_shortcuts_toggle->set_toggle_mode(true); - node_shortcuts_toggle->set_tooltip(TTR("Switch to Favorite Nodes")); + node_shortcuts_toggle->set_tooltip_text(TTR("Switch to Favorite Nodes")); node_shortcuts_toggle->set_pressed(EDITOR_GET("_use_favorites_root_selection")); node_shortcuts_toggle->set_anchors_and_offsets_preset(Control::PRESET_CENTER_RIGHT); node_shortcuts_toggle->connect("pressed", callable_mp(this, &SceneTreeDock::_update_create_root_dialog)); @@ -3397,14 +3397,14 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec button_add = memnew(Button); button_add->set_flat(true); button_add->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_NEW, false)); - button_add->set_tooltip(TTR("Add/Create a New Node.")); + button_add->set_tooltip_text(TTR("Add/Create a New Node.")); button_add->set_shortcut(ED_GET_SHORTCUT("scene_tree/add_child_node")); filter_hbc->add_child(button_add); button_instance = memnew(Button); button_instance->set_flat(true); button_instance->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_INSTANTIATE, false)); - button_instance->set_tooltip(TTR("Instantiate a scene file as a Node. Creates an inherited scene if no root node exists.")); + button_instance->set_tooltip_text(TTR("Instantiate a scene file as a Node. Creates an inherited scene if no root node exists.")); button_instance->set_shortcut(ED_GET_SHORTCUT("scene_tree/instance_scene")); filter_hbc->add_child(button_instance); @@ -3419,7 +3419,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec button_create_script = memnew(Button); button_create_script->set_flat(true); button_create_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_ATTACH_SCRIPT, false)); - button_create_script->set_tooltip(TTR("Attach a new or existing script to the selected node.")); + button_create_script->set_tooltip_text(TTR("Attach a new or existing script to the selected node.")); button_create_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/attach_script")); filter_hbc->add_child(button_create_script); button_create_script->hide(); @@ -3427,7 +3427,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec button_detach_script = memnew(Button); button_detach_script->set_flat(true); button_detach_script->connect("pressed", callable_mp(this, &SceneTreeDock::_tool_selected).bind(TOOL_DETACH_SCRIPT, false)); - button_detach_script->set_tooltip(TTR("Detach the script from the selected node.")); + button_detach_script->set_tooltip_text(TTR("Detach the script from the selected node.")); button_detach_script->set_shortcut(ED_GET_SHORTCUT("scene_tree/detach_script")); filter_hbc->add_child(button_detach_script); button_detach_script->hide(); @@ -3450,7 +3450,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec edit_remote->set_h_size_flags(SIZE_EXPAND_FILL); edit_remote->set_text(TTR("Remote")); edit_remote->set_toggle_mode(true); - edit_remote->set_tooltip(TTR("If selected, the Remote scene tree dock will cause the project to stutter every time it updates.\nSwitch back to the Local scene tree dock to improve performance.")); + edit_remote->set_tooltip_text(TTR("If selected, the Remote scene tree dock will cause the project to stutter every time it updates.\nSwitch back to the Local scene tree dock to improve performance.")); edit_remote->connect("pressed", callable_mp(this, &SceneTreeDock::_remote_tree_selected)); edit_local = memnew(Button); diff --git a/editor/scene_tree_editor.cpp b/editor/scene_tree_editor.cpp index 00fd0c3aac..7b0c68fb6b 100644 --- a/editor/scene_tree_editor.cpp +++ b/editor/scene_tree_editor.cpp @@ -1345,10 +1345,6 @@ void SceneTreeDialog::popup_scenetree_dialog() { popup_centered_clamped(Size2(350, 700) * EDSCALE); } -void SceneTreeDialog::_update_theme() { - filter->set_right_icon(tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); -} - void SceneTreeDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { @@ -1359,11 +1355,10 @@ void SceneTreeDialog::_notification(int p_what) { case NOTIFICATION_ENTER_TREE: { connect("confirmed", callable_mp(this, &SceneTreeDialog::_select)); - _update_theme(); } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + filter->set_right_icon(tree->get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); } break; case NOTIFICATION_EXIT_TREE: { diff --git a/editor/scene_tree_editor.h b/editor/scene_tree_editor.h index 0c13ad96cd..f3ca0347ea 100644 --- a/editor/scene_tree_editor.h +++ b/editor/scene_tree_editor.h @@ -179,7 +179,6 @@ class SceneTreeDialog : public ConfirmationDialog { void _cancel(); void _selected_changed(); void _filter_changed(const String &p_filter); - void _update_theme(); protected: void _notification(int p_what); diff --git a/editor/script_create_dialog.cpp b/editor/script_create_dialog.cpp index 15e992ce18..28790f2711 100644 --- a/editor/script_create_dialog.cpp +++ b/editor/script_create_dialog.cpp @@ -120,9 +120,8 @@ void ScriptCreateDialog::_notification(int p_what) { } else { language_menu->select(default_language); } + } break; - [[fallthrough]]; - } case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < ScriptServer::get_language_count(); i++) { Ref<Texture2D> language_icon = get_theme_icon(ScriptServer::get_language(i)->get_type(), SNAME("EditorIcons")); diff --git a/editor/shader_create_dialog.cpp b/editor/shader_create_dialog.cpp index 8c4a231e8a..fc7fff325c 100644 --- a/editor/shader_create_dialog.cpp +++ b/editor/shader_create_dialog.cpp @@ -47,8 +47,6 @@ enum ShaderType { void ShaderCreateDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { - _update_theme(); - String last_lang = EditorSettings::get_singleton()->get_project_metadata("shader_setup", "last_selected_language", ""); if (!last_lang.is_empty()) { for (int i = 0; i < type_menu->get_item_count(); i++) { @@ -67,29 +65,25 @@ void ShaderCreateDialog::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); - } break; - } -} + Ref<Texture2D> shader_icon = gc->get_theme_icon(SNAME("Shader"), SNAME("EditorIcons")); + if (shader_icon.is_valid()) { + type_menu->set_item_icon(0, shader_icon); + } -void ShaderCreateDialog::_update_theme() { - Ref<Texture2D> shader_icon = gc->get_theme_icon(SNAME("Shader"), SNAME("EditorIcons")); - if (shader_icon.is_valid()) { - type_menu->set_item_icon(0, shader_icon); - } + Ref<Texture2D> visual_shader_icon = gc->get_theme_icon(SNAME("VisualShader"), SNAME("EditorIcons")); + if (visual_shader_icon.is_valid()) { + type_menu->set_item_icon(1, visual_shader_icon); + } - Ref<Texture2D> visual_shader_icon = gc->get_theme_icon(SNAME("VisualShader"), SNAME("EditorIcons")); - if (visual_shader_icon.is_valid()) { - type_menu->set_item_icon(1, visual_shader_icon); - } + Ref<Texture2D> include_icon = gc->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")); + if (include_icon.is_valid()) { + type_menu->set_item_icon(2, include_icon); + } - Ref<Texture2D> include_icon = gc->get_theme_icon(SNAME("TextFile"), SNAME("EditorIcons")); - if (include_icon.is_valid()) { - type_menu->set_item_icon(2, include_icon); + path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); + status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); + } break; } - - path_button->set_icon(get_theme_icon(SNAME("Folder"), SNAME("EditorIcons"))); - status_panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } void ShaderCreateDialog::_update_language_info() { diff --git a/editor/shader_create_dialog.h b/editor/shader_create_dialog.h index 9ba655369b..9496d0ce9e 100644 --- a/editor/shader_create_dialog.h +++ b/editor/shader_create_dialog.h @@ -98,7 +98,6 @@ class ShaderCreateDialog : public ConfirmationDialog { void _update_dialog(); protected: - void _update_theme(); void _notification(int p_what); static void _bind_methods(); diff --git a/methods.py b/methods.py index 9b60d4251f..3a00aa12ca 100644 --- a/methods.py +++ b/methods.py @@ -705,7 +705,7 @@ def generate_vs_project(env, num_jobs): # required for Visual Studio to understand that it needs to generate an NMAKE # project. Do not modify without knowing what you are doing. PLATFORMS = ["Win32", "x64"] - PLATFORM_IDS = ["32", "64"] + PLATFORM_IDS = ["x86_32", "x86_64"] CONFIGURATIONS = ["debug", "release", "release_debug"] CONFIGURATION_IDS = ["tools", "opt", "opt.tools"] diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index 243c23342e..6294790132 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -1838,7 +1838,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { u_step *= curve_length / path_u_distance; } double v_step = 1.0 / shape_sides; - double spin_step = Math::deg2rad(spin_degrees / spin_sides); + double spin_step = Math::deg_to_rad(spin_degrees / spin_sides); double extrusion_step = 1.0 / extrusions; if (mode == MODE_PATH) { if (path_joined) { @@ -1902,7 +1902,7 @@ CSGBrush *CSGPolygon3D::_build_brush() { } } - real_t angle_simplify_dot = Math::cos(Math::deg2rad(path_simplify_angle)); + real_t angle_simplify_dot = Math::cos(Math::deg_to_rad(path_simplify_angle)); Vector3 previous_simplify_dir = Vector3(0, 0, 0); int faces_combined = 0; diff --git a/modules/enet/doc_classes/ENetPacketPeer.xml b/modules/enet/doc_classes/ENetPacketPeer.xml index 46008317a2..67760ba5e8 100644 --- a/modules/enet/doc_classes/ENetPacketPeer.xml +++ b/modules/enet/doc_classes/ENetPacketPeer.xml @@ -18,6 +18,18 @@ Returns the number of channels allocated for communication with peer. </description> </method> + <method name="get_remote_address" qualifiers="const"> + <return type="String" /> + <description> + Returns the IP address of this peer. + </description> + </method> + <method name="get_remote_port" qualifiers="const"> + <return type="int" /> + <description> + Returns the remote port of this peer. + </description> + </method> <method name="get_state" qualifiers="const"> <return type="int" enum="ENetPacketPeer.PeerState" /> <description> diff --git a/modules/enet/enet_packet_peer.cpp b/modules/enet/enet_packet_peer.cpp index 62c0550edb..5a96f75c4f 100644 --- a/modules/enet/enet_packet_peer.cpp +++ b/modules/enet/enet_packet_peer.cpp @@ -206,6 +206,8 @@ void ENetPacketPeer::_bind_methods() { ClassDB::bind_method(D_METHOD("send", "channel", "packet", "flags"), &ENetPacketPeer::_send); ClassDB::bind_method(D_METHOD("throttle_configure", "interval", "acceleration", "deceleration"), &ENetPacketPeer::throttle_configure); ClassDB::bind_method(D_METHOD("set_timeout", "timeout", "timeout_min", "timeout_max"), &ENetPacketPeer::set_timeout); + ClassDB::bind_method(D_METHOD("get_remote_address"), &ENetPacketPeer::get_remote_address); + ClassDB::bind_method(D_METHOD("get_remote_port"), &ENetPacketPeer::get_remote_port); ClassDB::bind_method(D_METHOD("get_statistic", "statistic"), &ENetPacketPeer::get_statistic); ClassDB::bind_method(D_METHOD("get_state"), &ENetPacketPeer::get_state); ClassDB::bind_method(D_METHOD("get_channels"), &ENetPacketPeer::get_channels); diff --git a/modules/gdscript/doc_classes/@GDScript.xml b/modules/gdscript/doc_classes/@GDScript.xml index a44be04b2d..c2301c3e27 100644 --- a/modules/gdscript/doc_classes/@GDScript.xml +++ b/modules/gdscript/doc_classes/@GDScript.xml @@ -74,11 +74,11 @@ [/codeblock] </description> </method> - <method name="dict2inst"> + <method name="dict_to_inst"> <return type="Object" /> <param index="0" name="dictionary" type="Dictionary" /> <description> - Converts a dictionary (previously created with [method inst2dict]) back to an instance. Useful for deserializing. + Converts a [param dictionary] (previously created with [method inst_to_dict]) back to an Object instance. Useful for deserializing. </description> </method> <method name="get_stack"> @@ -102,15 +102,15 @@ [b]Note:[/b] Not supported for calling from threads. Instead, this will return an empty array. </description> </method> - <method name="inst2dict"> + <method name="inst_to_dict"> <return type="Dictionary" /> <param index="0" name="instance" type="Object" /> <description> - Returns the passed instance converted to a dictionary (useful for serializing). + Returns the passed [param instance] converted to a Dictionary (useful for serializing). [codeblock] var foo = "bar" func _ready(): - var d = inst2dict(self) + var d = inst_to_dict(self) print(d.keys()) print(d.values()) [/codeblock] diff --git a/modules/gdscript/editor/gdscript_highlighter.cpp b/modules/gdscript/editor/gdscript_highlighter.cpp index b9560ea69b..61df8cdf06 100644 --- a/modules/gdscript/editor/gdscript_highlighter.cpp +++ b/modules/gdscript/editor/gdscript_highlighter.cpp @@ -293,7 +293,12 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l String word = str.substr(j, to - j); Color col = Color(); - if (keywords.has(word)) { + if (global_functions.has(word)) { + // "assert" and "preload" are reserved, so highlight even if not followed by a bracket. + if (word == "assert" || word == "preload" || str[to] == '(') { + col = global_function_color; + } + } else if (keywords.has(word)) { col = keywords[word]; } else if (member_keywords.has(word)) { col = member_keywords[word]; @@ -302,12 +307,13 @@ Dictionary GDScriptSyntaxHighlighter::_get_line_syntax_highlighting_impl(int p_l if (col != Color()) { for (int k = j - 1; k >= 0; k--) { if (str[k] == '.') { - col = Color(); // keyword & member indexing not allowed + col = Color(); // keyword, member & global func indexing not allowed break; } else if (str[k] > 32) { break; } } + if (col != Color()) { in_keyword = true; keyword_color = col; @@ -535,6 +541,7 @@ PackedStringArray GDScriptSyntaxHighlighter::_get_supported_languages() const { void GDScriptSyntaxHighlighter::_update_cache() { keywords.clear(); member_keywords.clear(); + global_functions.clear(); color_regions.clear(); color_region_cache.clear(); @@ -591,6 +598,17 @@ void GDScriptSyntaxHighlighter::_update_cache() { } } + /* Global functions. */ + List<StringName> global_function_list; + GDScriptUtilityFunctions::get_function_list(&global_function_list); + Variant::get_utility_function_list(&global_function_list); + // "assert" and "preload" are not utility functions, but are global nonetheless, so insert them. + global_functions.insert(SNAME("assert")); + global_functions.insert(SNAME("preload")); + for (const StringName &E : global_function_list) { + global_functions.insert(E); + } + /* Comments */ const Color comment_color = EDITOR_GET("text_editor/theme/highlighting/comment_color"); List<String> comments; @@ -643,12 +661,14 @@ void GDScriptSyntaxHighlighter::_update_cache() { if (godot_2_theme || EditorSettings::get_singleton()->is_dark_theme()) { function_definition_color = Color(0.4, 0.9, 1.0); + global_function_color = Color(0.6, 0.6, 0.9); node_path_color = Color(0.72, 0.77, 0.49); node_ref_color = Color(0.39, 0.76, 0.35); annotation_color = Color(1.0, 0.7, 0.45); string_name_color = Color(1.0, 0.76, 0.65); } else { function_definition_color = Color(0, 0.6, 0.6); + global_function_color = Color(0.4, 0.2, 0.8); node_path_color = Color(0.18, 0.55, 0); node_ref_color = Color(0.0, 0.5, 0); annotation_color = Color(0.8, 0.37, 0); @@ -656,6 +676,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { } EDITOR_DEF("text_editor/theme/highlighting/gdscript/function_definition_color", function_definition_color); + EDITOR_DEF("text_editor/theme/highlighting/gdscript/global_function_color", global_function_color); EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_path_color", node_path_color); EDITOR_DEF("text_editor/theme/highlighting/gdscript/node_reference_color", node_ref_color); EDITOR_DEF("text_editor/theme/highlighting/gdscript/annotation_color", annotation_color); @@ -666,6 +687,10 @@ void GDScriptSyntaxHighlighter::_update_cache() { function_definition_color, true); EditorSettings::get_singleton()->set_initial_value( + "text_editor/theme/highlighting/gdscript/global_function_color", + global_function_color, + true); + EditorSettings::get_singleton()->set_initial_value( "text_editor/theme/highlighting/gdscript/node_path_color", node_path_color, true); @@ -684,6 +709,7 @@ void GDScriptSyntaxHighlighter::_update_cache() { } function_definition_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/function_definition_color"); + global_function_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/global_function_color"); node_path_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_path_color"); node_ref_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/node_reference_color"); annotation_color = EDITOR_GET("text_editor/theme/highlighting/gdscript/annotation_color"); diff --git a/modules/gdscript/editor/gdscript_highlighter.h b/modules/gdscript/editor/gdscript_highlighter.h index f434d03a31..60b5b092d4 100644 --- a/modules/gdscript/editor/gdscript_highlighter.h +++ b/modules/gdscript/editor/gdscript_highlighter.h @@ -49,6 +49,7 @@ private: HashMap<StringName, Color> keywords; HashMap<StringName, Color> member_keywords; + HashSet<StringName> global_functions; enum Type { NONE, @@ -67,10 +68,11 @@ private: TYPE, }; - // colours + // Colors. Color font_color; Color symbol_color; Color function_color; + Color global_function_color; Color function_definition_color; Color built_in_type_color; Color number_color; diff --git a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp index 9b540b16f2..518d4bcb62 100644 --- a/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp +++ b/modules/gdscript/editor/gdscript_translation_parser_plugin.cpp @@ -41,7 +41,7 @@ Error GDScriptEditorTranslationParserPlugin::parse_file(const String &p_path, Ve // Extract all translatable strings using the parsed tree from GDSriptParser. // The strategy is to find all ExpressionNode and AssignmentNode from the tree and extract strings if relevant, i.e // Search strings in ExpressionNode -> CallNode -> tr(), set_text(), set_placeholder() etc. - // Search strings in AssignmentNode -> text = "__", hint_tooltip = "__" etc. + // Search strings in AssignmentNode -> text = "__", tooltip_text = "__" etc. Error err; Ref<Resource> loaded_res = ResourceLoader::load(p_path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &err); @@ -221,7 +221,7 @@ void GDScriptEditorTranslationParserPlugin::_assess_assignment(GDScriptParser::A } if (assignment_patterns.has(assignee_name) && p_assignment->assigned_value->type == GDScriptParser::Node::LITERAL) { - // If the assignment is towards one of the extract patterns (text, hint_tooltip etc.), and the value is a string literal, we collect the string. + // If the assignment is towards one of the extract patterns (text, tooltip_text etc.), and the value is a string literal, we collect the string. ids->push_back(static_cast<GDScriptParser::LiteralNode *>(p_assignment->assigned_value)->value); } else if (assignee_name == fd_filters && p_assignment->assigned_value->type == GDScriptParser::Node::CALL) { // FileDialog.filters accepts assignment in the form of PackedStringArray. For example, @@ -330,10 +330,10 @@ void GDScriptEditorTranslationParserPlugin::_extract_fd_literals(GDScriptParser: GDScriptEditorTranslationParserPlugin::GDScriptEditorTranslationParserPlugin() { assignment_patterns.insert("text"); assignment_patterns.insert("placeholder_text"); - assignment_patterns.insert("hint_tooltip"); + assignment_patterns.insert("tooltip_text"); first_arg_patterns.insert("set_text"); - first_arg_patterns.insert("set_tooltip"); + first_arg_patterns.insert("set_tooltip_text"); first_arg_patterns.insert("set_placeholder"); first_arg_patterns.insert("add_tab"); first_arg_patterns.insert("add_check_item"); diff --git a/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd b/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd index a379d915a9..b8fc8c75dc 100644 --- a/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd +++ b/modules/gdscript/editor/script_templates/CharacterBody2D/basic_movement.gd @@ -6,7 +6,7 @@ extends _BASE_ const SPEED = 300.0 const JUMP_VELOCITY = -400.0 -# Get the gravity from the project settings to be synced with RigidDynamicBody nodes. +# Get the gravity from the project settings to be synced with RigidBody nodes. var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity") diff --git a/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd b/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd index 360b199e56..53bc606c9a 100644 --- a/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd +++ b/modules/gdscript/editor/script_templates/CharacterBody3D/basic_movement.gd @@ -6,7 +6,7 @@ extends _BASE_ const SPEED = 5.0 const JUMP_VELOCITY = 4.5 -# Get the gravity from the project settings to be synced with RigidDynamicBody nodes. +# Get the gravity from the project settings to be synced with RigidBody nodes. var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity") diff --git a/modules/gdscript/gdscript_utility_functions.cpp b/modules/gdscript/gdscript_utility_functions.cpp index 38893a422d..bcbe8b8d2b 100644 --- a/modules/gdscript/gdscript_utility_functions.cpp +++ b/modules/gdscript/gdscript_utility_functions.cpp @@ -262,7 +262,7 @@ struct GDScriptUtilityFunctionsDefinitions { } } - static inline void inst2dict(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + static inline void inst_to_dict(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() == Variant::NIL) { @@ -329,7 +329,7 @@ struct GDScriptUtilityFunctionsDefinitions { } } - static inline void dict2inst(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { + static inline void dict_to_inst(Variant *r_ret, const Variant **p_args, int p_arg_count, Callable::CallError &r_error) { VALIDATE_ARG_COUNT(1); if (p_args[0]->get_type() != Variant::DICTIONARY) { @@ -653,8 +653,8 @@ void GDScriptUtilityFunctions::register_functions() { REGISTER_VARARG_FUNC(str, true, Variant::STRING); REGISTER_VARARG_FUNC(range, false, Variant::ARRAY); REGISTER_CLASS_FUNC(load, false, "Resource", ARG("path", Variant::STRING)); - REGISTER_FUNC(inst2dict, false, Variant::DICTIONARY, ARG("instance", Variant::OBJECT)); - REGISTER_FUNC(dict2inst, false, Variant::OBJECT, ARG("dictionary", Variant::DICTIONARY)); + REGISTER_FUNC(inst_to_dict, false, Variant::DICTIONARY, ARG("instance", Variant::OBJECT)); + REGISTER_FUNC(dict_to_inst, false, Variant::OBJECT, ARG("dictionary", Variant::DICTIONARY)); REGISTER_FUNC_DEF(Color8, true, 255, Variant::COLOR, ARG("r8", Variant::INT), ARG("g8", Variant::INT), ARG("b8", Variant::INT), ARG("a8", Variant::INT)); REGISTER_VARARG_FUNC(print_debug, false, Variant::NIL); REGISTER_FUNC_NO_ARGS(print_stack, false, Variant::NIL); diff --git a/modules/gltf/editor/editor_scene_importer_blend.cpp b/modules/gltf/editor/editor_scene_importer_blend.cpp index 8002c185c7..707769da35 100644 --- a/modules/gltf/editor/editor_scene_importer_blend.cpp +++ b/modules/gltf/editor/editor_scene_importer_blend.cpp @@ -451,7 +451,7 @@ bool EditorFileSystemImportFormatSupportQueryBlend::query() { configure_blender_dialog->set_ok_button_text(TTR("Confirm Path")); configure_blender_dialog->set_cancel_button_text(TTR("Disable '.blend' Import")); - configure_blender_dialog->get_cancel_button()->set_tooltip(TTR("Disables Blender '.blend' files import for this project. Can be re-enabled in Project Settings.")); + configure_blender_dialog->get_cancel_button()->set_tooltip_text(TTR("Disables Blender '.blend' files import for this project. Can be re-enabled in Project Settings.")); configure_blender_dialog->connect("confirmed", callable_mp(this, &EditorFileSystemImportFormatSupportQueryBlend::_path_confirmed)); browse_dialog = memnew(EditorFileDialog); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index b913a771e1..87ba1d9869 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -5176,7 +5176,7 @@ Node3D *GLTFDocument::_generate_light(Ref<GLTFState> state, const GLTFNodeIndex SpotLight3D *light = memnew(SpotLight3D); light->set_param(SpotLight3D::PARAM_ENERGY, intensity); light->set_param(SpotLight3D::PARAM_RANGE, range); - light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad2deg(l->outer_cone_angle)); + light->set_param(SpotLight3D::PARAM_SPOT_ANGLE, Math::rad_to_deg(l->outer_cone_angle)); light->set_color(l->color); // Line of best fit derived from guessing, see https://www.desmos.com/calculator/biiflubp8b @@ -5200,7 +5200,7 @@ Camera3D *GLTFDocument::_generate_camera(Ref<GLTFState> state, const GLTFNodeInd Ref<GLTFCamera> c = state->cameras[gltf_node->camera]; camera->set_projection(c->get_perspective() ? Camera3D::PROJECTION_PERSPECTIVE : Camera3D::PROJECTION_ORTHOGONAL); // GLTF spec (yfov) is in radians, Godot's camera (fov) is in degrees. - camera->set_fov(Math::rad2deg(c->get_fov())); + camera->set_fov(Math::rad_to_deg(c->get_fov())); // GLTF spec (xmag and ymag) is a radius in meters, Godot's camera (size) is a diameter in meters. camera->set_size(c->get_size_mag() * 2.0f); camera->set_near(c->get_depth_near()); @@ -5215,7 +5215,7 @@ GLTFCameraIndex GLTFDocument::_convert_camera(Ref<GLTFState> state, Camera3D *p_ c.instantiate(); c->set_perspective(p_camera->get_projection() == Camera3D::ProjectionType::PROJECTION_PERSPECTIVE); // GLTF spec (yfov) is in radians, Godot's camera (fov) is in degrees. - c->set_fov(Math::deg2rad(p_camera->get_fov())); + c->set_fov(Math::deg_to_rad(p_camera->get_fov())); // GLTF spec (xmag and ymag) is a radius in meters, Godot's camera (size) is a diameter in meters. c->set_size_mag(p_camera->get_size() * 0.5f); c->set_depth_far(p_camera->get_far()); @@ -5246,7 +5246,7 @@ GLTFLightIndex GLTFDocument::_convert_light(Ref<GLTFState> state, Light3D *p_lig SpotLight3D *light = cast_to<SpotLight3D>(p_light); l->range = light->get_param(SpotLight3D::PARAM_RANGE); l->intensity = light->get_param(SpotLight3D::PARAM_ENERGY); - l->outer_cone_angle = Math::deg2rad(light->get_param(SpotLight3D::PARAM_SPOT_ANGLE)); + l->outer_cone_angle = Math::deg_to_rad(light->get_param(SpotLight3D::PARAM_SPOT_ANGLE)); // This equation is the inverse of the import equation (which has a desmos link). float angle_ratio = 1 - (0.2 / (0.1 + light->get_param(SpotLight3D::PARAM_SPOT_ATTENUATION))); diff --git a/modules/gltf/structures/gltf_camera.h b/modules/gltf/structures/gltf_camera.h index 714ec21693..8e528c063f 100644 --- a/modules/gltf/structures/gltf_camera.h +++ b/modules/gltf/structures/gltf_camera.h @@ -44,7 +44,7 @@ private: // GLTF has no default camera values, they should always be specified in // the GLTF file. Here we default to Godot's default camera settings. bool perspective = true; - real_t fov = Math::deg2rad(75.0); + real_t fov = Math::deg_to_rad(75.0); real_t size_mag = 0.5; real_t depth_far = 4000.0; real_t depth_near = 0.05; diff --git a/modules/gridmap/editor/grid_map_editor_plugin.cpp b/modules/gridmap/editor/grid_map_editor_plugin.cpp index 17f9832096..b0f73a98c9 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.cpp +++ b/modules/gridmap/editor/grid_map_editor_plugin.cpp @@ -1011,13 +1011,6 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { } } -void GridMapEditor::_update_theme() { - options->set_icon(get_theme_icon(SNAME("GridMap"), SNAME("EditorIcons"))); - search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); - mode_thumbnail->set_icon(get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons"))); - mode_list->set_icon(get_theme_icon(SNAME("FileList"), SNAME("EditorIcons"))); -} - void GridMapEditor::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -1038,7 +1031,6 @@ void GridMapEditor::_notification(int p_what) { _update_selection_transform(); _update_paste_indicator(); - _update_theme(); } break; case NOTIFICATION_EXIT_TREE: { @@ -1079,7 +1071,10 @@ void GridMapEditor::_notification(int p_what) { } break; case NOTIFICATION_THEME_CHANGED: { - _update_theme(); + options->set_icon(get_theme_icon(SNAME("GridMap"), SNAME("EditorIcons"))); + search_box->set_right_icon(get_theme_icon(SNAME("Search"), SNAME("EditorIcons"))); + mode_thumbnail->set_icon(get_theme_icon(SNAME("FileThumbnail"), SNAME("EditorIcons"))); + mode_list->set_icon(get_theme_icon(SNAME("FileList"), SNAME("EditorIcons"))); } break; case NOTIFICATION_APPLICATION_FOCUS_OUT: { diff --git a/modules/gridmap/editor/grid_map_editor_plugin.h b/modules/gridmap/editor/grid_map_editor_plugin.h index a64dc4a80b..773bf4b6a4 100644 --- a/modules/gridmap/editor/grid_map_editor_plugin.h +++ b/modules/gridmap/editor/grid_map_editor_plugin.h @@ -193,7 +193,6 @@ class GridMapEditor : public VBoxContainer { void _item_selected_cbk(int idx); void _update_cursor_transform(); void _update_cursor_instance(); - void _update_theme(); void _text_changed(const String &p_text); void _sbox_input(const Ref<InputEvent> &p_ie); diff --git a/modules/lightmapper_rd/lightmapper_rd.cpp b/modules/lightmapper_rd/lightmapper_rd.cpp index 83ac478a97..2dcf644a06 100644 --- a/modules/lightmapper_rd/lightmapper_rd.cpp +++ b/modules/lightmapper_rd/lightmapper_rd.cpp @@ -62,7 +62,7 @@ void LightmapperRD::add_directional_light(bool p_static, const Vector3 &p_direct l.color[2] = p_color.b; l.energy = p_energy; l.static_bake = p_static; - l.size = Math::tan(Math::deg2rad(p_angular_distance)); + l.size = Math::tan(Math::deg_to_rad(p_angular_distance)); l.shadow_blur = p_shadow_blur; lights.push_back(l); } @@ -96,7 +96,7 @@ void LightmapperRD::add_spot_light(bool p_static, const Vector3 &p_position, con l.direction[2] = p_direction.z; l.range = p_range; l.attenuation = p_attenuation; - l.cos_spot_angle = Math::cos(Math::deg2rad(p_spot_angle)); + l.cos_spot_angle = Math::cos(Math::deg_to_rad(p_spot_angle)); l.inv_spot_attenuation = 1.0f / p_spot_attenuation; l.color[0] = p_color.r; l.color[1] = p_color.g; diff --git a/modules/mono/build_scripts/mono_configure.py b/modules/mono/build_scripts/mono_configure.py index 3277f9beeb..ef7dbabf66 100644 --- a/modules/mono/build_scripts/mono_configure.py +++ b/modules/mono/build_scripts/mono_configure.py @@ -153,6 +153,7 @@ def find_app_host_version(dotnet_cmd, search_version_str): from distutils.version import LooseVersion search_version = LooseVersion(search_version_str) + found_match = False try: env = dict(os.environ, DOTNET_CLI_UI_LANGUAGE="en-US") @@ -172,7 +173,10 @@ def find_app_host_version(dotnet_cmd, search_version_str): version = LooseVersion(version_str) if version >= search_version: - return version_str + search_version = version + found_match = True + if found_match: + return str(search_version) except (subprocess.CalledProcessError, OSError) as e: import sys diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs index 3dfa8000ba..e28788ec0b 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs @@ -168,6 +168,32 @@ namespace Godot.SourceGenerators location?.SourceTree?.FilePath)); } + public static void ReportExportedMemberIsIndexer( + GeneratorExecutionContext context, + ISymbol exportedMemberSymbol + ) + { + var locations = exportedMemberSymbol.Locations; + var location = locations.FirstOrDefault(l => l.SourceTree != null) ?? locations.FirstOrDefault(); + + string message = $"Attempted to export indexer property: " + + $"'{exportedMemberSymbol.ToDisplayString()}'"; + + string description = $"{message}. Indexer properties can't be exported." + + " Remove the '[Export]' attribute."; + + context.ReportDiagnostic(Diagnostic.Create( + new DiagnosticDescriptor(id: "GD0105", + title: message, + messageFormat: message, + category: "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description), + location, + location?.SourceTree?.FilePath)); + } + public static void ReportSignalDelegateMissingSuffix( GeneratorExecutionContext context, INamedTypeSymbol delegateSymbol) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs index 7629595b3a..fc46d82dff 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs @@ -112,7 +112,8 @@ namespace Godot.SourceGenerators var propertySymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Property) - .Cast<IPropertySymbol>(); + .Cast<IPropertySymbol>() + .Where(s => !s.IsIndexer); var fieldSymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs index 85fadaa52e..c7745391d0 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -134,6 +134,12 @@ namespace Godot.SourceGenerators continue; } + if (property.IsIndexer) + { + Common.ReportExportedMemberIsIndexer(context, property); + continue; + } + // TODO: We should still restore read-only properties after reloading assembly. Two possible ways: reflection or turn RestoreGodotObjectData into a constructor overload. // Ignore properties without a getter or without a setter. Godot properties must be both readable and writable. if (property.IsWriteOnly) @@ -148,7 +154,6 @@ namespace Godot.SourceGenerators continue; } - var propertyType = property.Type; var marshalType = MarshalUtils.ConvertManagedTypeToMarshalType(propertyType, typeCache); diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs index 5a84122c4c..39a99ff8ba 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSerializationGenerator.cs @@ -112,7 +112,8 @@ namespace Godot.SourceGenerators var propertySymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Property) - .Cast<IPropertySymbol>(); + .Cast<IPropertySymbol>() + .Where(s => !s.IsIndexer); var fieldSymbols = members .Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs index 161834a4be..6b06f10db1 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptSignalsGenerator.cs @@ -117,10 +117,6 @@ namespace Godot.SourceGenerators source.Append(symbol.NameWithTypeParameters()); source.Append("\n{\n"); - // TODO: - // The delegate name already needs to end with 'Signal' to avoid collision with the event name. - // Requiring SignalAttribute is redundant. Should we remove it to make declaration shorter? - var members = symbol.GetMembers(); var signalDelegateSymbols = members diff --git a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs index 686202e81e..2448a2953b 100644 --- a/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs +++ b/modules/mono/editor/GodotTools/GodotTools.IdeMessaging/GodotIdeMetadata.cs @@ -25,10 +25,7 @@ namespace GodotTools.IdeMessaging public override bool Equals(object obj) { - if (obj is GodotIdeMetadata metadata) - return metadata == this; - - return false; + return obj is GodotIdeMetadata metadata && metadata == this; } public bool Equals(GodotIdeMetadata other) diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs index 3c5b897719..edbf53a389 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/BuildInfo.cs @@ -27,15 +27,13 @@ namespace GodotTools.Build public override bool Equals(object? obj) { - if (obj is BuildInfo other) - return other.Solution == Solution && - other.Configuration == Configuration && other.RuntimeIdentifier == RuntimeIdentifier && - other.PublishOutputDir == PublishOutputDir && other.Restore == Restore && - other.Rebuild == Rebuild && other.OnlyClean == OnlyClean && - other.CustomProperties == CustomProperties && - other.LogsDirPath == LogsDirPath; - - return false; + return obj is BuildInfo other && + other.Solution == Solution && + other.Configuration == Configuration && other.RuntimeIdentifier == RuntimeIdentifier && + other.PublishOutputDir == PublishOutputDir && other.Restore == Restore && + other.Rebuild == Rebuild && other.OnlyClean == OnlyClean && + other.CustomProperties == CustomProperties && + other.LogsDirPath == LogsDirPath; } public override int GetHashCode() diff --git a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs index 6dae0a3a0e..d05995c495 100644 --- a/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs +++ b/modules/mono/editor/GodotTools/GodotTools/Build/MSBuildPanel.cs @@ -139,7 +139,7 @@ namespace GodotTools.Build _errorsBtn = new Button { - HintTooltip = "Show Errors".TTR(), + TooltipText = "Show Errors".TTR(), Icon = GetThemeIcon("StatusError", "EditorIcons"), ExpandIcon = false, ToggleMode = true, @@ -151,7 +151,7 @@ namespace GodotTools.Build _warningsBtn = new Button { - HintTooltip = "Show Warnings".TTR(), + TooltipText = "Show Warnings".TTR(), Icon = GetThemeIcon("NodeWarning", "EditorIcons"), ExpandIcon = false, ToggleMode = true, diff --git a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs index c784ca62ee..994c11fa72 100644 --- a/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs +++ b/modules/mono/editor/GodotTools/GodotTools/GodotSharpEditor.cs @@ -433,7 +433,7 @@ namespace GodotTools _toolBarBuildButton = new Button { Text = "Build", - HintTooltip = "Build Solution".TTR(), + TooltipText = "Build Solution".TTR(), FocusMode = Control.FocusModeEnum.None, Shortcut = buildSolutionShortcut, ShortcutInTooltip = true diff --git a/modules/mono/editor/bindings_generator.cpp b/modules/mono/editor/bindings_generator.cpp index 5e51a28551..d70a1e6c88 100644 --- a/modules/mono/editor/bindings_generator.cpp +++ b/modules/mono/editor/bindings_generator.cpp @@ -2257,7 +2257,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf } String delegate_name = p_isignal.proxy_name; - delegate_name += "Handler"; // Delegate name is [SignalName]Handler + delegate_name += "EventHandler"; // Delegate name is [SignalName]EventHandler // Generate delegate p_output.append(MEMBER_BEGIN "public delegate void "); @@ -2271,7 +2271,7 @@ Error BindingsGenerator::_generate_cs_signal(const BindingsGenerator::TypeInterf // If so, we could store the pointer we get from `data_unique_pointer()` instead of allocating StringName here. // Generate event - p_output.append(MEMBER_BEGIN "[Signal]" MEMBER_BEGIN "public "); + p_output.append(MEMBER_BEGIN "public "); if (p_itype.is_singleton) { p_output.append("static "); diff --git a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs index c34f1a17f3..1f5ea7532d 100644 --- a/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs +++ b/modules/mono/editor/script_templates/CharacterBody2D/basic_movement.cs @@ -8,7 +8,7 @@ public partial class _CLASS_ : _BASE_ public const float Speed = 300.0f; public const float JumpVelocity = -400.0f; - // Get the gravity from the project settings to be synced with RigidDynamicBody nodes. + // Get the gravity from the project settings to be synced with RigidBody nodes. public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle(); public override void _PhysicsProcess(float delta) diff --git a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs index 069908c426..4e978b7549 100644 --- a/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs +++ b/modules/mono/editor/script_templates/CharacterBody3D/basic_movement.cs @@ -8,7 +8,7 @@ public partial class _CLASS_ : _BASE_ public const float Speed = 5.0f; public const float JumpVelocity = 4.5f; - // Get the gravity from the project settings to be synced with RigidDynamicBody nodes. + // Get the gravity from the project settings to be synced with RigidBody nodes. public float gravity = ProjectSettings.GetSetting("physics/3d/default_gravity").AsSingle(); public override void _PhysicsProcess(float delta) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs index 33fec350e3..17f680361d 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/AABB.cs @@ -700,12 +700,7 @@ namespace Godot /// <returns>Whether or not the AABB and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is AABB) - { - return Equals((AABB)obj); - } - - return false; + return obj is AABB other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs index 07a214f543..38e68a89d5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/SignalAttribute.cs @@ -2,6 +2,6 @@ using System; namespace Godot { - [AttributeUsage(AttributeTargets.Delegate | AttributeTargets.Event)] + [AttributeUsage(AttributeTargets.Delegate)] public class SignalAttribute : Attribute { } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs index 0fdd73cc5b..fbd59d649f 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Basis.cs @@ -501,6 +501,15 @@ namespace Godot ); } + internal Basis Lerp(Basis to, real_t weight) + { + Basis b = this; + b.Row0 = Row0.Lerp(to.Row0, weight); + b.Row1 = Row1.Lerp(to.Row1, weight); + b.Row2 = Row2.Lerp(to.Row2, weight); + return b; + } + /// <summary> /// Returns the orthonormalized version of the basis matrix (useful to /// call occasionally to avoid rounding errors for orthogonal matrices). @@ -895,12 +904,7 @@ namespace Godot /// <returns>Whether or not the basis matrix and the object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Basis) - { - return Equals((Basis)obj); - } - - return false; + return obj is Basis other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index 0dc5ba7678..3884781988 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -831,7 +831,7 @@ namespace Godot.Bridge } else { - interopProperties = ((godotsharp_property_info*)NativeMemory.Alloc((nuint)length))!; + interopProperties = ((godotsharp_property_info*)NativeMemory.Alloc((nuint)length, (nuint)sizeof(godotsharp_property_info)))!; } try @@ -951,7 +951,7 @@ namespace Godot.Bridge } else { - interopDefaultValues = ((godotsharp_property_def_val_pair*)NativeMemory.Alloc((nuint)length))!; + interopDefaultValues = ((godotsharp_property_def_val_pair*)NativeMemory.Alloc((nuint)length, (nuint)sizeof(godotsharp_property_def_val_pair)))!; } try diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs index 884dbb9fb2..33d8aef1a9 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Color.cs @@ -1151,12 +1151,7 @@ namespace Godot /// <returns>Whether or not the color and the other object are equal.</returns> public override bool Equals(object obj) { - if (obj is Color) - { - return Equals((Color)obj); - } - - return false; + return obj is Color other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs index bacf7c89e6..5bce66ea87 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Colors.cs @@ -10,136 +10,136 @@ namespace Godot { // Color names and values are derived from core/math/color_names.inc internal static readonly Dictionary<string, Color> namedColors = new Dictionary<string, Color> { - { "ALICE_BLUE", new Color(0xF0F8FFFF) }, - { "ANTIQUE_WHITE", new Color(0xFAEBD7FF) }, + { "ALICEBLUE", new Color(0xF0F8FFFF) }, + { "ANTIQUEWHITE", new Color(0xFAEBD7FF) }, { "AQUA", new Color(0x00FFFFFF) }, { "AQUAMARINE", new Color(0x7FFFD4FF) }, { "AZURE", new Color(0xF0FFFFFF) }, { "BEIGE", new Color(0xF5F5DCFF) }, { "BISQUE", new Color(0xFFE4C4FF) }, { "BLACK", new Color(0x000000FF) }, - { "BLANCHED_ALMOND", new Color(0xFFEBCDFF) }, + { "BLANCHEDALMOND", new Color(0xFFEBCDFF) }, { "BLUE", new Color(0x0000FFFF) }, - { "BLUE_VIOLET", new Color(0x8A2BE2FF) }, + { "BLUEVIOLET", new Color(0x8A2BE2FF) }, { "BROWN", new Color(0xA52A2AFF) }, { "BURLYWOOD", new Color(0xDEB887FF) }, - { "CADET_BLUE", new Color(0x5F9EA0FF) }, + { "CADETBLUE", new Color(0x5F9EA0FF) }, { "CHARTREUSE", new Color(0x7FFF00FF) }, { "CHOCOLATE", new Color(0xD2691EFF) }, { "CORAL", new Color(0xFF7F50FF) }, - { "CORNFLOWER_BLUE", new Color(0x6495EDFF) }, + { "CORNFLOWERBLUE", new Color(0x6495EDFF) }, { "CORNSILK", new Color(0xFFF8DCFF) }, { "CRIMSON", new Color(0xDC143CFF) }, { "CYAN", new Color(0x00FFFFFF) }, - { "DARK_BLUE", new Color(0x00008BFF) }, - { "DARK_CYAN", new Color(0x008B8BFF) }, - { "DARK_GOLDENROD", new Color(0xB8860BFF) }, - { "DARK_GRAY", new Color(0xA9A9A9FF) }, - { "DARK_GREEN", new Color(0x006400FF) }, - { "DARK_KHAKI", new Color(0xBDB76BFF) }, - { "DARK_MAGENTA", new Color(0x8B008BFF) }, - { "DARK_OLIVE_GREEN", new Color(0x556B2FFF) }, - { "DARK_ORANGE", new Color(0xFF8C00FF) }, - { "DARK_ORCHID", new Color(0x9932CCFF) }, - { "DARK_RED", new Color(0x8B0000FF) }, - { "DARK_SALMON", new Color(0xE9967AFF) }, - { "DARK_SEA_GREEN", new Color(0x8FBC8FFF) }, - { "DARK_SLATE_BLUE", new Color(0x483D8BFF) }, - { "DARK_SLATE_GRAY", new Color(0x2F4F4FFF) }, - { "DARK_TURQUOISE", new Color(0x00CED1FF) }, - { "DARK_VIOLET", new Color(0x9400D3FF) }, - { "DEEP_PINK", new Color(0xFF1493FF) }, - { "DEEP_SKY_BLUE", new Color(0x00BFFFFF) }, - { "DIM_GRAY", new Color(0x696969FF) }, - { "DODGER_BLUE", new Color(0x1E90FFFF) }, + { "DARKBLUE", new Color(0x00008BFF) }, + { "DARKCYAN", new Color(0x008B8BFF) }, + { "DARKGOLDENROD", new Color(0xB8860BFF) }, + { "DARKGRAY", new Color(0xA9A9A9FF) }, + { "DARKGREEN", new Color(0x006400FF) }, + { "DARKKHAKI", new Color(0xBDB76BFF) }, + { "DARKMAGENTA", new Color(0x8B008BFF) }, + { "DARKOLIVEGREEN", new Color(0x556B2FFF) }, + { "DARKORANGE", new Color(0xFF8C00FF) }, + { "DARKORCHID", new Color(0x9932CCFF) }, + { "DARKRED", new Color(0x8B0000FF) }, + { "DARKSALMON", new Color(0xE9967AFF) }, + { "DARKSEAGREEN", new Color(0x8FBC8FFF) }, + { "DARKSLATEBLUE", new Color(0x483D8BFF) }, + { "DARKSLATEGRAY", new Color(0x2F4F4FFF) }, + { "DARKTURQUOISE", new Color(0x00CED1FF) }, + { "DARKVIOLET", new Color(0x9400D3FF) }, + { "DEEPPINK", new Color(0xFF1493FF) }, + { "DEEPSKYBLUE", new Color(0x00BFFFFF) }, + { "DIMGRAY", new Color(0x696969FF) }, + { "DODGERBLUE", new Color(0x1E90FFFF) }, { "FIREBRICK", new Color(0xB22222FF) }, - { "FLORAL_WHITE", new Color(0xFFFAF0FF) }, - { "FOREST_GREEN", new Color(0x228B22FF) }, + { "FLORALWHITE", new Color(0xFFFAF0FF) }, + { "FORESTGREEN", new Color(0x228B22FF) }, { "FUCHSIA", new Color(0xFF00FFFF) }, { "GAINSBORO", new Color(0xDCDCDCFF) }, - { "GHOST_WHITE", new Color(0xF8F8FFFF) }, + { "GHOSTWHITE", new Color(0xF8F8FFFF) }, { "GOLD", new Color(0xFFD700FF) }, { "GOLDENROD", new Color(0xDAA520FF) }, { "GRAY", new Color(0xBEBEBEFF) }, { "GREEN", new Color(0x00FF00FF) }, - { "GREEN_YELLOW", new Color(0xADFF2FFF) }, + { "GREENYELLOW", new Color(0xADFF2FFF) }, { "HONEYDEW", new Color(0xF0FFF0FF) }, - { "HOT_PINK", new Color(0xFF69B4FF) }, - { "INDIAN_RED", new Color(0xCD5C5CFF) }, + { "HOTPINK", new Color(0xFF69B4FF) }, + { "INDIANRED", new Color(0xCD5C5CFF) }, { "INDIGO", new Color(0x4B0082FF) }, { "IVORY", new Color(0xFFFFF0FF) }, { "KHAKI", new Color(0xF0E68CFF) }, { "LAVENDER", new Color(0xE6E6FAFF) }, - { "LAVENDER_BLUSH", new Color(0xFFF0F5FF) }, - { "LAWN_GREEN", new Color(0x7CFC00FF) }, - { "LEMON_CHIFFON", new Color(0xFFFACDFF) }, - { "LIGHT_BLUE", new Color(0xADD8E6FF) }, - { "LIGHT_CORAL", new Color(0xF08080FF) }, - { "LIGHT_CYAN", new Color(0xE0FFFFFF) }, - { "LIGHT_GOLDENROD", new Color(0xFAFAD2FF) }, - { "LIGHT_GRAY", new Color(0xD3D3D3FF) }, - { "LIGHT_GREEN", new Color(0x90EE90FF) }, - { "LIGHT_PINK", new Color(0xFFB6C1FF) }, - { "LIGHT_SALMON", new Color(0xFFA07AFF) }, - { "LIGHT_SEA_GREEN", new Color(0x20B2AAFF) }, - { "LIGHT_SKY_BLUE", new Color(0x87CEFAFF) }, - { "LIGHT_SLATE_GRAY", new Color(0x778899FF) }, - { "LIGHT_STEEL_BLUE", new Color(0xB0C4DEFF) }, - { "LIGHT_YELLOW", new Color(0xFFFFE0FF) }, + { "LAVENDERBLUSH", new Color(0xFFF0F5FF) }, + { "LAWNGREEN", new Color(0x7CFC00FF) }, + { "LEMONCHIFFON", new Color(0xFFFACDFF) }, + { "LIGHTBLUE", new Color(0xADD8E6FF) }, + { "LIGHTCORAL", new Color(0xF08080FF) }, + { "LIGHTCYAN", new Color(0xE0FFFFFF) }, + { "LIGHTGOLDENROD", new Color(0xFAFAD2FF) }, + { "LIGHTGRAY", new Color(0xD3D3D3FF) }, + { "LIGHTGREEN", new Color(0x90EE90FF) }, + { "LIGHTPINK", new Color(0xFFB6C1FF) }, + { "LIGHTSALMON", new Color(0xFFA07AFF) }, + { "LIGHTSEAGREEN", new Color(0x20B2AAFF) }, + { "LIGHTSKYBLUE", new Color(0x87CEFAFF) }, + { "LIGHTSLATEGRAY", new Color(0x778899FF) }, + { "LIGHTSTEELBLUE", new Color(0xB0C4DEFF) }, + { "LIGHTYELLOW", new Color(0xFFFFE0FF) }, { "LIME", new Color(0x00FF00FF) }, - { "LIME_GREEN", new Color(0x32CD32FF) }, + { "LIMEGREEN", new Color(0x32CD32FF) }, { "LINEN", new Color(0xFAF0E6FF) }, { "MAGENTA", new Color(0xFF00FFFF) }, { "MAROON", new Color(0xB03060FF) }, - { "MEDIUM_AQUAMARINE", new Color(0x66CDAAFF) }, - { "MEDIUM_BLUE", new Color(0x0000CDFF) }, - { "MEDIUM_ORCHID", new Color(0xBA55D3FF) }, - { "MEDIUM_PURPLE", new Color(0x9370DBFF) }, - { "MEDIUM_SEA_GREEN", new Color(0x3CB371FF) }, - { "MEDIUM_SLATE_BLUE", new Color(0x7B68EEFF) }, - { "MEDIUM_SPRING_GREEN", new Color(0x00FA9AFF) }, - { "MEDIUM_TURQUOISE", new Color(0x48D1CCFF) }, - { "MEDIUM_VIOLET_RED", new Color(0xC71585FF) }, - { "MIDNIGHT_BLUE", new Color(0x191970FF) }, - { "MINT_CREAM", new Color(0xF5FFFAFF) }, - { "MISTY_ROSE", new Color(0xFFE4E1FF) }, + { "MEDIUMAQUAMARINE", new Color(0x66CDAAFF) }, + { "MEDIUMBLUE", new Color(0x0000CDFF) }, + { "MEDIUMORCHID", new Color(0xBA55D3FF) }, + { "MEDIUMPURPLE", new Color(0x9370DBFF) }, + { "MEDIUMSEAGREEN", new Color(0x3CB371FF) }, + { "MEDIUMSLATEBLUE", new Color(0x7B68EEFF) }, + { "MEDIUMSPRINGGREEN", new Color(0x00FA9AFF) }, + { "MEDIUMTURQUOISE", new Color(0x48D1CCFF) }, + { "MEDIUMVIOLETRED", new Color(0xC71585FF) }, + { "MIDNIGHTBLUE", new Color(0x191970FF) }, + { "MINTCREAM", new Color(0xF5FFFAFF) }, + { "MISTYROSE", new Color(0xFFE4E1FF) }, { "MOCCASIN", new Color(0xFFE4B5FF) }, - { "NAVAJO_WHITE", new Color(0xFFDEADFF) }, - { "NAVY_BLUE", new Color(0x000080FF) }, - { "OLD_LACE", new Color(0xFDF5E6FF) }, + { "NAVAJOWHITE", new Color(0xFFDEADFF) }, + { "NAVYBLUE", new Color(0x000080FF) }, + { "OLDLACE", new Color(0xFDF5E6FF) }, { "OLIVE", new Color(0x808000FF) }, - { "OLIVE_DRAB", new Color(0x6B8E23FF) }, + { "OLIVEDRAB", new Color(0x6B8E23FF) }, { "ORANGE", new Color(0xFFA500FF) }, - { "ORANGE_RED", new Color(0xFF4500FF) }, + { "ORANGERED", new Color(0xFF4500FF) }, { "ORCHID", new Color(0xDA70D6FF) }, - { "PALE_GOLDENROD", new Color(0xEEE8AAFF) }, - { "PALE_GREEN", new Color(0x98FB98FF) }, - { "PALE_TURQUOISE", new Color(0xAFEEEEFF) }, - { "PALE_VIOLET_RED", new Color(0xDB7093FF) }, - { "PAPAYA_WHIP", new Color(0xFFEFD5FF) }, - { "PEACH_PUFF", new Color(0xFFDAB9FF) }, + { "PALEGOLDENROD", new Color(0xEEE8AAFF) }, + { "PALEGREEN", new Color(0x98FB98FF) }, + { "PALETURQUOISE", new Color(0xAFEEEEFF) }, + { "PALEVIOLETRED", new Color(0xDB7093FF) }, + { "PAPAYAWHIP", new Color(0xFFEFD5FF) }, + { "PEACHPUFF", new Color(0xFFDAB9FF) }, { "PERU", new Color(0xCD853FFF) }, { "PINK", new Color(0xFFC0CBFF) }, { "PLUM", new Color(0xDDA0DDFF) }, - { "POWDER_BLUE", new Color(0xB0E0E6FF) }, + { "POWDERBLUE", new Color(0xB0E0E6FF) }, { "PURPLE", new Color(0xA020F0FF) }, - { "REBECCA_PURPLE", new Color(0x663399FF) }, + { "REBECCAPURPLE", new Color(0x663399FF) }, { "RED", new Color(0xFF0000FF) }, - { "ROSY_BROWN", new Color(0xBC8F8FFF) }, - { "ROYAL_BLUE", new Color(0x4169E1FF) }, - { "SADDLE_BROWN", new Color(0x8B4513FF) }, + { "ROSYBROWN", new Color(0xBC8F8FFF) }, + { "ROYALBLUE", new Color(0x4169E1FF) }, + { "SADDLEBROWN", new Color(0x8B4513FF) }, { "SALMON", new Color(0xFA8072FF) }, - { "SANDY_BROWN", new Color(0xF4A460FF) }, - { "SEA_GREEN", new Color(0x2E8B57FF) }, + { "SANDYBROWN", new Color(0xF4A460FF) }, + { "SEAGREEN", new Color(0x2E8B57FF) }, { "SEASHELL", new Color(0xFFF5EEFF) }, { "SIENNA", new Color(0xA0522DFF) }, { "SILVER", new Color(0xC0C0C0FF) }, - { "SKY_BLUE", new Color(0x87CEEBFF) }, - { "SLATE_BLUE", new Color(0x6A5ACDFF) }, - { "SLATE_GRAY", new Color(0x708090FF) }, + { "SKYBLUE", new Color(0x87CEEBFF) }, + { "SLATEBLUE", new Color(0x6A5ACDFF) }, + { "SLATEGRAY", new Color(0x708090FF) }, { "SNOW", new Color(0xFFFAFAFF) }, - { "SPRING_GREEN", new Color(0x00FF7FFF) }, - { "STEEL_BLUE", new Color(0x4682B4FF) }, + { "SPRINGGREEN", new Color(0x00FF7FFF) }, + { "STEELBLUE", new Color(0x4682B4FF) }, { "TAN", new Color(0xD2B48CFF) }, { "TEAL", new Color(0x008080FF) }, { "THISTLE", new Color(0xD8BFD8FF) }, @@ -147,15 +147,15 @@ namespace Godot { "TRANSPARENT", new Color(0xFFFFFF00) }, { "TURQUOISE", new Color(0x40E0D0FF) }, { "VIOLET", new Color(0xEE82EEFF) }, - { "WEB_GRAY", new Color(0x808080FF) }, - { "WEB_GREEN", new Color(0x008000FF) }, - { "WEB_MAROON", new Color(0x800000FF) }, - { "WEB_PURPLE", new Color(0x800080FF) }, + { "WEBGRAY", new Color(0x808080FF) }, + { "WEBGREEN", new Color(0x008000FF) }, + { "WEBMAROON", new Color(0x800000FF) }, + { "WEBPURPLE", new Color(0x800080FF) }, { "WHEAT", new Color(0xF5DEB3FF) }, { "WHITE", new Color(0xFFFFFFFF) }, - { "WHITE_SMOKE", new Color(0xF5F5F5FF) }, + { "WHITESMOKE", new Color(0xF5F5F5FF) }, { "YELLOW", new Color(0xFFFF00FF) }, - { "YELLOW_GREEN", new Color(0x9ACD32FF) }, + { "YELLOWGREEN", new Color(0x9ACD32FF) }, }; #pragma warning disable CS1591 // Disable warning: "Missing XML comment for publicly visible type or member" diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs index 6fbc04702a..c4161d2ded 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DebuggingUtils.cs @@ -121,8 +121,8 @@ namespace Godot var sb = new StringBuilder(); - if (methodBase is MethodInfo) - sb.AppendTypeName(((MethodInfo)methodBase).ReturnType); + if (methodBase is MethodInfo methodInfo) + sb.AppendTypeName(methodInfo.ReturnType); sb.Append(methodBase.DeclaringType?.FullName ?? "<unknown>"); sb.Append('.'); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs index 266038a0af..3c75d18943 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/DelegateUtils.cs @@ -181,9 +181,9 @@ namespace Godot if (variantType == Variant.Type.Nil) return false; - static byte[] Var2Bytes(in godot_variant var) + static byte[] VarToBytes(in godot_variant var) { - NativeFuncs.godotsharp_var2bytes(var, false.ToGodotBool(), out var varBytes); + NativeFuncs.godotsharp_var_to_bytes(var, false.ToGodotBool(), out var varBytes); using (varBytes) return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes); } @@ -192,7 +192,7 @@ namespace Godot var fieldValue = field.GetValue(target); using var fieldValueVariant = Marshaling.ConvertManagedObjectToVariant(fieldValue); - byte[] valueBuffer = Var2Bytes(fieldValueVariant); + byte[] valueBuffer = VarToBytes(fieldValueVariant); writer.Write(valueBuffer.Length); writer.Write(valueBuffer); } @@ -448,7 +448,7 @@ namespace Godot FieldInfo? fieldInfo = targetType.GetField(name, BindingFlags.Instance | BindingFlags.Public); - fieldInfo?.SetValue(recreatedTarget, GD.Bytes2Var(valueBuffer)); + fieldInfo?.SetValue(recreatedTarget, GD.BytesToVar(valueBuffer)); } @delegate = Delegate.CreateDelegate(delegateType, recreatedTarget, methodInfo, diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs index 9e7da7757a..e4b79e7ec4 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/GD.cs @@ -21,10 +21,10 @@ namespace Godot /// <param name="bytes">Byte array that will be decoded to a <c>Variant</c>.</param> /// <param name="allowObjects">If objects should be decoded.</param> /// <returns>The decoded <c>Variant</c>.</returns> - public static Variant Bytes2Var(Span<byte> bytes, bool allowObjects = false) + public static Variant BytesToVar(Span<byte> bytes, bool allowObjects = false) { using var varBytes = Marshaling.ConvertSystemArrayToNativePackedByteArray(bytes); - NativeFuncs.godotsharp_bytes2var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret); + NativeFuncs.godotsharp_bytes_to_var(varBytes, allowObjects.ToGodotBool(), out godot_variant ret); return Variant.CreateTakingOwnershipOfDisposableValue(ret); } @@ -52,10 +52,10 @@ namespace Godot /// <summary> /// Converts from decibels to linear energy (audio). /// </summary> - /// <seealso cref="Linear2Db(real_t)"/> + /// <seealso cref="LinearToDb(real_t)"/> /// <param name="db">Decibels to convert.</param> /// <returns>Audio volume as linear energy.</returns> - public static real_t Db2Linear(real_t db) + public static real_t DbToLinear(real_t db) { return (real_t)Math.Exp(db * 0.11512925464970228420089957273422); } @@ -115,18 +115,18 @@ namespace Godot /// Converts from linear energy to decibels (audio). /// This can be used to implement volume sliders that behave as expected (since volume isn't linear). /// </summary> - /// <seealso cref="Db2Linear(real_t)"/> + /// <seealso cref="DbToLinear(real_t)"/> /// <example> /// <code> /// // "slider" refers to a node that inherits Range such as HSlider or VSlider. /// // Its range must be configured to go from 0 to 1. /// // Change the bus name if you'd like to change the volume of a specific bus only. - /// AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), GD.Linear2Db(slider.value)); + /// AudioServer.SetBusVolumeDb(AudioServer.GetBusIndex("Master"), GD.LinearToDb(slider.value)); /// </code> /// </example> /// <param name="linear">The linear energy to convert.</param> /// <returns>Audio as decibels.</returns> - public static real_t Linear2Db(real_t linear) + public static real_t LinearToDb(real_t linear) { return (real_t)(Math.Log(linear) * 8.6858896380650365530225783783321); } @@ -518,21 +518,21 @@ namespace Godot } /// <summary> - /// Converts a formatted string that was returned by <see cref="Var2Str(Variant)"/> to the original value. + /// Converts a formatted string that was returned by <see cref="VarToStr(Variant)"/> to the original value. /// </summary> /// <example> /// <code> /// string a = "{\"a\": 1, \"b\": 2 }"; - /// var b = (Godot.Collections.Dictionary)GD.Str2Var(a); + /// var b = (Godot.Collections.Dictionary)GD.StrToVar(a); /// GD.Print(b["a"]); // Prints 1 /// </code> /// </example> /// <param name="str">String that will be converted to Variant.</param> /// <returns>The decoded <c>Variant</c>.</returns> - public static Variant Str2Var(string str) + public static Variant StrToVar(string str) { using var godotStr = Marshaling.ConvertStringToNative(str); - NativeFuncs.godotsharp_str2var(godotStr, out godot_variant ret); + NativeFuncs.godotsharp_str_to_var(godotStr, out godot_variant ret); return Variant.CreateTakingOwnershipOfDisposableValue(ret); } @@ -540,26 +540,26 @@ namespace Godot /// Encodes a <c>Variant</c> value to a byte array. /// If <paramref name="fullObjects"/> is <see langword="true"/> encoding objects is allowed /// (and can potentially include code). - /// Deserialization can be done with <see cref="Bytes2Var(Span{byte}, bool)"/>. + /// Deserialization can be done with <see cref="BytesToVar(Span{byte}, bool)"/>. /// </summary> /// <param name="var">Variant that will be encoded.</param> /// <param name="fullObjects">If objects should be serialized.</param> /// <returns>The <c>Variant</c> encoded as an array of bytes.</returns> - public static byte[] Var2Bytes(Variant var, bool fullObjects = false) + public static byte[] VarToBytes(Variant var, bool fullObjects = false) { - NativeFuncs.godotsharp_var2bytes((godot_variant)var.NativeVar, fullObjects.ToGodotBool(), out var varBytes); + NativeFuncs.godotsharp_var_to_bytes((godot_variant)var.NativeVar, fullObjects.ToGodotBool(), out var varBytes); using (varBytes) return Marshaling.ConvertNativePackedByteArrayToSystemArray(varBytes); } /// <summary> /// Converts a <c>Variant</c> <paramref name="var"/> to a formatted string that - /// can later be parsed using <see cref="Str2Var(string)"/>. + /// can later be parsed using <see cref="StrToVar(string)"/>. /// </summary> /// <example> /// <code> /// var a = new Godot.Collections.Dictionary { ["a"] = 1, ["b"] = 2 }; - /// GD.Print(GD.Var2Str(a)); + /// GD.Print(GD.VarToStr(a)); /// // Prints /// // { /// // "a": 1, @@ -569,9 +569,9 @@ namespace Godot /// </example> /// <param name="var">Variant that will be converted to string.</param> /// <returns>The <c>Variant</c> encoded as a string.</returns> - public static string Var2Str(Variant var) + public static string VarToStr(Variant var) { - NativeFuncs.godotsharp_var2str((godot_variant)var.NativeVar, out godot_string ret); + NativeFuncs.godotsharp_var_to_str((godot_variant)var.NativeVar, out godot_string ret); using (ret) return Marshaling.ConvertStringToManaged(ret); } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs index 41a0dd871c..b30012d214 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Mathf.cs @@ -35,9 +35,9 @@ namespace Godot public const real_t NaN = real_t.NaN; // 0.0174532924f and 0.0174532925199433 - private const real_t _deg2RadConst = (real_t)0.0174532925199432957692369077M; + private const real_t _degToRadConst = (real_t)0.0174532925199432957692369077M; // 57.29578f and 57.2957795130823 - private const real_t _rad2DegConst = (real_t)57.295779513082320876798154814M; + private const real_t _radToDegConst = (real_t)57.295779513082320876798154814M; /// <summary> /// Returns the absolute value of <paramref name="s"/> (i.e. positive value). @@ -175,7 +175,8 @@ namespace Godot } /// <summary> - /// Cubic interpolates between two values by a normalized value with pre and post values. + /// Cubic interpolates between two values by the factor defined in <paramref name="weight"/> + /// with pre and post values. /// </summary> /// <param name="from">The start value for interpolation.</param> /// <param name="to">The destination value for interpolation.</param> @@ -193,6 +194,93 @@ namespace Godot } /// <summary> + /// Cubic interpolates between two rotation values with shortest path + /// by the factor defined in <paramref name="weight"/> with pre and post values. + /// See also <see cref="LerpAngle"/>. + /// </summary> + /// <param name="from">The start value for interpolation.</param> + /// <param name="to">The destination value for interpolation.</param> + /// <param name="pre">The value which before "from" value for interpolation.</param> + /// <param name="post">The value which after "to" value for interpolation.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The resulting value of the interpolation.</returns> + public static real_t CubicInterpolateAngle(real_t from, real_t to, real_t pre, real_t post, real_t weight) + { + real_t fromRot = from % Mathf.Tau; + + real_t preDiff = (pre - fromRot) % Mathf.Tau; + real_t preRot = fromRot + (2.0f * preDiff) % Mathf.Tau - preDiff; + + real_t toDiff = (to - fromRot) % Mathf.Tau; + real_t toRot = fromRot + (2.0f * toDiff) % Mathf.Tau - toDiff; + + real_t postDiff = (post - toRot) % Mathf.Tau; + real_t postRot = toRot + (2.0f * postDiff) % Mathf.Tau - postDiff; + + return CubicInterpolate(fromRot, toRot, preRot, postRot, weight); + } + + /// <summary> + /// Cubic interpolates between two values by the factor defined in <paramref name="weight"/> + /// with pre and post values. + /// It can perform smoother interpolation than <see cref="CubicInterpolate"/> + /// by the time values. + /// </summary> + /// <param name="from">The start value for interpolation.</param> + /// <param name="to">The destination value for interpolation.</param> + /// <param name="pre">The value which before "from" value for interpolation.</param> + /// <param name="post">The value which after "to" value for interpolation.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <param name="toT"></param> + /// <param name="preT"></param> + /// <param name="postT"></param> + /// <returns>The resulting value of the interpolation.</returns> + public static real_t CubicInterpolateInTime(real_t from, real_t to, real_t pre, real_t post, real_t weight, real_t toT, real_t preT, real_t postT) + { + /* Barry-Goldman method */ + real_t t = Lerp(0.0f, toT, weight); + real_t a1 = Lerp(pre, from, preT == 0 ? 0.0f : (t - preT) / -preT); + real_t a2 = Lerp(from, to, toT == 0 ? 0.5f : t / toT); + real_t a3 = Lerp(to, post, postT - toT == 0 ? 1.0f : (t - toT) / (postT - toT)); + real_t b1 = Lerp(a1, a2, toT - preT == 0 ? 0.0f : (t - preT) / (toT - preT)); + real_t b2 = Lerp(a2, a3, postT == 0 ? 1.0f : t / postT); + return Lerp(b1, b2, toT == 0 ? 0.5f : t / toT); + } + + /// <summary> + /// Cubic interpolates between two rotation values with shortest path + /// by the factor defined in <paramref name="weight"/> with pre and post values. + /// See also <see cref="LerpAngle"/>. + /// It can perform smoother interpolation than <see cref="CubicInterpolateAngle"/> + /// by the time values. + /// </summary> + /// <param name="from">The start value for interpolation.</param> + /// <param name="to">The destination value for interpolation.</param> + /// <param name="pre">The value which before "from" value for interpolation.</param> + /// <param name="post">The value which after "to" value for interpolation.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <param name="toT"></param> + /// <param name="preT"></param> + /// <param name="postT"></param> + /// <returns>The resulting value of the interpolation.</returns> + public static real_t CubicInterpolateAngleInTime(real_t from, real_t to, real_t pre, real_t post, real_t weight, + real_t toT, real_t preT, real_t postT) + { + real_t fromRot = from % Mathf.Tau; + + real_t preDiff = (pre - fromRot) % Mathf.Tau; + real_t preRot = fromRot + (2.0f * preDiff) % Mathf.Tau - preDiff; + + real_t toDiff = (to - fromRot) % Mathf.Tau; + real_t toRot = fromRot + (2.0f * toDiff) % Mathf.Tau - toDiff; + + real_t postDiff = (post - toRot) % Mathf.Tau; + real_t postRot = toRot + (2.0f * postDiff) % Mathf.Tau - postDiff; + + return CubicInterpolateInTime(fromRot, toRot, preRot, postRot, weight, toT, preT, postT); + } + + /// <summary> /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by /// the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. /// </summary> @@ -219,9 +307,9 @@ namespace Godot /// </summary> /// <param name="deg">An angle expressed in degrees.</param> /// <returns>The same angle expressed in radians.</returns> - public static real_t Deg2Rad(real_t deg) + public static real_t DegToRad(real_t deg) { - return deg * _deg2RadConst; + return deg * _degToRadConst; } /// <summary> @@ -531,9 +619,9 @@ namespace Godot /// </summary> /// <param name="rad">An angle expressed in radians.</param> /// <returns>The same angle expressed in degrees.</returns> - public static real_t Rad2Deg(real_t rad) + public static real_t RadToDeg(real_t rad) { - return rad * _rad2DegConst; + return rad * _radToDegConst; } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index 939c0056ac..94dda5a74b 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -461,7 +461,7 @@ namespace Godot.NativeInterop // GD, etc - internal static partial void godotsharp_bytes2var(in godot_packed_byte_array p_bytes, + internal static partial void godotsharp_bytes_to_var(in godot_packed_byte_array p_bytes, godot_bool p_allow_objects, out godot_variant r_ret); @@ -504,12 +504,12 @@ namespace Godot.NativeInterop internal static partial void godotsharp_str(in godot_array p_what, out godot_string r_ret); - internal static partial void godotsharp_str2var(in godot_string p_str, out godot_variant r_ret); + internal static partial void godotsharp_str_to_var(in godot_string p_str, out godot_variant r_ret); - internal static partial void godotsharp_var2bytes(in godot_variant p_what, godot_bool p_full_objects, + internal static partial void godotsharp_var_to_bytes(in godot_variant p_what, godot_bool p_full_objects, out godot_packed_byte_array r_bytes); - internal static partial void godotsharp_var2str(in godot_variant p_var, out godot_string r_ret); + internal static partial void godotsharp_var_to_str(in godot_variant p_var, out godot_string r_ret); internal static partial void godotsharp_pusherror(in godot_string p_str); diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs index 50832d7679..13070c8033 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Plane.cs @@ -353,12 +353,7 @@ namespace Godot /// <returns>Whether or not the plane and the other object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Plane) - { - return Equals((Plane)obj); - } - - return false; + return obj is Plane other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs index 7f422848d5..da895fd121 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Projection.cs @@ -226,7 +226,7 @@ namespace Godot { fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); } - real_t radians = Mathf.Deg2Rad(fovyDegrees / (real_t)2.0); + real_t radians = Mathf.DegToRad(fovyDegrees / (real_t)2.0); real_t deltaZ = zFar - zNear; real_t sine = Mathf.Sin(radians); @@ -256,7 +256,7 @@ namespace Godot fovyDegrees = GetFovy(fovyDegrees, (real_t)1.0 / aspect); } - real_t ymax = zNear * Mathf.Tan(Mathf.Deg2Rad(fovyDegrees / (real_t)2.0)); + real_t ymax = zNear * Mathf.Tan(Mathf.DegToRad(fovyDegrees / (real_t)2.0)); real_t xmax = ymax * aspect; real_t frustumshift = (intraocularDist / (real_t)2.0) * zNear / convergenceDist; real_t left; @@ -313,18 +313,18 @@ namespace Godot Plane rightPlane = new Plane(x.w - x.x, y.w - y.x, z.w - z.x, -w.w + w.x).Normalized(); if (z.x == 0 && z.y == 0) { - return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0; + return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))) * (real_t)2.0; } else { Plane leftPlane = new Plane(x.w + x.x, y.w + y.x, z.w + z.x, w.w + w.x).Normalized(); - return Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.Rad2Deg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))); + return Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(leftPlane.Normal.x))) + Mathf.RadToDeg(Mathf.Acos(Mathf.Abs(rightPlane.Normal.x))); } } public static real_t GetFovy(real_t fovx, real_t aspect) { - return Mathf.Rad2Deg(Mathf.Atan(aspect * Mathf.Tan(Mathf.Deg2Rad(fovx) * (real_t)0.5)) * (real_t)2.0); + return Mathf.RadToDeg(Mathf.Atan(aspect * Mathf.Tan(Mathf.DegToRad(fovx) * (real_t)0.5)) * (real_t)2.0); } public real_t GetLodMultiplier() @@ -806,11 +806,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Projection) - { - return Equals((Projection)obj); - } - return false; + return obj is Projection other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs index 39416a34f2..d459fe8c96 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Quaternion.cs @@ -135,7 +135,7 @@ namespace Godot } /// <summary> - /// Performs a cubic spherical interpolation between quaternions <paramref name="preA"/>, this quaternion, + /// Performs a spherical cubic interpolation between quaternions <paramref name="preA"/>, this quaternion, /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>. /// </summary> /// <param name="b">The destination quaternion.</param> @@ -143,12 +143,128 @@ namespace Godot /// <param name="postB">A quaternion after <paramref name="b"/>.</param> /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> /// <returns>The interpolated quaternion.</returns> - public Quaternion CubicSlerp(Quaternion b, Quaternion preA, Quaternion postB, real_t weight) + public Quaternion SphericalCubicInterpolate(Quaternion b, Quaternion preA, Quaternion postB, real_t weight) { - real_t t2 = (1.0f - weight) * weight * 2f; - Quaternion sp = Slerp(b, weight); - Quaternion sq = preA.Slerpni(postB, weight); - return sp.Slerpni(sq, t2); +#if DEBUG + if (!IsNormalized()) + { + throw new InvalidOperationException("Quaternion is not normalized"); + } + if (!b.IsNormalized()) + { + throw new ArgumentException("Argument is not normalized", nameof(b)); + } +#endif + + // Align flip phases. + Quaternion fromQ = new Basis(this).GetRotationQuaternion(); + Quaternion preQ = new Basis(preA).GetRotationQuaternion(); + Quaternion toQ = new Basis(b).GetRotationQuaternion(); + Quaternion postQ = new Basis(postB).GetRotationQuaternion(); + + // Flip quaternions to shortest path if necessary. + bool flip1 = Math.Sign(fromQ.Dot(preQ)) < 0; + preQ = flip1 ? -preQ : preQ; + bool flip2 = Math.Sign(fromQ.Dot(toQ)) < 0; + toQ = flip2 ? -toQ : toQ; + bool flip3 = flip2 ? toQ.Dot(postQ) <= 0 : Math.Sign(toQ.Dot(postQ)) < 0; + postQ = flip3 ? -postQ : postQ; + + // Calc by Expmap in fromQ space. + Quaternion lnFrom = new Quaternion(0, 0, 0, 0); + Quaternion lnTo = (fromQ.Inverse() * toQ).Log(); + Quaternion lnPre = (fromQ.Inverse() * preQ).Log(); + Quaternion lnPost = (fromQ.Inverse() * postQ).Log(); + Quaternion ln = new Quaternion( + Mathf.CubicInterpolate(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight), + Mathf.CubicInterpolate(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight), + Mathf.CubicInterpolate(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight), + 0); + Quaternion q1 = fromQ * ln.Exp(); + + // Calc by Expmap in toQ space. + lnFrom = (toQ.Inverse() * fromQ).Log(); + lnTo = new Quaternion(0, 0, 0, 0); + lnPre = (toQ.Inverse() * preQ).Log(); + lnPost = (toQ.Inverse() * postQ).Log(); + ln = new Quaternion( + Mathf.CubicInterpolate(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight), + Mathf.CubicInterpolate(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight), + Mathf.CubicInterpolate(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight), + 0); + Quaternion q2 = toQ * ln.Exp(); + + // To cancel error made by Expmap ambiguity, do blends. + return q1.Slerp(q2, weight); + } + + /// <summary> + /// Performs a spherical cubic interpolation between quaternions <paramref name="preA"/>, this quaternion, + /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>. + /// It can perform smoother interpolation than <see cref="SphericalCubicInterpolate"/> + /// by the time values. + /// </summary> + /// <param name="b">The destination quaternion.</param> + /// <param name="preA">A quaternion before this quaternion.</param> + /// <param name="postB">A quaternion after <paramref name="b"/>.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <param name="bT"></param> + /// <param name="preAT"></param> + /// <param name="postBT"></param> + /// <returns>The interpolated quaternion.</returns> + public Quaternion SphericalCubicInterpolateInTime(Quaternion b, Quaternion preA, Quaternion postB, real_t weight, real_t bT, real_t preAT, real_t postBT) + { +#if DEBUG + if (!IsNormalized()) + { + throw new InvalidOperationException("Quaternion is not normalized"); + } + if (!b.IsNormalized()) + { + throw new ArgumentException("Argument is not normalized", nameof(b)); + } +#endif + + // Align flip phases. + Quaternion fromQ = new Basis(this).GetRotationQuaternion(); + Quaternion preQ = new Basis(preA).GetRotationQuaternion(); + Quaternion toQ = new Basis(b).GetRotationQuaternion(); + Quaternion postQ = new Basis(postB).GetRotationQuaternion(); + + // Flip quaternions to shortest path if necessary. + bool flip1 = Math.Sign(fromQ.Dot(preQ)) < 0; + preQ = flip1 ? -preQ : preQ; + bool flip2 = Math.Sign(fromQ.Dot(toQ)) < 0; + toQ = flip2 ? -toQ : toQ; + bool flip3 = flip2 ? toQ.Dot(postQ) <= 0 : Math.Sign(toQ.Dot(postQ)) < 0; + postQ = flip3 ? -postQ : postQ; + + // Calc by Expmap in fromQ space. + Quaternion lnFrom = new Quaternion(0, 0, 0, 0); + Quaternion lnTo = (fromQ.Inverse() * toQ).Log(); + Quaternion lnPre = (fromQ.Inverse() * preQ).Log(); + Quaternion lnPost = (fromQ.Inverse() * postQ).Log(); + Quaternion ln = new Quaternion( + Mathf.CubicInterpolateInTime(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight, bT, preAT, postBT), + Mathf.CubicInterpolateInTime(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight, bT, preAT, postBT), + Mathf.CubicInterpolateInTime(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight, bT, preAT, postBT), + 0); + Quaternion q1 = fromQ * ln.Exp(); + + // Calc by Expmap in toQ space. + lnFrom = (toQ.Inverse() * fromQ).Log(); + lnTo = new Quaternion(0, 0, 0, 0); + lnPre = (toQ.Inverse() * preQ).Log(); + lnPost = (toQ.Inverse() * postQ).Log(); + ln = new Quaternion( + Mathf.CubicInterpolateInTime(lnFrom.x, lnTo.x, lnPre.x, lnPost.x, weight, bT, preAT, postBT), + Mathf.CubicInterpolateInTime(lnFrom.y, lnTo.y, lnPre.y, lnPost.y, weight, bT, preAT, postBT), + Mathf.CubicInterpolateInTime(lnFrom.z, lnTo.z, lnPre.z, lnPost.z, weight, bT, preAT, postBT), + 0); + Quaternion q2 = toQ * ln.Exp(); + + // To cancel error made by Expmap ambiguity, do blends. + return q1.Slerp(q2, weight); } /// <summary> @@ -161,6 +277,34 @@ namespace Godot return (x * b.x) + (y * b.y) + (z * b.z) + (w * b.w); } + public Quaternion Exp() + { + Vector3 v = new Vector3(x, y, z); + real_t theta = v.Length(); + v = v.Normalized(); + if (theta < Mathf.Epsilon || !v.IsNormalized()) + { + return new Quaternion(0, 0, 0, 1); + } + return new Quaternion(v, theta); + } + + public real_t GetAngle() + { + return 2 * Mathf.Acos(w); + } + + public Vector3 GetAxis() + { + if (Mathf.Abs(w) > 1 - Mathf.Epsilon) + { + return new Vector3(x, y, z); + } + + real_t r = 1 / Mathf.Sqrt(1 - w * w); + return new Vector3(x * r, y * r, z * r); + } + /// <summary> /// Returns Euler angles (in the YXZ convention: when decomposing, /// first Z, then X, and Y last) corresponding to the rotation @@ -204,6 +348,12 @@ namespace Godot return Mathf.Abs(LengthSquared - 1) <= Mathf.Epsilon; } + public Quaternion Log() + { + Vector3 v = GetAxis() * GetAngle(); + return new Quaternion(v.x, v.y, v.z, 0); + } + /// <summary> /// Returns a copy of the quaternion, normalized to unit length. /// </summary> @@ -236,7 +386,7 @@ namespace Godot #endif // Calculate cosine. - real_t cosom = x * to.x + y * to.y + z * to.z + w * to.w; + real_t cosom = Dot(to); var to1 = new Quaternion(); @@ -244,17 +394,11 @@ namespace Godot if (cosom < 0.0) { cosom = -cosom; - to1.x = -to.x; - to1.y = -to.y; - to1.z = -to.z; - to1.w = -to.w; + to1 = -to; } else { - to1.x = to.x; - to1.y = to.y; - to1.z = to.z; - to1.w = to.w; + to1 = to; } real_t sinom, scale0, scale1; @@ -295,6 +439,17 @@ namespace Godot /// <returns>The resulting quaternion of the interpolation.</returns> public Quaternion Slerpni(Quaternion to, real_t weight) { +#if DEBUG + if (!IsNormalized()) + { + throw new InvalidOperationException("Quaternion is not normalized"); + } + if (!to.IsNormalized()) + { + throw new ArgumentException("Argument is not normalized", nameof(to)); + } +#endif + real_t dot = Dot(to); if (Mathf.Abs(dot) > 0.9999f) @@ -583,12 +738,7 @@ namespace Godot /// <returns>Whether or not the quaternion and the other object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Quaternion) - { - return Equals((Quaternion)obj); - } - - return false; + return obj is Quaternion other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs index d2c9b0ca8b..0b475fec19 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2.cs @@ -426,12 +426,7 @@ namespace Godot /// <returns>Whether or not the rect and the other object are exactly equal.</returns> public override bool Equals(object obj) { - if (obj is Rect2) - { - return Equals((Rect2)obj); - } - - return false; + return obj is Rect2 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs index 5d53b8330e..8a2a98d6ee 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Rect2i.cs @@ -426,12 +426,7 @@ namespace Godot /// <returns>Whether or not the rect and the other object are equal.</returns> public override bool Equals(object obj) { - if (obj is Rect2i) - { - return Equals((Rect2i)obj); - } - - return false; + return obj is Rect2i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs index d8acfca33b..894667db76 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform2D.cs @@ -605,7 +605,7 @@ namespace Godot /// <returns>Whether or not the transform and the object are exactly equal.</returns> public override bool Equals(object obj) { - return obj is Transform2D transform2D && Equals(transform2D); + return obj is Transform2D other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs index 23e276ef8a..2f7891e7ef 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Transform3D.cs @@ -122,23 +122,9 @@ namespace Godot /// <returns>The interpolated transform.</returns> public Transform3D InterpolateWith(Transform3D transform, real_t weight) { - /* not sure if very "efficient" but good enough? */ - - Vector3 sourceScale = basis.Scale; - Quaternion sourceRotation = basis.GetRotationQuaternion(); - Vector3 sourceLocation = origin; - - Vector3 destinationScale = transform.basis.Scale; - Quaternion destinationRotation = transform.basis.GetRotationQuaternion(); - Vector3 destinationLocation = transform.origin; - - var interpolated = new Transform3D(); - Quaternion quaternion = sourceRotation.Slerp(destinationRotation, weight).Normalized(); - Vector3 scale = sourceScale.Lerp(destinationScale, weight); - interpolated.basis.SetQuaternionScale(quaternion, scale); - interpolated.origin = sourceLocation.Lerp(destinationLocation, weight); - - return interpolated; + Basis retBasis = basis.Lerp(transform.basis, weight); + Vector3 retOrigin = origin.Lerp(transform.origin, weight); + return new Transform3D(retBasis, retOrigin); } /// <summary> @@ -237,6 +223,34 @@ namespace Godot return new Transform3D(basis * tmpBasis, origin); } + /// <summary> + /// Returns a transform spherically interpolated between this transform and + /// another <paramref name="transform"/> by <paramref name="weight"/>. + /// </summary> + /// <param name="transform">The other transform.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <returns>The interpolated transform.</returns> + public Transform3D SphericalInterpolateWith(Transform3D transform, real_t weight) + { + /* not sure if very "efficient" but good enough? */ + + Vector3 sourceScale = basis.Scale; + Quaternion sourceRotation = basis.GetRotationQuaternion(); + Vector3 sourceLocation = origin; + + Vector3 destinationScale = transform.basis.Scale; + Quaternion destinationRotation = transform.basis.GetRotationQuaternion(); + Vector3 destinationLocation = transform.origin; + + var interpolated = new Transform3D(); + Quaternion quaternion = sourceRotation.Slerp(destinationRotation, weight).Normalized(); + Vector3 scale = sourceScale.Lerp(destinationScale, weight); + interpolated.basis.SetQuaternionScale(quaternion, scale); + interpolated.origin = sourceLocation.Lerp(destinationLocation, weight); + + return interpolated; + } + private void SetLookAt(Vector3 eye, Vector3 target, Vector3 up) { // Make rotation matrix @@ -582,12 +596,7 @@ namespace Godot /// <returns>Whether or not the transform and the object are exactly equal.</returns> public override readonly bool Equals(object obj) { - if (obj is Transform3D) - { - return Equals((Transform3D)obj); - } - - return false; + return obj is Transform3D other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs index efaf56fddf..87f397891e 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2.cs @@ -216,6 +216,29 @@ namespace Godot } /// <summary> + /// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector, + /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>. + /// It can perform smoother interpolation than <see cref="CubicInterpolate"/> + /// by the time values. + /// </summary> + /// <param name="b">The destination vector.</param> + /// <param name="preA">A vector before this vector.</param> + /// <param name="postB">A vector after <paramref name="b"/>.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <param name="t"></param> + /// <param name="preAT"></param> + /// <param name="postBT"></param> + /// <returns>The interpolated vector.</returns> + public Vector2 CubicInterpolateInTime(Vector2 b, Vector2 preA, Vector2 postB, real_t weight, real_t t, real_t preAT, real_t postBT) + { + return new Vector2 + ( + Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT), + Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT) + ); + } + + /// <summary> /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. /// </summary> @@ -925,11 +948,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector2) - { - return Equals((Vector2)obj); - } - return false; + return obj is Vector2 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs index f7eb6f180a..bdadf696e3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector2i.cs @@ -667,12 +667,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector2i) - { - return Equals((Vector2i)obj); - } - - return false; + return obj is Vector2i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs index 88f279ccff..6649f3b784 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3.cs @@ -209,6 +209,30 @@ namespace Godot } /// <summary> + /// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector, + /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>. + /// It can perform smoother interpolation than <see cref="CubicInterpolate"/> + /// by the time values. + /// </summary> + /// <param name="b">The destination vector.</param> + /// <param name="preA">A vector before this vector.</param> + /// <param name="postB">A vector after <paramref name="b"/>.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <param name="t"></param> + /// <param name="preAT"></param> + /// <param name="postBT"></param> + /// <returns>The interpolated vector.</returns> + public Vector3 CubicInterpolateInTime(Vector3 b, Vector3 preA, Vector3 postB, real_t weight, real_t t, real_t preAT, real_t postBT) + { + return new Vector3 + ( + Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT), + Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT), + Mathf.CubicInterpolateInTime(z, b.z, preA.z, postB.z, weight, t, preAT, postBT) + ); + } + + /// <summary> /// Returns the point at the given <paramref name="t"/> on a one-dimensional Bezier curve defined by this vector /// and the given <paramref name="control1"/>, <paramref name="control2"/> and <paramref name="end"/> points. /// </summary> @@ -993,12 +1017,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector3) - { - return Equals((Vector3)obj); - } - - return false; + return obj is Vector3 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs index 582956fce8..e88a043cb3 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector3i.cs @@ -676,12 +676,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector3i) - { - return Equals((Vector3i)obj); - } - - return false; + return obj is Vector3i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs index 9a99e23d44..d1962c68cf 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4.cs @@ -193,6 +193,31 @@ namespace Godot } /// <summary> + /// Performs a cubic interpolation between vectors <paramref name="preA"/>, this vector, + /// <paramref name="b"/>, and <paramref name="postB"/>, by the given amount <paramref name="weight"/>. + /// It can perform smoother interpolation than <see cref="CubicInterpolate"/> + /// by the time values. + /// </summary> + /// <param name="b">The destination vector.</param> + /// <param name="preA">A vector before this vector.</param> + /// <param name="postB">A vector after <paramref name="b"/>.</param> + /// <param name="weight">A value on the range of 0.0 to 1.0, representing the amount of interpolation.</param> + /// <param name="t"></param> + /// <param name="preAT"></param> + /// <param name="postBT"></param> + /// <returns>The interpolated vector.</returns> + public Vector4 CubicInterpolateInTime(Vector4 b, Vector4 preA, Vector4 postB, real_t weight, real_t t, real_t preAT, real_t postBT) + { + return new Vector4 + ( + Mathf.CubicInterpolateInTime(x, b.x, preA.x, postB.x, weight, t, preAT, postBT), + Mathf.CubicInterpolateInTime(y, b.y, preA.y, postB.y, weight, t, preAT, postBT), + Mathf.CubicInterpolateInTime(y, b.z, preA.z, postB.z, weight, t, preAT, postBT), + Mathf.CubicInterpolateInTime(w, b.w, preA.w, postB.w, weight, t, preAT, postBT) + ); + } + + /// <summary> /// Returns the normalized vector pointing from this vector to <paramref name="to"/>. /// </summary> /// <param name="to">The other vector to point towards.</param> @@ -754,12 +779,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector4) - { - return Equals((Vector4)obj); - } - - return false; + return obj is Vector4 other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs index d4dbdbec93..4b1bb3ba19 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Vector4i.cs @@ -629,12 +629,7 @@ namespace Godot /// <returns>Whether or not the vector and the object are equal.</returns> public override bool Equals(object obj) { - if (obj is Vector4i) - { - return Equals((Vector4i)obj); - } - - return false; + return obj is Vector4i other && Equals(other); } /// <summary> diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 13d4395a64..0d68cb54b9 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -1233,13 +1233,13 @@ void godotsharp_pushwarning(const godot_string *p_str) { WARN_PRINT(*reinterpret_cast<const String *>(p_str)); } -void godotsharp_var2str(const godot_variant *p_var, godot_string *r_ret) { +void godotsharp_var_to_str(const godot_variant *p_var, godot_string *r_ret) { const Variant &var = *reinterpret_cast<const Variant *>(p_var); String &vars = *memnew_placement(r_ret, String); VariantWriter::write_to_string(var, vars); } -void godotsharp_str2var(const godot_string *p_str, godot_variant *r_ret) { +void godotsharp_str_to_var(const godot_string *p_str, godot_variant *r_ret) { Variant ret; VariantParser::StreamString ss; @@ -1256,7 +1256,7 @@ void godotsharp_str2var(const godot_string *p_str, godot_variant *r_ret) { memnew_placement(r_ret, Variant(ret)); } -void godotsharp_var2bytes(const godot_variant *p_var, bool p_full_objects, godot_packed_array *r_bytes) { +void godotsharp_var_to_bytes(const godot_variant *p_var, bool p_full_objects, godot_packed_array *r_bytes) { const Variant &var = *reinterpret_cast<const Variant *>(p_var); PackedByteArray &bytes = *memnew_placement(r_bytes, PackedByteArray); @@ -1268,7 +1268,7 @@ void godotsharp_var2bytes(const godot_variant *p_var, bool p_full_objects, godot encode_variant(var, bytes.ptrw(), len, p_full_objects); } -void godotsharp_bytes2var(const godot_packed_array *p_bytes, bool p_allow_objects, godot_variant *r_ret) { +void godotsharp_bytes_to_var(const godot_packed_array *p_bytes, bool p_allow_objects, godot_variant *r_ret) { const PackedByteArray *bytes = reinterpret_cast<const PackedByteArray *>(p_bytes); Variant ret; Error err = decode_variant(ret, bytes->ptr(), bytes->size(), nullptr, p_allow_objects); @@ -1479,7 +1479,7 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_node_path_get_subname, (void *)godotsharp_node_path_get_subname_count, (void *)godotsharp_node_path_is_absolute, - (void *)godotsharp_bytes2var, + (void *)godotsharp_bytes_to_var, (void *)godotsharp_convert, (void *)godotsharp_hash, (void *)godotsharp_instance_from_id, @@ -1499,9 +1499,9 @@ static const void *unmanaged_callbacks[]{ (void *)godotsharp_seed, (void *)godotsharp_weakref, (void *)godotsharp_str, - (void *)godotsharp_str2var, - (void *)godotsharp_var2bytes, - (void *)godotsharp_var2str, + (void *)godotsharp_str_to_var, + (void *)godotsharp_var_to_bytes, + (void *)godotsharp_var_to_str, (void *)godotsharp_pusherror, (void *)godotsharp_pushwarning, (void *)godotsharp_object_to_string, diff --git a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp index c243e3e6e3..5cdff7b52a 100644 --- a/modules/navigation/editor/navigation_mesh_editor_plugin.cpp +++ b/modules/navigation/editor/navigation_mesh_editor_plugin.cpp @@ -110,7 +110,7 @@ NavigationMeshEditor::NavigationMeshEditor() { button_reset->set_flat(true); bake_hbox->add_child(button_reset); // No button text, we only use a revert icon which is set when entering the tree. - button_reset->set_tooltip(TTR("Clear the navigation mesh.")); + button_reset->set_tooltip_text(TTR("Clear the navigation mesh.")); button_reset->connect("pressed", callable_mp(this, &NavigationMeshEditor::_clear_pressed)); bake_info = memnew(Label); diff --git a/modules/noise/config.py b/modules/noise/config.py index 74db20f2a4..2318d28c53 100644 --- a/modules/noise/config.py +++ b/modules/noise/config.py @@ -10,7 +10,7 @@ def get_doc_classes(): return [ "FastNoiseLite", "Noise", - "NoiseTexture", + "NoiseTexture2D", ] diff --git a/modules/noise/doc_classes/NoiseTexture.xml b/modules/noise/doc_classes/NoiseTexture2D.xml index 62a223b387..9eea2738c5 100644 --- a/modules/noise/doc_classes/NoiseTexture.xml +++ b/modules/noise/doc_classes/NoiseTexture2D.xml @@ -1,14 +1,14 @@ <?xml version="1.0" encoding="UTF-8" ?> -<class name="NoiseTexture" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> +<class name="NoiseTexture2D" inherits="Texture2D" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> A texture filled with noise generated by a [Noise] object. </brief_description> <description> Uses [FastNoiseLite] or other libraries to fill the texture data of your desired size. - NoiseTexture can also generate normalmap textures. + NoiseTexture2D can also generate normalmap textures. The class uses [Thread]s to generate the texture data internally, so [method Texture2D.get_image] may return [code]null[/code] if the generation process has not completed yet. In that case, you need to wait for the texture to be generated before accessing the image and the generated byte data: [codeblock] - var texture = NoiseTexture.new() + var texture = NoiseTexture2D.new() texture.noise = FastNoiseLite.new() await texture.changed var image = texture.get_image() diff --git a/modules/noise/editor/noise_editor_plugin.cpp b/modules/noise/editor/noise_editor_plugin.cpp index 27a86f45b5..e8e73e4fd9 100644 --- a/modules/noise/editor/noise_editor_plugin.cpp +++ b/modules/noise/editor/noise_editor_plugin.cpp @@ -35,7 +35,7 @@ #include "editor/editor_scale.h" #include "modules/noise/noise.h" -#include "modules/noise/noise_texture.h" +#include "modules/noise/noise_texture_2d.h" class NoisePreview : public Control { GDCLASS(NoisePreview, Control) @@ -60,7 +60,7 @@ public: _3d_space_switch = memnew(Button); _3d_space_switch->set_text(TTR("3D")); - _3d_space_switch->set_tooltip(TTR("Toggles whether the noise preview is computed in 3D space.")); + _3d_space_switch->set_tooltip_text(TTR("Toggles whether the noise preview is computed in 3D space.")); _3d_space_switch->set_toggle_mode(true); _3d_space_switch->set_offset(SIDE_LEFT, PADDING_3D_SPACE_SWITCH); _3d_space_switch->set_offset(SIDE_TOP, PADDING_3D_SPACE_SWITCH); @@ -102,7 +102,7 @@ private: void update_preview() { if (MIN(_preview_texture_size.width, _preview_texture_size.height) > 0) { - Ref<NoiseTexture> tex; + Ref<NoiseTexture2D> tex; tex.instantiate(); tex->set_width(_preview_texture_size.width); tex->set_height(_preview_texture_size.height); diff --git a/modules/noise/noise_texture.cpp b/modules/noise/noise_texture_2d.cpp index 923b420581..8d279f9dd3 100644 --- a/modules/noise/noise_texture.cpp +++ b/modules/noise/noise_texture_2d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* noise_texture.cpp */ +/* noise_texture_2d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,58 +28,58 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "noise_texture.h" +#include "noise_texture_2d.h" #include "core/core_string_names.h" #include "noise.h" -NoiseTexture::NoiseTexture() { +NoiseTexture2D::NoiseTexture2D() { noise = Ref<Noise>(); _queue_update(); } -NoiseTexture::~NoiseTexture() { +NoiseTexture2D::~NoiseTexture2D() { if (texture.is_valid()) { RS::get_singleton()->free(texture); } noise_thread.wait_to_finish(); } -void NoiseTexture::_bind_methods() { - ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture::_update_texture); - ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture::_generate_texture); - ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture::_thread_done); +void NoiseTexture2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("_update_texture"), &NoiseTexture2D::_update_texture); + ClassDB::bind_method(D_METHOD("_generate_texture"), &NoiseTexture2D::_generate_texture); + ClassDB::bind_method(D_METHOD("_thread_done", "image"), &NoiseTexture2D::_thread_done); - ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture::set_width); - ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture::set_height); + ClassDB::bind_method(D_METHOD("set_width", "width"), &NoiseTexture2D::set_width); + ClassDB::bind_method(D_METHOD("set_height", "height"), &NoiseTexture2D::set_height); - ClassDB::bind_method(D_METHOD("set_invert", "invert"), &NoiseTexture::set_invert); - ClassDB::bind_method(D_METHOD("get_invert"), &NoiseTexture::get_invert); + ClassDB::bind_method(D_METHOD("set_invert", "invert"), &NoiseTexture2D::set_invert); + ClassDB::bind_method(D_METHOD("get_invert"), &NoiseTexture2D::get_invert); - ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &NoiseTexture::set_in_3d_space); - ClassDB::bind_method(D_METHOD("is_in_3d_space"), &NoiseTexture::is_in_3d_space); + ClassDB::bind_method(D_METHOD("set_in_3d_space", "enable"), &NoiseTexture2D::set_in_3d_space); + ClassDB::bind_method(D_METHOD("is_in_3d_space"), &NoiseTexture2D::is_in_3d_space); - ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "invert"), &NoiseTexture::set_generate_mipmaps); - ClassDB::bind_method(D_METHOD("is_generating_mipmaps"), &NoiseTexture::is_generating_mipmaps); + ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "invert"), &NoiseTexture2D::set_generate_mipmaps); + ClassDB::bind_method(D_METHOD("is_generating_mipmaps"), &NoiseTexture2D::is_generating_mipmaps); - ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture::set_seamless); - ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture::get_seamless); + ClassDB::bind_method(D_METHOD("set_seamless", "seamless"), &NoiseTexture2D::set_seamless); + ClassDB::bind_method(D_METHOD("get_seamless"), &NoiseTexture2D::get_seamless); - ClassDB::bind_method(D_METHOD("set_seamless_blend_skirt", "seamless_blend_skirt"), &NoiseTexture::set_seamless_blend_skirt); - ClassDB::bind_method(D_METHOD("get_seamless_blend_skirt"), &NoiseTexture::get_seamless_blend_skirt); + ClassDB::bind_method(D_METHOD("set_seamless_blend_skirt", "seamless_blend_skirt"), &NoiseTexture2D::set_seamless_blend_skirt); + ClassDB::bind_method(D_METHOD("get_seamless_blend_skirt"), &NoiseTexture2D::get_seamless_blend_skirt); - ClassDB::bind_method(D_METHOD("set_as_normal_map", "as_normal_map"), &NoiseTexture::set_as_normal_map); - ClassDB::bind_method(D_METHOD("is_normal_map"), &NoiseTexture::is_normal_map); + ClassDB::bind_method(D_METHOD("set_as_normal_map", "as_normal_map"), &NoiseTexture2D::set_as_normal_map); + ClassDB::bind_method(D_METHOD("is_normal_map"), &NoiseTexture2D::is_normal_map); - ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture::set_bump_strength); - ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture::get_bump_strength); + ClassDB::bind_method(D_METHOD("set_bump_strength", "bump_strength"), &NoiseTexture2D::set_bump_strength); + ClassDB::bind_method(D_METHOD("get_bump_strength"), &NoiseTexture2D::get_bump_strength); - ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &NoiseTexture::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &NoiseTexture::get_color_ramp); + ClassDB::bind_method(D_METHOD("set_color_ramp", "gradient"), &NoiseTexture2D::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &NoiseTexture2D::get_color_ramp); - ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture::set_noise); - ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture::get_noise); + ClassDB::bind_method(D_METHOD("set_noise", "noise"), &NoiseTexture2D::set_noise); + ClassDB::bind_method(D_METHOD("get_noise"), &NoiseTexture2D::get_noise); ADD_PROPERTY(PropertyInfo(Variant::INT, "width", PROPERTY_HINT_RANGE, "1,2048,1,or_greater,suffix:px"), "set_width", "get_width"); ADD_PROPERTY(PropertyInfo(Variant::INT, "height", PROPERTY_HINT_RANGE, "1,2048,1,or_greater,suffix:px"), "set_height", "get_height"); @@ -94,7 +94,7 @@ void NoiseTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "noise", PROPERTY_HINT_RESOURCE_TYPE, "Noise"), "set_noise", "get_noise"); } -void NoiseTexture::_validate_property(PropertyInfo &p_property) const { +void NoiseTexture2D::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "bump_strength") { if (!as_normal_map) { p_property.usage = PROPERTY_USAGE_NO_EDITOR; @@ -108,7 +108,7 @@ void NoiseTexture::_validate_property(PropertyInfo &p_property) const { } } -void NoiseTexture::_set_texture_image(const Ref<Image> &p_image) { +void NoiseTexture2D::_set_texture_image(const Ref<Image> &p_image) { image = p_image; if (image.is_valid()) { if (texture.is_valid()) { @@ -121,7 +121,7 @@ void NoiseTexture::_set_texture_image(const Ref<Image> &p_image) { emit_changed(); } -void NoiseTexture::_thread_done(const Ref<Image> &p_image) { +void NoiseTexture2D::_thread_done(const Ref<Image> &p_image) { _set_texture_image(p_image); noise_thread.wait_to_finish(); if (regen_queued) { @@ -130,12 +130,12 @@ void NoiseTexture::_thread_done(const Ref<Image> &p_image) { } } -void NoiseTexture::_thread_function(void *p_ud) { - NoiseTexture *tex = static_cast<NoiseTexture *>(p_ud); +void NoiseTexture2D::_thread_function(void *p_ud) { + NoiseTexture2D *tex = static_cast<NoiseTexture2D *>(p_ud); tex->call_deferred(SNAME("_thread_done"), tex->_generate_texture()); } -void NoiseTexture::_queue_update() { +void NoiseTexture2D::_queue_update() { if (update_queued) { return; } @@ -144,7 +144,7 @@ void NoiseTexture::_queue_update() { call_deferred(SNAME("_update_texture")); } -Ref<Image> NoiseTexture::_generate_texture() { +Ref<Image> NoiseTexture2D::_generate_texture() { // Prevent memdelete due to unref() on other thread. Ref<Noise> ref_noise = noise; @@ -172,7 +172,7 @@ Ref<Image> NoiseTexture::_generate_texture() { return image; } -Ref<Image> NoiseTexture::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient) { +Ref<Image> NoiseTexture2D::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradient> p_gradient) { int width = p_image->get_width(); int height = p_image->get_height(); @@ -191,7 +191,7 @@ Ref<Image> NoiseTexture::_modulate_with_gradient(Ref<Image> p_image, Ref<Gradien return new_image; } -void NoiseTexture::_update_texture() { +void NoiseTexture2D::_update_texture() { bool use_thread = true; if (first_time) { use_thread = false; @@ -215,25 +215,25 @@ void NoiseTexture::_update_texture() { update_queued = false; } -void NoiseTexture::set_noise(Ref<Noise> p_noise) { +void NoiseTexture2D::set_noise(Ref<Noise> p_noise) { if (p_noise == noise) { return; } if (noise.is_valid()) { - noise->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + noise->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } noise = p_noise; if (noise.is_valid()) { - noise->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + noise->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } _queue_update(); } -Ref<Noise> NoiseTexture::get_noise() { +Ref<Noise> NoiseTexture2D::get_noise() { return noise; } -void NoiseTexture::set_width(int p_width) { +void NoiseTexture2D::set_width(int p_width) { ERR_FAIL_COND(p_width <= 0); if (p_width == size.x) { return; @@ -242,7 +242,7 @@ void NoiseTexture::set_width(int p_width) { _queue_update(); } -void NoiseTexture::set_height(int p_height) { +void NoiseTexture2D::set_height(int p_height) { ERR_FAIL_COND(p_height <= 0); if (p_height == size.y) { return; @@ -251,7 +251,7 @@ void NoiseTexture::set_height(int p_height) { _queue_update(); } -void NoiseTexture::set_invert(bool p_invert) { +void NoiseTexture2D::set_invert(bool p_invert) { if (p_invert == invert) { return; } @@ -259,22 +259,22 @@ void NoiseTexture::set_invert(bool p_invert) { _queue_update(); } -bool NoiseTexture::get_invert() const { +bool NoiseTexture2D::get_invert() const { return invert; } -void NoiseTexture::set_in_3d_space(bool p_enable) { +void NoiseTexture2D::set_in_3d_space(bool p_enable) { if (p_enable == in_3d_space) { return; } in_3d_space = p_enable; _queue_update(); } -bool NoiseTexture::is_in_3d_space() const { +bool NoiseTexture2D::is_in_3d_space() const { return in_3d_space; } -void NoiseTexture::set_generate_mipmaps(bool p_enable) { +void NoiseTexture2D::set_generate_mipmaps(bool p_enable) { if (p_enable == generate_mipmaps) { return; } @@ -282,11 +282,11 @@ void NoiseTexture::set_generate_mipmaps(bool p_enable) { _queue_update(); } -bool NoiseTexture::is_generating_mipmaps() const { +bool NoiseTexture2D::is_generating_mipmaps() const { return generate_mipmaps; } -void NoiseTexture::set_seamless(bool p_seamless) { +void NoiseTexture2D::set_seamless(bool p_seamless) { if (p_seamless == seamless) { return; } @@ -295,11 +295,11 @@ void NoiseTexture::set_seamless(bool p_seamless) { notify_property_list_changed(); } -bool NoiseTexture::get_seamless() { +bool NoiseTexture2D::get_seamless() { return seamless; } -void NoiseTexture::set_seamless_blend_skirt(real_t p_blend_skirt) { +void NoiseTexture2D::set_seamless_blend_skirt(real_t p_blend_skirt) { ERR_FAIL_COND(p_blend_skirt < 0.05 || p_blend_skirt > 1); if (p_blend_skirt == seamless_blend_skirt) { @@ -308,11 +308,11 @@ void NoiseTexture::set_seamless_blend_skirt(real_t p_blend_skirt) { seamless_blend_skirt = p_blend_skirt; _queue_update(); } -real_t NoiseTexture::get_seamless_blend_skirt() { +real_t NoiseTexture2D::get_seamless_blend_skirt() { return seamless_blend_skirt; } -void NoiseTexture::set_as_normal_map(bool p_as_normal_map) { +void NoiseTexture2D::set_as_normal_map(bool p_as_normal_map) { if (p_as_normal_map == as_normal_map) { return; } @@ -321,11 +321,11 @@ void NoiseTexture::set_as_normal_map(bool p_as_normal_map) { notify_property_list_changed(); } -bool NoiseTexture::is_normal_map() { +bool NoiseTexture2D::is_normal_map() { return as_normal_map; } -void NoiseTexture::set_bump_strength(float p_bump_strength) { +void NoiseTexture2D::set_bump_strength(float p_bump_strength) { if (p_bump_strength == bump_strength) { return; } @@ -335,37 +335,37 @@ void NoiseTexture::set_bump_strength(float p_bump_strength) { } } -float NoiseTexture::get_bump_strength() { +float NoiseTexture2D::get_bump_strength() { return bump_strength; } -void NoiseTexture::set_color_ramp(const Ref<Gradient> &p_gradient) { +void NoiseTexture2D::set_color_ramp(const Ref<Gradient> &p_gradient) { if (p_gradient == color_ramp) { return; } if (color_ramp.is_valid()) { - color_ramp->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + color_ramp->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } color_ramp = p_gradient; if (color_ramp.is_valid()) { - color_ramp->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture::_queue_update)); + color_ramp->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NoiseTexture2D::_queue_update)); } _queue_update(); } -Ref<Gradient> NoiseTexture::get_color_ramp() const { +Ref<Gradient> NoiseTexture2D::get_color_ramp() const { return color_ramp; } -int NoiseTexture::get_width() const { +int NoiseTexture2D::get_width() const { return size.x; } -int NoiseTexture::get_height() const { +int NoiseTexture2D::get_height() const { return size.y; } -RID NoiseTexture::get_rid() const { +RID NoiseTexture2D::get_rid() const { if (!texture.is_valid()) { texture = RS::get_singleton()->texture_2d_placeholder_create(); } @@ -373,6 +373,6 @@ RID NoiseTexture::get_rid() const { return texture; } -Ref<Image> NoiseTexture::get_image() const { +Ref<Image> NoiseTexture2D::get_image() const { return image; } diff --git a/modules/noise/noise_texture.h b/modules/noise/noise_texture_2d.h index 83fbcc2d10..8f8e256fb9 100644 --- a/modules/noise/noise_texture.h +++ b/modules/noise/noise_texture_2d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* noise_texture.h */ +/* noise_texture_2d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,16 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef NOISE_TEXTURE_H -#define NOISE_TEXTURE_H +#ifndef NOISE_TEXTURE_2D_H +#define NOISE_TEXTURE_2D_H #include "noise.h" #include "core/object/ref_counted.h" #include "scene/resources/texture.h" -class NoiseTexture : public Texture2D { - GDCLASS(NoiseTexture, Texture2D); +class NoiseTexture2D : public Texture2D { + GDCLASS(NoiseTexture2D, Texture2D); private: Ref<Image> image; @@ -116,8 +116,8 @@ public: virtual Ref<Image> get_image() const override; - NoiseTexture(); - virtual ~NoiseTexture(); + NoiseTexture2D(); + virtual ~NoiseTexture2D(); }; -#endif // NOISE_TEXTURE_H +#endif // NOISE_TEXTURE_2D_H diff --git a/modules/noise/register_types.cpp b/modules/noise/register_types.cpp index d0cfc4e944..c44bf9828f 100644 --- a/modules/noise/register_types.cpp +++ b/modules/noise/register_types.cpp @@ -32,7 +32,7 @@ #include "fastnoise_lite.h" #include "noise.h" -#include "noise_texture.h" +#include "noise_texture_2d.h" #ifdef TOOLS_ENABLED #include "editor/editor_plugin.h" @@ -41,9 +41,10 @@ void initialize_noise_module(ModuleInitializationLevel p_level) { if (p_level == MODULE_INITIALIZATION_LEVEL_SCENE) { - GDREGISTER_CLASS(NoiseTexture); + GDREGISTER_CLASS(NoiseTexture2D); GDREGISTER_ABSTRACT_CLASS(Noise); GDREGISTER_CLASS(FastNoiseLite); + ClassDB::add_compatibility_class("NoiseTexture", "NoiseTexture2D"); } #ifdef TOOLS_ENABLED diff --git a/modules/openxr/editor/openxr_action_editor.cpp b/modules/openxr/editor/openxr_action_editor.cpp index 41c6465f43..c4789d501f 100644 --- a/modules/openxr/editor/openxr_action_editor.cpp +++ b/modules/openxr/editor/openxr_action_editor.cpp @@ -34,15 +34,10 @@ void OpenXRActionEditor::_bind_methods() { ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_editor"))); } -void OpenXRActionEditor::_theme_changed() { - rem_action->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); -} - void OpenXRActionEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - _theme_changed(); + rem_action->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); } break; } } @@ -104,7 +99,7 @@ OpenXRActionEditor::OpenXRActionEditor(Ref<OpenXRAction> p_action) { // maybe add dropdown to edit our toplevel paths, or do we deduce them from our suggested bindings? rem_action = memnew(Button); - rem_action->set_tooltip(TTR("Remove action")); + rem_action->set_tooltip_text(TTR("Remove action")); rem_action->connect("pressed", callable_mp(this, &OpenXRActionEditor::_on_remove_action)); rem_action->set_flat(true); add_child(rem_action); diff --git a/modules/openxr/editor/openxr_action_editor.h b/modules/openxr/editor/openxr_action_editor.h index 6cf098cf08..2667268e9a 100644 --- a/modules/openxr/editor/openxr_action_editor.h +++ b/modules/openxr/editor/openxr_action_editor.h @@ -49,7 +49,6 @@ private: OptionButton *action_type = nullptr; Button *rem_action = nullptr; - void _theme_changed(); void _on_action_name_changed(const String p_new_text); void _on_action_localized_name_changed(const String p_new_text); void _on_item_selected(int p_idx); diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp index 0a2d0a3110..6be04d8119 100644 --- a/modules/openxr/editor/openxr_action_map_editor.cpp +++ b/modules/openxr/editor/openxr_action_map_editor.cpp @@ -52,7 +52,6 @@ void OpenXRActionMapEditor::_bind_methods() { void OpenXRActionMapEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { for (int i = 0; i < tabs->get_child_count(); i++) { Control *tab = static_cast<Control *>(tabs->get_child(i)); @@ -316,13 +315,13 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() { add_action_set = memnew(Button); add_action_set->set_text(TTR("Add Action Set")); - add_action_set->set_tooltip(TTR("Add an action set.")); + add_action_set->set_tooltip_text(TTR("Add an action set.")); add_action_set->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_add_action_set)); top_hb->add_child(add_action_set); add_interaction_profile = memnew(Button); add_interaction_profile->set_text(TTR("Add profile")); - add_interaction_profile->set_tooltip(TTR("Add an interaction profile.")); + add_interaction_profile->set_tooltip_text(TTR("Add an interaction profile.")); add_interaction_profile->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_add_interaction_profile)); top_hb->add_child(add_interaction_profile); @@ -331,13 +330,13 @@ OpenXRActionMapEditor::OpenXRActionMapEditor() { save_as = memnew(Button); save_as->set_text(TTR("Save")); - save_as->set_tooltip(TTR("Save this OpenXR action map.")); + save_as->set_tooltip_text(TTR("Save this OpenXR action map.")); save_as->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_save_action_map)); top_hb->add_child(save_as); _default = memnew(Button); _default->set_text(TTR("Reset to Default")); - _default->set_tooltip(TTR("Reset to default OpenXR action map.")); + _default->set_tooltip_text(TTR("Reset to default OpenXR action map.")); _default->connect("pressed", callable_mp(this, &OpenXRActionMapEditor::_on_reset_to_default_layout)); top_hb->add_child(_default); diff --git a/modules/openxr/editor/openxr_action_set_editor.cpp b/modules/openxr/editor/openxr_action_set_editor.cpp index 7bf8557c5b..6f70a91cfd 100644 --- a/modules/openxr/editor/openxr_action_set_editor.cpp +++ b/modules/openxr/editor/openxr_action_set_editor.cpp @@ -44,17 +44,12 @@ void OpenXRActionSetEditor::_set_fold_icon() { } } -void OpenXRActionSetEditor::_theme_changed() { - _set_fold_icon(); - add_action->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); - rem_action_set->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); -} - void OpenXRActionSetEditor::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { - _theme_changed(); + _set_fold_icon(); + add_action->set_icon(get_theme_icon(SNAME("Add"), SNAME("EditorIcons"))); + rem_action_set->set_icon(get_theme_icon(SNAME("Remove"), SNAME("EditorIcons"))); panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer"))); } break; } @@ -199,13 +194,13 @@ OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, action_set_hb->add_child(action_set_priority); add_action = memnew(Button); - add_action->set_tooltip("Add Action."); + add_action->set_tooltip_text("Add Action."); add_action->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_add_action)); add_action->set_flat(true); action_set_hb->add_child(add_action); rem_action_set = memnew(Button); - rem_action_set->set_tooltip("Remove Action Set."); + rem_action_set->set_tooltip_text("Remove Action Set."); rem_action_set->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_remove_action_set)); rem_action_set->set_flat(true); action_set_hb->add_child(rem_action_set); diff --git a/modules/openxr/editor/openxr_action_set_editor.h b/modules/openxr/editor/openxr_action_set_editor.h index d8c85d03dd..0a9e3fe7b0 100644 --- a/modules/openxr/editor/openxr_action_set_editor.h +++ b/modules/openxr/editor/openxr_action_set_editor.h @@ -61,7 +61,6 @@ private: VBoxContainer *actions_vb = nullptr; void _set_fold_icon(); - void _theme_changed(); OpenXRActionEditor *_add_action_editor(Ref<OpenXRAction> p_action); void _update_actions(); diff --git a/modules/openxr/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp index 80e58044d5..1b7423ec73 100644 --- a/modules/openxr/editor/openxr_select_action_dialog.cpp +++ b/modules/openxr/editor/openxr_select_action_dialog.cpp @@ -37,7 +37,6 @@ void OpenXRSelectActionDialog::_bind_methods() { void OpenXRSelectActionDialog::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } break; diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp index 23b025db08..8c88e268e9 100644 --- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp +++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp @@ -36,7 +36,6 @@ void OpenXRSelectInteractionProfileDialog::_bind_methods() { void OpenXRSelectInteractionProfileDialog::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { scroll->add_theme_style_override("bg", get_theme_stylebox(SNAME("bg"), SNAME("Tree"))); } break; diff --git a/modules/raycast/config.py b/modules/raycast/config.py index 438779343e..833ad50018 100644 --- a/modules/raycast/config.py +++ b/modules/raycast/config.py @@ -1,5 +1,8 @@ def can_build(env, platform): # Depends on Embree library, which only supports x86_64 and arm64. + if platform == "windows": + return env["arch"] == "x86_64" # TODO build for Windows on ARM + return env["arch"] in ["x86_64", "arm64"] diff --git a/modules/text_server_adv/text_server_adv.cpp b/modules/text_server_adv/text_server_adv.cpp index e80eb43369..366e1ba604 100644 --- a/modules/text_server_adv/text_server_adv.cpp +++ b/modules/text_server_adv/text_server_adv.cpp @@ -29,12 +29,12 @@ /*************************************************************************/ #include "text_server_adv.h" -#include "core/object/worker_thread_pool.h" #ifdef GDEXTENSION // Headers for building as GDExtension plug-in. #include <godot_cpp/classes/file.hpp> +#include <godot_cpp/classes/project_settings.hpp> #include <godot_cpp/classes/rendering_server.hpp> #include <godot_cpp/classes/translation_server.hpp> #include <godot_cpp/core/error_macros.hpp> @@ -44,8 +44,10 @@ using namespace godot; #else // Headers for building as built-in module. +#include "core/config/project_settings.h" #include "core/core_bind.h" #include "core/error/error_macros.h" +#include "core/object/worker_thread_pool.h" #include "core/string/print_string.h" #include "core/string/translation.h" @@ -791,6 +793,10 @@ _FORCE_INLINE_ TextServerAdvanced::FontTexturePosition TextServerAdvanced::find_ for (int i = 0; i < p_data->textures.size(); i++) { const FontTexture &ct = p_data->textures[i]; + if (p_image_format != ct.format) { + continue; + } + if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture. continue; } @@ -1082,9 +1088,28 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_msdf( #endif #ifdef MODULE_FREETYPE_ENABLED -_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const { int w = bitmap.width; int h = bitmap.rows; + int color_size = 2; + + switch (bitmap.pixel_mode) { + case FT_PIXEL_MODE_MONO: + case FT_PIXEL_MODE_GRAY: { + color_size = 2; + } break; + case FT_PIXEL_MODE_BGRA: { + color_size = 4; + } break; + case FT_PIXEL_MODE_LCD: { + color_size = 4; + w /= 3; + } break; + case FT_PIXEL_MODE_LCD_V: { + color_size = 4; + h /= 3; + } break; + } int mw = w + p_rect_margin * 4; int mh = h + p_rect_margin * 4; @@ -1092,7 +1117,6 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph()); - int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false); @@ -1127,6 +1151,34 @@ _FORCE_INLINE_ TextServerAdvanced::FontGlyph TextServerAdvanced::rasterize_bitma wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; wr[ofs + 3] = bitmap.buffer[ofs_color + 3]; } break; + case FT_PIXEL_MODE_LCD: { + int ofs_color = i * bitmap.pitch + (j * 3); + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } + } break; + case FT_PIXEL_MODE_LCD_V: { + int ofs_color = i * bitmap.pitch * 3 + j; + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 3] = 255; + } + } break; default: ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + "."); break; @@ -1230,9 +1282,44 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, FT_Outline_Transform(&fd->face->glyph->outline, &mat); } + FT_Render_Mode aa_mode = FT_RENDER_MODE_NORMAL; + bool bgra = false; + switch (p_font_data->antialiasing) { + case FONT_ANTIALIASING_NONE: { + aa_mode = FT_RENDER_MODE_MONO; + } break; + case FONT_ANTIALIASING_GRAY: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + case FONT_ANTIALIASING_LCD: { + int aa_layout = (int)((p_glyph >> 24) & 7); + switch (aa_layout) { + case FONT_LCD_SUBPIXEL_LAYOUT_HRGB: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_HBGR: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = true; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VRGB: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VBGR: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = true; + } break; + default: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + } + } break; + } + if (!outline) { if (!p_font_data->msdf) { - error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); + error = FT_Render_Glyph(fd->face->glyph, aa_mode); } FT_GlyphSlot slot = fd->face->glyph; if (!error) { @@ -1244,7 +1331,7 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!"); #endif } else { - gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0); + gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra); } } } else { @@ -1264,11 +1351,11 @@ _FORCE_INLINE_ bool TextServerAdvanced::_ensure_glyph(FontAdvanced *p_font_data, if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) { goto cleanup_glyph; } - if (FT_Glyph_To_Bitmap(&glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1) != 0) { + if (FT_Glyph_To_Bitmap(&glyph, aa_mode, nullptr, 1) != 0) { goto cleanup_glyph; } glyph_bitmap = (FT_BitmapGlyph)glyph; - gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2()); + gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2(), bgra); cleanup_glyph: FT_Done_Glyph(glyph); @@ -1925,23 +2012,23 @@ String TextServerAdvanced::font_get_name(const RID &p_font_rid) const { return fd->font_name; } -void TextServerAdvanced::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { +void TextServerAdvanced::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) { FontAdvanced *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); - if (fd->antialiased != p_antialiased) { + if (fd->antialiasing != p_antialiasing) { _font_clear_cache(fd); - fd->antialiased = p_antialiased; + fd->antialiasing = p_antialiasing; } } -bool TextServerAdvanced::font_is_antialiased(const RID &p_font_rid) const { +TextServer::FontAntialiasing TextServerAdvanced::font_get_antialiasing(RID p_font_rid) const { FontAdvanced *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND_V(!fd, false); + ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE); MutexLock lock(fd->mutex); - return fd->antialiased; + return fd->antialiasing; } void TextServerAdvanced::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { @@ -2514,7 +2601,16 @@ Vector2 TextServerAdvanced::font_get_glyph_advance(const RID &p_font_rid, int64_ Vector2i size = _get_size(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2557,7 +2653,16 @@ Vector2 TextServerAdvanced::font_get_glyph_offset(const RID &p_font_rid, const V Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2593,7 +2698,16 @@ Vector2 TextServerAdvanced::font_get_glyph_size(const RID &p_font_rid, const Vec Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2629,7 +2743,16 @@ Rect2 TextServerAdvanced::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Rect2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2660,7 +2783,16 @@ int64_t TextServerAdvanced::font_get_glyph_texture_idx(const RID &p_font_rid, co Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return -1; // Invalid or non graphicl glyph, do not display errors. } @@ -2691,7 +2823,16 @@ RID TextServerAdvanced::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return RID(); // Invalid or non graphicl glyph, do not display errors. } @@ -2730,7 +2871,16 @@ Size2 TextServerAdvanced::font_get_glyph_texture_size(const RID &p_font_rid, con Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Size2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2986,16 +3136,18 @@ void TextServerAdvanced::font_render_range(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -3016,16 +3168,18 @@ void TextServerAdvanced::font_render_glyph(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -3041,9 +3195,19 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -3065,7 +3229,7 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can if (gl.texture_idx != -1) { Color modulate = p_color; #ifdef MODULE_FREETYPE_ENABLED - if (fd->cache[size]->face && fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) { + if (fd->cache[size]->face && (fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) && !lcd_aa) { modulate.r = modulate.g = modulate.b = 1.0; } #endif @@ -3103,7 +3267,11 @@ void TextServerAdvanced::font_draw_glyph(const RID &p_font_rid, const RID &p_can } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } @@ -3119,9 +3287,19 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -3181,7 +3359,11 @@ void TextServerAdvanced::font_draw_glyph_outline(const RID &p_font_rid, const RI } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } @@ -4947,6 +5129,14 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(p_sd->hb_buffer, &glyph_count); hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(p_sd->hb_buffer, &glyph_count); + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + // Process glyphs. if (glyph_count > 0) { Glyph *w = (Glyph *)memalloc(glyph_count * sizeof(Glyph)); @@ -5000,7 +5190,7 @@ void TextServerAdvanced::_shape_run(ShapedTextDataAdvanced *p_sd, int64_t p_star gl.index = glyph_info[i].codepoint; if (gl.index != 0) { - _ensure_glyph(fd, fss, gl.index); + _ensure_glyph(fd, fss, gl.index | mod); if (p_sd->orientation == ORIENTATION_HORIZONTAL) { if (subpos) { gl.advance = glyph_pos[i].x_advance / (64.0 / scale) + ea; diff --git a/modules/text_server_adv/text_server_adv.h b/modules/text_server_adv/text_server_adv.h index 6c3e8dbdcb..02abc31c55 100644 --- a/modules/text_server_adv/text_server_adv.h +++ b/modules/text_server_adv/text_server_adv.h @@ -223,7 +223,7 @@ class TextServerAdvanced : public TextServerExtension { struct FontAdvanced { Mutex mutex; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool msdf = false; int msdf_range = 14; @@ -271,7 +271,7 @@ class TextServerAdvanced : public TextServerExtension { _FORCE_INLINE_ FontGlyph rasterize_msdf(FontAdvanced *p_font_data, FontForSizeAdvanced *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif #ifdef MODULE_FREETYPE_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeAdvanced *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const; #endif _FORCE_INLINE_ bool _ensure_glyph(FontAdvanced *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontAdvanced *p_font_data, const Vector2i &p_size) const; @@ -498,8 +498,8 @@ public: virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_name(const RID &p_font_rid) const override; - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(const RID &p_font_rid) const override; + virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override; + virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; diff --git a/modules/text_server_fb/text_server_fb.cpp b/modules/text_server_fb/text_server_fb.cpp index 016bcfc886..53b303cb20 100644 --- a/modules/text_server_fb/text_server_fb.cpp +++ b/modules/text_server_fb/text_server_fb.cpp @@ -34,6 +34,7 @@ // Headers for building as GDExtension plug-in. #include <godot_cpp/classes/file.hpp> +#include <godot_cpp/classes/project_settings.hpp> #include <godot_cpp/classes/rendering_server.hpp> #include <godot_cpp/classes/translation_server.hpp> #include <godot_cpp/core/error_macros.hpp> @@ -43,6 +44,7 @@ using namespace godot; #else // Headers for building as built-in module. +#include "core/config/project_settings.h" #include "core/error/error_macros.h" #include "core/string/print_string.h" #include "core/string/ucaps.h" @@ -209,6 +211,10 @@ _FORCE_INLINE_ TextServerFallback::FontTexturePosition TextServerFallback::find_ for (int i = 0; i < p_data->textures.size(); i++) { const FontTexture &ct = p_data->textures[i]; + if (p_image_format != ct.format) { + continue; + } + if (mw > ct.texture_w || mh > ct.texture_h) { // Too big for this texture. continue; } @@ -500,9 +506,28 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_msdf( #endif #ifdef MODULE_FREETYPE_ENABLED -_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const { +_FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const { int w = bitmap.width; int h = bitmap.rows; + int color_size = 2; + + switch (bitmap.pixel_mode) { + case FT_PIXEL_MODE_MONO: + case FT_PIXEL_MODE_GRAY: { + color_size = 2; + } break; + case FT_PIXEL_MODE_BGRA: { + color_size = 4; + } break; + case FT_PIXEL_MODE_LCD: { + color_size = 4; + w /= 3; + } break; + case FT_PIXEL_MODE_LCD_V: { + color_size = 4; + h /= 3; + } break; + } int mw = w + p_rect_margin * 4; int mh = h + p_rect_margin * 4; @@ -510,7 +535,6 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma ERR_FAIL_COND_V(mw > 4096, FontGlyph()); ERR_FAIL_COND_V(mh > 4096, FontGlyph()); - int color_size = bitmap.pixel_mode == FT_PIXEL_MODE_BGRA ? 4 : 2; Image::Format require_format = color_size == 4 ? Image::FORMAT_RGBA8 : Image::FORMAT_LA8; FontTexturePosition tex_pos = find_texture_pos_for_glyph(p_data, color_size, require_format, mw, mh, false); @@ -545,6 +569,34 @@ _FORCE_INLINE_ TextServerFallback::FontGlyph TextServerFallback::rasterize_bitma wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; wr[ofs + 3] = bitmap.buffer[ofs_color + 3]; } break; + case FT_PIXEL_MODE_LCD: { + int ofs_color = i * bitmap.pitch + (j * 3); + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + 1]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } + } break; + case FT_PIXEL_MODE_LCD_V: { + int ofs_color = i * bitmap.pitch * 3 + j; + if (p_bgra) { + wr[ofs + 0] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 3] = 255; + } else { + wr[ofs + 0] = bitmap.buffer[ofs_color + 0]; + wr[ofs + 1] = bitmap.buffer[ofs_color + bitmap.pitch]; + wr[ofs + 2] = bitmap.buffer[ofs_color + bitmap.pitch * 2]; + wr[ofs + 3] = 255; + } + } break; default: ERR_FAIL_V_MSG(FontGlyph(), "Font uses unsupported pixel format: " + String::num_int64(bitmap.pixel_mode) + "."); break; @@ -650,9 +702,44 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, FT_Outline_Transform(&fd->face->glyph->outline, &mat); } + FT_Render_Mode aa_mode = FT_RENDER_MODE_NORMAL; + bool bgra = false; + switch (p_font_data->antialiasing) { + case FONT_ANTIALIASING_NONE: { + aa_mode = FT_RENDER_MODE_MONO; + } break; + case FONT_ANTIALIASING_GRAY: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + case FONT_ANTIALIASING_LCD: { + int aa_layout = (int)((p_glyph >> 24) & 7); + switch (aa_layout) { + case FONT_LCD_SUBPIXEL_LAYOUT_HRGB: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_HBGR: { + aa_mode = FT_RENDER_MODE_LCD; + bgra = true; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VRGB: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = false; + } break; + case FONT_LCD_SUBPIXEL_LAYOUT_VBGR: { + aa_mode = FT_RENDER_MODE_LCD_V; + bgra = true; + } break; + default: { + aa_mode = FT_RENDER_MODE_NORMAL; + } break; + } + } break; + } + if (!outline) { if (!p_font_data->msdf) { - error = FT_Render_Glyph(fd->face->glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); + error = FT_Render_Glyph(fd->face->glyph, aa_mode); } FT_GlyphSlot slot = fd->face->glyph; if (!error) { @@ -664,7 +751,7 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, ERR_FAIL_V_MSG(false, "Compiled without MSDFGEN support!"); #endif } else { - gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0); + gl = rasterize_bitmap(fd, rect_range, slot->bitmap, slot->bitmap_top, slot->bitmap_left, Vector2((h + (1 << 9)) >> 10, (v + (1 << 9)) >> 10) / 64.0, bgra); } } } else { @@ -684,11 +771,11 @@ _FORCE_INLINE_ bool TextServerFallback::_ensure_glyph(FontFallback *p_font_data, if (FT_Glyph_Stroke(&glyph, stroker, 1) != 0) { goto cleanup_glyph; } - if (FT_Glyph_To_Bitmap(&glyph, p_font_data->antialiased ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, nullptr, 1) != 0) { + if (FT_Glyph_To_Bitmap(&glyph, aa_mode, nullptr, 1) != 0) { goto cleanup_glyph; } glyph_bitmap = (FT_BitmapGlyph)glyph; - gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2()); + gl = rasterize_bitmap(fd, rect_range, glyph_bitmap->bitmap, glyph_bitmap->top, glyph_bitmap->left, Vector2(), bgra); cleanup_glyph: FT_Done_Glyph(glyph); @@ -1014,23 +1101,23 @@ String TextServerFallback::font_get_name(const RID &p_font_rid) const { return fd->font_name; } -void TextServerFallback::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { +void TextServerFallback::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) { FontFallback *fd = font_owner.get_or_null(p_font_rid); ERR_FAIL_COND(!fd); MutexLock lock(fd->mutex); - if (fd->antialiased != p_antialiased) { + if (fd->antialiasing != p_antialiasing) { _font_clear_cache(fd); - fd->antialiased = p_antialiased; + fd->antialiasing = p_antialiasing; } } -bool TextServerFallback::font_is_antialiased(const RID &p_font_rid) const { +TextServer::FontAntialiasing TextServerFallback::font_get_antialiasing(RID p_font_rid) const { FontFallback *fd = font_owner.get_or_null(p_font_rid); - ERR_FAIL_COND_V(!fd, false); + ERR_FAIL_COND_V(!fd, TextServer::FONT_ANTIALIASING_NONE); MutexLock lock(fd->mutex); - return fd->antialiased; + return fd->antialiasing; } void TextServerFallback::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { @@ -1589,7 +1676,16 @@ Vector2 TextServerFallback::font_get_glyph_advance(const RID &p_font_rid, int64_ Vector2i size = _get_size(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1632,7 +1728,16 @@ Vector2 TextServerFallback::font_get_glyph_offset(const RID &p_font_rid, const V Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1668,7 +1773,16 @@ Vector2 TextServerFallback::font_get_glyph_size(const RID &p_font_rid, const Vec Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Vector2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Vector2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1704,7 +1818,16 @@ Rect2 TextServerFallback::font_get_glyph_uv_rect(const RID &p_font_rid, const Ve Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Rect2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Rect2(); // Invalid or non graphicl glyph, do not display errors. } @@ -1735,7 +1858,16 @@ int64_t TextServerFallback::font_get_glyph_texture_idx(const RID &p_font_rid, co Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), -1); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return -1; // Invalid or non graphicl glyph, do not display errors. } @@ -1766,7 +1898,16 @@ RID TextServerFallback::font_get_glyph_texture_rid(const RID &p_font_rid, const Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), RID()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return RID(); // Invalid or non graphicl glyph, do not display errors. } @@ -1805,7 +1946,16 @@ Size2 TextServerFallback::font_get_glyph_texture_size(const RID &p_font_rid, con Vector2i size = _get_size_outline(fd, p_size); ERR_FAIL_COND_V(!_ensure_cache_for_size(fd, size), Size2()); - if (!_ensure_glyph(fd, size, p_glyph)) { + + int mod = 0; + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + mod = (layout << 24); + } + } + + if (!_ensure_glyph(fd, size, p_glyph | mod)) { return Size2(); // Invalid or non graphicl glyph, do not display errors. } @@ -2043,16 +2193,18 @@ void TextServerFallback::font_render_range(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -2073,16 +2225,18 @@ void TextServerFallback::font_render_glyph(const RID &p_font_rid, const Vector2i if (fd->msdf) { _ensure_glyph(fd, size, (int32_t)idx); } else { - if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (2 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (3 << 27)); - } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { - _ensure_glyph(fd, size, (int32_t)idx | (1 << 27)); - _ensure_glyph(fd, size, (int32_t)idx | (0 << 27)); - } else { - _ensure_glyph(fd, size, (int32_t)idx); + for (int aa = 0; aa < ((fd->antialiasing == FONT_ANTIALIASING_LCD) ? FONT_LCD_SUBPIXEL_LAYOUT_MAX : 1); aa++) { + if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (2 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (3 << 27) | (aa << 24)); + } else if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_HALF) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_HALF_MAX_SIZE)) { + _ensure_glyph(fd, size, (int32_t)idx | (1 << 27) | (aa << 24)); + _ensure_glyph(fd, size, (int32_t)idx | (0 << 27) | (aa << 24)); + } else { + _ensure_glyph(fd, size, (int32_t)idx | (aa << 24)); + } } } } @@ -2098,9 +2252,19 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -2122,7 +2286,7 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can if (gl.texture_idx != -1) { Color modulate = p_color; #ifdef MODULE_FREETYPE_ENABLED - if (fd->cache[size]->face && fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) { + if (fd->cache[size]->face && (fd->cache[size]->textures[gl.texture_idx].format == Image::FORMAT_RGBA8) && !lcd_aa) { modulate.r = modulate.g = modulate.b = 1.0; } #endif @@ -2160,7 +2324,11 @@ void TextServerFallback::font_draw_glyph(const RID &p_font_rid, const RID &p_can } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } @@ -2176,9 +2344,19 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI ERR_FAIL_COND(!_ensure_cache_for_size(fd, size)); int32_t index = p_index & 0xffffff; // Remove subpixel shifts. + bool lcd_aa = false; #ifdef MODULE_FREETYPE_ENABLED if (!fd->msdf && fd->cache[size]->face) { + // LCD layout, bits 24, 25, 26 + if (fd->antialiasing == FONT_ANTIALIASING_LCD) { + TextServer::FontLCDSubpixelLayout layout = (TextServer::FontLCDSubpixelLayout)(int)GLOBAL_GET("gui/theme/lcd_subpixel_layout"); + if (layout != FONT_LCD_SUBPIXEL_LAYOUT_NONE) { + lcd_aa = true; + index = index | (layout << 24); + } + } + // Subpixel X-shift, bits 27, 28 if ((fd->subpixel_positioning == SUBPIXEL_POSITIONING_ONE_QUARTER) || (fd->subpixel_positioning == SUBPIXEL_POSITIONING_AUTO && size.x <= SUBPIXEL_POSITIONING_ONE_QUARTER_MAX_SIZE)) { int xshift = (int)(Math::floor(4 * (p_pos.x + 0.125)) - 4 * Math::floor(p_pos.x + 0.125)); index = index | (xshift << 27); @@ -2238,7 +2416,11 @@ void TextServerFallback::font_draw_glyph_outline(const RID &p_font_rid, const RI } cpos += gl.rect.position; Size2 csize = gl.rect.size; - RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + if (lcd_aa) { + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate); + } else { + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas, Rect2(cpos, csize), texture, gl.uv_rect, modulate, false, false); + } } } } diff --git a/modules/text_server_fb/text_server_fb.h b/modules/text_server_fb/text_server_fb.h index 8e81433a2a..940c57a354 100644 --- a/modules/text_server_fb/text_server_fb.h +++ b/modules/text_server_fb/text_server_fb.h @@ -179,7 +179,7 @@ class TextServerFallback : public TextServerExtension { struct FontFallback { Mutex mutex; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool msdf = false; int msdf_range = 14; @@ -225,7 +225,7 @@ class TextServerFallback : public TextServerExtension { _FORCE_INLINE_ FontGlyph rasterize_msdf(FontFallback *p_font_data, FontForSizeFallback *p_data, int p_pixel_range, int p_rect_margin, FT_Outline *outline, const Vector2 &advance) const; #endif #ifdef MODULE_FREETYPE_ENABLED - _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance) const; + _FORCE_INLINE_ FontGlyph rasterize_bitmap(FontForSizeFallback *p_data, int p_rect_margin, FT_Bitmap bitmap, int yofs, int xofs, const Vector2 &advance, bool p_bgra) const; #endif _FORCE_INLINE_ bool _ensure_glyph(FontFallback *p_font_data, const Vector2i &p_size, int32_t p_glyph) const; _FORCE_INLINE_ bool _ensure_cache_for_size(FontFallback *p_font_data, const Vector2i &p_size) const; @@ -378,8 +378,8 @@ public: virtual void font_set_name(const RID &p_font_rid, const String &p_name) override; virtual String font_get_name(const RID &p_font_rid) const override; - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(const RID &p_font_rid) const override; + virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override; + virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; diff --git a/modules/upnp/doc_classes/UPNP.xml b/modules/upnp/doc_classes/UPNP.xml index 847110abd4..4888dca822 100644 --- a/modules/upnp/doc_classes/UPNP.xml +++ b/modules/upnp/doc_classes/UPNP.xml @@ -1,16 +1,15 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="UPNP" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> - UPNP network functions. + Universal Plug and Play (UPnP) functions for network device discovery, querying and port forwarding. </brief_description> <description> - Provides UPNP functionality to discover [UPNPDevice]s on the local network and execute commands on them, like managing port mappings (port forwarding) and querying the local and remote network IP address. Note that methods on this class are synchronous and block the calling thread. - To forward a specific port: + This class can be used to discover compatible [UPNPDevice]s on the local network and execute commands on them, like managing port mappings (for port forwarding/NAT traversal) and querying the local and remote network IP address. Note that methods on this class are synchronous and block the calling thread. + To forward a specific port (here [code]7777[/code], note both [method discover] and [method add_port_mapping] can return errors that should be checked): [codeblock] - const PORT = 7777 var upnp = UPNP.new() - upnp.discover(2000, 2, "InternetGatewayDevice") - upnp.add_port_mapping(port) + upnp.discover() + upnp.add_port_mapping(7777) [/codeblock] To close a specific port (e.g. after you have finished using it): [codeblock] @@ -21,7 +20,7 @@ # Emitted when UPnP port mapping setup is completed (regardless of success or failure). signal upnp_completed(error) - # Replace this with your own server port number between 1025 and 65535. + # Replace this with your own server port number between 1024 and 65535. const SERVER_PORT = 3928 var thread = null @@ -48,6 +47,14 @@ # Wait for thread finish here to handle game exit while the thread is running. thread.wait_to_finish() [/codeblock] + [b]Terminology:[/b] In the context of UPnP networking, "gateway" (or "internet gateway device", short IGD) refers to network devices that allow computers in the local network to access the internet ("wide area network", WAN). These gateways are often also called "routers". + [b]Pitfalls:[/b] + - As explained above, these calls are blocking and shouldn't be run on the main thread, especially as they can block for multiple seconds at a time. Use threading! + - Networking is physical and messy. Packets get lost in transit or get filtered, addresses, free ports and assigned mappings change, and devices may leave or join the network at any time. Be mindful of this, be diligent when checking and handling errors, and handle these gracefully if you can: add clear error UI, timeouts and re-try handling. + - Port mappings may change (and be removed) at any time, and the remote/external IP address of the gateway can change likewise. You should consider re-querying the external IP and try to update/refresh the port mapping periodically (for example, every 5 minutes and on networking failures). + - Not all devices support UPnP, and some users disable UPnP support. You need to handle this (e.g. documenting and requiring the user to manually forward ports, or adding alternative methods of NAT traversal, like a relay/mirror server, or NAT hole punching, STUN/TURN, etc.). + - Consider what happens on mapping conflicts. Maybe multiple users on the same network would like to play your game at the same time, or maybe another application uses the same port. Make the port configurable, and optimally choose a port automatically (re-trying with a different port on failure). + [b]Further reading:[/b] If you want to know more about UPnP (and the Internet Gateway Device (IGD) and Port Control Protocol (PCP) specifically), [url=https://en.wikipedia.org/wiki/Universal_Plug_and_Play]Wikipedia[/url] is a good first stop, the specification can be found at the [url=https://openconnectivity.org/developer/specifications/upnp-resources/upnp/]Open Connectivity Foundation[/url] and Godot's implementation is based on the [url=https://github.com/miniupnp/miniupnp]MiniUPnP client[/url]. </description> <tutorials> </tutorials> @@ -67,9 +74,11 @@ <param index="3" name="proto" type="String" default=""UDP"" /> <param index="4" name="duration" type="int" default="0" /> <description> - Adds a mapping to forward the external [code]port[/code] (between 1 and 65535) on the default gateway (see [method get_gateway]) to the [code]internal_port[/code] on the local machine for the given protocol [code]proto[/code] (either [code]TCP[/code] or [code]UDP[/code], with UDP being the default). If a port mapping for the given port and protocol combination already exists on that gateway device, this method tries to overwrite it. If that is not desired, you can retrieve the gateway manually with [method get_gateway] and call [method add_port_mapping] on it, if any. + Adds a mapping to forward the external [code]port[/code] (between 1 and 65535, although recommended to use port 1024 or above) on the default gateway (see [method get_gateway]) to the [code]internal_port[/code] on the local machine for the given protocol [code]proto[/code] (either [code]TCP[/code] or [code]UDP[/code], with UDP being the default). If a port mapping for the given port and protocol combination already exists on that gateway device, this method tries to overwrite it. If that is not desired, you can retrieve the gateway manually with [method get_gateway] and call [method add_port_mapping] on it, if any. Note that forwarding a well-known port (below 1024) with UPnP may fail depending on the device. + Depending on the gateway device, if a mapping for that port already exists, it will either be updated or it will refuse this command due to that conflict, especially if the existing mapping for that port wasn't created via UPnP or points to a different network address (or device) than this one. If [code]internal_port[/code] is [code]0[/code] (the default), the same port number is used for both the external and the internal port (the [code]port[/code] value). - The description ([code]desc[/code]) is shown in some router UIs and can be used to point out which application added the mapping. The mapping's lease duration can be limited by specifying a [code]duration[/code] (in seconds). However, some routers are incompatible with one or both of these, so use with caution and add fallback logic in case of errors to retry without them if in doubt. + The description ([code]desc[/code]) is shown in some routers management UIs and can be used to point out which application added the mapping. + The mapping's lease [code]duration[/code] can be limited by specifying a duration in seconds. The default of [code]0[/code] means no duration, i.e. a permanent lease and notably some devices only support these permanent leases. Note that whether permanent or not, this is only a request and the gateway may still decide at any point to remove the mapping (which usually happens on a reboot of the gateway, when its external IP address changes, or on some models when it detects a port mapping has become inactive, i.e. had no traffic for multiple minutes). If not [code]0[/code] (permanent), the allowed range according to spec is between [code]120[/code] (2 minutes) and [code]86400[/code] seconds (24 hours). See [enum UPNPResult] for possible return values. </description> </method> @@ -84,7 +93,7 @@ <param index="0" name="port" type="int" /> <param index="1" name="proto" type="String" default=""UDP"" /> <description> - Deletes the port mapping for the given port and protocol combination on the default gateway (see [method get_gateway]) if one exists. [code]port[/code] must be a valid port between 1 and 65535, [code]proto[/code] can be either [code]TCP[/code] or [code]UDP[/code]. See [enum UPNPResult] for possible return values. + Deletes the port mapping for the given port and protocol combination on the default gateway (see [method get_gateway]) if one exists. [code]port[/code] must be a valid port between 1 and 65535, [code]proto[/code] can be either [code]TCP[/code] or [code]UDP[/code]. May be refused for mappings pointing to addresses other than this one, for well-known ports (below 1024), or for mappings not added via UPnP. See [enum UPNPResult] for possible return values. </description> </method> <method name="discover"> diff --git a/modules/upnp/doc_classes/UPNPDevice.xml b/modules/upnp/doc_classes/UPNPDevice.xml index b599acaba2..538ca72391 100644 --- a/modules/upnp/doc_classes/UPNPDevice.xml +++ b/modules/upnp/doc_classes/UPNPDevice.xml @@ -1,10 +1,10 @@ <?xml version="1.0" encoding="UTF-8" ?> <class name="UPNPDevice" inherits="RefCounted" version="4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../doc/class.xsd"> <brief_description> - UPNP device. + Universal Plug and Play (UPnP) device. </brief_description> <description> - UPNP device. See [UPNP] for UPNP discovery and utility functions. Provides low-level access to UPNP control commands. Allows to manage port mappings (port forwarding) and to query network information of the device (like local and external IP address and status). Note that methods on this class are synchronous and block the calling thread. + Universal Plug and Play (UPnP) device. See [UPNP] for UPnP discovery and utility functions. Provides low-level access to UPNP control commands. Allows to manage port mappings (port forwarding) and to query network information of the device (like local and external IP address and status). Note that methods on this class are synchronous and block the calling thread. </description> <tutorials> </tutorials> diff --git a/modules/upnp/upnp.cpp b/modules/upnp/upnp.cpp index d762ca4f09..82fe39e003 100644 --- a/modules/upnp/upnp.cpp +++ b/modules/upnp/upnp.cpp @@ -319,8 +319,6 @@ int UPNP::add_port_mapping(int port, int port_internal, String desc, String prot return UPNP_RESULT_NO_GATEWAY; } - dev->delete_port_mapping(port, proto); - return dev->add_port_mapping(port, port_internal, desc, proto, duration); } diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 016af40b52..685b1f01af 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -588,9 +588,9 @@ zip_fileinfo EditorExportPlatformAndroid::get_zip_fileinfo() { Vector<String> EditorExportPlatformAndroid::get_abis() { Vector<String> abis; - abis.push_back("arm32"); - abis.push_back("arm64"); - abis.push_back("x86_32"); + abis.push_back("armeabi-v7a"); + abis.push_back("arm64-v8a"); + abis.push_back("x86"); abis.push_back("x86_64"); return abis; } @@ -1710,7 +1710,7 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio const String abi = abis[i]; // All Android devices supporting Vulkan run 64-bit Android, // so there is usually no point in exporting for 32-bit Android. - const bool is_default = abi == "arm64"; + const bool is_default = abi == "arm64-v8a"; r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, vformat("%s/%s", PNAME("architectures"), abi)), is_default)); } diff --git a/platform/ios/export/export_plugin.cpp b/platform/ios/export/export_plugin.cpp index db55c7944f..f49cf7a88d 100644 --- a/platform/ios/export/export_plugin.cpp +++ b/platform/ios/export/export_plugin.cpp @@ -387,13 +387,17 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ String locale_files; Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); if (translations.size() > 0) { - int index = 0; + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };"; + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); } + } + + int index = 0; + for (const String &lang : languages) { + locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = " + lang + "; path = " + lang + ".lproj/InfoPlist.strings; sourceTree = \"<group>\"; };\n"; index++; } } @@ -402,13 +406,17 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ String locale_files; Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); if (translations.size() > 0) { - int index = 0; + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,"; + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); } + } + + int index = 0; + for (const String &lang : languages) { + locale_files += "D0BCFE4518AEBDA2004A" + itos(index).pad_zeros(4) + " /* " + lang + " */,\n"; index++; } } @@ -1658,27 +1666,31 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";"); } + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - String fname = dest_dir + binary_name + "/" + lang + ".lproj"; - tmp_app_path->make_dir_recursive(fname); - Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - f->store_line("/* Localized versions of Info.plist keys */"); - f->store_line(""); - if (appnames.has(lang)) { - f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";"); - } - if (camera_usage_descriptions.has(lang)) { - f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";"); - } - if (microphone_usage_descriptions.has(lang)) { - f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";"); - } - if (photolibrary_usage_descriptions.has(lang)) { - f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";"); - } + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); + } + } + + for (const String &lang : languages) { + String fname = dest_dir + binary_name + "/" + lang + ".lproj"; + tmp_app_path->make_dir_recursive(fname); + Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + f->store_line("/* Localized versions of Info.plist keys */"); + f->store_line(""); + if (appnames.has(lang)) { + f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";"); + } + if (camera_usage_descriptions.has(lang)) { + f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";"); + } + if (microphone_usage_descriptions.has(lang)) { + f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";"); + } + if (photolibrary_usage_descriptions.has(lang)) { + f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";"); } } } diff --git a/platform/linuxbsd/detect.py b/platform/linuxbsd/detect.py index 8563cc3cb2..dd829bdb9b 100644 --- a/platform/linuxbsd/detect.py +++ b/platform/linuxbsd/detect.py @@ -387,7 +387,9 @@ def configure(env): import subprocess import re - linker_version_str = subprocess.check_output([env.subst(env["LINK"]), "-Wl,--version"]).decode("utf-8") + linker_version_str = subprocess.check_output( + [env.subst(env["LINK"]), "-Wl,--version"] + env.subst(env["LINKFLAGS"]) + ).decode("utf-8") gnu_ld_version = re.search("^GNU ld [^$]*(\d+\.\d+)$", linker_version_str, re.MULTILINE) if not gnu_ld_version: print( diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp index 197d31dc81..a74ca155a4 100644 --- a/platform/linuxbsd/os_linuxbsd.cpp +++ b/platform/linuxbsd/os_linuxbsd.cpp @@ -519,8 +519,6 @@ String OS_LinuxBSD::get_system_dir(SystemDir p_dir, bool p_shared_storage) const } void OS_LinuxBSD::run() { - force_quit = false; - if (!main_loop) { return; } @@ -532,7 +530,7 @@ void OS_LinuxBSD::run() { //int frames=0; //uint64_t frame=0; - while (!force_quit) { + while (true) { DisplayServer::get_singleton()->process_events(); // get rid of pending events #ifdef JOYDEV_ENABLED joypad->process_joypads(); @@ -730,7 +728,6 @@ Error OS_LinuxBSD::move_to_trash(const String &p_path) { OS_LinuxBSD::OS_LinuxBSD() { main_loop = nullptr; - force_quit = false; #ifdef PULSEAUDIO_ENABLED AudioDriverManager::add_driver(&driver_pulseaudio); diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h index cc4e91e885..d5b2321316 100644 --- a/platform/linuxbsd/os_linuxbsd.h +++ b/platform/linuxbsd/os_linuxbsd.h @@ -43,8 +43,6 @@ class OS_LinuxBSD : public OS_Unix { virtual void delete_main_loop() override; - bool force_quit; - #ifdef FONTCONFIG_ENABLED bool font_config_initialized = false; #endif diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index e305ff3593..a08667a259 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -377,6 +377,11 @@ public: virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override; virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override; + virtual bool window_maximize_on_title_dbl_click() const override; + virtual bool window_minimize_on_title_dbl_click() const override; + + virtual Vector2i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const override; + virtual Point2i ime_get_selection() const override; virtual String ime_get_text() const override; diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index fa6bcda902..b06ae9f27c 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -703,6 +703,7 @@ bool DisplayServerMacOS::has_feature(Feature p_feature) const { //case FEATURE_KEEP_SCREEN_ON: case FEATURE_SWAP_BUFFERS: case FEATURE_TEXT_TO_SPEECH: + case FEATURE_EXTEND_TO_TITLE: return true; default: { } @@ -2538,6 +2539,45 @@ bool DisplayServerMacOS::window_is_maximize_allowed(WindowID p_window) const { return true; } +bool DisplayServerMacOS::window_maximize_on_title_dbl_click() const { + id value = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleActionOnDoubleClick"]; + if ([value isKindOfClass:[NSString class]]) { + return [value isEqualToString:@"Maximize"]; + } + return false; +} + +bool DisplayServerMacOS::window_minimize_on_title_dbl_click() const { + id value = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleActionOnDoubleClick"]; + if ([value isKindOfClass:[NSString class]]) { + return [value isEqualToString:@"Minimize"]; + } + return false; +} + +Vector2i DisplayServerMacOS::window_get_safe_title_margins(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Vector2i()); + const WindowData &wd = windows[p_window]; + + float max_x = 0.f; + NSButton *cb = [wd.window_object standardWindowButton:NSWindowCloseButton]; + if (cb) { + max_x = MAX(max_x, [cb frame].origin.x + [cb frame].size.width); + } + NSButton *mb = [wd.window_object standardWindowButton:NSWindowMiniaturizeButton]; + if (mb) { + max_x = MAX(max_x, [mb frame].origin.x + [mb frame].size.width); + } + NSButton *zb = [wd.window_object standardWindowButton:NSWindowZoomButton]; + if (zb) { + max_x = MAX(max_x, [zb frame].origin.x + [zb frame].size.width); + } + + return Vector2i(max_x * screen_get_max_scale(), 0); +} + void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -2556,6 +2596,19 @@ void DisplayServerMacOS::window_set_flag(WindowFlags p_flag, bool p_enabled, Win [wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskResizable]; } } break; + case WINDOW_FLAG_EXTEND_TO_TITLE: { + NSRect rect = [wd.window_object frame]; + if (p_enabled) { + [wd.window_object setTitlebarAppearsTransparent:YES]; + [wd.window_object setTitleVisibility:NSWindowTitleHidden]; + [wd.window_object setStyleMask:[wd.window_object styleMask] | NSWindowStyleMaskFullSizeContentView]; + } else { + [wd.window_object setTitlebarAppearsTransparent:NO]; + [wd.window_object setTitleVisibility:NSWindowTitleVisible]; + [wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskFullSizeContentView]; + } + [wd.window_object setFrame:rect display:YES]; + } break; case WINDOW_FLAG_BORDERLESS: { // OrderOut prevents a lose focus bug with the window. if ([wd.window_object isVisible]) { @@ -2623,6 +2676,9 @@ bool DisplayServerMacOS::window_get_flag(WindowFlags p_flag, WindowID p_window) case WINDOW_FLAG_RESIZE_DISABLED: { return wd.resize_disabled; } break; + case WINDOW_FLAG_EXTEND_TO_TITLE: { + return [wd.window_object styleMask] & NSWindowStyleMaskFullSizeContentView; + } break; case WINDOW_FLAG_BORDERLESS: { return [wd.window_object styleMask] == NSWindowStyleMaskBorderless; } break; diff --git a/platform/macos/export/export.cpp b/platform/macos/export/export.cpp index ff7457081f..f219616df4 100644 --- a/platform/macos/export/export.cpp +++ b/platform/macos/export/export.cpp @@ -33,8 +33,12 @@ #include "export_plugin.h" void register_macos_exporter() { - EDITOR_DEF("export/macos/force_builtin_codesign", false); - EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::BOOL, "export/macos/force_builtin_codesign", PROPERTY_HINT_NONE)); + EDITOR_DEF("export/macos/rcodesign", ""); +#ifdef WINDOWS_ENABLED + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/macos/rcodesign", PROPERTY_HINT_GLOBAL_FILE, "*.exe")); +#else + EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/macos/rcodesign", PROPERTY_HINT_GLOBAL_FILE)); +#endif Ref<EditorExportPlatformMacOS> platform; platform.instantiate(); diff --git a/platform/macos/export/export_plugin.cpp b/platform/macos/export/export_plugin.cpp index edce9c0380..4b453add5a 100644 --- a/platform/macos/export/export_plugin.cpp +++ b/platform/macos/export/export_plugin.cpp @@ -51,11 +51,51 @@ void EditorExportPlatformMacOS::get_preset_features(const Ref<EditorExportPreset r_features->push_back(p_preset->get("binary_format/architecture")); } -bool EditorExportPlatformMacOS::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { - // These options are not supported by built-in codesign, used on non macOS host. - if (!OS::get_singleton()->has_feature("macos")) { - if (p_option == "codesign/identity" || p_option == "codesign/timestamp" || p_option == "codesign/hardened_runtime" || p_option == "codesign/custom_options" || p_option.begins_with("notarization/")) { - return false; +bool EditorExportPlatformMacOS::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const { + // Hide irrelevant code signing options. + if (p_preset) { + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + if (p_option == "codesign/identity" || p_option == "codesign/certificate_file" || p_option == "codesign/certificate_password" || p_option == "codesign/custom_options") { + return false; + } + } break; + case 2: { // "rcodesign" + if (p_option == "codesign/identity") { + return false; + } + } break; +#ifdef MACOS_ENABLED + case 3: { // "codesign" + if (p_option == "codesign/certificate_file" || p_option == "codesign/certificate_password") { + return false; + } + } break; +#endif + default: { // disabled + if (p_option == "codesign/identity" || p_option == "codesign/certificate_file" || p_option == "codesign/certificate_password" || p_option == "codesign/custom_options" || p_option.begins_with("codesign/entitlements")) { + return false; + } + } break; + } + + // Hide irrelevant notarization options. + int notary_tool = p_preset->get("notarization/notarization"); + switch (notary_tool) { + case 1: { // "rcodesign" + if (p_option == "notarization/apple_id_name" || p_option == "notarization/apple_id_password" || p_option == "notarization/apple_team_id") { + return false; + } + } break; + case 2: { // "altool" + // All options are visible. + } break; + default: { // disabled + if (p_option == "notarization/apple_id_name" || p_option == "notarization/apple_id_password" || p_option == "notarization/apple_team_id" || p_option == "notarization/api_uuid" || p_option == "notarization/api_key") { + return false; + } + } break; } } @@ -83,40 +123,22 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/copyright"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "application/copyright_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "display/high_res"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/location_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the location information"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/location_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/address_book_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the address book"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/address_book_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/calendar_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the calendar"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/calendar_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photos_library_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the photo library"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photos_library_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/desktop_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Desktop folder"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/desktop_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/documents_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Documents folder"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/documents_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/downloads_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Downloads folder"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/downloads_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/network_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use network volumes"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/network_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/removable_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), true)); +#ifdef MACOS_ENABLED + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),PyOxidizer rcodesign,Xcode codesign"), 3, true)); +#else + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/codesign", PROPERTY_HINT_ENUM, "Disabled,Built-in (ad-hoc only),PyOxidizer rcodesign"), 1, true)); +#endif + // "codesign" only options: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_PLACEHOLDER_TEXT, "Type: Name (ID)"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/replace_existing_signature"), true)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/hardened_runtime"), true)); + // "rcodesign" only options: + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_file", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/certificate_password", PROPERTY_HINT_PASSWORD), "")); + // "codesign" and "rcodesign" only options: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements/custom_file", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_jit_code_execution"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_unsigned_executable_memory"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/allow_dyld_environment_variables"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/disable_library_validation"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/audio_input"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/camera"), false)); @@ -126,7 +148,6 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/photos_library"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/apple_events"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/debugging"), false)); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/enabled"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_server"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/entitlements/app_sandbox/network_client"), false)); @@ -137,13 +158,43 @@ void EditorExportPlatformMacOS::get_export_options(List<ExportOption> *r_options r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array())); - r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray())); - r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "notarization/enable"), false)); +#ifdef MACOS_ENABLED + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,PyOxidizer rcodesign,Xcode altool"), 0, true)); +#else + r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "notarization/notarization", PROPERTY_HINT_ENUM, "Disabled,PyOxidizer rcodesign"), 0, true)); +#endif + // "altool" only options: r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Apple ID email"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PLACEHOLDER_TEXT, "Enable two-factor authentication and provide app-specific password"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PASSWORD, "Enable two-factor authentication and provide app-specific password"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_team_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide team ID if your Apple ID belongs to multiple teams"), "")); + // "altool" and "rcodesign" only options: + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_uuid", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect issuer ID"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/api_key", PROPERTY_HINT_PLACEHOLDER_TEXT, "App Store Connect API key ID"), "")); + + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/microphone_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the microphone"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/microphone_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/camera_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the camera"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/camera_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/location_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the location information"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/location_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/address_book_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the address book"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/address_book_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/calendar_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the calendar"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/calendar_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/photos_library_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use the photo library"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/photos_library_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/desktop_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Desktop folder"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/desktop_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/documents_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Documents folder"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/documents_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/downloads_folder_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use Downloads folder"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/downloads_folder_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/network_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use network volumes"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/network_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "privacy/removable_volumes_usage_description", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide a message if you need to use removable volumes"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::DICTIONARY, "privacy/removable_volumes_usage_description_localized", PROPERTY_HINT_LOCALIZABLE_STRING), Dictionary())); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/etc"), false)); @@ -415,156 +466,284 @@ void EditorExportPlatformMacOS::_fix_plist(const Ref<EditorExportPreset> &p_pres */ Error EditorExportPlatformMacOS::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) { + int notary_tool = p_preset->get("notarization/notarization"); + switch (notary_tool) { + case 1: { // "rcodesign" + print_verbose("using rcodesign notarization..."); + + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("rcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).")); + return Error::FAILED; + } + + List<String> args; + + args.push_back("notary-submit"); + + if (p_preset->get("notarization/api_uuid") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect issuer ID name not specified.")); + return Error::FAILED; + } + if (p_preset->get("notarization/api_key") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified.")); + return Error::FAILED; + } + + args.push_back("--api-issuer"); + args.push_back(p_preset->get("notarization/api_uuid")); + + args.push_back("--api-key"); + args.push_back(p_preset->get("notarization/api_key")); + + args.push_back(p_path); + + String str; + int exitcode = 0; + + Error err = OS::get_singleton()->execute(rcodesign, args, &str, &exitcode, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start rcodesign executable.")); + return err; + } + + int rq_offset = str.find("created submission ID:"); + if (exitcode != 0 || rq_offset == -1) { + print_line("rcodesign (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed, see editor log for details.")); + return Error::FAILED; + } else { + print_verbose("rcodesign (" + p_path + "):\n" + str); + int next_nl = str.find("\n", rq_offset); + String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour.")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"rcodesign notary-log --api-issuer <api uuid> --api-key <api key> <request uuid>\""); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"rcodesign staple <app path>\""); + } + } break; #ifdef MACOS_ENABLED - List<String> args; + case 2: { // "altool" + print_verbose("using altool notarization..."); - args.push_back("altool"); - args.push_back("--notarize-app"); + if (!FileAccess::exists("/usr/bin/xcrun") && !FileAccess::exists("/bin/xcrun")) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Xcode command line tools are not installed.")); + return Error::FAILED; + } - args.push_back("--primary-bundle-id"); - args.push_back(p_preset->get("application/bundle_identifier")); + List<String> args; - args.push_back("--username"); - args.push_back(p_preset->get("notarization/apple_id_name")); + args.push_back("altool"); + args.push_back("--notarize-app"); - args.push_back("--password"); - args.push_back(p_preset->get("notarization/apple_id_password")); + args.push_back("--primary-bundle-id"); + args.push_back(p_preset->get("application/bundle_identifier")); - args.push_back("--type"); - args.push_back("osx"); + if (p_preset->get("notarization/apple_id_name") == "" && p_preset->get("notarization/api_uuid") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Neither Apple ID name nor App Store Connect issuer ID name not specified.")); + return Error::FAILED; + } + if (p_preset->get("notarization/apple_id_name") != "" && p_preset->get("notarization/api_uuid") != "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Both Apple ID name and App Store Connect issuer ID name are specified, only one should be set at the same time.")); + return Error::FAILED; + } - if (p_preset->get("notarization/apple_team_id")) { - args.push_back("--asc-provider"); - args.push_back(p_preset->get("notarization/apple_team_id")); - } + if (p_preset->get("notarization/apple_id_name") != "") { + if (p_preset->get("notarization/apple_id_password") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("Apple ID password not specified.")); + return Error::FAILED; + } + args.push_back("--username"); + args.push_back(p_preset->get("notarization/apple_id_name")); - args.push_back("--file"); - args.push_back(p_path); + args.push_back("--password"); + args.push_back(p_preset->get("notarization/apple_id_password")); + } else { + if (p_preset->get("notarization/api_key") == "") { + add_message(EXPORT_MESSAGE_ERROR, TTR("Notarization"), TTR("App Store Connect API key ID not specified.")); + return Error::FAILED; + } + args.push_back("--apiIssuer"); + args.push_back(p_preset->get("notarization/api_uuid")); - String str; - Error err = OS::get_singleton()->execute("xcrun", args, &str, nullptr, true); - if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start xcrun executable.")); - return err; - } + args.push_back("--apiKey"); + args.push_back(p_preset->get("notarization/api_key")); + } - print_verbose("altool (" + p_path + "):\n" + str); - int rq_offset = str.find("RequestUUID"); - if (rq_offset == -1) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed.")); - return FAILED; - } else { - int next_nl = str.find("\n", rq_offset); - String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour. When the process is completed, you'll receive an email.")); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:")); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun altool --notarization-history 0 -u <your email> -p <app-specific pwd>\""); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):")); - add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun stapler staple <app path>\""); - } + args.push_back("--type"); + args.push_back("osx"); -#endif + if (p_preset->get("notarization/apple_team_id")) { + args.push_back("--asc-provider"); + args.push_back(p_preset->get("notarization/apple_team_id")); + } + + args.push_back("--file"); + args.push_back(p_path); + String str; + int exitcode = 0; + Error err = OS::get_singleton()->execute("xcrun", args, &str, &exitcode, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Could not start xcrun executable.")); + return err; + } + + int rq_offset = str.find("RequestUUID"); + if (exitcode != 0 || rq_offset == -1) { + print_line("xcrun altool (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Notarization"), TTR("Notarization failed, see editor log for details.")); + return Error::FAILED; + } else { + print_verbose("xcrun altool (" + p_path + "):\n" + str); + int next_nl = str.find("\n", rq_offset); + String request_uuid = (next_nl == -1) ? str.substr(rq_offset + 14, -1) : str.substr(rq_offset + 14, next_nl - rq_offset - 14); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), vformat(TTR("Notarization request UUID: \"%s\""), request_uuid)); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("The notarization process generally takes less than an hour. When the process is completed, you'll receive an email.")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("You can check progress manually by opening a Terminal and running the following command:")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun altool --notarization-history 0 -u <your email> -p <app-specific pwd>\""); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t" + TTR("Run the following command to staple the notarization ticket to the exported application (optional):")); + add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), "\t\t\"xcrun stapler staple <app path>\""); + } + } break; +#endif + default: { + }; + } return OK; } Error EditorExportPlatformMacOS::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path, const String &p_ent_path, bool p_warn) { - bool force_builtin_codesign = EditorSettings::get_singleton()->get("export/macos/force_builtin_codesign"); - bool ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); - - if ((!FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) || force_builtin_codesign) { - print_verbose("using built-in codesign..."); + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + print_verbose("using built-in codesign..."); #ifdef MODULE_REGEX_ENABLED - -#ifdef MACOS_ENABLED - if (p_preset->get("codesign/timestamp") && p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!")); - } - if (p_preset->get("codesign/hardened_runtime") && p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!")); - } -#endif - - String error_msg; - Error err = CodeSign::codesign(false, p_preset->get("codesign/replace_existing_signature"), p_path, p_ent_path, error_msg); - if (err != OK) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Built-in CodeSign failed with error \"%s\"."), error_msg)); - return FAILED; - } + String error_msg; + Error err = CodeSign::codesign(false, true, p_path, p_ent_path, error_msg); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), vformat(TTR("Built-in CodeSign failed with error \"%s\"."), error_msg)); + return Error::FAILED; + } #else - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Built-in CodeSign require regex module.")); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Built-in CodeSign require regex module.")); #endif - return OK; - } else { - print_verbose("using external codesign..."); - List<String> args; - if (p_preset->get("codesign/timestamp")) { - if (ad_hoc) { - if (p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Timestamping is not compatible with ad-hoc signature, and was disabled!")); - } - } else { - args.push_back("--timestamp"); + } break; + case 2: { // "rcodesign" + print_verbose("using rcodesign codesign..."); + + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Xrcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).")); + return Error::FAILED; } - } - if (p_preset->get("codesign/hardened_runtime")) { - if (ad_hoc) { - if (p_warn) { - add_message(EXPORT_MESSAGE_INFO, TTR("Code Signing"), TTR("Hardened Runtime is not compatible with ad-hoc signature, and was disabled!")); - } + + List<String> args; + args.push_back("sign"); + + if (p_path.get_extension() != "dmg") { + args.push_back("--entitlements-xml-path"); + args.push_back(p_ent_path); + } + + String certificate_file = p_preset->get("codesign/certificate_file"); + String certificate_pass = p_preset->get("codesign/certificate_password"); + if (!certificate_file.is_empty() && !certificate_file.is_empty()) { + args.push_back("--p12-file"); + args.push_back(certificate_file); + args.push_back("--p12-password"); + args.push_back(certificate_pass); + } + + args.push_back("-v"); /* provide some more feedback */ + + args.push_back(p_path); + + String str; + int exitcode = 0; + + Error err = OS::get_singleton()->execute(rcodesign, args, &str, &exitcode, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start rcodesign executable.")); + return err; + } + + if (exitcode != 0) { + print_line("rcodesign (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Code signing failed, see editor log for details.")); + return Error::FAILED; } else { + print_verbose("rcodesign (" + p_path + "):\n" + str); + } + } break; +#ifdef MACOS_ENABLED + case 3: { // "codesign" + print_verbose("using xcode codesign..."); + + if (!FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) { + add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Xcode command line tools are not installed.")); + return Error::FAILED; + } + + bool ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); + + List<String> args; + if (!ad_hoc) { + args.push_back("--timestamp"); args.push_back("--options"); args.push_back("runtime"); } - } - if (p_path.get_extension() != "dmg") { - args.push_back("--entitlements"); - args.push_back(p_ent_path); - } - - PackedStringArray user_args = p_preset->get("codesign/custom_options"); - for (int i = 0; i < user_args.size(); i++) { - String user_arg = user_args[i].strip_edges(); - if (!user_arg.is_empty()) { - args.push_back(user_arg); + if (p_path.get_extension() != "dmg") { + args.push_back("--entitlements"); + args.push_back(p_ent_path); } - } - args.push_back("-s"); - if (ad_hoc) { - args.push_back("-"); - } else { - args.push_back(p_preset->get("codesign/identity")); - } + PackedStringArray user_args = p_preset->get("codesign/custom_options"); + for (int i = 0; i < user_args.size(); i++) { + String user_arg = user_args[i].strip_edges(); + if (!user_arg.is_empty()) { + args.push_back(user_arg); + } + } - args.push_back("-v"); /* provide some more feedback */ + args.push_back("-s"); + if (ad_hoc) { + args.push_back("-"); + } else { + args.push_back(p_preset->get("codesign/identity")); + } - if (p_preset->get("codesign/replace_existing_signature")) { + args.push_back("-v"); /* provide some more feedback */ args.push_back("-f"); - } - args.push_back(p_path); + args.push_back(p_path); - String str; - Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true); - if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start codesign executable, make sure Xcode command line tools are installed.")); - return err; - } + String str; + int exitcode = 0; - print_verbose("codesign (" + p_path + "):\n" + str); - if (str.find("no identity found") != -1) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("No identity found.")); - return FAILED; - } - if ((str.find("unrecognized blob type") != -1) || (str.find("cannot read entitlement data") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Invalid entitlements file.")); - return FAILED; - } - return OK; + Error err = OS::get_singleton()->execute("codesign", args, &str, nullptr, true); + if (err != OK) { + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start codesign executable, make sure Xcode command line tools are installed.")); + return err; + } + + if (exitcode != 0) { + print_line("codesign (" + p_path + "):\n" + str); + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Code signing failed, see editor log for details.")); + return Error::FAILED; + } else { + print_verbose("codesign (" + p_path + "):\n" + str); + } + } break; +#endif + default: { + }; } + + return OK; } Error EditorExportPlatformMacOS::_code_sign_directory(const Ref<EditorExportPreset> &p_preset, const String &p_path, @@ -816,7 +995,9 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p err = ERR_CANT_CREATE; } - DirAccess::remove_file_or_error(scr_path); + if (FileAccess::exists(scr_path)) { + DirAccess::remove_file_or_error(scr_path); + } if (DirAccess::exists(tmp_app_path_name)) { String old_dir = tmp_app_dir->get_current_dir(); if (tmp_app_dir->change_dir(tmp_app_path_name) == OK) { @@ -919,54 +1100,58 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p f->store_line("NSHumanReadableCopyright = \"" + p_preset->get("application/copyright").operator String() + "\";"); } + HashSet<String> languages; for (const String &E : translations) { Ref<Translation> tr = ResourceLoader::load(E); - if (tr.is_valid()) { - String lang = tr->get_locale(); - String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj"; - tmp_app_dir->make_dir_recursive(fname); - Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); - f->store_line("/* Localized versions of Info.plist keys */"); - f->store_line(""); - if (appnames.has(lang)) { - f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";"); - } - if (microphone_usage_descriptions.has(lang)) { - f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";"); - } - if (camera_usage_descriptions.has(lang)) { - f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";"); - } - if (location_usage_descriptions.has(lang)) { - f->store_line("NSLocationUsageDescription = \"" + location_usage_descriptions[lang].operator String() + "\";"); - } - if (address_book_usage_descriptions.has(lang)) { - f->store_line("NSContactsUsageDescription = \"" + address_book_usage_descriptions[lang].operator String() + "\";"); - } - if (calendar_usage_descriptions.has(lang)) { - f->store_line("NSCalendarsUsageDescription = \"" + calendar_usage_descriptions[lang].operator String() + "\";"); - } - if (photos_library_usage_descriptions.has(lang)) { - f->store_line("NSPhotoLibraryUsageDescription = \"" + photos_library_usage_descriptions[lang].operator String() + "\";"); - } - if (desktop_folder_usage_descriptions.has(lang)) { - f->store_line("NSDesktopFolderUsageDescription = \"" + desktop_folder_usage_descriptions[lang].operator String() + "\";"); - } - if (documents_folder_usage_descriptions.has(lang)) { - f->store_line("NSDocumentsFolderUsageDescription = \"" + documents_folder_usage_descriptions[lang].operator String() + "\";"); - } - if (downloads_folder_usage_descriptions.has(lang)) { - f->store_line("NSDownloadsFolderUsageDescription = \"" + downloads_folder_usage_descriptions[lang].operator String() + "\";"); - } - if (network_volumes_usage_descriptions.has(lang)) { - f->store_line("NSNetworkVolumesUsageDescription = \"" + network_volumes_usage_descriptions[lang].operator String() + "\";"); - } - if (removable_volumes_usage_descriptions.has(lang)) { - f->store_line("NSRemovableVolumesUsageDescription = \"" + removable_volumes_usage_descriptions[lang].operator String() + "\";"); - } - if (copyrights.has(lang)) { - f->store_line("NSHumanReadableCopyright = \"" + copyrights[lang].operator String() + "\";"); - } + if (tr.is_valid() && tr->get_locale() != "en") { + languages.insert(tr->get_locale()); + } + } + + for (const String &lang : languages) { + String fname = tmp_app_path_name + "/Contents/Resources/" + lang + ".lproj"; + tmp_app_dir->make_dir_recursive(fname); + Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + f->store_line("/* Localized versions of Info.plist keys */"); + f->store_line(""); + if (appnames.has(lang)) { + f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";"); + } + if (microphone_usage_descriptions.has(lang)) { + f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";"); + } + if (camera_usage_descriptions.has(lang)) { + f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";"); + } + if (location_usage_descriptions.has(lang)) { + f->store_line("NSLocationUsageDescription = \"" + location_usage_descriptions[lang].operator String() + "\";"); + } + if (address_book_usage_descriptions.has(lang)) { + f->store_line("NSContactsUsageDescription = \"" + address_book_usage_descriptions[lang].operator String() + "\";"); + } + if (calendar_usage_descriptions.has(lang)) { + f->store_line("NSCalendarsUsageDescription = \"" + calendar_usage_descriptions[lang].operator String() + "\";"); + } + if (photos_library_usage_descriptions.has(lang)) { + f->store_line("NSPhotoLibraryUsageDescription = \"" + photos_library_usage_descriptions[lang].operator String() + "\";"); + } + if (desktop_folder_usage_descriptions.has(lang)) { + f->store_line("NSDesktopFolderUsageDescription = \"" + desktop_folder_usage_descriptions[lang].operator String() + "\";"); + } + if (documents_folder_usage_descriptions.has(lang)) { + f->store_line("NSDocumentsFolderUsageDescription = \"" + documents_folder_usage_descriptions[lang].operator String() + "\";"); + } + if (downloads_folder_usage_descriptions.has(lang)) { + f->store_line("NSDownloadsFolderUsageDescription = \"" + downloads_folder_usage_descriptions[lang].operator String() + "\";"); + } + if (network_volumes_usage_descriptions.has(lang)) { + f->store_line("NSNetworkVolumesUsageDescription = \"" + network_volumes_usage_descriptions[lang].operator String() + "\";"); + } + if (removable_volumes_usage_descriptions.has(lang)) { + f->store_line("NSRemovableVolumesUsageDescription = \"" + removable_volumes_usage_descriptions[lang].operator String() + "\";"); + } + if (copyrights.has(lang)) { + f->store_line("NSHumanReadableCopyright = \"" + copyrights[lang].operator String() + "\";"); } } } @@ -1144,7 +1329,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p err = save_pack(p_preset, p_debug, pack_path, &shared_objects); // See if we can code sign our new package. - bool sign_enabled = p_preset->get("codesign/enable"); + bool sign_enabled = (p_preset->get("codesign/codesign").operator int() > 0); String ent_path = p_preset->get("codesign/entitlements/custom_file"); String hlp_ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + "_helper.entitlements"); @@ -1310,14 +1495,25 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p } } - bool ad_hoc = true; - if (err == OK) { + bool ad_hoc = false; + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + ad_hoc = true; + } break; + case 2: { // "rcodesign" + ad_hoc = p_preset->get("codesign/certificate_file").operator String().is_empty() || p_preset->get("codesign/certificate_password").operator String().is_empty(); + } break; #ifdef MACOS_ENABLED - String sign_identity = p_preset->get("codesign/identity"); -#else - String sign_identity = "-"; + case 3: { // "codesign" + ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); + } break; #endif - ad_hoc = (sign_identity == "" || sign_identity == "-"); + default: { + }; + } + + if (err == OK) { bool lib_validation = p_preset->get("codesign/entitlements/disable_library_validation"); if ((!dylibs_found.is_empty() || !shared_objects.is_empty()) && sign_enabled && ad_hoc && !lib_validation) { add_message(EXPORT_MESSAGE_ERROR, TTR("Code Signing"), TTR("Ad-hoc signed applications require the 'Disable Library Validation' entitlement to load dynamic libraries.")); @@ -1400,8 +1596,7 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p } } -#ifdef MACOS_ENABLED - bool noto_enabled = p_preset->get("notarization/enable"); + bool noto_enabled = (p_preset->get("notarization/notarization").operator int() > 0); if (err == OK && noto_enabled) { if (export_format == "app") { add_message(EXPORT_MESSAGE_INFO, TTR("Notarization"), TTR("Notarization requires the app to be archived first, select the DMG or ZIP export format instead.")); @@ -1412,10 +1607,11 @@ Error EditorExportPlatformMacOS::export_project(const Ref<EditorExportPreset> &p err = _notarize(p_preset, p_path); } } -#endif // Clean up temporary entitlements files. - DirAccess::remove_file_or_error(hlp_ent_path); + if (FileAccess::exists(hlp_ent_path)) { + DirAccess::remove_file_or_error(hlp_ent_path); + } // Clean up temporary .app dir and generated entitlements. if ((String)(p_preset->get("codesign/entitlements/custom_file")) == "") { @@ -1598,65 +1794,98 @@ bool EditorExportPlatformMacOS::has_valid_project_configuration(const Ref<Editor valid = false; } - bool sign_enabled = p_preset->get("codesign/enable"); - + bool ad_hoc = false; + int codesign_tool = p_preset->get("codesign/codesign"); + switch (codesign_tool) { + case 1: { // built-in ad-hoc + ad_hoc = true; + } break; + case 2: { // "rcodesign" + ad_hoc = p_preset->get("codesign/certificate_file").operator String().is_empty() || p_preset->get("codesign/certificate_password").operator String().is_empty(); + } break; #ifdef MACOS_ENABLED - bool noto_enabled = p_preset->get("notarization/enable"); - bool ad_hoc = ((p_preset->get("codesign/identity") == "") || (p_preset->get("codesign/identity") == "-")); - - if (!ad_hoc && (bool)EditorSettings::get_singleton()->get("export/macos/force_builtin_codesign")) { - err += TTR("Warning: Built-in \"codesign\" is selected in the Editor Settings. Code signing is limited to ad-hoc signature only.") + "\n"; - } - if (!ad_hoc && !FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) { - err += TTR("Warning: Xcode command line tools are not installed, using built-in \"codesign\". Code signing is limited to ad-hoc signature only.") + "\n"; + case 3: { // "codesign" + ad_hoc = (p_preset->get("codesign/identity") == "" || p_preset->get("codesign/identity") == "-"); + } break; +#endif + default: { + }; } + int notary_tool = p_preset->get("notarization/notarization"); - if (noto_enabled) { + if (notary_tool > 0) { if (ad_hoc) { err += TTR("Notarization: Notarization with an ad-hoc signature is not supported.") + "\n"; valid = false; } - if (!sign_enabled) { + if (codesign_tool == 0) { err += TTR("Notarization: Code signing is required for notarization.") + "\n"; valid = false; } - if (!(bool)p_preset->get("codesign/hardened_runtime")) { - err += TTR("Notarization: Hardened runtime is required for notarization.") + "\n"; - valid = false; - } - if (!(bool)p_preset->get("codesign/timestamp")) { - err += TTR("Notarization: Timestamping is required for notarization.") + "\n"; - valid = false; - } - if (p_preset->get("notarization/apple_id_name") == "") { - err += TTR("Notarization: Apple ID name not specified.") + "\n"; - valid = false; - } - if (p_preset->get("notarization/apple_id_password") == "") { - err += TTR("Notarization: Apple ID password not specified.") + "\n"; - valid = false; + if (notary_tool == 2) { + if (!FileAccess::exists("/usr/bin/xcrun") && !FileAccess::exists("/bin/xcrun")) { + err += TTR("Notarization: Xcode command line tools are not installed.") + "\n"; + valid = false; + } + if (p_preset->get("notarization/apple_id_name") == "" && p_preset->get("notarization/api_uuid") == "") { + err += TTR("Notarization: Neither Apple ID name nor App Store Connect issuer ID name not specified.") + "\n"; + valid = false; + } else if (p_preset->get("notarization/apple_id_name") != "" && p_preset->get("notarization/api_uuid") != "") { + err += TTR("Notarization: Both Apple ID name and App Store Connect issuer ID name are specified, only one should be set at the same time.") + "\n"; + valid = false; + } else { + if (p_preset->get("notarization/apple_id_name") != "") { + if (p_preset->get("notarization/apple_id_password") == "") { + err += TTR("Notarization: Apple ID password not specified.") + "\n"; + } + valid = false; + } + if (p_preset->get("notarization/api_uuid") != "") { + if (p_preset->get("notarization/api_key") == "") { + err += TTR("Notarization: App Store Connect API key ID not specified.") + "\n"; + valid = false; + } + } + } + } else if (notary_tool == 1) { + if (p_preset->get("notarization/api_uuid") == "") { + err += TTR("Notarization: App Store Connect issuer ID name not specified.") + "\n"; + valid = false; + } + if (p_preset->get("notarization/api_key") == "") { + err += TTR("Notarization: App Store Connect API key ID not specified.") + "\n"; + valid = false; + } + + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + err += TTR("Notarization: rcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).") + "\n"; + valid = false; + } } } else { err += TTR("Warning: Notarization is disabled. The exported project will be blocked by Gatekeeper if it's downloaded from an unknown source.") + "\n"; - if (!sign_enabled) { + if (codesign_tool == 0) { err += TTR("Code signing is disabled. The exported project will not run on Macs with enabled Gatekeeper and Apple Silicon powered Macs.") + "\n"; - } else { - if ((bool)p_preset->get("codesign/hardened_runtime") && ad_hoc) { - err += TTR("Hardened Runtime is not compatible with ad-hoc signature, and will be disabled!") + "\n"; - } - if ((bool)p_preset->get("codesign/timestamp") && ad_hoc) { - err += TTR("Timestamping is not compatible with ad-hoc signature, and will be disabled!") + "\n"; - } } } -#else - err += TTR("Warning: Notarization is not supported from this OS. The exported project will be blocked by Gatekeeper if it's downloaded from an unknown source.") + "\n"; - if (!sign_enabled) { - err += TTR("Code signing is disabled. The exported project will not run on Macs with enabled Gatekeeper and Apple Silicon powered Macs.") + "\n"; - } -#endif - if (sign_enabled) { + if (codesign_tool > 0) { + if (ad_hoc) { + err += TTR("Code signing: Using ad-hoc signature. The exported project will be blocked by Gatekeeper") + "\n"; + } + if (codesign_tool == 3) { + if (!FileAccess::exists("/usr/bin/codesign") && !FileAccess::exists("/bin/codesign")) { + err += TTR("Code signing: Xcode command line tools are not installed.") + "\n"; + valid = false; + } + } else if (codesign_tool == 2) { + String rcodesign = EditorSettings::get_singleton()->get("export/macos/rcodesign").operator String(); + if (rcodesign.is_empty()) { + err += TTR("Code signing: rcodesign path is not set. Configure rcodesign path in the Editor Settings (Export > macOS > rcodesign).") + "\n"; + valid = false; + } + } if ((bool)p_preset->get("codesign/entitlements/audio_input") && ((String)p_preset->get("privacy/microphone_usage_description")).is_empty()) { err += TTR("Privacy: Microphone access is enabled, but usage description is not specified.") + "\n"; valid = false; diff --git a/platform/macos/export/export_plugin.h b/platform/macos/export/export_plugin.h index 4603c61a28..87790129d3 100644 --- a/platform/macos/export/export_plugin.h +++ b/platform/macos/export/export_plugin.h @@ -101,7 +101,7 @@ class EditorExportPlatformMacOS : public EditorExportPlatform { protected: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) const override; virtual void get_export_options(List<ExportOption> *r_options) override; - virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override; + virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; public: virtual String get_name() const override { return "macOS"; } diff --git a/platform/macos/os_macos.h b/platform/macos/os_macos.h index a1eb0f7f69..61db99689c 100644 --- a/platform/macos/os_macos.h +++ b/platform/macos/os_macos.h @@ -40,8 +40,6 @@ #include "servers/audio_server.h" class OS_MacOS : public OS_Unix { - bool force_quit = false; - JoypadMacOS *joypad_macos = nullptr; #ifdef COREAUDIO_ENABLED diff --git a/platform/macos/os_macos.mm b/platform/macos/os_macos.mm index cc550043de..47b53bba69 100644 --- a/platform/macos/os_macos.mm +++ b/platform/macos/os_macos.mm @@ -512,8 +512,6 @@ Error OS_MacOS::move_to_trash(const String &p_path) { } void OS_MacOS::run() { - force_quit = false; - if (!main_loop) { return; } @@ -521,7 +519,7 @@ void OS_MacOS::run() { main_loop->initialize(); bool quit = false; - while (!force_quit && !quit) { + while (!quit) { @try { if (DisplayServer::get_singleton()) { DisplayServer::get_singleton()->process_events(); // Get rid of pending events. @@ -541,7 +539,6 @@ void OS_MacOS::run() { OS_MacOS::OS_MacOS() { main_loop = nullptr; - force_quit = false; Vector<Logger *> loggers; loggers.push_back(memnew(MacOSTerminalLogger)); diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 40f93bb18b..494f5ec4b9 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -781,7 +781,7 @@ void OS_UWP::run() { int frames = 0; uint64_t frame = 0; - while (!force_quit) { + while (true) { CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); if (managed_object->alert_close_handle) { continue; @@ -811,7 +811,6 @@ bool OS_UWP::_check_internal_feature_support(const String &p_feature) { OS_UWP::OS_UWP() { key_event_pos = 0; - force_quit = false; alt_mem = false; gr_mem = false; shift_mem = false; diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index fe61f60548..5a58486ee7 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -106,7 +106,6 @@ private: bool shift_mem; bool control_mem; bool meta_mem; - bool force_quit; MouseButton last_button_state = MouseButton::NONE; CursorShape cursor_shape; diff --git a/platform/windows/crash_handler_windows.cpp b/platform/windows/crash_handler_windows.cpp index 6ce10e6f0f..b501ee78db 100644 --- a/platform/windows/crash_handler_windows.cpp +++ b/platform/windows/crash_handler_windows.cpp @@ -173,10 +173,18 @@ DWORD CrashHandlerException(EXCEPTION_POINTERS *ep) { frame.AddrStack.Mode = AddrModeFlat; frame.AddrFrame.Mode = AddrModeFlat; -#ifdef _M_X64 +#if defined(_M_X64) frame.AddrPC.Offset = context->Rip; frame.AddrStack.Offset = context->Rsp; frame.AddrFrame.Offset = context->Rbp; +#elif defined(_M_ARM64) || defined(_M_ARM64EC) + frame.AddrPC.Offset = context->Pc; + frame.AddrStack.Offset = context->Sp; + frame.AddrFrame.Offset = context->Fp; +#elif defined(_M_ARM) + frame.AddrPC.Offset = context->Pc; + frame.AddrStack.Offset = context->Sp; + frame.AddrFrame.Offset = context->R11; #else frame.AddrPC.Offset = context->Eip; frame.AddrStack.Offset = context->Esp; diff --git a/platform/windows/detect.py b/platform/windows/detect.py index 6dd6892757..5607eab342 100644 --- a/platform/windows/detect.py +++ b/platform/windows/detect.py @@ -1,5 +1,7 @@ import methods import os +import subprocess +import sys from platform_methods import detect_arch # To match other platforms @@ -14,6 +16,38 @@ def get_name(): return "Windows" +def try_cmd(test, prefix, arch): + if arch: + try: + out = subprocess.Popen( + get_mingw_bin_prefix(prefix, arch) + test, + shell=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + out.communicate() + if out.returncode == 0: + return True + except Exception: + pass + else: + for a in ["x86_64", "x86_32", "arm64", "arm32"]: + try: + out = subprocess.Popen( + get_mingw_bin_prefix(prefix, a) + test, + shell=True, + stderr=subprocess.PIPE, + stdout=subprocess.PIPE, + ) + out.communicate() + if out.returncode == 0: + return True + except Exception: + pass + + return False + + def can_build(): if os.name == "nt": # Building natively on Windows @@ -21,7 +55,7 @@ def can_build(): if os.getenv("VCINSTALLDIR"): # MSVC, manual setup return True - # Otherwise, let SCons find MSVC if installed, or else Mingw. + # Otherwise, let SCons find MSVC if installed, or else MinGW. # Since we're just returning True here, if there's no compiler # installed, we'll get errors when it tries to build with the # null compiler. @@ -29,47 +63,132 @@ def can_build(): if os.name == "posix": # Cross-compiling with MinGW-w64 (old MinGW32 is not supported) - mingw32 = "i686-w64-mingw32-" - mingw64 = "x86_64-w64-mingw32-" + prefix = os.getenv("MINGW_PREFIX", "") - if os.getenv("MINGW32_PREFIX"): - mingw32 = os.getenv("MINGW32_PREFIX") - if os.getenv("MINGW64_PREFIX"): - mingw64 = os.getenv("MINGW64_PREFIX") - - test = "gcc --version > /dev/null 2>&1" - if os.system(mingw64 + test) == 0 or os.system(mingw32 + test) == 0: + if try_cmd("gcc --version", prefix, "") or try_cmd("clang --version", prefix, ""): return True return False +def get_mingw_bin_prefix(prefix, arch): + if not prefix: + mingw_bin_prefix = "" + elif prefix[-1] != "/": + mingw_bin_prefix = prefix + "/bin/" + else: + mingw_bin_prefix = prefix + "bin/" + + if arch == "x86_64": + mingw_bin_prefix += "x86_64-w64-mingw32-" + elif arch == "x86_32": + mingw_bin_prefix += "i686-w64-mingw32-" + elif arch == "arm32": + mingw_bin_prefix += "armv7-w64-mingw32-" + elif arch == "arm64": + mingw_bin_prefix += "aarch64-w64-mingw32-" + + return mingw_bin_prefix + + +def detect_build_env_arch(): + msvc_target_aliases = { + "amd64": "x86_64", + "i386": "x86_32", + "i486": "x86_32", + "i586": "x86_32", + "i686": "x86_32", + "x86": "x86_32", + "x64": "x86_64", + "x86_64": "x86_64", + "arm": "arm32", + "arm64": "arm64", + "aarch64": "arm64", + } + if os.getenv("VCINSTALLDIR") or os.getenv("VCTOOLSINSTALLDIR"): + if os.getenv("Platform"): + msvc_arch = os.getenv("Platform").lower() + if msvc_arch in msvc_target_aliases.keys(): + return msvc_target_aliases[msvc_arch] + + if os.getenv("VSCMD_ARG_TGT_ARCH"): + msvc_arch = os.getenv("VSCMD_ARG_TGT_ARCH").lower() + if msvc_arch in msvc_target_aliases.keys(): + return msvc_target_aliases[msvc_arch] + + # Pre VS 2017 checks. + if os.getenv("VCINSTALLDIR"): + PATH = os.getenv("PATH").upper() + VCINSTALLDIR = os.getenv("VCINSTALLDIR").upper() + path_arch = { + "BIN\\x86_ARM;": "arm32", + "BIN\\amd64_ARM;": "arm32", + "BIN\\x86_ARM64;": "arm64", + "BIN\\amd64_ARM64;": "arm64", + "BIN\\x86_amd64;": "a86_64", + "BIN\\amd64;": "x86_64", + "BIN\\amd64_x86;": "x86_32", + "BIN;": "x86_32", + } + for path, arch in path_arch.items(): + final_path = VCINSTALLDIR + path + if final_path in PATH: + return arch + + # VS 2017 and newer. + if os.getenv("VCTOOLSINSTALLDIR"): + host_path_index = os.getenv("PATH").upper().find(os.getenv("VCTOOLSINSTALLDIR").upper() + "BIN\\HOST") + if host_path_index > -1: + first_path_arch = os.getenv("PATH").split(";")[0].rsplit("\\", 1)[-1].lower() + return msvc_target_aliases[first_path_arch] + + msys_target_aliases = { + "mingw32": "x86_32", + "mingw64": "x86_64", + "ucrt64": "x86_64", + "clang64": "x86_64", + "clang32": "x86_32", + "clangarm64": "arm64", + } + if os.getenv("MSYSTEM"): + msys_arch = os.getenv("MSYSTEM").lower() + if msys_arch in msys_target_aliases.keys(): + return msys_target_aliases[msys_arch] + + return "" + + def get_opts(): from SCons.Variables import BoolVariable, EnumVariable - # TODO: These shouldn't be hard-coded for x86. - mingw32 = "" - mingw64 = "" - if os.name == "posix": - mingw32 = "i686-w64-mingw32-" - mingw64 = "x86_64-w64-mingw32-" - - if os.getenv("MINGW32_PREFIX"): - mingw32 = os.getenv("MINGW32_PREFIX") - if os.getenv("MINGW64_PREFIX"): - mingw64 = os.getenv("MINGW64_PREFIX") + mingw = os.getenv("MINGW_PREFIX", "") return [ - ("mingw_prefix_32", "MinGW prefix (Win32)", mingw32), - ("mingw_prefix_64", "MinGW prefix (Win64)", mingw64), + ("mingw_prefix", "MinGW prefix", mingw), # Targeted Windows version: 7 (and later), minimum supported version # XP support dropped after EOL due to missing API for IPv6 and other issues # Vista support dropped after EOL due to GH-10243 - ("target_win_version", "Targeted Windows version, >= 0x0601 (Windows 7)", "0x0601"), - BoolVariable("debug_symbols", "Add debugging symbols to release/release_debug builds", True), + ( + "target_win_version", + "Targeted Windows version, >= 0x0601 (Windows 7)", + "0x0601", + ), + BoolVariable( + "debug_symbols", + "Add debugging symbols to release/release_debug builds", + True, + ), EnumVariable("windows_subsystem", "Windows subsystem", "gui", ("gui", "console")), - BoolVariable("separate_debug_symbols", "Create a separate file containing debugging symbols", False), - ("msvc_version", "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.", None), + BoolVariable( + "separate_debug_symbols", + "Create a separate file containing debugging symbols", + False, + ), + ( + "msvc_version", + "MSVC version to use. Ignored if VCINSTALLDIR is set in shell env.", + None, + ), BoolVariable("use_mingw", "Use the Mingw compiler, even if MSVC is installed.", False), BoolVariable("use_llvm", "Use the LLVM compiler", False), BoolVariable("use_thinlto", "Use ThinLTO", False), @@ -79,73 +198,63 @@ def get_opts(): def get_flags(): + arch = detect_build_env_arch() or detect_arch() + return [ - ("arch", detect_arch()), + ("arch", arch), ] def build_res_file(target, source, env): - # TODO: This shouldn't be hard-coded for x86. - if env["arch"] == "x86_32": - cmdbase = env["mingw_prefix_32"] - else: - cmdbase = env["mingw_prefix_64"] - cmdbase = cmdbase + "windres --include-dir . " - import subprocess + arch_aliases = { + "x86_32": "pe-i386", + "x86_64": "pe-x86-64", + "arm32": "armv7-w64-mingw32", + "arm64": "aarch64-w64-mingw32", + } + cmdbase = "windres --include-dir . --target=" + arch_aliases[env["arch"]] + + mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) for x in range(len(source)): - cmd = cmdbase + "-i " + str(source[x]) + " -o " + str(target[x]) + ok = True + # Try prefixed executable (MinGW on Linux). + cmd = mingw_bin_prefix + cmdbase + " -i " + str(source[x]) + " -o " + str(target[x]) try: out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate() if len(out[1]): - return 1 + ok = False except Exception: - return 1 + ok = False + + # Try generic executable (MSYS2). + if not ok: + cmd = cmdbase + " -i " + str(source[x]) + " -o " + str(target[x]) + try: + out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate() + if len(out[1]): + return -1 + except Exception: + return -1 + return 0 def setup_msvc_manual(env): - # FIXME: This is super hacky, and probably obsolete. - # Won't work with detect_arch() used for `arch` by default. + """Running from VCVARS environment""" - """Set up env to use MSVC manually, using VCINSTALLDIR""" - if env["arch"] != "auto": + env_arch = detect_build_env_arch() + if env["arch"] != env_arch: print( """ - Arch argument is not supported for MSVC manual configuration (VCINSTALLDIR configured). - Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons. - As a consequence, the arch argument is disabled. Run scons again without arch argument (example: scons p=windows) - and SCons will attempt to detect what MSVC compiler will be executed and inform you. + Arch argument (%s) is not matching Native/Cross Compile Tools Prompt/Developer Console (or Visual Studio settings) that is being used to run SCons (%s). + Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you. """ + % (env["arch"], env_arch) ) - raise SCons.Errors.UserError("Arch argument should not be used when using VCINSTALLDIR") - - # Force ARCH arg - # (Actually msys2 mingw can support 64-bit, we could detect that) - # TODO: This is wrong, but not sure what to do about it. - # We want to determine the arch and bitness in the SConstruct only. - # We can check if it's correct in here, but if it's not, it should - # just fail with an error message instead of trying to force it. - - # find compiler manually - compiler_version_str = methods.detect_visual_c_compiler_version(env["ENV"]) - print("Found MSVC compiler: " + compiler_version_str) - - # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writing)... vc compiler for 64bit can not compile _asm - if compiler_version_str == "amd64" or compiler_version_str == "x86_amd64": - env["arch"] = "x86_64" - env["x86_libtheora_opt_vc"] = False - print("Compiled program architecture will be a 64 bit executable (forcing arch=x86_64).") - elif compiler_version_str == "x86" or compiler_version_str == "amd64_x86": - env["arch"] = "x86_32" - env["x86_libtheora_opt_vc"] = True - print("Compiled program architecture will be a 32 bit executable (forcing arch=x86_32).") - else: - print( - "Failed to manually detect MSVC compiler architecture version.\n" - "You should check your settings/compilation setup, or avoid setting VCINSTALLDIR." - ) - sys.exit() + sys.exit(200) + + print("Found MSVC, arch %s" % (env_arch)) def setup_msvc_auto(env): @@ -179,23 +288,50 @@ def setup_msvc_auto(env): env["MSVC_VERSION"] = env["msvc_version"] env.Tool("msvc") env.Tool("mssdk") # we want the MS SDK + # Note: actual compiler version can be found in env['MSVC_VERSION'], e.g. "14.1" for VS2015 - print("Found MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["TARGET_ARCH"])) - if env["arch"] == "x86_32": - env["x86_libtheora_opt_vc"] = False + print("Found MSVC version %s, arch %s" % (env["MSVC_VERSION"], env["arch"])) def setup_mingw(env): """Set up env for use with mingw""" - # Nothing to do here - print("Using MinGW") + + env_arch = detect_build_env_arch() + if os.getenv("MSYSTEM") == "MSYS": + print( + """ + Running from base MSYS2 console/environment, use target specific environment instead (e.g., mingw32, mingw64, clang32, clang64). + """ + ) + sys.exit(201) + + if env_arch != "" and env["arch"] != env_arch: + print( + """ + Arch argument (%s) is not matching MSYS2 console/environment that is being used to run SCons (%s). + Run SCons again without arch argument (example: scons p=windows) and SCons will attempt to detect what MSYS2 compiler will be executed and inform you. + """ + % (env["arch"], env_arch) + ) + sys.exit(202) + + if not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]) and not try_cmd( + "clang --version", env["mingw_prefix"], env["arch"] + ): + print( + """ + No valid compilers found, use MINGW_PREFIX environment variable to set MinGW path. + """ + ) + sys.exit(202) + + print("Using MinGW, arch %s" % (env["arch"])) -def configure_msvc(env, manual_msvc_config): +def configure_msvc(env, vcvars_msvc_config): """Configure env to work with MSVC""" # Build type - if env["target"] == "release": if env["optimize"] == "speed": # optimize for speed (default) env.Append(CCFLAGS=["/O2"]) @@ -235,6 +371,9 @@ def configure_msvc(env, manual_msvc_config): else: env.AppendUnique(CCFLAGS=["/MD"]) + if env["arch"] == "x86_32": + env["x86_libtheora_opt_vc"] = True + env.AppendUnique(CCFLAGS=["/Gd", "/GR", "/nologo"]) env.AppendUnique(CCFLAGS=["/utf-8"]) # Force to use Unicode encoding. env.AppendUnique(CXXFLAGS=["/TP"]) # assume all sources are C++ @@ -243,7 +382,7 @@ def configure_msvc(env, manual_msvc_config): # for notes on why this shouldn't be enabled for gcc env.AppendUnique(CCFLAGS=["/bigobj"]) - if manual_msvc_config: # should be automatic if SCons found it + if vcvars_msvc_config: # should be automatic if SCons found it if os.getenv("WindowsSdkDir") is not None: env.Prepend(CPPPATH=[os.getenv("WindowsSdkDir") + "/Include"]) else: @@ -302,7 +441,7 @@ def configure_msvc(env, manual_msvc_config): env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS]) - if manual_msvc_config: + if vcvars_msvc_config: if os.getenv("WindowsSdkDir") is not None: env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"]) else: @@ -318,7 +457,7 @@ def configure_msvc(env, manual_msvc_config): else: env.AppendUnique(LINKFLAGS=["/LTCG"]) - if manual_msvc_config: + if vcvars_msvc_config: env.Prepend(CPPPATH=[p for p in os.getenv("INCLUDE").split(";")]) env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")]) @@ -342,6 +481,12 @@ def configure_mingw(env): ## Build type + if not env["use_llvm"] and not try_cmd("gcc --version", env["mingw_prefix"], env["arch"]): + env["use_llvm"] = True + + if env["use_llvm"] and not try_cmd("clang --version", env["mingw_prefix"], env["arch"]): + env["use_llvm"] = False + if env["target"] == "release": env.Append(CCFLAGS=["-msse2"]) @@ -383,36 +528,39 @@ def configure_mingw(env): if os.name != "nt": env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation - mingw_prefix = "" - - # TODO: This doesn't seem to be working, or maybe I just have - # MinGW set up incorrectly. It always gives me x86_64 builds, - # even though arch == "x86_32" and the file name has x86_32 in it. if env["arch"] == "x86_32": if env["use_static_cpp"]: env.Append(LINKFLAGS=["-static"]) env.Append(LINKFLAGS=["-static-libgcc"]) env.Append(LINKFLAGS=["-static-libstdc++"]) - mingw_prefix = env["mingw_prefix_32"] else: if env["use_static_cpp"]: env.Append(LINKFLAGS=["-static"]) - mingw_prefix = env["mingw_prefix_64"] + + if env["arch"] in ["x86_32", "x86_64"]: + env["x86_libtheora_opt_gcc"] = True + + mingw_bin_prefix = get_mingw_bin_prefix(env["mingw_prefix"], env["arch"]) if env["use_llvm"]: - env["CC"] = mingw_prefix + "clang" - env["CXX"] = mingw_prefix + "clang++" - env["AS"] = mingw_prefix + "as" - env["AR"] = mingw_prefix + "ar" - env["RANLIB"] = mingw_prefix + "ranlib" + env["CC"] = mingw_bin_prefix + "clang" + env["CXX"] = mingw_bin_prefix + "clang++" + if try_cmd("as --version", env["mingw_prefix"], env["arch"]): + env["AS"] = mingw_bin_prefix + "as" + if try_cmd("ar --version", env["mingw_prefix"], env["arch"]): + env["AR"] = mingw_bin_prefix + "ar" + if try_cmd("ranlib --version", env["mingw_prefix"], env["arch"]): + env["RANLIB"] = mingw_bin_prefix + "ranlib" + env.extra_suffix = ".llvm" + env.extra_suffix else: - env["CC"] = mingw_prefix + "gcc" - env["CXX"] = mingw_prefix + "g++" - env["AS"] = mingw_prefix + "as" - env["AR"] = mingw_prefix + "gcc-ar" - env["RANLIB"] = mingw_prefix + "gcc-ranlib" - - env["x86_libtheora_opt_gcc"] = True + env["CC"] = mingw_bin_prefix + "gcc" + env["CXX"] = mingw_bin_prefix + "g++" + if try_cmd("as --version", env["mingw_prefix"], env["arch"]): + env["AS"] = mingw_bin_prefix + "as" + if try_cmd("gcc-ar --version", env["mingw_prefix"], env["arch"]): + env["AR"] = mingw_bin_prefix + "gcc-ar" + if try_cmd("gcc-ranlib --version", env["mingw_prefix"], env["arch"]): + env["RANLIB"] = mingw_bin_prefix + "gcc-ranlib" if env["use_lto"]: if not env["use_llvm"] and env.GetOption("num_jobs") > 1: @@ -430,10 +578,16 @@ def configure_mingw(env): ## Compile flags - env.Append(CCFLAGS=["-mwindows"]) + if not env["use_llvm"]: + env.Append(CCFLAGS=["-mwindows"]) env.Append(CPPDEFINES=["WINDOWS_ENABLED", "WASAPI_ENABLED", "WINMIDI_ENABLED"]) - env.Append(CPPDEFINES=[("WINVER", env["target_win_version"]), ("_WIN32_WINNT", env["target_win_version"])]) + env.Append( + CPPDEFINES=[ + ("WINVER", env["target_win_version"]), + ("_WIN32_WINNT", env["target_win_version"]), + ] + ) env.Append( LIBS=[ "mingw32", @@ -492,22 +646,21 @@ def configure(env): env["ENV"]["TMP"] = os.environ["TMP"] # First figure out which compiler, version, and target arch we're using - if os.getenv("VCINSTALLDIR") and not env["use_mingw"]: - # Manual setup of MSVC + if os.getenv("VCINSTALLDIR") and detect_build_env_arch() and not env["use_mingw"]: setup_msvc_manual(env) env.msvc = True - manual_msvc_config = True + vcvars_msvc_config = True elif env.get("MSVC_VERSION", "") and not env["use_mingw"]: setup_msvc_auto(env) env.msvc = True - manual_msvc_config = False + vcvars_msvc_config = False else: setup_mingw(env) env.msvc = False # Now set compiler/linker flags if env.msvc: - configure_msvc(env, manual_msvc_config) + configure_msvc(env, vcvars_msvc_config) else: # MinGW configure_mingw(env) diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 9d3ec31f73..016d201f2c 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -113,7 +113,7 @@ List<String> EditorExportPlatformWindows::get_binary_extensions(const Ref<Editor return list; } -bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const { +bool EditorExportPlatformWindows::get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const { // This option is not supported by "osslsigncode", used on non-Windows host. if (!OS::get_singleton()->has_feature("windows") && p_option == "codesign/identity_type") { return false; @@ -123,12 +123,12 @@ bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_o void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_options) { EditorExportPlatformPC::get_export_options(r_options); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32"), "x86_64")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "binary_format/architecture", PROPERTY_HINT_ENUM, "x86_64,x86_32,arm64"), "x86_64")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/enable"), false)); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/identity_type", PROPERTY_HINT_ENUM, "Select automatically,Use PKCS12 file (specify *.PFX/*.P12 file),Use certificate store (specify SHA1 hash)"), 0)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/identity", PROPERTY_HINT_GLOBAL_FILE, "*.pfx,*.p12"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/password", PROPERTY_HINT_PASSWORD), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/timestamp"), true)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/timestamp_server_url"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/digest_algorithm", PROPERTY_HINT_ENUM, "SHA1,SHA256"), 1)); @@ -231,7 +231,7 @@ Error EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset String str; Error err = OS::get_singleton()->execute(rcedit_path, args, &str, nullptr, true); if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable. Configure rcedit path in the Editor Settings (Export > Windows > Rcedit), or disable \"Application > Modify Resources\" in the export preset.")); + add_message(EXPORT_MESSAGE_WARNING, TTR("Resources Modification"), TTR("Could not start rcedit executable. Configure rcedit path in the Editor Settings (Export > Windows > rcedit), or disable \"Application > Modify Resources\" in the export preset.")); return err; } print_line("rcedit (" + p_path + "): " + str); @@ -379,7 +379,11 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p String str; Error err = OS::get_singleton()->execute(signtool_path, args, &str, nullptr, true); if (err != OK || (str.find("not found") != -1) || (str.find("not recognized") != -1)) { - add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable. Configure signtool path in the Editor Settings (Export > Windows > Signtool), or disable \"Codesign\" in the export preset.")); +#ifndef WINDOWS_ENABLED + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start signtool executable. Configure signtool path in the Editor Settings (Export > Windows > signtool), or disable \"Codesign\" in the export preset.")); +#else + add_message(EXPORT_MESSAGE_WARNING, TTR("Code Signing"), TTR("Could not start osslsigncode executable. Configure signtool path in the Editor Settings (Export > Windows > osslsigncode), or disable \"Codesign\" in the export preset.")); +#endif return err; } @@ -418,7 +422,7 @@ bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref<Edito String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); if (p_preset->get("application/modify_resources") && rcedit_path.is_empty()) { - err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > Rcedit) to change the icon or app information data.") + "\n"; + err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > rcedit) to change the icon or app information data.") + "\n"; } if (!err.is_empty()) { diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 3ea8ff3dc9..f85331c898 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -48,9 +48,9 @@ public: virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override; virtual void get_export_options(List<ExportOption> *r_options) override; - virtual bool get_export_option_visibility(const String &p_option, const HashMap<StringName, Variant> &p_options) const override; virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override; + virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option, const HashMap<StringName, Variant> &p_options) const override; virtual String get_template_file_name(const String &p_target, const String &p_arch) const override; virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override; }; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index ad4be950cc..0e4d5f79b9 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -902,7 +902,7 @@ void OS_Windows::run() { main_loop->initialize(); - while (!force_quit) { + while (true) { DisplayServer::get_singleton()->process_events(); // get rid of pending events if (Main::iteration()) { break; @@ -1132,8 +1132,6 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { main_loop = nullptr; process_map = nullptr; - force_quit = false; - hInstance = _hInstance; #ifdef STDOUT_FILE stdo = fopen("stdout.txt", "wb"); diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 80fc860738..3e054c068c 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -110,7 +110,6 @@ class OS_Windows : public OS { ErrorHandlerList error_handlers; #endif - bool force_quit; HWND main_window; // functions used by main to initialize/deinitialize the OS diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 177f587f4f..4565462247 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -115,14 +115,17 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { names.sort_custom<StringName::AlphCompare>(); bool current_found = false; + bool is_first_element = true; - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - if (E->prev()) { + for (const StringName &E : names) { + if (!is_first_element) { p_property.hint_string += ","; + } else { + is_first_element = false; } - p_property.hint_string += String(E->get()); - if (animation == E->get()) { + p_property.hint_string += String(E); + if (animation == E) { current_found = true; } } diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index fa49552085..fc019b6cf9 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -185,7 +185,7 @@ void AudioStreamPlayer2D::_update_panning() { } float multiplier = Math::pow(1.0f - dist / max_distance, attenuation); - multiplier *= Math::db2linear(volume_db); //also apply player volume! + multiplier *= Math::db_to_linear(volume_db); //also apply player volume! float pan = relative_to_listener.x / screen_size.x; // Don't let the panning effect extend (too far) beyond the screen. diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index 8df29851e5..04cd999982 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -239,7 +239,7 @@ TypedArray<String> CollisionPolygon2D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject2D>(get_parent())) { - warnings.push_back(RTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidDynamicBody2D, CharacterBody2D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionPolygon2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape.")); } int polygon_count = polygon.size(); diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index 9c0c26f6d9..cbecf28877 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -172,7 +172,7 @@ TypedArray<String> CollisionShape2D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject2D>(get_parent())) { - warnings.push_back(RTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidDynamicBody2D, CharacterBody2D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionShape2D only serves to provide a collision shape to a CollisionObject2D derived node. Please only use it as a child of Area2D, StaticBody2D, RigidBody2D, CharacterBody2D, etc. to give them a shape.")); } if (!shape.is_valid()) { warnings.push_back(RTR("A shape must be provided for CollisionShape2D to function. Please create a shape resource for it!")); diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 40f74d3f50..1929475c8f 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -32,7 +32,7 @@ #include "core/core_string_names.h" #include "scene/2d/gpu_particles_2d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" void CPUParticles2D::set_emitting(bool p_emitting) { if (emitting == p_emitting) { @@ -745,12 +745,12 @@ void CPUParticles2D::_particles_process(double p_delta) { p.start_color_rand = Color(1, 1, 1, 1); } - real_t angle1_rad = direction.angle() + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread); + real_t angle1_rad = direction.angle() + Math::deg_to_rad((Math::randf() * 2.0 - 1.0) * spread); Vector2 rot = Vector2(Math::cos(angle1_rad), Math::sin(angle1_rad)); p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf()); real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); - p.rotation = Math::deg2rad(base_angle); + p.rotation = Math::deg_to_rad(base_angle); p.custom[0] = 0.0; // unused p.custom[1] = 0.0; // phase [0..1] @@ -890,7 +890,7 @@ void CPUParticles2D::_particles_process(double p_delta) { real_t orbit_amount = tex_orbit_velocity * Math::lerp(parameters_min[PARAM_ORBIT_VELOCITY], parameters_max[PARAM_ORBIT_VELOCITY], rand_from_seed(alt_seed)); if (orbit_amount != 0.0) { real_t ang = orbit_amount * local_delta * Math_TAU; - // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix, + // Not sure why the ParticleProcessMaterial code uses a clockwise rotation matrix, // but we use -ang here to reproduce its behavior. Transform2D rot = Transform2D(-ang, Vector2()); p.transform[2] -= diff; @@ -912,7 +912,7 @@ void CPUParticles2D::_particles_process(double p_delta) { } real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed)); - p.rotation = Math::deg2rad(base_angle); //angle + p.rotation = Math::deg_to_rad(base_angle); //angle p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed)); } //apply color @@ -1184,7 +1184,7 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { set_material(mat); } - Ref<ParticlesMaterial> material = particles->get_process_material(); + Ref<ParticleProcessMaterial> material = particles->get_process_material(); if (material.is_null()) { return; } @@ -1205,14 +1205,14 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { set_color_initial_ramp(gti->get_gradient()); } - set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); + set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); set_emission_shape(EmissionShape(material->get_emission_shape())); set_emission_sphere_radius(material->get_emission_sphere_radius()); Vector2 rect_extents = Vector2(material->get_emission_box_extents().x, material->get_emission_box_extents().y); set_emission_rect_extents(rect_extents); - Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticlesMaterial::PARAM_SCALE); + Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticleProcessMaterial::PARAM_SCALE); if (scale3D.is_valid()) { split_scale = true; scale_curve_x = scale3D->get_curve_x(); @@ -1222,14 +1222,14 @@ void CPUParticles2D::convert_from_particles(Node *p_particles) { set_gravity(gravity); set_lifetime_randomness(material->get_lifetime_randomness()); -#define CONVERT_PARAM(m_param) \ - set_param_min(m_param, material->get_param_min(ParticlesMaterial::m_param)); \ - { \ - Ref<CurveTexture> ctex = material->get_param_texture(ParticlesMaterial::m_param); \ - if (ctex.is_valid()) \ - set_param_curve(m_param, ctex->get_curve()); \ - } \ - set_param_max(m_param, material->get_param_max(ParticlesMaterial::m_param)); +#define CONVERT_PARAM(m_param) \ + set_param_min(m_param, material->get_param_min(ParticleProcessMaterial::m_param)); \ + { \ + Ref<CurveTexture> ctex = material->get_param_texture(ParticleProcessMaterial::m_param); \ + if (ctex.is_valid()) \ + set_param_curve(m_param, ctex->get_curve()); \ + } \ + set_param_max(m_param, material->get_param_max(ParticleProcessMaterial::m_param)); CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY); CONVERT_PARAM(PARAM_ANGULAR_VELOCITY); diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index e4354a69e2..65ead7afbc 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -30,7 +30,7 @@ #include "gpu_particles_2d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" #ifdef TOOLS_ENABLED #include "core/config/engine.h" @@ -123,10 +123,10 @@ void GPUParticles2D::_update_particle_emission_transform() { void GPUParticles2D::set_process_material(const Ref<Material> &p_material) { process_material = p_material; - Ref<ParticlesMaterial> pm = p_material; - if (pm.is_valid() && !pm->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z) && pm->get_gravity() == Vector3(0, -9.8, 0)) { + Ref<ParticleProcessMaterial> pm = p_material; + if (pm.is_valid() && !pm->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_DISABLE_Z) && pm->get_gravity() == Vector3(0, -9.8, 0)) { // Likely a new (3D) material, modify it to match 2D space - pm->set_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z, true); + pm->set_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_DISABLE_Z, true); pm->set_gravity(Vector3(0, 98, 0)); } RID material_rid; @@ -308,10 +308,10 @@ TypedArray<String> GPUParticles2D::get_configuration_warnings() const { CanvasItemMaterial *mat = Object::cast_to<CanvasItemMaterial>(get_material().ptr()); if (get_material().is_null() || (mat && !mat->get_particles_animation())) { - const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(process_material.ptr()); + const ParticleProcessMaterial *process = Object::cast_to<ParticleProcessMaterial>(process_material.ptr()); if (process && - (process->get_param_max(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || - process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { + (process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_OFFSET) != 0.0 || + process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_OFFSET).is_valid())) { warnings.push_back(RTR("Particles2D animation requires the usage of a CanvasItemMaterial with \"Particles Animation\" enabled.")); } } @@ -625,7 +625,7 @@ void GPUParticles2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_sections", PROPERTY_HINT_RANGE, "2,128,1"), "set_trail_sections", "get_trail_sections"); ADD_PROPERTY(PropertyInfo(Variant::INT, "trail_section_subdivisions", PROPERTY_HINT_RANGE, "1,1024,1"), "set_trail_section_subdivisions", "get_trail_section_subdivisions"); ADD_GROUP("Process Material", "process_"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material"); ADD_GROUP("Textures", ""); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "texture", PROPERTY_HINT_RESOURCE_TYPE, "Texture2D"), "set_texture", "get_texture"); diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index c5966bedd2..a592d20cba 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -127,7 +127,7 @@ TypedArray<String> NavigationObstacle2D::get_configuration_warnings() const { } if (Object::cast_to<StaticBody2D>(get_parent())) { - warnings.push_back(RTR("The NavigationObstacle2D is intended for constantly moving bodies like CharacterBody2D or RigidDynamicBody2D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." + warnings.push_back(RTR("The NavigationObstacle2D is intended for constantly moving bodies like CharacterBody2D or RigidBody2D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." "\nNot constantly moving or complete static objects should be captured with a refreshed NavigationPolygon so agents can not only avoid them but also move along those objects outline at high detail")); } diff --git a/scene/2d/physical_bone_2d.cpp b/scene/2d/physical_bone_2d.cpp index 62f4d855ef..e6933b8a40 100644 --- a/scene/2d/physical_bone_2d.cpp +++ b/scene/2d/physical_bone_2d.cpp @@ -35,7 +35,7 @@ void PhysicalBone2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { - // Position the RigidDynamicBody in the correct position. + // Position the RigidBody in the correct position. if (follow_bone_when_simulating) { _position_at_bone2d(); } @@ -287,7 +287,7 @@ void PhysicalBone2D::_bind_methods() { } PhysicalBone2D::PhysicalBone2D() { - // Stop the RigidDynamicBody from executing its force integration. + // Stop the RigidBody from executing its force integration. PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), 0); PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), 0); PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BodyMode::BODY_MODE_STATIC); diff --git a/scene/2d/physical_bone_2d.h b/scene/2d/physical_bone_2d.h index 22d329c320..9fbfa04100 100644 --- a/scene/2d/physical_bone_2d.h +++ b/scene/2d/physical_bone_2d.h @@ -36,8 +36,8 @@ class Joint2D; -class PhysicalBone2D : public RigidDynamicBody2D { - GDCLASS(PhysicalBone2D, RigidDynamicBody2D); +class PhysicalBone2D : public RigidBody2D { + GDCLASS(PhysicalBone2D, RigidBody2D); protected: void _notification(int p_what); diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index a317285a1b..43158344b4 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -325,7 +325,7 @@ AnimatableBody2D::AnimatableBody2D() : StaticBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) { } -void RigidDynamicBody2D::_body_enter_tree(ObjectID p_id) { +void RigidBody2D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -347,7 +347,7 @@ void RigidDynamicBody2D::_body_enter_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody2D::_body_exit_tree(ObjectID p_id) { +void RigidBody2D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -368,7 +368,7 @@ void RigidDynamicBody2D::_body_exit_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { +void RigidBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { bool body_in = p_status == 1; ObjectID objid = p_instance; @@ -387,8 +387,8 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p //E->value.rc=0; E->value.in_scene = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree).bind(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree).bind(objid)); if (E->value.in_scene) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } @@ -416,8 +416,8 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p if (E->value.shapes.is_empty()) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree)); if (in_scene) { emit_signal(SceneStringNames::get_singleton()->body_exited, node); } @@ -431,19 +431,19 @@ void RigidDynamicBody2D::_body_inout(int p_status, const RID &p_body, ObjectID p } } -struct _RigidDynamicBody2DInOut { +struct _RigidBody2DInOut { RID rid; ObjectID id; int shape = 0; int local_shape = 0; }; -void RigidDynamicBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { - RigidDynamicBody2D *body = static_cast<RigidDynamicBody2D *>(p_instance); +void RigidBody2D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState2D *p_state) { + RigidBody2D *body = static_cast<RigidBody2D *>(p_instance); body->_body_state_changed(p_state); } -void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { +void RigidBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) { set_block_transform_notify(true); // don't want notify (would feedback loop) if (!freeze || freeze_mode != FREEZE_MODE_KINEMATIC) { set_global_transform(p_state->get_transform()); @@ -473,9 +473,9 @@ void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) } } - _RigidDynamicBody2DInOut *toadd = (_RigidDynamicBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidDynamicBody2DInOut)); + _RigidBody2DInOut *toadd = (_RigidBody2DInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBody2DInOut)); int toadd_count = 0; //state->get_contact_count(); - RigidDynamicBody2D_RemoveAction *toremove = (RigidDynamicBody2D_RemoveAction *)alloca(rc * sizeof(RigidDynamicBody2D_RemoveAction)); + RigidBody2D_RemoveAction *toremove = (RigidBody2D_RemoveAction *)alloca(rc * sizeof(RigidBody2D_RemoveAction)); int toremove_count = 0; //put the ones to add @@ -539,7 +539,7 @@ void RigidDynamicBody2D::_body_state_changed(PhysicsDirectBodyState2D *p_state) } } -void RigidDynamicBody2D::_apply_body_mode() { +void RigidBody2D::_apply_body_mode() { if (freeze) { switch (freeze_mode) { case FREEZE_MODE_STATIC: { @@ -550,13 +550,13 @@ void RigidDynamicBody2D::_apply_body_mode() { } break; } } else if (lock_rotation) { - set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR); + set_body_mode(PhysicsServer2D::BODY_MODE_RIGID_LINEAR); } else { - set_body_mode(PhysicsServer2D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer2D::BODY_MODE_RIGID); } } -void RigidDynamicBody2D::set_lock_rotation_enabled(bool p_lock_rotation) { +void RigidBody2D::set_lock_rotation_enabled(bool p_lock_rotation) { if (p_lock_rotation == lock_rotation) { return; } @@ -565,11 +565,11 @@ void RigidDynamicBody2D::set_lock_rotation_enabled(bool p_lock_rotation) { _apply_body_mode(); } -bool RigidDynamicBody2D::is_lock_rotation_enabled() const { +bool RigidBody2D::is_lock_rotation_enabled() const { return lock_rotation; } -void RigidDynamicBody2D::set_freeze_enabled(bool p_freeze) { +void RigidBody2D::set_freeze_enabled(bool p_freeze) { if (p_freeze == freeze) { return; } @@ -578,11 +578,11 @@ void RigidDynamicBody2D::set_freeze_enabled(bool p_freeze) { _apply_body_mode(); } -bool RigidDynamicBody2D::is_freeze_enabled() const { +bool RigidBody2D::is_freeze_enabled() const { return freeze; } -void RigidDynamicBody2D::set_freeze_mode(FreezeMode p_freeze_mode) { +void RigidBody2D::set_freeze_mode(FreezeMode p_freeze_mode) { if (p_freeze_mode == freeze_mode) { return; } @@ -591,31 +591,31 @@ void RigidDynamicBody2D::set_freeze_mode(FreezeMode p_freeze_mode) { _apply_body_mode(); } -RigidDynamicBody2D::FreezeMode RigidDynamicBody2D::get_freeze_mode() const { +RigidBody2D::FreezeMode RigidBody2D::get_freeze_mode() const { return freeze_mode; } -void RigidDynamicBody2D::set_mass(real_t p_mass) { +void RigidBody2D::set_mass(real_t p_mass) { ERR_FAIL_COND(p_mass <= 0); mass = p_mass; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_MASS, mass); } -real_t RigidDynamicBody2D::get_mass() const { +real_t RigidBody2D::get_mass() const { return mass; } -void RigidDynamicBody2D::set_inertia(real_t p_inertia) { +void RigidBody2D::set_inertia(real_t p_inertia) { ERR_FAIL_COND(p_inertia < 0); inertia = p_inertia; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, inertia); } -real_t RigidDynamicBody2D::get_inertia() const { +real_t RigidBody2D::get_inertia() const { return inertia; } -void RigidDynamicBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) { +void RigidBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) { if (center_of_mass_mode == p_mode) { return; } @@ -637,11 +637,11 @@ void RigidDynamicBody2D::set_center_of_mass_mode(CenterOfMassMode p_mode) { } } -RigidDynamicBody2D::CenterOfMassMode RigidDynamicBody2D::get_center_of_mass_mode() const { +RigidBody2D::CenterOfMassMode RigidBody2D::get_center_of_mass_mode() const { return center_of_mass_mode; } -void RigidDynamicBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) { +void RigidBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) { if (center_of_mass == p_center_of_mass) { return; } @@ -652,102 +652,102 @@ void RigidDynamicBody2D::set_center_of_mass(const Vector2 &p_center_of_mass) { PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_CENTER_OF_MASS, center_of_mass); } -const Vector2 &RigidDynamicBody2D::get_center_of_mass() const { +const Vector2 &RigidBody2D::get_center_of_mass() const { return center_of_mass; } -void RigidDynamicBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { +void RigidBody2D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { if (physics_material_override.is_valid()) { - if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody2D::_reload_physics_characteristics))) { - physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody2D::_reload_physics_characteristics)); + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics))) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics)); } } physics_material_override = p_physics_material_override; if (physics_material_override.is_valid()) { - physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody2D::_reload_physics_characteristics)); + physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody2D::_reload_physics_characteristics)); } _reload_physics_characteristics(); } -Ref<PhysicsMaterial> RigidDynamicBody2D::get_physics_material_override() const { +Ref<PhysicsMaterial> RigidBody2D::get_physics_material_override() const { return physics_material_override; } -void RigidDynamicBody2D::set_gravity_scale(real_t p_gravity_scale) { +void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) { gravity_scale = p_gravity_scale; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE, gravity_scale); } -real_t RigidDynamicBody2D::get_gravity_scale() const { +real_t RigidBody2D::get_gravity_scale() const { return gravity_scale; } -void RigidDynamicBody2D::set_linear_damp_mode(DampMode p_mode) { +void RigidBody2D::set_linear_damp_mode(DampMode p_mode) { linear_damp_mode = p_mode; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode); } -RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_linear_damp_mode() const { +RigidBody2D::DampMode RigidBody2D::get_linear_damp_mode() const { return linear_damp_mode; } -void RigidDynamicBody2D::set_angular_damp_mode(DampMode p_mode) { +void RigidBody2D::set_angular_damp_mode(DampMode p_mode) { angular_damp_mode = p_mode; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode); } -RigidDynamicBody2D::DampMode RigidDynamicBody2D::get_angular_damp_mode() const { +RigidBody2D::DampMode RigidBody2D::get_angular_damp_mode() const { return angular_damp_mode; } -void RigidDynamicBody2D::set_linear_damp(real_t p_linear_damp) { +void RigidBody2D::set_linear_damp(real_t p_linear_damp) { ERR_FAIL_COND(p_linear_damp < -1); linear_damp = p_linear_damp; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP, linear_damp); } -real_t RigidDynamicBody2D::get_linear_damp() const { +real_t RigidBody2D::get_linear_damp() const { return linear_damp; } -void RigidDynamicBody2D::set_angular_damp(real_t p_angular_damp) { +void RigidBody2D::set_angular_damp(real_t p_angular_damp) { ERR_FAIL_COND(p_angular_damp < -1); angular_damp = p_angular_damp; PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP, angular_damp); } -real_t RigidDynamicBody2D::get_angular_damp() const { +real_t RigidBody2D::get_angular_damp() const { return angular_damp; } -void RigidDynamicBody2D::set_axis_velocity(const Vector2 &p_axis) { +void RigidBody2D::set_axis_velocity(const Vector2 &p_axis) { Vector2 axis = p_axis.normalized(); linear_velocity -= axis * axis.dot(linear_velocity); linear_velocity += p_axis; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -void RigidDynamicBody2D::set_linear_velocity(const Vector2 &p_velocity) { +void RigidBody2D::set_linear_velocity(const Vector2 &p_velocity) { linear_velocity = p_velocity; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -Vector2 RigidDynamicBody2D::get_linear_velocity() const { +Vector2 RigidBody2D::get_linear_velocity() const { return linear_velocity; } -void RigidDynamicBody2D::set_angular_velocity(real_t p_velocity) { +void RigidBody2D::set_angular_velocity(real_t p_velocity) { angular_velocity = p_velocity; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); } -real_t RigidDynamicBody2D::get_angular_velocity() const { +real_t RigidBody2D::get_angular_velocity() const { return angular_velocity; } -void RigidDynamicBody2D::set_use_custom_integrator(bool p_enable) { +void RigidBody2D::set_use_custom_integrator(bool p_enable) { if (custom_integrator == p_enable) { return; } @@ -756,105 +756,105 @@ void RigidDynamicBody2D::set_use_custom_integrator(bool p_enable) { PhysicsServer2D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); } -bool RigidDynamicBody2D::is_using_custom_integrator() { +bool RigidBody2D::is_using_custom_integrator() { return custom_integrator; } -void RigidDynamicBody2D::set_sleeping(bool p_sleeping) { +void RigidBody2D::set_sleeping(bool p_sleeping) { sleeping = p_sleeping; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_SLEEPING, sleeping); } -void RigidDynamicBody2D::set_can_sleep(bool p_active) { +void RigidBody2D::set_can_sleep(bool p_active) { can_sleep = p_active; PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_CAN_SLEEP, p_active); } -bool RigidDynamicBody2D::is_able_to_sleep() const { +bool RigidBody2D::is_able_to_sleep() const { return can_sleep; } -bool RigidDynamicBody2D::is_sleeping() const { +bool RigidBody2D::is_sleeping() const { return sleeping; } -void RigidDynamicBody2D::set_max_contacts_reported(int p_amount) { +void RigidBody2D::set_max_contacts_reported(int p_amount) { max_contacts_reported = p_amount; PhysicsServer2D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); } -int RigidDynamicBody2D::get_max_contacts_reported() const { +int RigidBody2D::get_max_contacts_reported() const { return max_contacts_reported; } -int RigidDynamicBody2D::get_contact_count() const { +int RigidBody2D::get_contact_count() const { PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(get_rid()); ERR_FAIL_NULL_V(bs, 0); return bs->get_contact_count(); } -void RigidDynamicBody2D::apply_central_impulse(const Vector2 &p_impulse) { +void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) { PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } -void RigidDynamicBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) { +void RigidBody2D::apply_impulse(const Vector2 &p_impulse, const Vector2 &p_position) { PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_impulse, p_position); } -void RigidDynamicBody2D::apply_torque_impulse(real_t p_torque) { +void RigidBody2D::apply_torque_impulse(real_t p_torque) { PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque); } -void RigidDynamicBody2D::apply_central_force(const Vector2 &p_force) { +void RigidBody2D::apply_central_force(const Vector2 &p_force) { PhysicsServer2D::get_singleton()->body_apply_central_force(get_rid(), p_force); } -void RigidDynamicBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) { +void RigidBody2D::apply_force(const Vector2 &p_force, const Vector2 &p_position) { PhysicsServer2D::get_singleton()->body_apply_force(get_rid(), p_force, p_position); } -void RigidDynamicBody2D::apply_torque(real_t p_torque) { +void RigidBody2D::apply_torque(real_t p_torque) { PhysicsServer2D::get_singleton()->body_apply_torque(get_rid(), p_torque); } -void RigidDynamicBody2D::add_constant_central_force(const Vector2 &p_force) { +void RigidBody2D::add_constant_central_force(const Vector2 &p_force) { PhysicsServer2D::get_singleton()->body_add_constant_central_force(get_rid(), p_force); } -void RigidDynamicBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) { +void RigidBody2D::add_constant_force(const Vector2 &p_force, const Vector2 &p_position) { PhysicsServer2D::get_singleton()->body_add_constant_force(get_rid(), p_force, p_position); } -void RigidDynamicBody2D::add_constant_torque(const real_t p_torque) { +void RigidBody2D::add_constant_torque(const real_t p_torque) { PhysicsServer2D::get_singleton()->body_add_constant_torque(get_rid(), p_torque); } -void RigidDynamicBody2D::set_constant_force(const Vector2 &p_force) { +void RigidBody2D::set_constant_force(const Vector2 &p_force) { PhysicsServer2D::get_singleton()->body_set_constant_force(get_rid(), p_force); } -Vector2 RigidDynamicBody2D::get_constant_force() const { +Vector2 RigidBody2D::get_constant_force() const { return PhysicsServer2D::get_singleton()->body_get_constant_force(get_rid()); } -void RigidDynamicBody2D::set_constant_torque(real_t p_torque) { +void RigidBody2D::set_constant_torque(real_t p_torque) { PhysicsServer2D::get_singleton()->body_set_constant_torque(get_rid(), p_torque); } -real_t RigidDynamicBody2D::get_constant_torque() const { +real_t RigidBody2D::get_constant_torque() const { return PhysicsServer2D::get_singleton()->body_get_constant_torque(get_rid()); } -void RigidDynamicBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { +void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { ccd_mode = p_mode; PhysicsServer2D::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), PhysicsServer2D::CCDMode(p_mode)); } -RigidDynamicBody2D::CCDMode RigidDynamicBody2D::get_continuous_collision_detection_mode() const { +RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const { return ccd_mode; } -TypedArray<Node2D> RigidDynamicBody2D::get_colliding_bodies() const { +TypedArray<Node2D> RigidBody2D::get_colliding_bodies() const { ERR_FAIL_COND_V(!contact_monitor, TypedArray<Node2D>()); TypedArray<Node2D> ret; @@ -872,7 +872,7 @@ TypedArray<Node2D> RigidDynamicBody2D::get_colliding_bodies() const { return ret; } -void RigidDynamicBody2D::set_contact_monitor(bool p_enabled) { +void RigidBody2D::set_contact_monitor(bool p_enabled) { if (p_enabled == is_contact_monitor_enabled()) { return; } @@ -886,8 +886,8 @@ void RigidDynamicBody2D::set_contact_monitor(bool p_enabled) { Node *node = Object::cast_to<Node>(obj); if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody2D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody2D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody2D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody2D::_body_exit_tree)); } } @@ -899,11 +899,11 @@ void RigidDynamicBody2D::set_contact_monitor(bool p_enabled) { } } -bool RigidDynamicBody2D::is_contact_monitor_enabled() const { +bool RigidBody2D::is_contact_monitor_enabled() const { return contact_monitor != nullptr; } -void RigidDynamicBody2D::_notification(int p_what) { +void RigidBody2D::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -921,103 +921,103 @@ void RigidDynamicBody2D::_notification(int p_what) { #endif } -TypedArray<String> RigidDynamicBody2D::get_configuration_warnings() const { +TypedArray<String> RigidBody2D::get_configuration_warnings() const { Transform2D t = get_transform(); TypedArray<String> warnings = CollisionObject2D::get_configuration_warnings(); if (ABS(t.columns[0].length() - 1.0) > 0.05 || ABS(t.columns[1].length() - 1.0) > 0.05) { - warnings.push_back(RTR("Size changes to RigidDynamicBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); + warnings.push_back(RTR("Size changes to RigidBody2D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } return warnings; } -void RigidDynamicBody2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidDynamicBody2D::set_mass); - ClassDB::bind_method(D_METHOD("get_mass"), &RigidDynamicBody2D::get_mass); +void RigidBody2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody2D::set_mass); + ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody2D::get_mass); - ClassDB::bind_method(D_METHOD("get_inertia"), &RigidDynamicBody2D::get_inertia); - ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidDynamicBody2D::set_inertia); + ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody2D::get_inertia); + ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody2D::set_inertia); - ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidDynamicBody2D::set_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidDynamicBody2D::get_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody2D::set_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody2D::get_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidDynamicBody2D::set_center_of_mass); - ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidDynamicBody2D::get_center_of_mass); + ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody2D::set_center_of_mass); + ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody2D::get_center_of_mass); - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidDynamicBody2D::set_physics_material_override); - ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidDynamicBody2D::get_physics_material_override); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody2D::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody2D::get_physics_material_override); - ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidDynamicBody2D::set_gravity_scale); - ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidDynamicBody2D::get_gravity_scale); + ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody2D::set_gravity_scale); + ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody2D::get_gravity_scale); - ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidDynamicBody2D::set_linear_damp_mode); - ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidDynamicBody2D::get_linear_damp_mode); + ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody2D::set_linear_damp_mode); + ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody2D::get_linear_damp_mode); - ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidDynamicBody2D::set_angular_damp_mode); - ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidDynamicBody2D::get_angular_damp_mode); + ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody2D::set_angular_damp_mode); + ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody2D::get_angular_damp_mode); - ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidDynamicBody2D::set_linear_damp); - ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidDynamicBody2D::get_linear_damp); + ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody2D::set_linear_damp); + ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody2D::get_linear_damp); - ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidDynamicBody2D::set_angular_damp); - ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidDynamicBody2D::get_angular_damp); + ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody2D::set_angular_damp); + ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody2D::get_angular_damp); - ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidDynamicBody2D::set_linear_velocity); - ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidDynamicBody2D::get_linear_velocity); + ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody2D::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody2D::get_linear_velocity); - ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidDynamicBody2D::set_angular_velocity); - ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidDynamicBody2D::get_angular_velocity); + ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody2D::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody2D::get_angular_velocity); - ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidDynamicBody2D::set_max_contacts_reported); - ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidDynamicBody2D::get_max_contacts_reported); - ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidDynamicBody2D::get_contact_count); + ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody2D::set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody2D::get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody2D::get_contact_count); - ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidDynamicBody2D::set_use_custom_integrator); - ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidDynamicBody2D::is_using_custom_integrator); + ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody2D::set_use_custom_integrator); + ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody2D::is_using_custom_integrator); - ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidDynamicBody2D::set_contact_monitor); - ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidDynamicBody2D::is_contact_monitor_enabled); + ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody2D::set_contact_monitor); + ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody2D::is_contact_monitor_enabled); - ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidDynamicBody2D::set_continuous_collision_detection_mode); - ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidDynamicBody2D::get_continuous_collision_detection_mode); + ClassDB::bind_method(D_METHOD("set_continuous_collision_detection_mode", "mode"), &RigidBody2D::set_continuous_collision_detection_mode); + ClassDB::bind_method(D_METHOD("get_continuous_collision_detection_mode"), &RigidBody2D::get_continuous_collision_detection_mode); - ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidDynamicBody2D::set_axis_velocity); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidDynamicBody2D::apply_central_impulse, Vector2()); - ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidDynamicBody2D::apply_impulse, Vector2()); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidDynamicBody2D::apply_torque_impulse); + ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody2D::set_axis_velocity); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody2D::apply_central_impulse, Vector2()); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody2D::apply_impulse, Vector2()); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "torque"), &RigidBody2D::apply_torque_impulse); - ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidDynamicBody2D::apply_central_force); - ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidDynamicBody2D::apply_force, Vector2()); - ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidDynamicBody2D::apply_torque); + ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody2D::apply_central_force); + ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody2D::apply_force, Vector2()); + ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody2D::apply_torque); - ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidDynamicBody2D::add_constant_central_force); - ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidDynamicBody2D::add_constant_force, Vector2()); - ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidDynamicBody2D::add_constant_torque); + ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody2D::add_constant_central_force); + ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody2D::add_constant_force, Vector2()); + ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody2D::add_constant_torque); - ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidDynamicBody2D::set_constant_force); - ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidDynamicBody2D::get_constant_force); + ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody2D::set_constant_force); + ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody2D::get_constant_force); - ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidDynamicBody2D::set_constant_torque); - ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidDynamicBody2D::get_constant_torque); + ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody2D::set_constant_torque); + ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody2D::get_constant_torque); - ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidDynamicBody2D::set_sleeping); - ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidDynamicBody2D::is_sleeping); + ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody2D::set_sleeping); + ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody2D::is_sleeping); - ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidDynamicBody2D::set_can_sleep); - ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidDynamicBody2D::is_able_to_sleep); + ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody2D::set_can_sleep); + ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody2D::is_able_to_sleep); - ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidDynamicBody2D::set_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidDynamicBody2D::is_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody2D::set_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody2D::is_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidDynamicBody2D::set_freeze_enabled); - ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidDynamicBody2D::is_freeze_enabled); + ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody2D::set_freeze_enabled); + ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody2D::is_freeze_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidDynamicBody2D::set_freeze_mode); - ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidDynamicBody2D::get_freeze_mode); + ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody2D::set_freeze_mode); + ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody2D::get_freeze_mode); - ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidDynamicBody2D::get_colliding_bodies); + ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody2D::get_colliding_bodies); GDVIRTUAL_BIND(_integrate_forces, "state"); @@ -1069,7 +1069,7 @@ void RigidDynamicBody2D::_bind_methods() { BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE); } -void RigidDynamicBody2D::_validate_property(PropertyInfo &p_property) const { +void RigidBody2D::_validate_property(PropertyInfo &p_property) const { if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) { if (p_property.name == "center_of_mass") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; @@ -1077,18 +1077,18 @@ void RigidDynamicBody2D::_validate_property(PropertyInfo &p_property) const { } } -RigidDynamicBody2D::RigidDynamicBody2D() : - PhysicsBody2D(PhysicsServer2D::BODY_MODE_DYNAMIC) { +RigidBody2D::RigidBody2D() : + PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) { PhysicsServer2D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); } -RigidDynamicBody2D::~RigidDynamicBody2D() { +RigidBody2D::~RigidBody2D() { if (contact_monitor) { memdelete(contact_monitor); } } -void RigidDynamicBody2D::_reload_physics_characteristics() { +void RigidBody2D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0); PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index fe64c087c6..eaba9aadad 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -113,8 +113,8 @@ private: bool is_sync_to_physics_enabled() const; }; -class RigidDynamicBody2D : public PhysicsBody2D { - GDCLASS(RigidDynamicBody2D, PhysicsBody2D); +class RigidBody2D : public PhysicsBody2D { + GDCLASS(RigidBody2D, PhysicsBody2D); public: enum FreezeMode { @@ -186,7 +186,7 @@ private: local_shape = p_ls; } }; - struct RigidDynamicBody2D_RemoveAction { + struct RigidBody2D_RemoveAction { RID rid; ObjectID body_id; ShapePair pair; @@ -311,17 +311,17 @@ public: virtual TypedArray<String> get_configuration_warnings() const override; - RigidDynamicBody2D(); - ~RigidDynamicBody2D(); + RigidBody2D(); + ~RigidBody2D(); private: void _reload_physics_characteristics(); }; -VARIANT_ENUM_CAST(RigidDynamicBody2D::FreezeMode); -VARIANT_ENUM_CAST(RigidDynamicBody2D::CenterOfMassMode); -VARIANT_ENUM_CAST(RigidDynamicBody2D::DampMode); -VARIANT_ENUM_CAST(RigidDynamicBody2D::CCDMode); +VARIANT_ENUM_CAST(RigidBody2D::FreezeMode); +VARIANT_ENUM_CAST(RigidBody2D::CenterOfMassMode); +VARIANT_ENUM_CAST(RigidBody2D::DampMode); +VARIANT_ENUM_CAST(RigidBody2D::CCDMode); class CharacterBody2D : public PhysicsBody2D { GDCLASS(CharacterBody2D, PhysicsBody2D); @@ -373,9 +373,9 @@ private: bool slide_on_ceiling = true; int max_slides = 4; int platform_layer = 0; - real_t floor_max_angle = Math::deg2rad((real_t)45.0); + real_t floor_max_angle = Math::deg_to_rad((real_t)45.0); real_t floor_snap_length = 1; - real_t wall_min_slide_angle = Math::deg2rad((real_t)15.0); + real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0); Vector2 up_direction = Vector2(0.0, -1.0); uint32_t platform_floor_layers = UINT32_MAX; uint32_t platform_wall_layers = 0; diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index cbacb7f579..13a32fbfd4 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -44,7 +44,7 @@ bool Bone2D::_set(const StringName &p_path, const Variant &p_value) { } else if (path.begins_with("length")) { set_length(p_value); } else if (path.begins_with("bone_angle")) { - set_bone_angle(Math::deg2rad(real_t(p_value))); + set_bone_angle(Math::deg_to_rad(real_t(p_value))); } else if (path.begins_with("default_length")) { set_length(p_value); } @@ -66,7 +66,7 @@ bool Bone2D::_get(const StringName &p_path, Variant &r_ret) const { } else if (path.begins_with("length")) { r_ret = get_length(); } else if (path.begins_with("bone_angle")) { - r_ret = Math::rad2deg(get_bone_angle()); + r_ret = Math::rad_to_deg(get_bone_angle()); } else if (path.begins_with("default_length")) { r_ret = get_length(); } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 13bdd2bd5f..129cce93fa 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -553,7 +553,7 @@ int TileMap::get_layers_count() const { void TileMap::add_layer(int p_to_pos) { if (p_to_pos < 0) { - p_to_pos = layers.size(); + p_to_pos = layers.size() + p_to_pos + 1; } ERR_FAIL_INDEX(p_to_pos, (int)layers.size() + 1); @@ -612,6 +612,9 @@ void TileMap::remove_layer(int p_layer) { } void TileMap::set_layer_name(int p_layer, String p_name) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].name = p_name; emit_signal(SNAME("changed")); @@ -623,6 +626,9 @@ String TileMap::get_layer_name(int p_layer) const { } void TileMap::set_layer_enabled(int p_layer, bool p_enabled) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].enabled = p_enabled; _clear_layer_internals(p_layer); @@ -638,6 +644,9 @@ bool TileMap::is_layer_enabled(int p_layer) const { } void TileMap::set_layer_modulate(int p_layer, Color p_modulate) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].modulate = p_modulate; _clear_layer_internals(p_layer); @@ -651,6 +660,9 @@ Color TileMap::get_layer_modulate(int p_layer) const { } void TileMap::set_layer_y_sort_enabled(int p_layer, bool p_y_sort_enabled) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].y_sort_enabled = p_y_sort_enabled; _clear_layer_internals(p_layer); @@ -666,6 +678,9 @@ bool TileMap::is_layer_y_sort_enabled(int p_layer) const { } void TileMap::set_layer_y_sort_origin(int p_layer, int p_y_sort_origin) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].y_sort_origin = p_y_sort_origin; _clear_layer_internals(p_layer); @@ -679,6 +694,9 @@ int TileMap::get_layer_y_sort_origin(int p_layer) const { } void TileMap::set_layer_z_index(int p_layer, int p_z_index) { + if (p_layer < 0) { + p_layer = layers.size() + p_layer; + } ERR_FAIL_INDEX(p_layer, (int)layers.size()); layers[p_layer].z_index = p_z_index; _clear_layer_internals(p_layer); @@ -3839,7 +3857,7 @@ void TileMap::_bind_methods() { ClassDB::bind_method(D_METHOD("get_layer_name", "layer"), &TileMap::get_layer_name); ClassDB::bind_method(D_METHOD("set_layer_enabled", "layer", "enabled"), &TileMap::set_layer_enabled); ClassDB::bind_method(D_METHOD("is_layer_enabled", "layer"), &TileMap::is_layer_enabled); - ClassDB::bind_method(D_METHOD("set_layer_modulate", "layer", "enabled"), &TileMap::set_layer_modulate); + ClassDB::bind_method(D_METHOD("set_layer_modulate", "layer", "modulate"), &TileMap::set_layer_modulate); ClassDB::bind_method(D_METHOD("get_layer_modulate", "layer"), &TileMap::get_layer_modulate); ClassDB::bind_method(D_METHOD("set_layer_y_sort_enabled", "layer", "y_sort_enabled"), &TileMap::set_layer_y_sort_enabled); ClassDB::bind_method(D_METHOD("is_layer_y_sort_enabled", "layer"), &TileMap::is_layer_y_sort_enabled); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 93e91f9b5b..0e7b71f74a 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -149,7 +149,7 @@ void AudioStreamPlayer3D::_calc_reverb_vol(Area3D *area, Vector3 listener_area_p if (uniformity > 0.0) { float distance = listener_area_pos.length(); - float attenuation = Math::db2linear(_get_attenuation_db(distance)); + float attenuation = Math::db_to_linear(_get_attenuation_db(distance)); // Determine the fraction of sound that would come from each speaker if they were all driven uniformly. float center_val[3] = { 0.5f, 0.25f, 0.16666f }; @@ -213,12 +213,12 @@ float AudioStreamPlayer3D::_get_attenuation_db(float p_distance) const { float att = 0; switch (attenuation_model) { case ATTENUATION_INVERSE_DISTANCE: { - att = Math::linear2db(1.0 / ((p_distance / unit_size) + CMP_EPSILON)); + att = Math::linear_to_db(1.0 / ((p_distance / unit_size) + CMP_EPSILON)); } break; case ATTENUATION_INVERSE_SQUARE_DISTANCE: { float d = (p_distance / unit_size); d *= d; - att = Math::linear2db(1.0 / (d + CMP_EPSILON)); + att = Math::linear_to_db(1.0 / (d + CMP_EPSILON)); } break; case ATTENUATION_LOGARITHMIC: { att = -20 * Math::log(p_distance / unit_size + CMP_EPSILON); @@ -443,7 +443,7 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() { } } - float multiplier = Math::db2linear(_get_attenuation_db(dist)); + float multiplier = Math::db_to_linear(_get_attenuation_db(dist)); if (max_distance > 0) { multiplier *= MAX(0, 1.0 - (dist / max_distance)); } @@ -453,13 +453,13 @@ Vector<AudioFrame> AudioStreamPlayer3D::_update_panning() { if (emission_angle_enabled) { Vector3 listenertopos = global_pos - listener_node->get_global_transform().origin; float c = listenertopos.normalized().dot(get_global_transform().basis.get_column(2).normalized()); //it's z negative - float angle = Math::rad2deg(Math::acos(c)); + float angle = Math::rad_to_deg(Math::acos(c)); if (angle > emission_angle) { db_att -= -emission_angle_filter_attenuation_db; } } - linear_attenuation = Math::db2linear(db_att); + linear_attenuation = Math::db_to_linear(db_att); for (Ref<AudioStreamPlayback> &playback : stream_playbacks) { AudioServer::get_singleton()->set_playback_highshelf_params(playback, linear_attenuation, attenuation_filter_cutoff_hz); } diff --git a/scene/3d/collision_polygon_3d.cpp b/scene/3d/collision_polygon_3d.cpp index bd6a70e566..90099d787b 100644 --- a/scene/3d/collision_polygon_3d.cpp +++ b/scene/3d/collision_polygon_3d.cpp @@ -171,7 +171,7 @@ TypedArray<String> CollisionPolygon3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject3D>(get_parent())) { - warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidDynamicBody3D, CharacterBody3D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionPolygon3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape.")); } if (polygon.is_empty()) { diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index 759997de7b..a9bc28b464 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -118,7 +118,7 @@ TypedArray<String> CollisionShape3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (!Object::cast_to<CollisionObject3D>(get_parent())) { - warnings.push_back(RTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidDynamicBody3D, CharacterBody3D, etc. to give them a shape.")); + warnings.push_back(RTR("CollisionShape3D only serves to provide a collision shape to a CollisionObject3D derived node. Please only use it as a child of Area3D, StaticBody3D, RigidBody3D, CharacterBody3D, etc. to give them a shape.")); } if (!shape.is_valid()) { @@ -126,9 +126,9 @@ TypedArray<String> CollisionShape3D::get_configuration_warnings() const { } if (shape.is_valid() && - Object::cast_to<RigidDynamicBody3D>(get_parent()) && + Object::cast_to<RigidBody3D>(get_parent()) && Object::cast_to<ConcavePolygonShape3D>(*shape)) { - warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidDynamicBody3D in another mode than static.")); + warnings.push_back(RTR("ConcavePolygonShape3D doesn't support RigidBody3D in another mode than static.")); } return warnings; diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index a79fd15b1a..9dc61b35af 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -33,7 +33,7 @@ #include "scene/3d/camera_3d.h" #include "scene/3d/gpu_particles_3d.h" #include "scene/main/viewport.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" AABB CPUParticles3D::get_aabb() const { return AABB(); @@ -766,13 +766,13 @@ void CPUParticles3D::_particles_process(double p_delta) { } if (particle_flags[PARTICLE_FLAG_DISABLE_Z]) { - real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg2rad((Math::randf() * 2.0 - 1.0) * spread); + real_t angle1_rad = Math::atan2(direction.y, direction.x) + Math::deg_to_rad((Math::randf() * 2.0 - 1.0) * spread); Vector3 rot = Vector3(Math::cos(angle1_rad), Math::sin(angle1_rad), 0.0); p.velocity = rot * Math::lerp(parameters_min[PARAM_INITIAL_LINEAR_VELOCITY], parameters_max[PARAM_INITIAL_LINEAR_VELOCITY], (real_t)Math::randf()); } else { //initiate velocity spread in 3D - real_t angle1_rad = Math::deg2rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * spread); - real_t angle2_rad = Math::deg2rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread); + real_t angle1_rad = Math::deg_to_rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * spread); + real_t angle2_rad = Math::deg_to_rad((Math::randf() * (real_t)2.0 - (real_t)1.0) * ((real_t)1.0 - flatness) * spread); Vector3 direction_xz = Vector3(Math::sin(angle1_rad), 0, Math::cos(angle1_rad)); Vector3 direction_yz = Vector3(0, Math::sin(angle2_rad), Math::cos(angle2_rad)); @@ -796,7 +796,7 @@ void CPUParticles3D::_particles_process(double p_delta) { } real_t base_angle = tex_angle * Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); - p.custom[0] = Math::deg2rad(base_angle); //angle + p.custom[0] = Math::deg_to_rad(base_angle); //angle p.custom[1] = 0.0; //phase p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand); //animation offset (0-1) p.transform = Transform3D(); @@ -983,7 +983,7 @@ void CPUParticles3D::_particles_process(double p_delta) { real_t orbit_amount = tex_orbit_velocity * Math::lerp(parameters_min[PARAM_ORBIT_VELOCITY], parameters_max[PARAM_ORBIT_VELOCITY], rand_from_seed(alt_seed)); if (orbit_amount != 0.0) { real_t ang = orbit_amount * local_delta * Math_TAU; - // Not sure why the ParticlesMaterial code uses a clockwise rotation matrix, + // Not sure why the ParticleProcessMaterial code uses a clockwise rotation matrix, // but we use -ang here to reproduce its behavior. Transform2D rot = Transform2D(-ang, Vector2()); Vector2 rotv = rot.basis_xform(Vector2(diff.x, diff.y)); @@ -1007,7 +1007,7 @@ void CPUParticles3D::_particles_process(double p_delta) { } real_t base_angle = (tex_angle)*Math::lerp(parameters_min[PARAM_ANGLE], parameters_max[PARAM_ANGLE], p.angle_rand); base_angle += p.custom[1] * lifetime * tex_angular_velocity * Math::lerp(parameters_min[PARAM_ANGULAR_VELOCITY], parameters_max[PARAM_ANGULAR_VELOCITY], rand_from_seed(alt_seed)); - p.custom[0] = Math::deg2rad(base_angle); //angle + p.custom[0] = Math::deg_to_rad(base_angle); //angle p.custom[2] = tex_anim_offset * Math::lerp(parameters_min[PARAM_ANIM_OFFSET], parameters_max[PARAM_ANIM_OFFSET], p.anim_offset_rand) + tv * tex_anim_speed * Math::lerp(parameters_min[PARAM_ANIM_SPEED], parameters_max[PARAM_ANIM_SPEED], rand_from_seed(alt_seed)); //angle } //apply color @@ -1343,7 +1343,7 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_draw_order(DrawOrder(particles->get_draw_order())); set_mesh(particles->get_draw_pass_mesh(0)); - Ref<ParticlesMaterial> material = particles->get_process_material(); + Ref<ParticleProcessMaterial> material = particles->get_process_material(); if (material.is_null()) { return; } @@ -1364,14 +1364,14 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_color_initial_ramp(gti->get_gradient()); } - set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); - set_particle_flag(PARTICLE_FLAG_ROTATE_Y, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_ROTATE_Y)); - set_particle_flag(PARTICLE_FLAG_DISABLE_Z, material->get_particle_flag(ParticlesMaterial::PARTICLE_FLAG_DISABLE_Z)); + set_particle_flag(PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY)); + set_particle_flag(PARTICLE_FLAG_ROTATE_Y, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_ROTATE_Y)); + set_particle_flag(PARTICLE_FLAG_DISABLE_Z, material->get_particle_flag(ParticleProcessMaterial::PARTICLE_FLAG_DISABLE_Z)); set_emission_shape(EmissionShape(material->get_emission_shape())); set_emission_sphere_radius(material->get_emission_sphere_radius()); set_emission_box_extents(material->get_emission_box_extents()); - Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticlesMaterial::PARAM_SCALE); + Ref<CurveXYZTexture> scale3D = material->get_param_texture(ParticleProcessMaterial::PARAM_SCALE); if (scale3D.is_valid()) { split_scale = true; scale_curve_x = scale3D->get_curve_x(); @@ -1382,14 +1382,14 @@ void CPUParticles3D::convert_from_particles(Node *p_particles) { set_gravity(material->get_gravity()); set_lifetime_randomness(material->get_lifetime_randomness()); -#define CONVERT_PARAM(m_param) \ - set_param_min(m_param, material->get_param_min(ParticlesMaterial::m_param)); \ - { \ - Ref<CurveTexture> ctex = material->get_param_texture(ParticlesMaterial::m_param); \ - if (ctex.is_valid()) \ - set_param_curve(m_param, ctex->get_curve()); \ - } \ - set_param_max(m_param, material->get_param_max(ParticlesMaterial::m_param)); +#define CONVERT_PARAM(m_param) \ + set_param_min(m_param, material->get_param_min(ParticleProcessMaterial::m_param)); \ + { \ + Ref<CurveTexture> ctex = material->get_param_texture(ParticleProcessMaterial::m_param); \ + if (ctex.is_valid()) \ + set_param_curve(m_param, ctex->get_curve()); \ + } \ + set_param_max(m_param, material->get_param_max(ParticleProcessMaterial::m_param)); CONVERT_PARAM(PARAM_INITIAL_LINEAR_VELOCITY); CONVERT_PARAM(PARAM_ANGULAR_VELOCITY); diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index b46e6a8b71..bd63939d74 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -30,7 +30,7 @@ #include "gpu_particles_3d.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" AABB GPUParticles3D::get_aabb() const { return AABB(); @@ -306,10 +306,10 @@ TypedArray<String> GPUParticles3D::get_configuration_warnings() const { if (process_material.is_null()) { warnings.push_back(RTR("A material to process the particles is not assigned, so no behavior is imprinted.")); } else { - const ParticlesMaterial *process = Object::cast_to<ParticlesMaterial>(process_material.ptr()); + const ParticleProcessMaterial *process = Object::cast_to<ParticleProcessMaterial>(process_material.ptr()); if (!anim_material_found && process && - (process->get_param_max(ParticlesMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticlesMaterial::PARAM_ANIM_OFFSET) != 0.0 || - process->get_param_texture(ParticlesMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticlesMaterial::PARAM_ANIM_OFFSET).is_valid())) { + (process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_SPEED) != 0.0 || process->get_param_max(ParticleProcessMaterial::PARAM_ANIM_OFFSET) != 0.0 || + process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_SPEED).is_valid() || process->get_param_texture(ParticleProcessMaterial::PARAM_ANIM_OFFSET).is_valid())) { warnings.push_back(RTR("Particles animation requires the usage of a BaseMaterial3D whose Billboard Mode is set to \"Particle Billboard\".")); } } @@ -585,7 +585,7 @@ void GPUParticles3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "trail_enabled"), "set_trail_enabled", "is_trail_enabled"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trail_length_secs", PROPERTY_HINT_RANGE, "0.01,10,0.01,suffix:s"), "set_trail_length", "get_trail_length"); ADD_GROUP("Process Material", ""); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticlesMaterial"), "set_process_material", "get_process_material"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "process_material", PROPERTY_HINT_RESOURCE_TYPE, "ShaderMaterial,ParticleProcessMaterial"), "set_process_material", "get_process_material"); ADD_GROUP("Draw Passes", "draw_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "draw_passes", PROPERTY_HINT_RANGE, "0," + itos(MAX_DRAW_PASSES) + ",1"), "set_draw_passes", "get_draw_passes"); for (int i = 0; i < MAX_DRAW_PASSES; i++) { diff --git a/scene/3d/label_3d.cpp b/scene/3d/label_3d.cpp index 35036b70d8..40b8af7d63 100644 --- a/scene/3d/label_3d.cpp +++ b/scene/3d/label_3d.cpp @@ -31,6 +31,7 @@ #include "label_3d.h" #include "core/core_string_names.h" +#include "scene/main/viewport.h" #include "scene/resources/theme.h" #include "scene/scene_string_names.h" @@ -184,6 +185,14 @@ void Label3D::_notification(int p_what) { if (!pending_update) { _im_update(); } + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + viewport->connect("size_changed", callable_mp(this, &Label3D::_font_changed)); + } break; + case NOTIFICATION_EXIT_TREE: { + Viewport *viewport = get_viewport(); + ERR_FAIL_COND(!viewport); + viewport->disconnect("size_changed", callable_mp(this, &Label3D::_font_changed)); } break; case NOTIFICATION_TRANSLATION_CHANGED: { String new_text = tr(text); diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 0581544e07..8d96d13f0c 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -149,7 +149,7 @@ AABB Light3D::get_aabb() const { } else if (type == RenderingServer::LIGHT_SPOT) { real_t len = param[PARAM_RANGE]; - real_t size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len; + real_t size = Math::tan(Math::deg_to_rad(param[PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); } diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index ef9e191f69..953e52e591 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -133,7 +133,7 @@ TypedArray<String> NavigationObstacle3D::get_configuration_warnings() const { } if (Object::cast_to<StaticBody3D>(get_parent())) { - warnings.push_back(RTR("The NavigationObstacle3D is intended for constantly moving bodies like CharacterBody3D or RigidDynamicBody3D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." + warnings.push_back(RTR("The NavigationObstacle3D is intended for constantly moving bodies like CharacterBody3D or RigidBody3D as it creates only an RVO avoidance radius and does not follow scene geometry exactly." "\nNot constantly moving or complete static objects should be (re)baked to a NavigationMesh so agents can not only avoid them but also move along those objects outline at high detail")); } diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index c690b5d6ff..5534bc28f1 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -376,7 +376,7 @@ AnimatableBody3D::AnimatableBody3D() : PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); } -void RigidDynamicBody3D::_body_enter_tree(ObjectID p_id) { +void RigidBody3D::_body_enter_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -399,7 +399,7 @@ void RigidDynamicBody3D::_body_enter_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody3D::_body_exit_tree(ObjectID p_id) { +void RigidBody3D::_body_exit_tree(ObjectID p_id) { Object *obj = ObjectDB::get_instance(p_id); Node *node = Object::cast_to<Node>(obj); ERR_FAIL_COND(!node); @@ -420,7 +420,7 @@ void RigidDynamicBody3D::_body_exit_tree(ObjectID p_id) { contact_monitor->locked = false; } -void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { +void RigidBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_local_shape) { bool body_in = p_status == 1; ObjectID objid = p_instance; @@ -439,8 +439,8 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p //E->value.rc=0; E->value.in_tree = node && node->is_inside_tree(); if (node) { - node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree).bind(objid)); - node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree).bind(objid)); + node->connect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree).bind(objid)); if (E->value.in_tree) { emit_signal(SceneStringNames::get_singleton()->body_entered, node); } @@ -466,8 +466,8 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p if (E->value.shapes.is_empty()) { if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree)); if (in_tree) { emit_signal(SceneStringNames::get_singleton()->body_exited, node); } @@ -481,19 +481,19 @@ void RigidDynamicBody3D::_body_inout(int p_status, const RID &p_body, ObjectID p } } -struct _RigidDynamicBodyInOut { +struct _RigidBodyInOut { RID rid; ObjectID id; int shape = 0; int local_shape = 0; }; -void RigidDynamicBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) { - RigidDynamicBody3D *body = (RigidDynamicBody3D *)p_instance; +void RigidBody3D::_body_state_changed_callback(void *p_instance, PhysicsDirectBodyState3D *p_state) { + RigidBody3D *body = (RigidBody3D *)p_instance; body->_body_state_changed(p_state); } -void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { +void RigidBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { set_ignore_transform_notification(true); set_global_transform(p_state->get_transform()); @@ -524,9 +524,9 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) } } - _RigidDynamicBodyInOut *toadd = (_RigidDynamicBodyInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidDynamicBodyInOut)); + _RigidBodyInOut *toadd = (_RigidBodyInOut *)alloca(p_state->get_contact_count() * sizeof(_RigidBodyInOut)); int toadd_count = 0; - RigidDynamicBody3D_RemoveAction *toremove = (RigidDynamicBody3D_RemoveAction *)alloca(rc * sizeof(RigidDynamicBody3D_RemoveAction)); + RigidBody3D_RemoveAction *toremove = (RigidBody3D_RemoveAction *)alloca(rc * sizeof(RigidBody3D_RemoveAction)); int toremove_count = 0; //put the ones to add @@ -590,7 +590,7 @@ void RigidDynamicBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) } } -void RigidDynamicBody3D::_notification(int p_what) { +void RigidBody3D::_notification(int p_what) { #ifdef TOOLS_ENABLED switch (p_what) { case NOTIFICATION_ENTER_TREE: { @@ -608,7 +608,7 @@ void RigidDynamicBody3D::_notification(int p_what) { #endif } -void RigidDynamicBody3D::_apply_body_mode() { +void RigidBody3D::_apply_body_mode() { if (freeze) { switch (freeze_mode) { case FREEZE_MODE_STATIC: { @@ -619,13 +619,13 @@ void RigidDynamicBody3D::_apply_body_mode() { } break; } } else if (lock_rotation) { - set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR); + set_body_mode(PhysicsServer3D::BODY_MODE_RIGID_LINEAR); } else { - set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer3D::BODY_MODE_RIGID); } } -void RigidDynamicBody3D::set_lock_rotation_enabled(bool p_lock_rotation) { +void RigidBody3D::set_lock_rotation_enabled(bool p_lock_rotation) { if (p_lock_rotation == lock_rotation) { return; } @@ -634,11 +634,11 @@ void RigidDynamicBody3D::set_lock_rotation_enabled(bool p_lock_rotation) { _apply_body_mode(); } -bool RigidDynamicBody3D::is_lock_rotation_enabled() const { +bool RigidBody3D::is_lock_rotation_enabled() const { return lock_rotation; } -void RigidDynamicBody3D::set_freeze_enabled(bool p_freeze) { +void RigidBody3D::set_freeze_enabled(bool p_freeze) { if (p_freeze == freeze) { return; } @@ -647,11 +647,11 @@ void RigidDynamicBody3D::set_freeze_enabled(bool p_freeze) { _apply_body_mode(); } -bool RigidDynamicBody3D::is_freeze_enabled() const { +bool RigidBody3D::is_freeze_enabled() const { return freeze; } -void RigidDynamicBody3D::set_freeze_mode(FreezeMode p_freeze_mode) { +void RigidBody3D::set_freeze_mode(FreezeMode p_freeze_mode) { if (p_freeze_mode == freeze_mode) { return; } @@ -660,21 +660,21 @@ void RigidDynamicBody3D::set_freeze_mode(FreezeMode p_freeze_mode) { _apply_body_mode(); } -RigidDynamicBody3D::FreezeMode RigidDynamicBody3D::get_freeze_mode() const { +RigidBody3D::FreezeMode RigidBody3D::get_freeze_mode() const { return freeze_mode; } -void RigidDynamicBody3D::set_mass(real_t p_mass) { +void RigidBody3D::set_mass(real_t p_mass) { ERR_FAIL_COND(p_mass <= 0); mass = p_mass; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass); } -real_t RigidDynamicBody3D::get_mass() const { +real_t RigidBody3D::get_mass() const { return mass; } -void RigidDynamicBody3D::set_inertia(const Vector3 &p_inertia) { +void RigidBody3D::set_inertia(const Vector3 &p_inertia) { ERR_FAIL_COND(p_inertia.x < 0); ERR_FAIL_COND(p_inertia.y < 0); ERR_FAIL_COND(p_inertia.z < 0); @@ -683,11 +683,11 @@ void RigidDynamicBody3D::set_inertia(const Vector3 &p_inertia) { PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_INERTIA, inertia); } -const Vector3 &RigidDynamicBody3D::get_inertia() const { +const Vector3 &RigidBody3D::get_inertia() const { return inertia; } -void RigidDynamicBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) { +void RigidBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) { if (center_of_mass_mode == p_mode) { return; } @@ -709,11 +709,11 @@ void RigidDynamicBody3D::set_center_of_mass_mode(CenterOfMassMode p_mode) { } } -RigidDynamicBody3D::CenterOfMassMode RigidDynamicBody3D::get_center_of_mass_mode() const { +RigidBody3D::CenterOfMassMode RigidBody3D::get_center_of_mass_mode() const { return center_of_mass_mode; } -void RigidDynamicBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) { +void RigidBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) { if (center_of_mass == p_center_of_mass) { return; } @@ -724,106 +724,106 @@ void RigidDynamicBody3D::set_center_of_mass(const Vector3 &p_center_of_mass) { PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_CENTER_OF_MASS, center_of_mass); } -const Vector3 &RigidDynamicBody3D::get_center_of_mass() const { +const Vector3 &RigidBody3D::get_center_of_mass() const { return center_of_mass; } -void RigidDynamicBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { +void RigidBody3D::set_physics_material_override(const Ref<PhysicsMaterial> &p_physics_material_override) { if (physics_material_override.is_valid()) { - if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody3D::_reload_physics_characteristics))) { - physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody3D::_reload_physics_characteristics)); + if (physics_material_override->is_connected(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics))) { + physics_material_override->disconnect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics)); } } physics_material_override = p_physics_material_override; if (physics_material_override.is_valid()) { - physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidDynamicBody3D::_reload_physics_characteristics)); + physics_material_override->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &RigidBody3D::_reload_physics_characteristics)); } _reload_physics_characteristics(); } -Ref<PhysicsMaterial> RigidDynamicBody3D::get_physics_material_override() const { +Ref<PhysicsMaterial> RigidBody3D::get_physics_material_override() const { return physics_material_override; } -void RigidDynamicBody3D::set_gravity_scale(real_t p_gravity_scale) { +void RigidBody3D::set_gravity_scale(real_t p_gravity_scale) { gravity_scale = p_gravity_scale; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale); } -real_t RigidDynamicBody3D::get_gravity_scale() const { +real_t RigidBody3D::get_gravity_scale() const { return gravity_scale; } -void RigidDynamicBody3D::set_linear_damp_mode(DampMode p_mode) { +void RigidBody3D::set_linear_damp_mode(DampMode p_mode) { linear_damp_mode = p_mode; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP_MODE, linear_damp_mode); } -RigidDynamicBody3D::DampMode RigidDynamicBody3D::get_linear_damp_mode() const { +RigidBody3D::DampMode RigidBody3D::get_linear_damp_mode() const { return linear_damp_mode; } -void RigidDynamicBody3D::set_angular_damp_mode(DampMode p_mode) { +void RigidBody3D::set_angular_damp_mode(DampMode p_mode) { angular_damp_mode = p_mode; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP_MODE, angular_damp_mode); } -RigidDynamicBody3D::DampMode RigidDynamicBody3D::get_angular_damp_mode() const { +RigidBody3D::DampMode RigidBody3D::get_angular_damp_mode() const { return angular_damp_mode; } -void RigidDynamicBody3D::set_linear_damp(real_t p_linear_damp) { +void RigidBody3D::set_linear_damp(real_t p_linear_damp) { ERR_FAIL_COND(p_linear_damp < 0.0); linear_damp = p_linear_damp; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp); } -real_t RigidDynamicBody3D::get_linear_damp() const { +real_t RigidBody3D::get_linear_damp() const { return linear_damp; } -void RigidDynamicBody3D::set_angular_damp(real_t p_angular_damp) { +void RigidBody3D::set_angular_damp(real_t p_angular_damp) { ERR_FAIL_COND(p_angular_damp < 0.0); angular_damp = p_angular_damp; PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp); } -real_t RigidDynamicBody3D::get_angular_damp() const { +real_t RigidBody3D::get_angular_damp() const { return angular_damp; } -void RigidDynamicBody3D::set_axis_velocity(const Vector3 &p_axis) { +void RigidBody3D::set_axis_velocity(const Vector3 &p_axis) { Vector3 axis = p_axis.normalized(); linear_velocity -= axis * axis.dot(linear_velocity); linear_velocity += p_axis; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -void RigidDynamicBody3D::set_linear_velocity(const Vector3 &p_velocity) { +void RigidBody3D::set_linear_velocity(const Vector3 &p_velocity) { linear_velocity = p_velocity; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } -Vector3 RigidDynamicBody3D::get_linear_velocity() const { +Vector3 RigidBody3D::get_linear_velocity() const { return linear_velocity; } -void RigidDynamicBody3D::set_angular_velocity(const Vector3 &p_velocity) { +void RigidBody3D::set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); } -Vector3 RigidDynamicBody3D::get_angular_velocity() const { +Vector3 RigidBody3D::get_angular_velocity() const { return angular_velocity; } -Basis RigidDynamicBody3D::get_inverse_inertia_tensor() const { +Basis RigidBody3D::get_inverse_inertia_tensor() const { return inverse_inertia_tensor; } -void RigidDynamicBody3D::set_use_custom_integrator(bool p_enable) { +void RigidBody3D::set_use_custom_integrator(bool p_enable) { if (custom_integrator == p_enable) { return; } @@ -832,108 +832,108 @@ void RigidDynamicBody3D::set_use_custom_integrator(bool p_enable) { PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); } -bool RigidDynamicBody3D::is_using_custom_integrator() { +bool RigidBody3D::is_using_custom_integrator() { return custom_integrator; } -void RigidDynamicBody3D::set_sleeping(bool p_sleeping) { +void RigidBody3D::set_sleeping(bool p_sleeping) { sleeping = p_sleeping; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_SLEEPING, sleeping); } -void RigidDynamicBody3D::set_can_sleep(bool p_active) { +void RigidBody3D::set_can_sleep(bool p_active) { can_sleep = p_active; PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active); } -bool RigidDynamicBody3D::is_able_to_sleep() const { +bool RigidBody3D::is_able_to_sleep() const { return can_sleep; } -bool RigidDynamicBody3D::is_sleeping() const { +bool RigidBody3D::is_sleeping() const { return sleeping; } -void RigidDynamicBody3D::set_max_contacts_reported(int p_amount) { +void RigidBody3D::set_max_contacts_reported(int p_amount) { max_contacts_reported = p_amount; PhysicsServer3D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); } -int RigidDynamicBody3D::get_max_contacts_reported() const { +int RigidBody3D::get_max_contacts_reported() const { return max_contacts_reported; } -int RigidDynamicBody3D::get_contact_count() const { +int RigidBody3D::get_contact_count() const { PhysicsDirectBodyState3D *bs = PhysicsServer3D::get_singleton()->body_get_direct_state(get_rid()); ERR_FAIL_NULL_V(bs, 0); return bs->get_contact_count(); } -void RigidDynamicBody3D::apply_central_impulse(const Vector3 &p_impulse) { +void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) { PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } -void RigidDynamicBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { +void RigidBody3D::apply_impulse(const Vector3 &p_impulse, const Vector3 &p_position) { PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); singleton->body_apply_impulse(get_rid(), p_impulse, p_position); } -void RigidDynamicBody3D::apply_torque_impulse(const Vector3 &p_impulse) { +void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) { PhysicsServer3D::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse); } -void RigidDynamicBody3D::apply_central_force(const Vector3 &p_force) { +void RigidBody3D::apply_central_force(const Vector3 &p_force) { PhysicsServer3D::get_singleton()->body_apply_central_force(get_rid(), p_force); } -void RigidDynamicBody3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) { +void RigidBody3D::apply_force(const Vector3 &p_force, const Vector3 &p_position) { PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); singleton->body_apply_force(get_rid(), p_force, p_position); } -void RigidDynamicBody3D::apply_torque(const Vector3 &p_torque) { +void RigidBody3D::apply_torque(const Vector3 &p_torque) { PhysicsServer3D::get_singleton()->body_apply_torque(get_rid(), p_torque); } -void RigidDynamicBody3D::add_constant_central_force(const Vector3 &p_force) { +void RigidBody3D::add_constant_central_force(const Vector3 &p_force) { PhysicsServer3D::get_singleton()->body_add_constant_central_force(get_rid(), p_force); } -void RigidDynamicBody3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) { +void RigidBody3D::add_constant_force(const Vector3 &p_force, const Vector3 &p_position) { PhysicsServer3D *singleton = PhysicsServer3D::get_singleton(); singleton->body_add_constant_force(get_rid(), p_force, p_position); } -void RigidDynamicBody3D::add_constant_torque(const Vector3 &p_torque) { +void RigidBody3D::add_constant_torque(const Vector3 &p_torque) { PhysicsServer3D::get_singleton()->body_add_constant_torque(get_rid(), p_torque); } -void RigidDynamicBody3D::set_constant_force(const Vector3 &p_force) { +void RigidBody3D::set_constant_force(const Vector3 &p_force) { PhysicsServer3D::get_singleton()->body_set_constant_force(get_rid(), p_force); } -Vector3 RigidDynamicBody3D::get_constant_force() const { +Vector3 RigidBody3D::get_constant_force() const { return PhysicsServer3D::get_singleton()->body_get_constant_force(get_rid()); } -void RigidDynamicBody3D::set_constant_torque(const Vector3 &p_torque) { +void RigidBody3D::set_constant_torque(const Vector3 &p_torque) { PhysicsServer3D::get_singleton()->body_set_constant_torque(get_rid(), p_torque); } -Vector3 RigidDynamicBody3D::get_constant_torque() const { +Vector3 RigidBody3D::get_constant_torque() const { return PhysicsServer3D::get_singleton()->body_get_constant_torque(get_rid()); } -void RigidDynamicBody3D::set_use_continuous_collision_detection(bool p_enable) { +void RigidBody3D::set_use_continuous_collision_detection(bool p_enable) { ccd = p_enable; PhysicsServer3D::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable); } -bool RigidDynamicBody3D::is_using_continuous_collision_detection() const { +bool RigidBody3D::is_using_continuous_collision_detection() const { return ccd; } -void RigidDynamicBody3D::set_contact_monitor(bool p_enabled) { +void RigidBody3D::set_contact_monitor(bool p_enabled) { if (p_enabled == is_contact_monitor_enabled()) { return; } @@ -947,8 +947,8 @@ void RigidDynamicBody3D::set_contact_monitor(bool p_enabled) { Node *node = Object::cast_to<Node>(obj); if (node) { - node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidDynamicBody3D::_body_enter_tree)); - node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidDynamicBody3D::_body_exit_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_entered, callable_mp(this, &RigidBody3D::_body_enter_tree)); + node->disconnect(SceneStringNames::get_singleton()->tree_exiting, callable_mp(this, &RigidBody3D::_body_exit_tree)); } } @@ -960,11 +960,11 @@ void RigidDynamicBody3D::set_contact_monitor(bool p_enabled) { } } -bool RigidDynamicBody3D::is_contact_monitor_enabled() const { +bool RigidBody3D::is_contact_monitor_enabled() const { return contact_monitor != nullptr; } -TypedArray<Node3D> RigidDynamicBody3D::get_colliding_bodies() const { +TypedArray<Node3D> RigidBody3D::get_colliding_bodies() const { ERR_FAIL_COND_V(!contact_monitor, TypedArray<Node3D>()); TypedArray<Node3D> ret; @@ -982,106 +982,106 @@ TypedArray<Node3D> RigidDynamicBody3D::get_colliding_bodies() const { return ret; } -TypedArray<String> RigidDynamicBody3D::get_configuration_warnings() const { +TypedArray<String> RigidBody3D::get_configuration_warnings() const { Transform3D t = get_transform(); TypedArray<String> warnings = Node::get_configuration_warnings(); if (ABS(t.basis.get_column(0).length() - 1.0) > 0.05 || ABS(t.basis.get_column(1).length() - 1.0) > 0.05 || ABS(t.basis.get_column(2).length() - 1.0) > 0.05) { - warnings.push_back(RTR("Size changes to RigidDynamicBody will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); + warnings.push_back(RTR("Size changes to RigidBody will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } return warnings; } -void RigidDynamicBody3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidDynamicBody3D::set_mass); - ClassDB::bind_method(D_METHOD("get_mass"), &RigidDynamicBody3D::get_mass); +void RigidBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_mass", "mass"), &RigidBody3D::set_mass); + ClassDB::bind_method(D_METHOD("get_mass"), &RigidBody3D::get_mass); - ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidDynamicBody3D::set_inertia); - ClassDB::bind_method(D_METHOD("get_inertia"), &RigidDynamicBody3D::get_inertia); + ClassDB::bind_method(D_METHOD("set_inertia", "inertia"), &RigidBody3D::set_inertia); + ClassDB::bind_method(D_METHOD("get_inertia"), &RigidBody3D::get_inertia); - ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidDynamicBody3D::set_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidDynamicBody3D::get_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("set_center_of_mass_mode", "mode"), &RigidBody3D::set_center_of_mass_mode); + ClassDB::bind_method(D_METHOD("get_center_of_mass_mode"), &RigidBody3D::get_center_of_mass_mode); - ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidDynamicBody3D::set_center_of_mass); - ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidDynamicBody3D::get_center_of_mass); + ClassDB::bind_method(D_METHOD("set_center_of_mass", "center_of_mass"), &RigidBody3D::set_center_of_mass); + ClassDB::bind_method(D_METHOD("get_center_of_mass"), &RigidBody3D::get_center_of_mass); - ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidDynamicBody3D::set_physics_material_override); - ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidDynamicBody3D::get_physics_material_override); + ClassDB::bind_method(D_METHOD("set_physics_material_override", "physics_material_override"), &RigidBody3D::set_physics_material_override); + ClassDB::bind_method(D_METHOD("get_physics_material_override"), &RigidBody3D::get_physics_material_override); - ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidDynamicBody3D::set_linear_velocity); - ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidDynamicBody3D::get_linear_velocity); + ClassDB::bind_method(D_METHOD("set_linear_velocity", "linear_velocity"), &RigidBody3D::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"), &RigidBody3D::get_linear_velocity); - ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidDynamicBody3D::set_angular_velocity); - ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidDynamicBody3D::get_angular_velocity); + ClassDB::bind_method(D_METHOD("set_angular_velocity", "angular_velocity"), &RigidBody3D::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"), &RigidBody3D::get_angular_velocity); - ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &RigidDynamicBody3D::get_inverse_inertia_tensor); + ClassDB::bind_method(D_METHOD("get_inverse_inertia_tensor"), &RigidBody3D::get_inverse_inertia_tensor); - ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidDynamicBody3D::set_gravity_scale); - ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidDynamicBody3D::get_gravity_scale); + ClassDB::bind_method(D_METHOD("set_gravity_scale", "gravity_scale"), &RigidBody3D::set_gravity_scale); + ClassDB::bind_method(D_METHOD("get_gravity_scale"), &RigidBody3D::get_gravity_scale); - ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidDynamicBody3D::set_linear_damp_mode); - ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidDynamicBody3D::get_linear_damp_mode); + ClassDB::bind_method(D_METHOD("set_linear_damp_mode", "linear_damp_mode"), &RigidBody3D::set_linear_damp_mode); + ClassDB::bind_method(D_METHOD("get_linear_damp_mode"), &RigidBody3D::get_linear_damp_mode); - ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidDynamicBody3D::set_angular_damp_mode); - ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidDynamicBody3D::get_angular_damp_mode); + ClassDB::bind_method(D_METHOD("set_angular_damp_mode", "angular_damp_mode"), &RigidBody3D::set_angular_damp_mode); + ClassDB::bind_method(D_METHOD("get_angular_damp_mode"), &RigidBody3D::get_angular_damp_mode); - ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidDynamicBody3D::set_linear_damp); - ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidDynamicBody3D::get_linear_damp); + ClassDB::bind_method(D_METHOD("set_linear_damp", "linear_damp"), &RigidBody3D::set_linear_damp); + ClassDB::bind_method(D_METHOD("get_linear_damp"), &RigidBody3D::get_linear_damp); - ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidDynamicBody3D::set_angular_damp); - ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidDynamicBody3D::get_angular_damp); + ClassDB::bind_method(D_METHOD("set_angular_damp", "angular_damp"), &RigidBody3D::set_angular_damp); + ClassDB::bind_method(D_METHOD("get_angular_damp"), &RigidBody3D::get_angular_damp); - ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidDynamicBody3D::set_max_contacts_reported); - ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidDynamicBody3D::get_max_contacts_reported); - ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidDynamicBody3D::get_contact_count); + ClassDB::bind_method(D_METHOD("set_max_contacts_reported", "amount"), &RigidBody3D::set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_max_contacts_reported"), &RigidBody3D::get_max_contacts_reported); + ClassDB::bind_method(D_METHOD("get_contact_count"), &RigidBody3D::get_contact_count); - ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidDynamicBody3D::set_use_custom_integrator); - ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidDynamicBody3D::is_using_custom_integrator); + ClassDB::bind_method(D_METHOD("set_use_custom_integrator", "enable"), &RigidBody3D::set_use_custom_integrator); + ClassDB::bind_method(D_METHOD("is_using_custom_integrator"), &RigidBody3D::is_using_custom_integrator); - ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidDynamicBody3D::set_contact_monitor); - ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidDynamicBody3D::is_contact_monitor_enabled); + ClassDB::bind_method(D_METHOD("set_contact_monitor", "enabled"), &RigidBody3D::set_contact_monitor); + ClassDB::bind_method(D_METHOD("is_contact_monitor_enabled"), &RigidBody3D::is_contact_monitor_enabled); - ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection", "enable"), &RigidDynamicBody3D::set_use_continuous_collision_detection); - ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidDynamicBody3D::is_using_continuous_collision_detection); + ClassDB::bind_method(D_METHOD("set_use_continuous_collision_detection", "enable"), &RigidBody3D::set_use_continuous_collision_detection); + ClassDB::bind_method(D_METHOD("is_using_continuous_collision_detection"), &RigidBody3D::is_using_continuous_collision_detection); - ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidDynamicBody3D::set_axis_velocity); + ClassDB::bind_method(D_METHOD("set_axis_velocity", "axis_velocity"), &RigidBody3D::set_axis_velocity); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidDynamicBody3D::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidDynamicBody3D::apply_impulse, Vector3()); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidDynamicBody3D::apply_torque_impulse); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &RigidBody3D::apply_central_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "impulse", "position"), &RigidBody3D::apply_impulse, Vector3()); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &RigidBody3D::apply_torque_impulse); - ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidDynamicBody3D::apply_central_force); - ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidDynamicBody3D::apply_force, Vector3()); - ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidDynamicBody3D::apply_torque); + ClassDB::bind_method(D_METHOD("apply_central_force", "force"), &RigidBody3D::apply_central_force); + ClassDB::bind_method(D_METHOD("apply_force", "force", "position"), &RigidBody3D::apply_force, Vector3()); + ClassDB::bind_method(D_METHOD("apply_torque", "torque"), &RigidBody3D::apply_torque); - ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidDynamicBody3D::add_constant_central_force); - ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidDynamicBody3D::add_constant_force, Vector3()); - ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidDynamicBody3D::add_constant_torque); + ClassDB::bind_method(D_METHOD("add_constant_central_force", "force"), &RigidBody3D::add_constant_central_force); + ClassDB::bind_method(D_METHOD("add_constant_force", "force", "position"), &RigidBody3D::add_constant_force, Vector3()); + ClassDB::bind_method(D_METHOD("add_constant_torque", "torque"), &RigidBody3D::add_constant_torque); - ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidDynamicBody3D::set_constant_force); - ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidDynamicBody3D::get_constant_force); + ClassDB::bind_method(D_METHOD("set_constant_force", "force"), &RigidBody3D::set_constant_force); + ClassDB::bind_method(D_METHOD("get_constant_force"), &RigidBody3D::get_constant_force); - ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidDynamicBody3D::set_constant_torque); - ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidDynamicBody3D::get_constant_torque); + ClassDB::bind_method(D_METHOD("set_constant_torque", "torque"), &RigidBody3D::set_constant_torque); + ClassDB::bind_method(D_METHOD("get_constant_torque"), &RigidBody3D::get_constant_torque); - ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidDynamicBody3D::set_sleeping); - ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidDynamicBody3D::is_sleeping); + ClassDB::bind_method(D_METHOD("set_sleeping", "sleeping"), &RigidBody3D::set_sleeping); + ClassDB::bind_method(D_METHOD("is_sleeping"), &RigidBody3D::is_sleeping); - ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidDynamicBody3D::set_can_sleep); - ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidDynamicBody3D::is_able_to_sleep); + ClassDB::bind_method(D_METHOD("set_can_sleep", "able_to_sleep"), &RigidBody3D::set_can_sleep); + ClassDB::bind_method(D_METHOD("is_able_to_sleep"), &RigidBody3D::is_able_to_sleep); - ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidDynamicBody3D::set_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidDynamicBody3D::is_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("set_lock_rotation_enabled", "lock_rotation"), &RigidBody3D::set_lock_rotation_enabled); + ClassDB::bind_method(D_METHOD("is_lock_rotation_enabled"), &RigidBody3D::is_lock_rotation_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidDynamicBody3D::set_freeze_enabled); - ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidDynamicBody3D::is_freeze_enabled); + ClassDB::bind_method(D_METHOD("set_freeze_enabled", "freeze_mode"), &RigidBody3D::set_freeze_enabled); + ClassDB::bind_method(D_METHOD("is_freeze_enabled"), &RigidBody3D::is_freeze_enabled); - ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidDynamicBody3D::set_freeze_mode); - ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidDynamicBody3D::get_freeze_mode); + ClassDB::bind_method(D_METHOD("set_freeze_mode", "freeze_mode"), &RigidBody3D::set_freeze_mode); + ClassDB::bind_method(D_METHOD("get_freeze_mode"), &RigidBody3D::get_freeze_mode); - ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidDynamicBody3D::get_colliding_bodies); + ClassDB::bind_method(D_METHOD("get_colliding_bodies"), &RigidBody3D::get_colliding_bodies); GDVIRTUAL_BIND(_integrate_forces, "state"); @@ -1129,7 +1129,7 @@ void RigidDynamicBody3D::_bind_methods() { BIND_ENUM_CONSTANT(DAMP_MODE_REPLACE); } -void RigidDynamicBody3D::_validate_property(PropertyInfo &p_property) const { +void RigidBody3D::_validate_property(PropertyInfo &p_property) const { if (center_of_mass_mode != CENTER_OF_MASS_MODE_CUSTOM) { if (p_property.name == "center_of_mass") { p_property.usage = PROPERTY_USAGE_NO_EDITOR; @@ -1137,18 +1137,18 @@ void RigidDynamicBody3D::_validate_property(PropertyInfo &p_property) const { } } -RigidDynamicBody3D::RigidDynamicBody3D() : - PhysicsBody3D(PhysicsServer3D::BODY_MODE_DYNAMIC) { +RigidBody3D::RigidBody3D() : + PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) { PhysicsServer3D::get_singleton()->body_set_state_sync_callback(get_rid(), this, _body_state_changed_callback); } -RigidDynamicBody3D::~RigidDynamicBody3D() { +RigidBody3D::~RigidBody3D() { if (contact_monitor) { memdelete(contact_monitor); } } -void RigidDynamicBody3D::_reload_physics_characteristics() { +void RigidBody3D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0); PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1); @@ -2284,13 +2284,13 @@ bool PhysicalBone3D::ConeJointData::_set(const StringName &p_name, const Variant } if ("joint_constraints/swing_span" == p_name) { - swing_span = Math::deg2rad(real_t(p_value)); + swing_span = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, swing_span); } } else if ("joint_constraints/twist_span" == p_name) { - twist_span = Math::deg2rad(real_t(p_value)); + twist_span = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, twist_span); } @@ -2326,9 +2326,9 @@ bool PhysicalBone3D::ConeJointData::_get(const StringName &p_name, Variant &r_re } if ("joint_constraints/swing_span" == p_name) { - r_ret = Math::rad2deg(swing_span); + r_ret = Math::rad_to_deg(swing_span); } else if ("joint_constraints/twist_span" == p_name) { - r_ret = Math::rad2deg(twist_span); + r_ret = Math::rad_to_deg(twist_span); } else if ("joint_constraints/bias" == p_name) { r_ret = bias; } else if ("joint_constraints/softness" == p_name) { @@ -2364,13 +2364,13 @@ bool PhysicalBone3D::HingeJointData::_set(const StringName &p_name, const Varian } } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); + angular_limit_upper = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper); } } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); + angular_limit_lower = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower); } @@ -2408,9 +2408,9 @@ bool PhysicalBone3D::HingeJointData::_get(const StringName &p_name, Variant &r_r if ("joint_constraints/angular_limit_enabled" == p_name) { r_ret = angular_limit_enabled; } else if ("joint_constraints/angular_limit_upper" == p_name) { - r_ret = Math::rad2deg(angular_limit_upper); + r_ret = Math::rad_to_deg(angular_limit_upper); } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(angular_limit_lower); + r_ret = Math::rad_to_deg(angular_limit_lower); } else if ("joint_constraints/angular_limit_bias" == p_name) { r_ret = angular_limit_bias; } else if ("joint_constraints/angular_limit_softness" == p_name) { @@ -2471,13 +2471,13 @@ bool PhysicalBone3D::SliderJointData::_set(const StringName &p_name, const Varia } } else if ("joint_constraints/angular_limit_upper" == p_name) { - angular_limit_upper = Math::deg2rad(real_t(p_value)); + angular_limit_upper = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper); } } else if ("joint_constraints/angular_limit_lower" == p_name) { - angular_limit_lower = Math::deg2rad(real_t(p_value)); + angular_limit_lower = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower); } @@ -2523,9 +2523,9 @@ bool PhysicalBone3D::SliderJointData::_get(const StringName &p_name, Variant &r_ } else if ("joint_constraints/linear_limit_damping" == p_name) { r_ret = linear_limit_damping; } else if ("joint_constraints/angular_limit_upper" == p_name) { - r_ret = Math::rad2deg(angular_limit_upper); + r_ret = Math::rad_to_deg(angular_limit_upper); } else if ("joint_constraints/angular_limit_lower" == p_name) { - r_ret = Math::rad2deg(angular_limit_lower); + r_ret = Math::rad_to_deg(angular_limit_lower); } else if ("joint_constraints/angular_limit_softness" == p_name) { r_ret = angular_limit_softness; } else if ("joint_constraints/angular_limit_restitution" == p_name) { @@ -2649,13 +2649,13 @@ bool PhysicalBone3D::SixDOFJointData::_set(const StringName &p_name, const Varia } } else if ("angular_limit_upper" == var_name) { - axis_data[axis].angular_limit_upper = Math::deg2rad(real_t(p_value)); + axis_data[axis].angular_limit_upper = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper); } } else if ("angular_limit_lower" == var_name) { - axis_data[axis].angular_limit_lower = Math::deg2rad(real_t(p_value)); + axis_data[axis].angular_limit_lower = Math::deg_to_rad(real_t(p_value)); if (j.is_valid()) { PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower); } @@ -2765,9 +2765,9 @@ bool PhysicalBone3D::SixDOFJointData::_get(const StringName &p_name, Variant &r_ } else if ("angular_limit_enabled" == var_name) { r_ret = axis_data[axis].angular_limit_enabled; } else if ("angular_limit_upper" == var_name) { - r_ret = Math::rad2deg(axis_data[axis].angular_limit_upper); + r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_upper); } else if ("angular_limit_lower" == var_name) { - r_ret = Math::rad2deg(axis_data[axis].angular_limit_lower); + r_ret = Math::rad_to_deg(axis_data[axis].angular_limit_lower); } else if ("angular_limit_softness" == var_name) { r_ret = axis_data[axis].angular_limit_softness; } else if ("angular_restitution" == var_name) { @@ -3421,7 +3421,7 @@ void PhysicalBone3D::_start_physics_simulation() { return; } reset_to_rest_position(); - set_body_mode(PhysicsServer3D::BODY_MODE_DYNAMIC); + set_body_mode(PhysicsServer3D::BODY_MODE_RIGID); PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); PhysicsServer3D::get_singleton()->body_set_collision_priority(get_rid(), get_collision_priority()); diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 14a1cf7228..184d8b00d0 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -129,8 +129,8 @@ private: bool is_sync_to_physics_enabled() const; }; -class RigidDynamicBody3D : public PhysicsBody3D { - GDCLASS(RigidDynamicBody3D, PhysicsBody3D); +class RigidBody3D : public PhysicsBody3D { + GDCLASS(RigidBody3D, PhysicsBody3D); public: enum FreezeMode { @@ -198,7 +198,7 @@ private: tagged = false; } }; - struct RigidDynamicBody3D_RemoveAction { + struct RigidBody3D_RemoveAction { RID rid; ObjectID body_id; ShapePair pair; @@ -327,16 +327,16 @@ public: virtual TypedArray<String> get_configuration_warnings() const override; - RigidDynamicBody3D(); - ~RigidDynamicBody3D(); + RigidBody3D(); + ~RigidBody3D(); private: void _reload_physics_characteristics(); }; -VARIANT_ENUM_CAST(RigidDynamicBody3D::FreezeMode); -VARIANT_ENUM_CAST(RigidDynamicBody3D::CenterOfMassMode); -VARIANT_ENUM_CAST(RigidDynamicBody3D::DampMode); +VARIANT_ENUM_CAST(RigidBody3D::FreezeMode); +VARIANT_ENUM_CAST(RigidBody3D::CenterOfMassMode); +VARIANT_ENUM_CAST(RigidBody3D::DampMode); class KinematicCollision3D; @@ -414,8 +414,8 @@ private: uint32_t platform_floor_layers = UINT32_MAX; uint32_t platform_wall_layers = 0; real_t floor_snap_length = 0.1; - real_t floor_max_angle = Math::deg2rad((real_t)45.0); - real_t wall_min_slide_angle = Math::deg2rad((real_t)15.0); + real_t floor_max_angle = Math::deg_to_rad((real_t)45.0); + real_t wall_min_slide_angle = Math::deg_to_rad((real_t)15.0); Vector3 up_direction = Vector3(0.0, 1.0, 0.0); Vector3 velocity; Vector3 floor_normal; diff --git a/scene/3d/soft_dynamic_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 2650d62fa4..47858b372c 100644 --- a/scene/3d/soft_dynamic_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* soft_dynamic_body_3d.cpp */ +/* soft_body_3d.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,13 +28,13 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "soft_dynamic_body_3d.h" +#include "soft_body_3d.h" #include "scene/3d/physics_body_3d.h" -SoftDynamicBodyRenderingServerHandler::SoftDynamicBodyRenderingServerHandler() {} +SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {} -void SoftDynamicBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { +void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { clear(); ERR_FAIL_COND(!p_mesh.is_valid()); @@ -56,7 +56,7 @@ void SoftDynamicBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { offset_normal = surface_offsets[RS::ARRAY_NORMAL]; } -void SoftDynamicBodyRenderingServerHandler::clear() { +void SoftBodyRenderingServerHandler::clear() { buffer.resize(0); stride = 0; offset_vertices = 0; @@ -66,23 +66,23 @@ void SoftDynamicBodyRenderingServerHandler::clear() { mesh = RID(); } -void SoftDynamicBodyRenderingServerHandler::open() { +void SoftBodyRenderingServerHandler::open() { write_buffer = buffer.ptrw(); } -void SoftDynamicBodyRenderingServerHandler::close() { +void SoftBodyRenderingServerHandler::close() { write_buffer = nullptr; } -void SoftDynamicBodyRenderingServerHandler::commit_changes() { +void SoftBodyRenderingServerHandler::commit_changes() { RS::get_singleton()->mesh_surface_update_vertex_region(mesh, surface, 0, buffer); } -void SoftDynamicBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { +void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { memcpy(&write_buffer[p_vertex_id * stride + offset_vertices], p_vector3, sizeof(float) * 3); } -void SoftDynamicBodyRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { +void SoftBodyRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { // Store normal vector in A2B10G10R10 format. Vector3 n; memcpy(&n, p_vector3, sizeof(Vector3)); @@ -95,28 +95,28 @@ void SoftDynamicBodyRenderingServerHandler::set_normal(int p_vertex_id, const vo memcpy(&write_buffer[p_vertex_id * stride + offset_normal], &value, sizeof(uint32_t)); } -void SoftDynamicBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) { +void SoftBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) { RS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb); } -SoftDynamicBody3D::PinnedPoint::PinnedPoint() { +SoftBody3D::PinnedPoint::PinnedPoint() { } -SoftDynamicBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { +SoftBody3D::PinnedPoint::PinnedPoint(const PinnedPoint &obj_tocopy) { point_index = obj_tocopy.point_index; spatial_attachment_path = obj_tocopy.spatial_attachment_path; spatial_attachment = obj_tocopy.spatial_attachment; offset = obj_tocopy.offset; } -void SoftDynamicBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { +void SoftBody3D::PinnedPoint::operator=(const PinnedPoint &obj) { point_index = obj.point_index; spatial_attachment_path = obj.spatial_attachment_path; spatial_attachment = obj.spatial_attachment; offset = obj.offset; } -void SoftDynamicBody3D::_update_pickable() { +void SoftBody3D::_update_pickable() { if (!is_inside_tree()) { return; } @@ -124,7 +124,7 @@ void SoftDynamicBody3D::_update_pickable() { PhysicsServer3D::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable); } -bool SoftDynamicBody3D::_set(const StringName &p_name, const Variant &p_value) { +bool SoftBody3D::_set(const StringName &p_name, const Variant &p_value) { String name = p_name; String which = name.get_slicec('/', 0); @@ -141,7 +141,7 @@ bool SoftDynamicBody3D::_set(const StringName &p_name, const Variant &p_value) { return false; } -bool SoftDynamicBody3D::_get(const StringName &p_name, Variant &r_ret) const { +bool SoftBody3D::_get(const StringName &p_name, Variant &r_ret) const { String name = p_name; String which = name.get_slicec('/', 0); @@ -168,7 +168,7 @@ bool SoftDynamicBody3D::_get(const StringName &p_name, Variant &r_ret) const { return false; } -void SoftDynamicBody3D::_get_property_list(List<PropertyInfo> *p_list) const { +void SoftBody3D::_get_property_list(List<PropertyInfo> *p_list) const { const int pinned_points_indices_size = pinned_points.size(); p_list->push_back(PropertyInfo(Variant::PACKED_INT32_ARRAY, PNAME("pinned_points"))); @@ -181,7 +181,7 @@ void SoftDynamicBody3D::_get_property_list(List<PropertyInfo> *p_list) const { } } -bool SoftDynamicBody3D::_set_property_pinned_points_indices(const Array &p_indices) { +bool SoftBody3D::_set_property_pinned_points_indices(const Array &p_indices) { const int p_indices_size = p_indices.size(); { // Remove the pined points on physics server that will be removed by resize @@ -210,7 +210,7 @@ bool SoftDynamicBody3D::_set_property_pinned_points_indices(const Array &p_indic return true; } -bool SoftDynamicBody3D::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) { +bool SoftBody3D::_set_property_pinned_points_attachment(int p_item, const String &p_what, const Variant &p_value) { if (pinned_points.size() <= p_item) { return false; } @@ -229,7 +229,7 @@ bool SoftDynamicBody3D::_set_property_pinned_points_attachment(int p_item, const return true; } -bool SoftDynamicBody3D::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { +bool SoftBody3D::_get_property_pinned_points(int p_item, const String &p_what, Variant &r_ret) const { if (pinned_points.size() <= p_item) { return false; } @@ -248,7 +248,7 @@ bool SoftDynamicBody3D::_get_property_pinned_points(int p_item, const String &p_ return true; } -void SoftDynamicBody3D::_notification(int p_what) { +void SoftBody3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_ENTER_WORLD: { if (Engine::get_singleton()->is_editor_hint()) { @@ -313,56 +313,56 @@ void SoftDynamicBody3D::_notification(int p_what) { } } -void SoftDynamicBody3D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftDynamicBody3D::get_physics_rid); +void SoftBody3D::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_physics_rid"), &SoftBody3D::get_physics_rid); - ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftDynamicBody3D::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftDynamicBody3D::get_collision_mask); + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &SoftBody3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &SoftBody3D::get_collision_mask); - ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftDynamicBody3D::set_collision_layer); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftDynamicBody3D::get_collision_layer); + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &SoftBody3D::set_collision_layer); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &SoftBody3D::get_collision_layer); - ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &SoftDynamicBody3D::set_collision_mask_value); - ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &SoftDynamicBody3D::get_collision_mask_value); + ClassDB::bind_method(D_METHOD("set_collision_mask_value", "layer_number", "value"), &SoftBody3D::set_collision_mask_value); + ClassDB::bind_method(D_METHOD("get_collision_mask_value", "layer_number"), &SoftBody3D::get_collision_mask_value); - ClassDB::bind_method(D_METHOD("set_collision_layer_value", "layer_number", "value"), &SoftDynamicBody3D::set_collision_layer_value); - ClassDB::bind_method(D_METHOD("get_collision_layer_value", "layer_number"), &SoftDynamicBody3D::get_collision_layer_value); + ClassDB::bind_method(D_METHOD("set_collision_layer_value", "layer_number", "value"), &SoftBody3D::set_collision_layer_value); + ClassDB::bind_method(D_METHOD("get_collision_layer_value", "layer_number"), &SoftBody3D::get_collision_layer_value); - ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftDynamicBody3D::set_parent_collision_ignore); - ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftDynamicBody3D::get_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("set_parent_collision_ignore", "parent_collision_ignore"), &SoftBody3D::set_parent_collision_ignore); + ClassDB::bind_method(D_METHOD("get_parent_collision_ignore"), &SoftBody3D::get_parent_collision_ignore); - ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftDynamicBody3D::set_disable_mode); - ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftDynamicBody3D::get_disable_mode); + ClassDB::bind_method(D_METHOD("set_disable_mode", "mode"), &SoftBody3D::set_disable_mode); + ClassDB::bind_method(D_METHOD("get_disable_mode"), &SoftBody3D::get_disable_mode); - ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftDynamicBody3D::get_collision_exceptions); - ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftDynamicBody3D::add_collision_exception_with); - ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftDynamicBody3D::remove_collision_exception_with); + ClassDB::bind_method(D_METHOD("get_collision_exceptions"), &SoftBody3D::get_collision_exceptions); + ClassDB::bind_method(D_METHOD("add_collision_exception_with", "body"), &SoftBody3D::add_collision_exception_with); + ClassDB::bind_method(D_METHOD("remove_collision_exception_with", "body"), &SoftBody3D::remove_collision_exception_with); - ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftDynamicBody3D::set_simulation_precision); - ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftDynamicBody3D::get_simulation_precision); + ClassDB::bind_method(D_METHOD("set_simulation_precision", "simulation_precision"), &SoftBody3D::set_simulation_precision); + ClassDB::bind_method(D_METHOD("get_simulation_precision"), &SoftBody3D::get_simulation_precision); - ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftDynamicBody3D::set_total_mass); - ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftDynamicBody3D::get_total_mass); + ClassDB::bind_method(D_METHOD("set_total_mass", "mass"), &SoftBody3D::set_total_mass); + ClassDB::bind_method(D_METHOD("get_total_mass"), &SoftBody3D::get_total_mass); - ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftDynamicBody3D::set_linear_stiffness); - ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftDynamicBody3D::get_linear_stiffness); + ClassDB::bind_method(D_METHOD("set_linear_stiffness", "linear_stiffness"), &SoftBody3D::set_linear_stiffness); + ClassDB::bind_method(D_METHOD("get_linear_stiffness"), &SoftBody3D::get_linear_stiffness); - ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftDynamicBody3D::set_pressure_coefficient); - ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftDynamicBody3D::get_pressure_coefficient); + ClassDB::bind_method(D_METHOD("set_pressure_coefficient", "pressure_coefficient"), &SoftBody3D::set_pressure_coefficient); + ClassDB::bind_method(D_METHOD("get_pressure_coefficient"), &SoftBody3D::get_pressure_coefficient); - ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftDynamicBody3D::set_damping_coefficient); - ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftDynamicBody3D::get_damping_coefficient); + ClassDB::bind_method(D_METHOD("set_damping_coefficient", "damping_coefficient"), &SoftBody3D::set_damping_coefficient); + ClassDB::bind_method(D_METHOD("get_damping_coefficient"), &SoftBody3D::get_damping_coefficient); - ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftDynamicBody3D::set_drag_coefficient); - ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftDynamicBody3D::get_drag_coefficient); + ClassDB::bind_method(D_METHOD("set_drag_coefficient", "drag_coefficient"), &SoftBody3D::set_drag_coefficient); + ClassDB::bind_method(D_METHOD("get_drag_coefficient"), &SoftBody3D::get_drag_coefficient); - ClassDB::bind_method(D_METHOD("get_point_transform", "point_index"), &SoftDynamicBody3D::get_point_transform); + ClassDB::bind_method(D_METHOD("get_point_transform", "point_index"), &SoftBody3D::get_point_transform); - ClassDB::bind_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path"), &SoftDynamicBody3D::pin_point, DEFVAL(NodePath())); - ClassDB::bind_method(D_METHOD("is_point_pinned", "point_index"), &SoftDynamicBody3D::is_point_pinned); + ClassDB::bind_method(D_METHOD("set_point_pinned", "point_index", "pinned", "attachment_path"), &SoftBody3D::pin_point, DEFVAL(NodePath())); + ClassDB::bind_method(D_METHOD("is_point_pinned", "point_index"), &SoftBody3D::is_point_pinned); - ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftDynamicBody3D::set_ray_pickable); - ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftDynamicBody3D::is_ray_pickable); + ClassDB::bind_method(D_METHOD("set_ray_pickable", "ray_pickable"), &SoftBody3D::set_ray_pickable); + ClassDB::bind_method(D_METHOD("is_ray_pickable"), &SoftBody3D::is_ray_pickable); ADD_GROUP("Collision", "collision_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_layer", "get_collision_layer"); @@ -384,7 +384,7 @@ void SoftDynamicBody3D::_bind_methods() { BIND_ENUM_CONSTANT(DISABLE_MODE_KEEP_ACTIVE); } -TypedArray<String> SoftDynamicBody3D::get_configuration_warnings() const { +TypedArray<String> SoftBody3D::get_configuration_warnings() const { TypedArray<String> warnings = Node::get_configuration_warnings(); if (mesh.is_null()) { @@ -393,13 +393,13 @@ TypedArray<String> SoftDynamicBody3D::get_configuration_warnings() const { Transform3D t = get_transform(); if ((ABS(t.basis.get_column(0).length() - 1.0) > 0.05 || ABS(t.basis.get_column(1).length() - 1.0) > 0.05 || ABS(t.basis.get_column(2).length() - 1.0) > 0.05)) { - warnings.push_back(RTR("Size changes to SoftDynamicBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); + warnings.push_back(RTR("Size changes to SoftBody3D will be overridden by the physics engine when running.\nChange the size in children collision shapes instead.")); } return warnings; } -void SoftDynamicBody3D::_update_physics_server() { +void SoftBody3D::_update_physics_server() { if (!simulation_started) { return; } @@ -415,7 +415,7 @@ void SoftDynamicBody3D::_update_physics_server() { } } -void SoftDynamicBody3D::_draw_soft_mesh() { +void SoftBody3D::_draw_soft_mesh() { if (mesh.is_null()) { return; } @@ -445,7 +445,7 @@ void SoftDynamicBody3D::_draw_soft_mesh() { rendering_server_handler->commit_changes(); } -void SoftDynamicBody3D::_prepare_physics_server() { +void SoftBody3D::_prepare_physics_server() { #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint()) { if (mesh.is_valid()) { @@ -465,22 +465,22 @@ void SoftDynamicBody3D::_prepare_physics_server() { mesh_rid = mesh->get_rid(); } PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, mesh_rid); - RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh)); + RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); } else { PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, RID()); - if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh))) { - RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftDynamicBody3D::_draw_soft_mesh)); + if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh))) { + RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); } } } -void SoftDynamicBody3D::_become_mesh_owner() { +void SoftBody3D::_become_mesh_owner() { Vector<Ref<Material>> copy_materials; copy_materials.append_array(surface_override_materials); ERR_FAIL_COND(!mesh->get_surface_count()); - // Get current mesh array and create new mesh array with necessary flag for SoftDynamicBody + // Get current mesh array and create new mesh array with necessary flag for SoftBody Array surface_arrays = mesh->surface_get_arrays(0); Array surface_blend_arrays = mesh->surface_get_blend_shape_arrays(0); Dictionary surface_lods = mesh->surface_get_lods(0); @@ -502,25 +502,25 @@ void SoftDynamicBody3D::_become_mesh_owner() { owned_mesh = soft_mesh->get_rid(); } -void SoftDynamicBody3D::set_collision_mask(uint32_t p_mask) { +void SoftBody3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; PhysicsServer3D::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask); } -uint32_t SoftDynamicBody3D::get_collision_mask() const { +uint32_t SoftBody3D::get_collision_mask() const { return collision_mask; } -void SoftDynamicBody3D::set_collision_layer(uint32_t p_layer) { +void SoftBody3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; PhysicsServer3D::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer); } -uint32_t SoftDynamicBody3D::get_collision_layer() const { +uint32_t SoftBody3D::get_collision_layer() const { return collision_layer; } -void SoftDynamicBody3D::set_collision_layer_value(int p_layer_number, bool p_value) { +void SoftBody3D::set_collision_layer_value(int p_layer_number, bool p_value) { ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive."); uint32_t collision_layer = get_collision_layer(); @@ -532,13 +532,13 @@ void SoftDynamicBody3D::set_collision_layer_value(int p_layer_number, bool p_val set_collision_layer(collision_layer); } -bool SoftDynamicBody3D::get_collision_layer_value(int p_layer_number) const { +bool SoftBody3D::get_collision_layer_value(int p_layer_number) const { ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive."); return get_collision_layer() & (1 << (p_layer_number - 1)); } -void SoftDynamicBody3D::set_collision_mask_value(int p_layer_number, bool p_value) { +void SoftBody3D::set_collision_mask_value(int p_layer_number, bool p_value) { ERR_FAIL_COND_MSG(p_layer_number < 1, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_MSG(p_layer_number > 32, "Collision layer number must be between 1 and 32 inclusive."); uint32_t mask = get_collision_mask(); @@ -550,13 +550,13 @@ void SoftDynamicBody3D::set_collision_mask_value(int p_layer_number, bool p_valu set_collision_mask(mask); } -bool SoftDynamicBody3D::get_collision_mask_value(int p_layer_number) const { +bool SoftBody3D::get_collision_mask_value(int p_layer_number) const { ERR_FAIL_COND_V_MSG(p_layer_number < 1, false, "Collision layer number must be between 1 and 32 inclusive."); ERR_FAIL_COND_V_MSG(p_layer_number > 32, false, "Collision layer number must be between 1 and 32 inclusive."); return get_collision_mask() & (1 << (p_layer_number - 1)); } -void SoftDynamicBody3D::set_disable_mode(DisableMode p_mode) { +void SoftBody3D::set_disable_mode(DisableMode p_mode) { if (disable_mode == p_mode) { return; } @@ -568,30 +568,30 @@ void SoftDynamicBody3D::set_disable_mode(DisableMode p_mode) { } } -SoftDynamicBody3D::DisableMode SoftDynamicBody3D::get_disable_mode() const { +SoftBody3D::DisableMode SoftBody3D::get_disable_mode() const { return disable_mode; } -void SoftDynamicBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { +void SoftBody3D::set_parent_collision_ignore(const NodePath &p_parent_collision_ignore) { parent_collision_ignore = p_parent_collision_ignore; } -const NodePath &SoftDynamicBody3D::get_parent_collision_ignore() const { +const NodePath &SoftBody3D::get_parent_collision_ignore() const { return parent_collision_ignore; } -void SoftDynamicBody3D::set_pinned_points_indices(Vector<SoftDynamicBody3D::PinnedPoint> p_pinned_points_indices) { +void SoftBody3D::set_pinned_points_indices(Vector<SoftBody3D::PinnedPoint> p_pinned_points_indices) { pinned_points = p_pinned_points_indices; for (int i = pinned_points.size() - 1; 0 <= i; --i) { pin_point(p_pinned_points_indices[i].point_index, true); } } -Vector<SoftDynamicBody3D::PinnedPoint> SoftDynamicBody3D::get_pinned_points_indices() { +Vector<SoftBody3D::PinnedPoint> SoftBody3D::get_pinned_points_indices() { return pinned_points; } -TypedArray<PhysicsBody3D> SoftDynamicBody3D::get_collision_exceptions() { +TypedArray<PhysicsBody3D> SoftBody3D::get_collision_exceptions() { List<RID> exceptions; PhysicsServer3D::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions); TypedArray<PhysicsBody3D> ret; @@ -604,77 +604,77 @@ TypedArray<PhysicsBody3D> SoftDynamicBody3D::get_collision_exceptions() { return ret; } -void SoftDynamicBody3D::add_collision_exception_with(Node *p_node) { +void SoftBody3D::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds."); PhysicsServer3D::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid()); } -void SoftDynamicBody3D::remove_collision_exception_with(Node *p_node) { +void SoftBody3D::remove_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to<CollisionObject3D>(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject3Ds."); PhysicsServer3D::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid()); } -int SoftDynamicBody3D::get_simulation_precision() { +int SoftBody3D::get_simulation_precision() { return PhysicsServer3D::get_singleton()->soft_body_get_simulation_precision(physics_rid); } -void SoftDynamicBody3D::set_simulation_precision(int p_simulation_precision) { +void SoftBody3D::set_simulation_precision(int p_simulation_precision) { PhysicsServer3D::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision); } -real_t SoftDynamicBody3D::get_total_mass() { +real_t SoftBody3D::get_total_mass() { return PhysicsServer3D::get_singleton()->soft_body_get_total_mass(physics_rid); } -void SoftDynamicBody3D::set_total_mass(real_t p_total_mass) { +void SoftBody3D::set_total_mass(real_t p_total_mass) { PhysicsServer3D::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass); } -void SoftDynamicBody3D::set_linear_stiffness(real_t p_linear_stiffness) { +void SoftBody3D::set_linear_stiffness(real_t p_linear_stiffness) { PhysicsServer3D::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness); } -real_t SoftDynamicBody3D::get_linear_stiffness() { +real_t SoftBody3D::get_linear_stiffness() { return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid); } -real_t SoftDynamicBody3D::get_pressure_coefficient() { +real_t SoftBody3D::get_pressure_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); } -void SoftDynamicBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { +void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); } -real_t SoftDynamicBody3D::get_damping_coefficient() { +real_t SoftBody3D::get_damping_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_damping_coefficient(physics_rid); } -void SoftDynamicBody3D::set_damping_coefficient(real_t p_damping_coefficient) { +void SoftBody3D::set_damping_coefficient(real_t p_damping_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient); } -real_t SoftDynamicBody3D::get_drag_coefficient() { +real_t SoftBody3D::get_drag_coefficient() { return PhysicsServer3D::get_singleton()->soft_body_get_drag_coefficient(physics_rid); } -void SoftDynamicBody3D::set_drag_coefficient(real_t p_drag_coefficient) { +void SoftBody3D::set_drag_coefficient(real_t p_drag_coefficient) { PhysicsServer3D::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient); } -Vector3 SoftDynamicBody3D::get_point_transform(int p_point_index) { +Vector3 SoftBody3D::get_point_transform(int p_point_index) { return PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index); } -void SoftDynamicBody3D::pin_point_toggle(int p_point_index) { +void SoftBody3D::pin_point_toggle(int p_point_index) { pin_point(p_point_index, !(-1 != _has_pinned_point(p_point_index))); } -void SoftDynamicBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) { +void SoftBody3D::pin_point(int p_point_index, bool pin, const NodePath &p_spatial_attachment_path) { _pin_point_on_physics_server(p_point_index, pin); if (pin) { _add_pinned_point(p_point_index, p_spatial_attachment_path); @@ -683,35 +683,35 @@ void SoftDynamicBody3D::pin_point(int p_point_index, bool pin, const NodePath &p } } -bool SoftDynamicBody3D::is_point_pinned(int p_point_index) const { +bool SoftBody3D::is_point_pinned(int p_point_index) const { return -1 != _has_pinned_point(p_point_index); } -void SoftDynamicBody3D::set_ray_pickable(bool p_ray_pickable) { +void SoftBody3D::set_ray_pickable(bool p_ray_pickable) { ray_pickable = p_ray_pickable; _update_pickable(); } -bool SoftDynamicBody3D::is_ray_pickable() const { +bool SoftBody3D::is_ray_pickable() const { return ray_pickable; } -SoftDynamicBody3D::SoftDynamicBody3D() : +SoftBody3D::SoftBody3D() : physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()) { - rendering_server_handler = memnew(SoftDynamicBodyRenderingServerHandler); + rendering_server_handler = memnew(SoftBodyRenderingServerHandler); PhysicsServer3D::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); } -SoftDynamicBody3D::~SoftDynamicBody3D() { +SoftBody3D::~SoftBody3D() { memdelete(rendering_server_handler); PhysicsServer3D::get_singleton()->free(physics_rid); } -void SoftDynamicBody3D::_make_cache_dirty() { +void SoftBody3D::_make_cache_dirty() { pinned_points_cache_dirty = true; } -void SoftDynamicBody3D::_update_cache_pin_points_datas() { +void SoftBody3D::_update_cache_pin_points_datas() { if (!pinned_points_cache_dirty) { return; } @@ -724,17 +724,17 @@ void SoftDynamicBody3D::_update_cache_pin_points_datas() { w[i].spatial_attachment = Object::cast_to<Node3D>(get_node(w[i].spatial_attachment_path)); } if (!w[i].spatial_attachment) { - ERR_PRINT("Node3D node not defined in the pinned point, this is undefined behavior for SoftDynamicBody3D!"); + ERR_PRINT("Node3D node not defined in the pinned point, this is undefined behavior for SoftBody3D!"); } } } -void SoftDynamicBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) { +void SoftBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) { PhysicsServer3D::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin); } -void SoftDynamicBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { - SoftDynamicBody3D::PinnedPoint *pinned_point; +void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { + SoftBody3D::PinnedPoint *pinned_point; if (-1 == _get_pinned_point(p_point_index, pinned_point)) { // Create new PinnedPoint pp; @@ -759,7 +759,7 @@ void SoftDynamicBody3D::_add_pinned_point(int p_point_index, const NodePath &p_s } } -void SoftDynamicBody3D::_reset_points_offsets() { +void SoftBody3D::_reset_points_offsets() { if (!Engine::get_singleton()->is_editor_hint()) { return; } @@ -781,25 +781,25 @@ void SoftDynamicBody3D::_reset_points_offsets() { } } -void SoftDynamicBody3D::_remove_pinned_point(int p_point_index) { +void SoftBody3D::_remove_pinned_point(int p_point_index) { const int id(_has_pinned_point(p_point_index)); if (-1 != id) { pinned_points.remove_at(id); } } -int SoftDynamicBody3D::_get_pinned_point(int p_point_index, SoftDynamicBody3D::PinnedPoint *&r_point) const { +int SoftBody3D::_get_pinned_point(int p_point_index, SoftBody3D::PinnedPoint *&r_point) const { const int id = _has_pinned_point(p_point_index); if (-1 == id) { r_point = nullptr; return -1; } else { - r_point = const_cast<SoftDynamicBody3D::PinnedPoint *>(&pinned_points.ptr()[id]); + r_point = const_cast<SoftBody3D::PinnedPoint *>(&pinned_points.ptr()[id]); return id; } } -int SoftDynamicBody3D::_has_pinned_point(int p_point_index) const { +int SoftBody3D::_has_pinned_point(int p_point_index) const { const PinnedPoint *r = pinned_points.ptr(); for (int i = pinned_points.size() - 1; 0 <= i; --i) { if (p_point_index == r[i].point_index) { diff --git a/scene/3d/soft_dynamic_body_3d.h b/scene/3d/soft_body_3d.h index 2b86fe2cae..40f3d6f1f4 100644 --- a/scene/3d/soft_dynamic_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* soft_dynamic_body_3d.h */ +/* soft_body_3d.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#ifndef SOFT_DYNAMIC_BODY_3D_H -#define SOFT_DYNAMIC_BODY_3D_H +#ifndef SOFT_BODY_3D_H +#define SOFT_BODY_3D_H #include "scene/3d/mesh_instance_3d.h" #include "servers/physics_server_3d.h" class PhysicsBody3D; -class SoftDynamicBody3D; +class SoftBody3D; -class SoftDynamicBodyRenderingServerHandler : public PhysicsServer3DRenderingServerHandler { - friend class SoftDynamicBody3D; +class SoftBodyRenderingServerHandler : public PhysicsServer3DRenderingServerHandler { + friend class SoftBody3D; RID mesh; int surface = 0; @@ -50,7 +50,7 @@ class SoftDynamicBodyRenderingServerHandler : public PhysicsServer3DRenderingSer uint8_t *write_buffer = nullptr; private: - SoftDynamicBodyRenderingServerHandler(); + SoftBodyRenderingServerHandler(); bool is_ready(RID p_mesh_rid) const { return mesh.is_valid() && mesh == p_mesh_rid; } void prepare(RID p_mesh_rid, int p_surface); void clear(); @@ -64,8 +64,8 @@ public: void set_aabb(const AABB &p_aabb) override; }; -class SoftDynamicBody3D : public MeshInstance3D { - GDCLASS(SoftDynamicBody3D, MeshInstance3D); +class SoftBody3D : public MeshInstance3D { + GDCLASS(SoftBody3D, MeshInstance3D); public: enum DisableMode { @@ -85,7 +85,7 @@ public: }; private: - SoftDynamicBodyRenderingServerHandler *rendering_server_handler = nullptr; + SoftBodyRenderingServerHandler *rendering_server_handler = nullptr; RID physics_rid; @@ -182,8 +182,8 @@ public: void set_ray_pickable(bool p_ray_pickable); bool is_ray_pickable() const; - SoftDynamicBody3D(); - ~SoftDynamicBody3D(); + SoftBody3D(); + ~SoftBody3D(); private: void _make_cache_dirty(); @@ -198,6 +198,6 @@ private: int _has_pinned_point(int p_point_index) const; }; -VARIANT_ENUM_CAST(SoftDynamicBody3D::DisableMode); +VARIANT_ENUM_CAST(SoftBody3D::DisableMode); -#endif // SOFT_DYNAMIC_BODY_3D_H +#endif // SOFT_BODY_3D_H diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 212d220ace..669c3eb7fd 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -1004,14 +1004,17 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &p_property) const { names.sort_custom<StringName::AlphCompare>(); bool current_found = false; + bool is_first_element = true; - for (List<StringName>::Element *E = names.front(); E; E = E->next()) { - if (E->prev()) { + for (const StringName &E : names) { + if (!is_first_element) { p_property.hint_string += ","; + } else { + is_first_element = false; } - p_property.hint_string += String(E->get()); - if (animation == E->get()) { + p_property.hint_string += String(E); + if (animation == E) { current_found = true; } } diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 42ed52c9f2..d61b49eaa7 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -807,7 +807,7 @@ void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) { } void VehicleBody3D::_body_state_changed(PhysicsDirectBodyState3D *p_state) { - RigidDynamicBody3D::_body_state_changed(p_state); + RigidBody3D::_body_state_changed(p_state); real_t step = p_state->get_step(); diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index 2f3a37af2a..5c4f4beaea 100644 --- a/scene/3d/vehicle_body_3d.h +++ b/scene/3d/vehicle_body_3d.h @@ -152,8 +152,8 @@ public: VehicleWheel3D(); }; -class VehicleBody3D : public RigidDynamicBody3D { - GDCLASS(VehicleBody3D, RigidDynamicBody3D); +class VehicleBody3D : public RigidBody3D { + GDCLASS(VehicleBody3D, RigidBody3D); real_t engine_force = 0.0; real_t brake = 0.0; diff --git a/scene/animation/animation_node_state_machine.cpp b/scene/animation/animation_node_state_machine.cpp index 4b3d7fd0a6..afb52de307 100644 --- a/scene/animation/animation_node_state_machine.cpp +++ b/scene/animation/animation_node_state_machine.cpp @@ -403,7 +403,7 @@ double AnimationNodeStateMachinePlayback::process(AnimationNodeStateMachine *p_s bool do_start = (p_seek && p_time == 0) || play_start || current == StringName(); if (do_start) { - if (p_state_machine->start_node != StringName() && p_seek && p_time == 0) { + if (p_state_machine->start_node != StringName() && p_seek && p_time == 0 && current == StringName()) { current = p_state_machine->start_node; } diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 48626ccc1b..0e2598cbc7 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -1151,7 +1151,7 @@ void AnimationPlayer::_animation_update_transforms() { } #endif - static_cast<Node2D *>(pa->object)->set_rotation(Math::deg2rad((double)pa->value_accum)); + static_cast<Node2D *>(pa->object)->set_rotation(Math::deg_to_rad((double)pa->value_accum)); } break; case SP_NODE2D_SCALE: { #ifdef DEBUG_ENABLED diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index 7dbe892299..d06324f0aa 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -602,6 +602,8 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { track_value->object = child; } + track_value->is_using_angle = anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; + track_value->subpath = leftover_path; track_value->object_id = track_value->object->get_instance_id(); @@ -804,6 +806,10 @@ bool AnimationTree::_update_caches(AnimationPlayer *player) { default: { } } + } else if (track_cache_type == Animation::TYPE_VALUE) { + // If it has at least one angle interpolation, it also uses angle interpolation for blending. + TrackCacheValue *track_value = memnew(TrackCacheValue); + track_value->is_using_angle |= anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_LINEAR_ANGLE || anim->track_get_interpolation_type(i) == Animation::INTERPOLATION_CUBIC_ANGLE; } track->setup_pass = setup_pass; @@ -1353,8 +1359,28 @@ void AnimationTree::_process_graph(double p_delta) { t->value = t->init_value; } - Variant::sub(value, t->init_value, value); - Variant::blend(t->value, value, blend, t->value); + // Special case for angle interpolation. + if (t->is_using_angle) { + // For blending consistency, it prevents rotation of more than 180 degrees from init_value. + // This is the same as for Quaternion blends. + float rot_a = t->value; + float rot_b = value; + float rot_init = t->init_value; + rot_a = Math::fposmod(rot_a, (float)Math_TAU); + rot_b = Math::fposmod(rot_b, (float)Math_TAU); + rot_init = Math::fposmod(rot_init, (float)Math_TAU); + if (rot_init < Math_PI) { + rot_a = rot_a > rot_init + Math_PI ? rot_a - Math_TAU : rot_a; + rot_b = rot_b > rot_init + Math_PI ? rot_b - Math_TAU : rot_b; + } else { + rot_a = rot_a < rot_init - Math_PI ? rot_a + Math_TAU : rot_a; + rot_b = rot_b < rot_init - Math_PI ? rot_b + Math_TAU : rot_b; + } + t->value = Math::fposmod(rot_a + (rot_b - rot_init) * (float)blend, (float)Math_TAU); + } else { + Variant::sub(value, t->init_value, value); + Variant::blend(t->value, value, blend, t->value); + } } else { if (blend < CMP_EPSILON) { continue; //nothing to blend @@ -1528,7 +1554,7 @@ void AnimationTree::_process_graph(double p_delta) { } } - real_t db = Math::linear2db(MAX(blend, 0.00001)); + real_t db = Math::linear_to_db(MAX(blend, 0.00001)); if (t->object->has_method(SNAME("set_unit_db"))) { t->object->call(SNAME("set_unit_db"), db); } else { diff --git a/scene/animation/animation_tree.h b/scene/animation/animation_tree.h index ee51a54557..ee0c0303dc 100644 --- a/scene/animation/animation_tree.h +++ b/scene/animation/animation_tree.h @@ -233,6 +233,7 @@ private: Variant init_value; Variant value; Vector<StringName> subpath; + bool is_using_angle = false; TrackCacheValue() { type = Animation::TYPE_VALUE; } }; diff --git a/scene/audio/audio_stream_player.cpp b/scene/audio/audio_stream_player.cpp index 7c85b650bf..04feb0dc6f 100644 --- a/scene/audio/audio_stream_player.cpp +++ b/scene/audio/audio_stream_player.cpp @@ -256,7 +256,7 @@ Vector<AudioFrame> AudioStreamPlayer::_get_volume_vector() { channel_volume_db = AudioFrame(0, 0); } - float volume_linear = Math::db2linear(volume_db); + float volume_linear = Math::db_to_linear(volume_db); // Set the volume vector up according to the speaker mode and mix target. // TODO do we need to scale the volume down when we output to more channels? diff --git a/scene/gui/code_edit.cpp b/scene/gui/code_edit.cpp index e54ba7ce13..b9760499ef 100644 --- a/scene/gui/code_edit.cpp +++ b/scene/gui/code_edit.cpp @@ -36,8 +36,7 @@ void CodeEdit::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_THEME_CHANGED: - case NOTIFICATION_ENTER_TREE: { + case NOTIFICATION_THEME_CHANGED: { style_normal = get_theme_stylebox(SNAME("normal")); font = get_theme_font(SNAME("font")); diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp index 9eef45f412..ed42d1c5ea 100644 --- a/scene/gui/color_picker.cpp +++ b/scene/gui/color_picker.cpp @@ -63,8 +63,8 @@ void ColorPicker::_notification(int p_what) { } } #endif - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { btn_pick->set_icon(get_theme_icon(SNAME("screen_picker"), SNAME("ColorPicker"))); btn_add_preset->set_icon(get_theme_icon(SNAME("add_preset"))); @@ -536,7 +536,7 @@ void ColorPicker::_add_preset_button(int p_size, const Color &p_color) { btn_preset->set_preset_color(p_color); btn_preset->set_custom_minimum_size(Size2(p_size, p_size)); btn_preset->connect("gui_input", callable_mp(this, &ColorPicker::_preset_input).bind(p_color)); - btn_preset->set_tooltip(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1))); + btn_preset->set_tooltip_text(vformat(RTR("Color: #%s\nLMB: Apply color\nRMB: Remove preset"), p_color.to_html(p_color.a < 1))); preset_container->add_child(btn_preset); } @@ -1236,7 +1236,7 @@ ColorPicker::ColorPicker() : btn_pick->set_flat(true); hb_smpl->add_child(btn_pick); btn_pick->set_toggle_mode(true); - btn_pick->set_tooltip(RTR("Pick a color from the editor window.")); + btn_pick->set_tooltip_text(RTR("Pick a color from the editor window.")); btn_pick->connect("pressed", callable_mp(this, &ColorPicker::_screen_pick_pressed)); VBoxContainer *vbl = memnew(VBoxContainer); @@ -1276,7 +1276,7 @@ ColorPicker::ColorPicker() : text_type = memnew(Button); hhb->add_child(text_type); text_type->set_text("#"); - text_type->set_tooltip(RTR("Switch between hexadecimal and code values.")); + text_type->set_tooltip_text(RTR("Switch between hexadecimal and code values.")); if (Engine::get_singleton()->is_editor_hint()) { text_type->connect("pressed", callable_mp(this, &ColorPicker::_text_type_toggled)); } else { @@ -1337,7 +1337,7 @@ ColorPicker::ColorPicker() : btn_add_preset = memnew(Button); btn_add_preset->set_icon_alignment(HORIZONTAL_ALIGNMENT_CENTER); - btn_add_preset->set_tooltip(RTR("Add current color as a preset.")); + btn_add_preset->set_tooltip_text(RTR("Add current color as a preset.")); btn_add_preset->connect("pressed", callable_mp(this, &ColorPicker::_add_preset_pressed)); preset_container->add_child(btn_add_preset); } diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 03fcef17f5..299c796091 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -252,36 +252,36 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) { if (name.begins_with("theme_override_icons/")) { String dname = name.get_slicec('/', 1); if (data.icon_override.has(dname)) { - data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.icon_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.icon_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_styles/")) { String dname = name.get_slicec('/', 1); if (data.style_override.has(dname)) { - data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.style_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.style_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_fonts/")) { String dname = name.get_slicec('/', 1); if (data.font_override.has(dname)) { - data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.font_override[dname]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.font_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_font_sizes/")) { String dname = name.get_slicec('/', 1); data.font_size_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_colors/")) { String dname = name.get_slicec('/', 1); data.color_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else if (name.begins_with("theme_override_constants/")) { String dname = name.get_slicec('/', 1); data.constant_override.erase(dname); - notification(NOTIFICATION_THEME_CHANGED); + _notify_theme_override_changed(); } else { return false; } @@ -2260,62 +2260,62 @@ bool Control::is_clipping_contents() { // Theming. -void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) { +void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_notify, bool p_assign) { Control *c = Object::cast_to<Control>(p_at); - - if (c && c != p_owner && c->data.theme.is_valid()) { // has a theme, this can't be propagated - return; - } - Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr; - if (w && w != p_owner_window && w->theme.is_valid()) { // has a theme, this can't be propagated + if (!c && !w) { + // Theme inheritance chains are broken by nodes that aren't Control or Window. return; } - for (int i = 0; i < p_at->get_child_count(); i++) { - CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i)); - if (child) { - _propagate_theme_changed(child, p_owner, p_owner_window, p_assign); - } else { - Window *window = Object::cast_to<Window>(p_at->get_child(i)); - if (window) { - _propagate_theme_changed(window, p_owner, p_owner_window, p_assign); - } + bool assign = p_assign; + if (c) { + if (c != p_owner && c->data.theme.is_valid()) { + // Has a theme, so we don't want to change the theme owner, + // but we still want to propagate in case this child has theme items + // it inherits from the theme this node uses. + // See https://github.com/godotengine/godot/issues/62844. + assign = false; } - } - if (c) { - if (p_assign) { + if (assign) { c->data.theme_owner = p_owner; c->data.theme_owner_window = p_owner_window; } - c->notification(Control::NOTIFICATION_THEME_CHANGED); - c->emit_signal(SceneStringNames::get_singleton()->theme_changed); - } - if (w) { - if (p_assign) { + if (p_notify) { + c->notification(Control::NOTIFICATION_THEME_CHANGED); + } + } else if (w) { + if (w != p_owner_window && w->theme.is_valid()) { + // Same as above. + assign = false; + } + + if (assign) { w->theme_owner = p_owner; w->theme_owner_window = p_owner_window; } - w->notification(Window::NOTIFICATION_THEME_CHANGED); - w->emit_signal(SceneStringNames::get_singleton()->theme_changed); + + if (p_notify) { + w->notification(Window::NOTIFICATION_THEME_CHANGED); + } } -} -void Control::_theme_changed() { - _propagate_theme_changed(this, this, nullptr, false); + for (int i = 0; i < p_at->get_child_count(); i++) { + _propagate_theme_changed(p_at->get_child(i), p_owner, p_owner_window, p_notify, assign); + } } -void Control::_theme_property_override_changed() { - notification(NOTIFICATION_THEME_CHANGED); - emit_signal(SceneStringNames::get_singleton()->theme_changed); - update_minimum_size(); // Overrides are likely to affect minimum size. +void Control::_theme_changed() { + if (is_inside_tree()) { + _propagate_theme_changed(this, this, nullptr, true, false); + } } -void Control::_notify_theme_changed() { - if (!data.bulk_theme_override) { +void Control::_notify_theme_override_changed() { + if (!data.bulk_theme_override && is_inside_tree()) { notification(NOTIFICATION_THEME_CHANGED); } } @@ -2339,28 +2339,25 @@ void Control::set_theme(const Ref<Theme> &p_theme) { } data.theme = p_theme; - if (!p_theme.is_null()) { - data.theme_owner = this; - data.theme_owner_window = nullptr; - _propagate_theme_changed(this, this, nullptr); - } else { - Control *parent_c = Object::cast_to<Control>(get_parent()); + if (data.theme.is_valid()) { + _propagate_theme_changed(this, this, nullptr, is_inside_tree(), true); + data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), CONNECT_DEFERRED); + return; + } - if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); - } else { - Window *parent_w = cast_to<Window>(get_parent()); - if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); - } else { - Control::_propagate_theme_changed(this, nullptr, nullptr); - } - } + Control *parent_c = Object::cast_to<Control>(get_parent()); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + _propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window, is_inside_tree(), true); + return; } - if (data.theme.is_valid()) { - data.theme->connect("changed", callable_mp(this, &Control::_theme_changed), CONNECT_DEFERRED); + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + _propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window, is_inside_tree(), true); + return; } + + _propagate_theme_changed(this, nullptr, nullptr, is_inside_tree(), true); } Ref<Theme> Control::get_theme() const { @@ -2372,7 +2369,9 @@ void Control::set_theme_type_variation(const StringName &p_theme_type) { return; } data.theme_type_variation = p_theme_type; - _propagate_theme_changed(this, data.theme_owner, data.theme_owner_window); + if (is_inside_tree()) { + notification(NOTIFICATION_THEME_CHANGED); + } } StringName Control::get_theme_type_variation() const { @@ -2697,93 +2696,93 @@ void Control::add_theme_icon_override(const StringName &p_name, const Ref<Textur ERR_FAIL_COND(!p_icon.is_valid()); if (data.icon_override.has(p_name)) { - data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.icon_override[p_name] = p_icon; - data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + data.icon_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); } void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) { ERR_FAIL_COND(!p_style.is_valid()); if (data.style_override.has(p_name)) { - data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.style_override[p_name] = p_style; - data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + data.style_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); } void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) { ERR_FAIL_COND(!p_font.is_valid()); if (data.font_override.has(p_name)) { - data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.font_override[p_name] = p_font; - data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_theme_property_override_changed), CONNECT_REFERENCE_COUNTED); - _notify_theme_changed(); + data.font_override[p_name]->connect("changed", callable_mp(this, &Control::_notify_theme_override_changed), CONNECT_REFERENCE_COUNTED); + _notify_theme_override_changed(); } void Control::add_theme_font_size_override(const StringName &p_name, int p_font_size) { data.font_size_override[p_name] = p_font_size; - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) { data.color_override[p_name] = p_color; - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::add_theme_constant_override(const StringName &p_name, int p_constant) { data.constant_override[p_name] = p_constant; - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_icon_override(const StringName &p_name) { if (data.icon_override.has(p_name)) { - data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.icon_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_style_override(const StringName &p_name) { if (data.style_override.has(p_name)) { - data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.style_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_font_override(const StringName &p_name) { if (data.font_override.has(p_name)) { - data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } data.font_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_font_size_override(const StringName &p_name) { data.font_size_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_color_override(const StringName &p_name) { data.color_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } void Control::remove_theme_constant_override(const StringName &p_name) { data.constant_override.erase(p_name); - _notify_theme_changed(); + _notify_theme_override_changed(); } bool Control::has_theme_icon_override(const StringName &p_name) const { @@ -2981,7 +2980,7 @@ void Control::end_bulk_theme_override() { ERR_FAIL_COND(!data.bulk_theme_override); data.bulk_theme_override = false; - _notify_theme_changed(); + _notify_theme_override_changed(); } // Internationalization. @@ -3063,12 +3062,12 @@ bool Control::is_auto_translating() const { // Extra properties. -void Control::set_tooltip(const String &p_tooltip) { - data.tooltip = p_tooltip; +void Control::set_tooltip_text(const String &p_hint) { + data.tooltip = p_hint; update_configuration_warnings(); } -String Control::_get_tooltip() const { +String Control::get_tooltip_text() const { return data.tooltip; } @@ -3087,37 +3086,26 @@ Control *Control::make_custom_tooltip(const String &p_text) const { // Base object overrides. void Control::add_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) { - _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) { - _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff + // We propagate when this node uses a custom theme, so it can pass it on to its children. + if (data.theme_owner || data.theme_owner_window) { + // `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`. + _propagate_theme_changed(p_child, data.theme_owner, data.theme_owner_window, false, true); } } void Control::remove_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { - _propagate_theme_changed(child_c, nullptr, nullptr); - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { - _propagate_theme_changed(child_w, nullptr, nullptr); + // If the removed child isn't inheriting any theme items through this node, then there's no need to propagate. + if (data.theme_owner || data.theme_owner_window) { + _propagate_theme_changed(p_child, nullptr, nullptr, false, true); } } void Control::_notification(int p_notification) { switch (p_notification) { case NOTIFICATION_ENTER_TREE: { - _invalidate_theme_cache(); + // Need to defer here, because theme owner information might be set in + // add_child_notify, which doesn't get called until right after this. + call_deferred(SNAME("notification"), NOTIFICATION_THEME_CHANGED); } break; case NOTIFICATION_POST_ENTER_TREE: { @@ -3142,18 +3130,6 @@ void Control::_notification(int p_notification) { data.parent_window = Object::cast_to<Window>(get_parent()); data.is_rtl_dirty = true; - if (data.theme.is_null()) { - if (data.parent && (data.parent->data.theme_owner || data.parent->data.theme_owner_window)) { - data.theme_owner = data.parent->data.theme_owner; - data.theme_owner_window = data.parent->data.theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } else if (data.parent_window && (data.parent_window->theme_owner || data.parent_window->theme_owner_window)) { - data.theme_owner = data.parent_window->theme_owner; - data.theme_owner_window = data.parent_window->theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } - } - CanvasItem *node = this; bool has_parent_control = false; @@ -3257,6 +3233,7 @@ void Control::_notification(int p_notification) { } break; case NOTIFICATION_THEME_CHANGED: { + emit_signal(SceneStringNames::get_singleton()->theme_changed); _invalidate_theme_cache(); update_minimum_size(); update(); @@ -3406,9 +3383,9 @@ void Control::_bind_methods() { ClassDB::bind_method(D_METHOD("set_v_grow_direction", "direction"), &Control::set_v_grow_direction); ClassDB::bind_method(D_METHOD("get_v_grow_direction"), &Control::get_v_grow_direction); - ClassDB::bind_method(D_METHOD("set_tooltip", "tooltip"), &Control::set_tooltip); + ClassDB::bind_method(D_METHOD("set_tooltip_text", "hint"), &Control::set_tooltip_text); + ClassDB::bind_method(D_METHOD("get_tooltip_text"), &Control::get_tooltip_text); ClassDB::bind_method(D_METHOD("get_tooltip", "at_position"), &Control::get_tooltip, DEFVAL(Point2())); - ClassDB::bind_method(D_METHOD("_get_tooltip"), &Control::_get_tooltip); ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Control::set_default_cursor_shape); ClassDB::bind_method(D_METHOD("get_default_cursor_shape"), &Control::get_default_cursor_shape); @@ -3498,8 +3475,8 @@ void Control::_bind_methods() { ADD_GROUP("Auto Translate", ""); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "auto_translate"), "set_auto_translate", "is_auto_translating"); - ADD_GROUP("Hint", "hint_"); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "hint_tooltip", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip", "_get_tooltip"); + ADD_GROUP("Tooltip", "tooltip_"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "tooltip_text", PROPERTY_HINT_MULTILINE_TEXT), "set_tooltip_text", "get_tooltip_text"); ADD_GROUP("Focus", "focus_"); ADD_PROPERTYI(PropertyInfo(Variant::NODE_PATH, "focus_neighbor_left", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Control"), "set_focus_neighbor", "get_focus_neighbor", SIDE_LEFT); @@ -3626,13 +3603,13 @@ void Control::_bind_methods() { Control::~Control() { // Resources need to be disconnected. for (KeyValue<StringName, Ref<Texture2D>> &E : data.icon_override) { - E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } for (KeyValue<StringName, Ref<StyleBox>> &E : data.style_override) { - E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } for (KeyValue<StringName, Ref<Font>> &E : data.font_override) { - E.value->disconnect("changed", callable_mp(this, &Control::_theme_property_override_changed)); + E.value->disconnect("changed", callable_mp(this, &Control::_notify_theme_override_changed)); } // Then override maps can be simply cleared. diff --git a/scene/gui/control.h b/scene/gui/control.h index c69067f82f..66cd15542a 100644 --- a/scene/gui/control.h +++ b/scene/gui/control.h @@ -300,11 +300,10 @@ private: // Theming. void _theme_changed(); - void _theme_property_override_changed(); - void _notify_theme_changed(); + void _notify_theme_override_changed(); void _invalidate_theme_cache(); - static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true); + static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_notify, bool p_assign); template <class T> static T get_theme_item_in_types(Control *p_theme_owner, Window *p_theme_owner_window, Theme::DataType p_data_type, const StringName &p_name, List<StringName> p_theme_types); @@ -313,7 +312,7 @@ private: // Extra properties. - String _get_tooltip() const; + String get_tooltip_text() const; protected: // Dynamic properties. @@ -358,6 +357,7 @@ public: NOTIFICATION_MOUSE_EXIT = 42, NOTIFICATION_FOCUS_ENTER = 43, NOTIFICATION_FOCUS_EXIT = 44, + // This doesn't need to be paired with `NOTIFICATION_ENTER_TREE`. NOTIFICATION_THEME_CHANGED = 45, NOTIFICATION_SCROLL_BEGIN = 47, NOTIFICATION_SCROLL_END = 48, @@ -605,7 +605,7 @@ public: // Extra properties. - void set_tooltip(const String &p_tooltip); + void set_tooltip_text(const String &text); virtual String get_tooltip(const Point2 &p_pos) const; virtual Control *make_custom_tooltip(const String &p_text) const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index 7965b12edd..ab2c19e9b1 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -59,38 +59,6 @@ VBoxContainer *FileDialog::get_vbox() { return vbox; } -void FileDialog::_theme_changed() { - Color font_color = vbox->get_theme_color(SNAME("font_color"), SNAME("Button")); - Color font_hover_color = vbox->get_theme_color(SNAME("font_hover_color"), SNAME("Button")); - Color font_focus_color = vbox->get_theme_color(SNAME("font_focus_color"), SNAME("Button")); - Color font_pressed_color = vbox->get_theme_color(SNAME("font_pressed_color"), SNAME("Button")); - - dir_up->add_theme_color_override("icon_normal_color", font_color); - dir_up->add_theme_color_override("icon_hover_color", font_hover_color); - dir_up->add_theme_color_override("icon_focus_color", font_focus_color); - dir_up->add_theme_color_override("icon_pressed_color", font_pressed_color); - - dir_prev->add_theme_color_override("icon_color_normal", font_color); - dir_prev->add_theme_color_override("icon_color_hover", font_hover_color); - dir_prev->add_theme_color_override("icon_focus_color", font_focus_color); - dir_prev->add_theme_color_override("icon_color_pressed", font_pressed_color); - - dir_next->add_theme_color_override("icon_color_normal", font_color); - dir_next->add_theme_color_override("icon_color_hover", font_hover_color); - dir_next->add_theme_color_override("icon_focus_color", font_focus_color); - dir_next->add_theme_color_override("icon_color_pressed", font_pressed_color); - - refresh->add_theme_color_override("icon_normal_color", font_color); - refresh->add_theme_color_override("icon_hover_color", font_hover_color); - refresh->add_theme_color_override("icon_focus_color", font_focus_color); - refresh->add_theme_color_override("icon_pressed_color", font_pressed_color); - - show_hidden->add_theme_color_override("icon_normal_color", font_color); - show_hidden->add_theme_color_override("icon_hover_color", font_hover_color); - show_hidden->add_theme_color_override("icon_focus_color", font_focus_color); - show_hidden->add_theme_color_override("icon_pressed_color", font_pressed_color); -} - void FileDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { @@ -99,22 +67,51 @@ void FileDialog::_notification(int p_what) { } } break; - case NOTIFICATION_ENTER_TREE: { - dir_up->set_icon(vbox->get_theme_icon(SNAME("parent_folder"), SNAME("FileDialog"))); + case NOTIFICATION_TRANSLATION_CHANGED: { + update_filters(); + } break; + + case NOTIFICATION_THEME_CHANGED: { + dir_up->set_icon(get_theme_icon(SNAME("parent_folder"), SNAME("FileDialog"))); if (vbox->is_layout_rtl()) { - dir_prev->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog"))); - dir_next->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog"))); + dir_prev->set_icon(get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog"))); + dir_next->set_icon(get_theme_icon(SNAME("back_folder"), SNAME("FileDialog"))); } else { - dir_prev->set_icon(vbox->get_theme_icon(SNAME("back_folder"), SNAME("FileDialog"))); - dir_next->set_icon(vbox->get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog"))); + dir_prev->set_icon(get_theme_icon(SNAME("back_folder"), SNAME("FileDialog"))); + dir_next->set_icon(get_theme_icon(SNAME("forward_folder"), SNAME("FileDialog"))); } - refresh->set_icon(vbox->get_theme_icon(SNAME("reload"), SNAME("FileDialog"))); - show_hidden->set_icon(vbox->get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog"))); - _theme_changed(); - } break; - - case NOTIFICATION_TRANSLATION_CHANGED: { - update_filters(); + refresh->set_icon(get_theme_icon(SNAME("reload"), SNAME("FileDialog"))); + show_hidden->set_icon(get_theme_icon(SNAME("toggle_hidden"), SNAME("FileDialog"))); + + Color font_color = get_theme_color(SNAME("font_color"), SNAME("Button")); + Color font_hover_color = get_theme_color(SNAME("font_hover_color"), SNAME("Button")); + Color font_focus_color = get_theme_color(SNAME("font_focus_color"), SNAME("Button")); + Color font_pressed_color = get_theme_color(SNAME("font_pressed_color"), SNAME("Button")); + + dir_up->add_theme_color_override("icon_normal_color", font_color); + dir_up->add_theme_color_override("icon_hover_color", font_hover_color); + dir_up->add_theme_color_override("icon_focus_color", font_focus_color); + dir_up->add_theme_color_override("icon_pressed_color", font_pressed_color); + + dir_prev->add_theme_color_override("icon_color_normal", font_color); + dir_prev->add_theme_color_override("icon_color_hover", font_hover_color); + dir_prev->add_theme_color_override("icon_focus_color", font_focus_color); + dir_prev->add_theme_color_override("icon_color_pressed", font_pressed_color); + + dir_next->add_theme_color_override("icon_color_normal", font_color); + dir_next->add_theme_color_override("icon_color_hover", font_hover_color); + dir_next->add_theme_color_override("icon_focus_color", font_focus_color); + dir_next->add_theme_color_override("icon_color_pressed", font_pressed_color); + + refresh->add_theme_color_override("icon_normal_color", font_color); + refresh->add_theme_color_override("icon_hover_color", font_hover_color); + refresh->add_theme_color_override("icon_focus_color", font_focus_color); + refresh->add_theme_color_override("icon_pressed_color", font_pressed_color); + + show_hidden->add_theme_color_override("icon_normal_color", font_color); + show_hidden->add_theme_color_override("icon_hover_color", font_hover_color); + show_hidden->add_theme_color_override("icon_focus_color", font_focus_color); + show_hidden->add_theme_color_override("icon_pressed_color", font_pressed_color); } break; } } @@ -506,10 +503,10 @@ void FileDialog::update_file_list() { } TreeItem *root = tree->create_item(); - Ref<Texture2D> folder = vbox->get_theme_icon(SNAME("folder"), SNAME("FileDialog")); - Ref<Texture2D> file_icon = vbox->get_theme_icon(SNAME("file"), SNAME("FileDialog")); - const Color folder_color = vbox->get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")); - const Color file_color = vbox->get_theme_color(SNAME("file_icon_modulate"), SNAME("FileDialog")); + Ref<Texture2D> folder = get_theme_icon(SNAME("folder"), SNAME("FileDialog")); + Ref<Texture2D> file_icon = get_theme_icon(SNAME("file"), SNAME("FileDialog")); + const Color folder_color = get_theme_color(SNAME("folder_icon_modulate"), SNAME("FileDialog")); + const Color file_color = get_theme_color(SNAME("file_icon_modulate"), SNAME("FileDialog")); List<String> files; List<String> dirs; @@ -606,7 +603,7 @@ void FileDialog::update_file_list() { ti->set_icon_modulate(0, file_color); if (mode == FILE_MODE_OPEN_DIR) { - ti->set_custom_color(0, vbox->get_theme_color(SNAME("files_disabled"), SNAME("FileDialog"))); + ti->set_custom_color(0, get_theme_color(SNAME("files_disabled"), SNAME("FileDialog"))); ti->set_selectable(0, false); } Dictionary d; @@ -1006,7 +1003,6 @@ FileDialog::FileDialog() { vbox = memnew(VBoxContainer); add_child(vbox, false, INTERNAL_MODE_FRONT); - vbox->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed)); mode = FILE_MODE_SAVE_FILE; set_title(TTRC("Save a File")); @@ -1015,13 +1011,13 @@ FileDialog::FileDialog() { dir_prev = memnew(Button); dir_prev->set_flat(true); - dir_prev->set_tooltip(RTR("Go to previous folder.")); + dir_prev->set_tooltip_text(RTR("Go to previous folder.")); dir_next = memnew(Button); dir_next->set_flat(true); - dir_next->set_tooltip(RTR("Go to next folder.")); + dir_next->set_tooltip_text(RTR("Go to next folder.")); dir_up = memnew(Button); dir_up->set_flat(true); - dir_up->set_tooltip(RTR("Go to parent folder.")); + dir_up->set_tooltip_text(RTR("Go to parent folder.")); hbc->add_child(dir_prev); hbc->add_child(dir_next); hbc->add_child(dir_up); @@ -1045,7 +1041,7 @@ FileDialog::FileDialog() { refresh = memnew(Button); refresh->set_flat(true); - refresh->set_tooltip(RTR("Refresh files.")); + refresh->set_tooltip_text(RTR("Refresh files.")); refresh->connect("pressed", callable_mp(this, &FileDialog::update_file_list)); hbc->add_child(refresh); @@ -1053,7 +1049,7 @@ FileDialog::FileDialog() { show_hidden->set_flat(true); show_hidden->set_toggle_mode(true); show_hidden->set_pressed(is_showing_hidden_files()); - show_hidden->set_tooltip(RTR("Toggle the visibility of hidden files.")); + show_hidden->set_tooltip_text(RTR("Toggle the visibility of hidden files.")); show_hidden->connect("toggled", callable_mp(this, &FileDialog::set_show_hidden_files)); hbc->add_child(show_hidden); diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 4945094086..4ea39691c1 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -143,8 +143,6 @@ private: virtual void _post_popup() override; protected: - void _theme_changed(); - void _notification(int p_what); static void _bind_methods(); //bind helpers diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp index cc27a6b7c2..be097f7543 100644 --- a/scene/gui/gradient_edit.cpp +++ b/scene/gui/gradient_edit.cpp @@ -292,8 +292,8 @@ void GradientEdit::_notification(int p_what) { if (!picker->is_connected("color_changed", callable_mp(this, &GradientEdit::_color_changed))) { picker->connect("color_changed", callable_mp(this, &GradientEdit::_color_changed)); } - [[fallthrough]]; - } + } break; + case NOTIFICATION_THEME_CHANGED: { draw_spacing = BASE_SPACING * get_theme_default_base_scale(); draw_point_width = BASE_POINT_WIDTH * get_theme_default_base_scale(); diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp index e6198b44ff..a556514e0d 100644 --- a/scene/gui/graph_edit.cpp +++ b/scene/gui/graph_edit.cpp @@ -424,7 +424,6 @@ void GraphEdit::remove_child_notify(Node *p_child) { void GraphEdit::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: case NOTIFICATION_THEME_CHANGED: { port_hotzone_inner_extent = get_theme_constant("port_hotzone_inner_extent"); port_hotzone_outer_extent = get_theme_constant("port_hotzone_outer_extent"); @@ -607,13 +606,16 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_color = Object::cast_to<GraphNode>(to)->get_connection_input_color(E.to_port); connecting_target = false; connecting_to = pos; - just_disconnected = true; - emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port); - to = get_node(String(connecting_from)); //maybe it was erased - if (Object::cast_to<GraphNode>(to)) { - connecting = true; - emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false); + if (connecting_type >= 0) { + just_disconnected = true; + + emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port); + to = get_node(String(connecting_from)); //maybe it was erased + if (Object::cast_to<GraphNode>(to)) { + connecting = true; + emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false); + } } return; } @@ -621,7 +623,6 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { } } - connecting = true; connecting_from = gn->get_name(); connecting_index = j; connecting_out = true; @@ -629,8 +630,11 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_color = gn->get_connection_output_color(j); connecting_target = false; connecting_to = pos; - just_disconnected = false; - emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true); + if (connecting_type >= 0) { + connecting = true; + just_disconnected = false; + emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true); + } return; } } @@ -657,11 +661,13 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_to = pos; just_disconnected = true; - emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port); - fr = get_node(String(connecting_from)); //maybe it was erased - if (Object::cast_to<GraphNode>(fr)) { - connecting = true; - emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true); + if (connecting_type >= 0) { + emit_signal(SNAME("disconnection_request"), E.from, E.from_port, E.to, E.to_port); + fr = get_node(String(connecting_from)); //maybe it was erased + if (Object::cast_to<GraphNode>(fr)) { + connecting = true; + emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, true); + } } return; } @@ -669,7 +675,6 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { } } - connecting = true; connecting_from = gn->get_name(); connecting_index = j; connecting_out = false; @@ -677,8 +682,11 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) { connecting_color = gn->get_connection_input_color(j); connecting_target = false; connecting_to = pos; - just_disconnected = false; - emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false); + if (connecting_type >= 0) { + connecting = true; + just_disconnected = false; + emit_signal(SNAME("connection_drag_started"), connecting_from, connecting_index, false); + } return; } } @@ -1127,7 +1135,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { drag_accum += mm->get_relative(); for (int i = get_child_count() - 1; i >= 0; i--) { GraphNode *gn = Object::cast_to<GraphNode>(get_child(i)); - if (gn && gn->is_selected()) { + if (gn && gn->is_selected() && gn->is_draggable()) { Vector2 pos = (gn->get_drag_from() * zoom + drag_accum) / zoom; // Snapping can be toggled temporarily by holding down Ctrl. @@ -1166,7 +1174,9 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } else if (gn->is_selected() && !box_selection_mode_additive) { emit_signal(SNAME("node_deselected"), gn); } - gn->set_selected(box_selection_mode_additive); + if (gn->is_selectable()) { + gn->set_selected(box_selection_mode_additive); + } } else { bool select = (previous_selected.find(gn) != nullptr); if (gn->is_selected() && !select) { @@ -1174,7 +1184,9 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } else if (!gn->is_selected() && select) { emit_signal(SNAME("node_selected"), gn); } - gn->set_selected(select); + if (gn->is_selectable()) { + gn->set_selected(select); + } } } @@ -1193,7 +1205,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { continue; } - bool select = (previous_selected.find(gn) != nullptr); + bool select = (gn->is_selectable() && previous_selected.find(gn) != nullptr); if (gn->is_selected() && !select) { emit_signal(SNAME("node_deselected"), gn); } else if (!gn->is_selected() && select) { @@ -1285,7 +1297,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i)); if (o_gn) { if (o_gn == gn) { - o_gn->set_selected(true); + o_gn->set_selected(o_gn->is_selectable()); } else { if (o_gn->is_selected()) { emit_signal(SNAME("node_deselected"), o_gn); @@ -1296,7 +1308,7 @@ void GraphEdit::gui_input(const Ref<InputEvent> &p_ev) { } } - gn->set_selected(true); + gn->set_selected(gn->is_selectable()); for (int i = 0; i < get_child_count(); i++) { GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i)); if (!o_gn) { @@ -1711,6 +1723,19 @@ bool GraphEdit::is_minimap_enabled() const { return minimap_button->is_pressed(); } +void GraphEdit::set_arrange_nodes_button_hidden(bool p_enable) { + arrange_nodes_button_hidden = p_enable; + if (arrange_nodes_button_hidden) { + layout_button->hide(); + } else { + layout_button->show(); + } +} + +bool GraphEdit::is_arrange_nodes_button_hidden() const { + return arrange_nodes_button_hidden; +} + void GraphEdit::_minimap_toggled() { if (is_minimap_enabled()) { minimap->set_visible(true); @@ -2343,6 +2368,9 @@ void GraphEdit::_bind_methods() { ClassDB::bind_method(D_METHOD("set_minimap_enabled", "enable"), &GraphEdit::set_minimap_enabled); ClassDB::bind_method(D_METHOD("is_minimap_enabled"), &GraphEdit::is_minimap_enabled); + ClassDB::bind_method(D_METHOD("set_arrange_nodes_button_hidden", "enable"), &GraphEdit::set_arrange_nodes_button_hidden); + ClassDB::bind_method(D_METHOD("is_arrange_nodes_button_hidden"), &GraphEdit::is_arrange_nodes_button_hidden); + ClassDB::bind_method(D_METHOD("set_right_disconnects", "enable"), &GraphEdit::set_right_disconnects); ClassDB::bind_method(D_METHOD("is_right_disconnects_enabled"), &GraphEdit::is_right_disconnects_enabled); @@ -2382,6 +2410,9 @@ void GraphEdit::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "minimap_size", PROPERTY_HINT_NONE, "suffix:px"), "set_minimap_size", "get_minimap_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "minimap_opacity"), "set_minimap_opacity", "get_minimap_opacity"); + ADD_GROUP("UI", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arrange_nodes_button_hidden"), "set_arrange_nodes_button_hidden", "is_arrange_nodes_button_hidden"); + ADD_SIGNAL(MethodInfo("connection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot"))); ADD_SIGNAL(MethodInfo("disconnection_request", PropertyInfo(Variant::STRING_NAME, "from"), PropertyInfo(Variant::INT, "from_slot"), PropertyInfo(Variant::STRING_NAME, "to"), PropertyInfo(Variant::INT, "to_slot"))); ADD_SIGNAL(MethodInfo("popup_request", PropertyInfo(Variant::VECTOR2, "position"))); @@ -2464,28 +2495,28 @@ GraphEdit::GraphEdit() { zoom_minus = memnew(Button); zoom_minus->set_flat(true); zoom_hb->add_child(zoom_minus); - zoom_minus->set_tooltip(RTR("Zoom Out")); + zoom_minus->set_tooltip_text(RTR("Zoom Out")); zoom_minus->connect("pressed", callable_mp(this, &GraphEdit::_zoom_minus)); zoom_minus->set_focus_mode(FOCUS_NONE); zoom_reset = memnew(Button); zoom_reset->set_flat(true); zoom_hb->add_child(zoom_reset); - zoom_reset->set_tooltip(RTR("Zoom Reset")); + zoom_reset->set_tooltip_text(RTR("Zoom Reset")); zoom_reset->connect("pressed", callable_mp(this, &GraphEdit::_zoom_reset)); zoom_reset->set_focus_mode(FOCUS_NONE); zoom_plus = memnew(Button); zoom_plus->set_flat(true); zoom_hb->add_child(zoom_plus); - zoom_plus->set_tooltip(RTR("Zoom In")); + zoom_plus->set_tooltip_text(RTR("Zoom In")); zoom_plus->connect("pressed", callable_mp(this, &GraphEdit::_zoom_plus)); zoom_plus->set_focus_mode(FOCUS_NONE); snap_button = memnew(Button); snap_button->set_flat(true); snap_button->set_toggle_mode(true); - snap_button->set_tooltip(RTR("Enable snap and show grid.")); + snap_button->set_tooltip_text(RTR("Enable snap and show grid.")); snap_button->connect("pressed", callable_mp(this, &GraphEdit::_snap_toggled)); snap_button->set_pressed(true); snap_button->set_focus_mode(FOCUS_NONE); @@ -2502,7 +2533,7 @@ GraphEdit::GraphEdit() { minimap_button = memnew(Button); minimap_button->set_flat(true); minimap_button->set_toggle_mode(true); - minimap_button->set_tooltip(RTR("Enable grid minimap.")); + minimap_button->set_tooltip_text(RTR("Enable grid minimap.")); minimap_button->connect("pressed", callable_mp(this, &GraphEdit::_minimap_toggled)); minimap_button->set_pressed(true); minimap_button->set_focus_mode(FOCUS_NONE); @@ -2511,7 +2542,7 @@ GraphEdit::GraphEdit() { layout_button = memnew(Button); layout_button->set_flat(true); zoom_hb->add_child(layout_button); - layout_button->set_tooltip(RTR("Arrange nodes.")); + layout_button->set_tooltip_text(RTR("Arrange nodes.")); layout_button->connect("pressed", callable_mp(this, &GraphEdit::arrange_nodes)); layout_button->set_focus_mode(FOCUS_NONE); diff --git a/scene/gui/graph_edit.h b/scene/gui/graph_edit.h index b8c9be9983..0a0676699f 100644 --- a/scene/gui/graph_edit.h +++ b/scene/gui/graph_edit.h @@ -133,6 +133,8 @@ private: void _pan_callback(Vector2 p_scroll_vec); void _zoom_callback(Vector2 p_scroll_vec, Vector2 p_origin, bool p_alt); + bool arrange_nodes_button_hidden = false; + bool connecting = false; String connecting_from; bool connecting_out = false; @@ -323,6 +325,9 @@ public: void set_minimap_enabled(bool p_enable); bool is_minimap_enabled() const; + void set_arrange_nodes_button_hidden(bool p_enable); + bool is_arrange_nodes_button_hidden() const; + GraphEditFilter *get_top_layer() const { return top_layer; } GraphEditMinimap *get_minimap() const { return minimap; } void get_connection_list(List<Connection> *r_connections) const; diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp index 7d31e929dc..b07d401e6b 100644 --- a/scene/gui/graph_node.cpp +++ b/scene/gui/graph_node.cpp @@ -1003,6 +1003,22 @@ bool GraphNode::is_resizable() const { return resizable; } +void GraphNode::set_draggable(bool p_draggable) { + draggable = p_draggable; +} + +bool GraphNode::is_draggable() { + return draggable; +} + +void GraphNode::set_selectable(bool p_selectable) { + selectable = p_selectable; +} + +bool GraphNode::is_selectable() { + return selectable; +} + Vector<int> GraphNode::get_allowed_size_flags_horizontal() const { Vector<int> flags; flags.append(SIZE_FILL); @@ -1064,6 +1080,12 @@ void GraphNode::_bind_methods() { ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &GraphNode::set_resizable); ClassDB::bind_method(D_METHOD("is_resizable"), &GraphNode::is_resizable); + ClassDB::bind_method(D_METHOD("set_draggable", "draggable"), &GraphNode::set_draggable); + ClassDB::bind_method(D_METHOD("is_draggable"), &GraphNode::is_draggable); + + ClassDB::bind_method(D_METHOD("set_selectable", "selectable"), &GraphNode::set_selectable); + ClassDB::bind_method(D_METHOD("is_selectable"), &GraphNode::is_selectable); + ClassDB::bind_method(D_METHOD("set_selected", "selected"), &GraphNode::set_selected); ClassDB::bind_method(D_METHOD("is_selected"), &GraphNode::is_selected); @@ -1089,6 +1111,8 @@ void GraphNode::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "position_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_position_offset", "get_position_offset"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_close"), "set_show_close_button", "is_close_button_visible"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable"), "set_resizable", "is_resizable"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "draggable"), "set_draggable", "is_draggable"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selectable"), "set_selectable", "is_selectable"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "selected"), "set_selected", "is_selected"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "comment"), "set_comment", "is_comment"); ADD_PROPERTY(PropertyInfo(Variant::INT, "overlay", PROPERTY_HINT_ENUM, "Disabled,Breakpoint,Position"), "set_overlay", "get_overlay"); diff --git a/scene/gui/graph_node.h b/scene/gui/graph_node.h index d575b6ceed..9c8f926403 100644 --- a/scene/gui/graph_node.h +++ b/scene/gui/graph_node.h @@ -67,6 +67,8 @@ private: Vector2 position_offset; bool comment = false; bool resizable = false; + bool draggable = true; + bool selectable = true; bool resizing = false; Vector2 resizing_from; @@ -183,6 +185,12 @@ public: void set_resizable(bool p_enable); bool is_resizable() const; + void set_draggable(bool p_draggable); + bool is_draggable(); + + void set_selectable(bool p_selectable); + bool is_selectable(); + virtual Size2 get_minimum_size() const override; virtual Vector<int> get_allowed_size_flags_horizontal() const override; diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index 7a88afaa3b..b15578f222 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -279,8 +279,8 @@ void Label::_notification(int p_what) { return; // Nothing new. } xl_text = new_text; - if (percent_visible < 1) { - visible_chars = get_total_character_count() * percent_visible; + if (visible_ratio < 1) { + visible_chars = get_total_character_count() * visible_ratio; } dirty = true; @@ -348,7 +348,7 @@ void Label::_notification(int p_what) { total_h += TS->shaped_text_get_size(lines_rid[i]).y + line_spacing; total_glyphs += TS->shaped_text_get_glyph_count(lines_rid[i]) + TS->shaped_text_get_ellipsis_glyph_count(lines_rid[i]); } - int visible_glyphs = total_glyphs * percent_visible; + int visible_glyphs = total_glyphs * visible_ratio; int processed_glyphs = 0; total_h += style->get_margin(SIDE_TOP) + style->get_margin(SIDE_BOTTOM); @@ -652,8 +652,8 @@ void Label::set_text(const String &p_string) { text = p_string; xl_text = atr(p_string); dirty = true; - if (percent_visible < 1) { - visible_chars = get_total_character_count() * percent_visible; + if (visible_ratio < 1) { + visible_chars = get_total_character_count() * visible_ratio; } update(); update_minimum_size(); @@ -771,9 +771,9 @@ void Label::set_visible_characters(int p_amount) { if (visible_chars != p_amount) { visible_chars = p_amount; if (get_total_character_count() > 0) { - percent_visible = (float)p_amount / (float)get_total_character_count(); + visible_ratio = (float)p_amount / (float)get_total_character_count(); } else { - percent_visible = 1.0; + visible_ratio = 1.0; } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { dirty = true; @@ -786,17 +786,17 @@ int Label::get_visible_characters() const { return visible_chars; } -void Label::set_percent_visible(float p_percent) { - if (percent_visible != p_percent) { - if (percent_visible >= 1.0) { +void Label::set_visible_ratio(float p_ratio) { + if (visible_ratio != p_ratio) { + if (visible_ratio >= 1.0) { visible_chars = -1; - percent_visible = 1.0; - } else if (percent_visible < 0.0) { + visible_ratio = 1.0; + } else if (visible_ratio < 0.0) { visible_chars = 0; - percent_visible = 0.0; + visible_ratio = 0.0; } else { - visible_chars = get_total_character_count() * p_percent; - percent_visible = p_percent; + visible_chars = get_total_character_count() * p_ratio; + visible_ratio = p_ratio; } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { @@ -806,8 +806,8 @@ void Label::set_percent_visible(float p_percent) { } } -float Label::get_percent_visible() const { - return percent_visible; +float Label::get_visible_ratio() const { + return visible_ratio; } TextServer::VisibleCharactersBehavior Label::get_visible_characters_behavior() const { @@ -889,8 +889,8 @@ void Label::_bind_methods() { ClassDB::bind_method(D_METHOD("get_visible_characters"), &Label::get_visible_characters); ClassDB::bind_method(D_METHOD("get_visible_characters_behavior"), &Label::get_visible_characters_behavior); ClassDB::bind_method(D_METHOD("set_visible_characters_behavior", "behavior"), &Label::set_visible_characters_behavior); - ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &Label::set_percent_visible); - ClassDB::bind_method(D_METHOD("get_percent_visible"), &Label::get_percent_visible); + ClassDB::bind_method(D_METHOD("set_visible_ratio", "ratio"), &Label::set_visible_ratio); + ClassDB::bind_method(D_METHOD("get_visible_ratio"), &Label::get_visible_ratio); ClassDB::bind_method(D_METHOD("set_lines_skipped", "lines_skipped"), &Label::set_lines_skipped); ClassDB::bind_method(D_METHOD("get_lines_skipped"), &Label::get_lines_skipped); ClassDB::bind_method(D_METHOD("set_max_lines_visible", "lines_visible"), &Label::set_max_lines_visible); @@ -911,10 +911,10 @@ void Label::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "lines_skipped", PROPERTY_HINT_RANGE, "0,999,1"), "set_lines_skipped", "get_lines_skipped"); ADD_PROPERTY(PropertyInfo(Variant::INT, "max_lines_visible", PROPERTY_HINT_RANGE, "-1,999,1"), "set_max_lines_visible", "get_max_lines_visible"); - // Note: "visible_characters" and "percent_visible" should be set after "text" to be correctly applied. + // Note: "visible_characters" and "visible_ratio" should be set after "text" to be correctly applied. ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visible_ratio", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_visible_ratio", "get_visible_ratio"); ADD_GROUP("BiDi", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left,Inherited"), "set_text_direction", "get_text_direction"); diff --git a/scene/gui/label.h b/scene/gui/label.h index cab5b36d68..65831cab6e 100644 --- a/scene/gui/label.h +++ b/scene/gui/label.h @@ -59,10 +59,9 @@ private: TextServer::StructuredTextParser st_parser = TextServer::STRUCTURED_TEXT_DEFAULT; Array st_args; - float percent_visible = 1.0; - TextServer::VisibleCharactersBehavior visible_chars_behavior = TextServer::VC_CHARS_BEFORE_SHAPING; int visible_chars = -1; + float visible_ratio = 1.0; int lines_skipped = 0; int max_lines_visible = -1; @@ -110,22 +109,22 @@ public: void set_uppercase(bool p_uppercase); bool is_uppercase() const; - TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const; void set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior); + TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const; void set_visible_characters(int p_amount); int get_visible_characters() const; int get_total_character_count() const; + void set_visible_ratio(float p_ratio); + float get_visible_ratio() const; + void set_clip_text(bool p_clip); bool is_clipping_text() const; void set_text_overrun_behavior(TextServer::OverrunBehavior p_behavior); TextServer::OverrunBehavior get_text_overrun_behavior() const; - void set_percent_visible(float p_percent); - float get_percent_visible() const; - void set_lines_skipped(int p_lines); int get_lines_skipped() const; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index cc39b0e57a..34a60b907c 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -718,7 +718,7 @@ void LineEdit::_notification(int p_what) { case NOTIFICATION_RESIZED: { _fit_to_width(); - scroll_offset = 0; + scroll_offset = 0.0; set_caret_column(get_caret_column()); } break; @@ -801,7 +801,7 @@ void LineEdit::_notification(int p_what) { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - (text_width)) / 2); @@ -846,7 +846,7 @@ void LineEdit::_notification(int p_what) { r_icon->draw(ci, Point2(width - r_icon->get_width() - style->get_margin(SIDE_RIGHT), height / 2 - r_icon->get_height() / 2), color_icon); if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(size.width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1208,7 +1208,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - (text_width)) / 2); @@ -1228,7 +1228,7 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) { if (right_icon.is_valid() || display_clear_icon) { Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon; if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1236,11 +1236,11 @@ void LineEdit::set_caret_at_pixel_pos(int p_x) { } } - int ofs = TS->shaped_text_hit_test_position(text_rid, p_x - x_ofs - scroll_offset); + int ofs = ceil(TS->shaped_text_hit_test_position(text_rid, p_x - x_ofs - scroll_offset)); set_caret_column(ofs); } -Vector2i LineEdit::get_caret_pixel_pos() { +Vector2 LineEdit::get_caret_pixel_pos() { Ref<StyleBox> style = get_theme_stylebox(SNAME("normal")); bool rtl = is_layout_rtl(); @@ -1256,7 +1256,7 @@ Vector2i LineEdit::get_caret_pixel_pos() { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - (text_width)) / 2); @@ -1276,7 +1276,7 @@ Vector2i LineEdit::get_caret_pixel_pos() { if (right_icon.is_valid() || display_clear_icon) { Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon; if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1284,7 +1284,7 @@ Vector2i LineEdit::get_caret_pixel_pos() { } } - Vector2i ret; + Vector2 ret; CaretInfo caret; // Get position of the start of caret. if (ime_text.length() != 0 && ime_selection.x != 0) { @@ -1427,7 +1427,7 @@ void LineEdit::set_text(String p_text) { update(); caret_column = 0; - scroll_offset = 0; + scroll_offset = 0.0; } void LineEdit::set_text_direction(Control::TextDirection p_text_direction) { @@ -1555,7 +1555,7 @@ void LineEdit::set_caret_column(int p_column) { // Fit to window. if (!is_inside_tree()) { - scroll_offset = 0; + scroll_offset = 0.0; return; } @@ -1574,7 +1574,7 @@ void LineEdit::set_caret_column(int p_column) { } } break; case HORIZONTAL_ALIGNMENT_CENTER: { - if (scroll_offset != 0) { + if (!Math::is_zero_approx(scroll_offset)) { x_ofs = style->get_offset().x; } else { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - (text_width)) / 2); @@ -1595,7 +1595,7 @@ void LineEdit::set_caret_column(int p_column) { if (right_icon.is_valid() || display_clear_icon) { Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon(SNAME("clear")) : right_icon; if (alignment == HORIZONTAL_ALIGNMENT_CENTER) { - if (scroll_offset == 0) { + if (Math::is_zero_approx(scroll_offset)) { x_ofs = MAX(style->get_margin(SIDE_LEFT), int(get_size().width - text_width - r_icon->get_width() - style->get_margin(SIDE_RIGHT) * 2) / 2); } } else { @@ -1605,12 +1605,12 @@ void LineEdit::set_caret_column(int p_column) { } // Note: Use two coordinates to fit IME input range. - Vector2i primary_catret_offset = get_caret_pixel_pos(); + Vector2 primary_caret_offset = get_caret_pixel_pos(); - if (MIN(primary_catret_offset.x, primary_catret_offset.y) <= x_ofs) { - scroll_offset += (x_ofs - MIN(primary_catret_offset.x, primary_catret_offset.y)); - } else if (MAX(primary_catret_offset.x, primary_catret_offset.y) >= ofs_max) { - scroll_offset += (ofs_max - MAX(primary_catret_offset.x, primary_catret_offset.y)); + if (MIN(primary_caret_offset.x, primary_caret_offset.y) <= x_ofs) { + scroll_offset += x_ofs - MIN(primary_caret_offset.x, primary_caret_offset.y); + } else if (MAX(primary_caret_offset.x, primary_caret_offset.y) >= ofs_max) { + scroll_offset += ofs_max - MAX(primary_caret_offset.x, primary_caret_offset.y); } scroll_offset = MIN(0, scroll_offset); @@ -1621,14 +1621,14 @@ int LineEdit::get_caret_column() const { return caret_column; } -void LineEdit::set_scroll_offset(int p_pos) { +void LineEdit::set_scroll_offset(float p_pos) { scroll_offset = p_pos; - if (scroll_offset < 0) { - scroll_offset = 0; + if (scroll_offset < 0.0) { + scroll_offset = 0.0; } } -int LineEdit::get_scroll_offset() const { +float LineEdit::get_scroll_offset() const { return scroll_offset; } @@ -1656,7 +1656,7 @@ void LineEdit::clear_internal() { deselect(); _clear_undo_stack(); caret_column = 0; - scroll_offset = 0; + scroll_offset = 0.0; undo_text = ""; text = ""; _shape(); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 254f842b66..dabdaa3395 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -113,7 +113,7 @@ private: bool caret_mid_grapheme_enabled = true; int caret_column = 0; - int scroll_offset = 0; + float scroll_offset = 0.0; int max_length = 0; // 0 for no maximum. String language; @@ -153,8 +153,7 @@ private: struct TextOperation { int caret_column = 0; - int scroll_offset = 0; - int cached_width = 0; + float scroll_offset = 0.0; String text; }; List<TextOperation> undo_stack; @@ -192,11 +191,11 @@ private: void shift_selection_check_post(bool); void selection_fill_at_caret(); - void set_scroll_offset(int p_pos); - int get_scroll_offset() const; + void set_scroll_offset(float p_pos); + float get_scroll_offset() const; void set_caret_at_pixel_pos(int p_x); - Vector2i get_caret_pixel_pos(); + Vector2 get_caret_pixel_pos(); void _reset_caret_blink_timer(); void _toggle_draw_caret(); diff --git a/scene/gui/menu_bar.cpp b/scene/gui/menu_bar.cpp index f450222130..9eba2feaf7 100644 --- a/scene/gui/menu_bar.cpp +++ b/scene/gui/menu_bar.cpp @@ -276,10 +276,7 @@ void MenuBar::_update_submenu(const String &p_menu_name, PopupMenu *p_child) { } bool MenuBar::is_native_menu() const { - if (!is_visible_in_tree()) { - return false; - } - if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root()->is_ancestor_of(this) || get_tree()->get_edited_scene_root() == this)) { + if (Engine::get_singleton()->is_editor_hint() && is_inside_tree() && get_tree()->get_edited_scene_root() && (get_tree()->get_edited_scene_root()->is_ancestor_of(this) || get_tree()->get_edited_scene_root() == this)) { return false; } @@ -308,7 +305,7 @@ void MenuBar::_clear_menu() { void MenuBar::_update_menu() { _clear_menu(); - if (!is_inside_tree()) { + if (!is_visible_in_tree()) { return; } diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index a03db82332..e6e17cc881 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -86,6 +86,11 @@ void MenuButton::_popup_visibility_changed(bool p_visible) { } void MenuButton::pressed() { + if (popup->is_visible()) { + popup->hide(); + return; + } + emit_signal(SNAME("about_to_popup")); Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); @@ -103,11 +108,7 @@ void MenuButton::pressed() { popup->set_current_index(0); } - if (popup->is_visible()) { - popup->hide(); - } else { - popup->popup(); - } + popup->popup(); } void MenuButton::gui_input(const Ref<InputEvent> &p_event) { diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp index 931dffe3bb..881acdbf3a 100644 --- a/scene/gui/option_button.cpp +++ b/scene/gui/option_button.cpp @@ -198,6 +198,11 @@ void OptionButton::_selected(int p_which) { } void OptionButton::pressed() { + if (popup->is_visible()) { + popup->hide(); + return; + } + Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale(); popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y)); popup->set_size(Size2(size.width, 0)); diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index c4396f636a..7461f48a6c 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -240,8 +240,7 @@ void PopupPanel::_notification(int p_what) { panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), get_class_name())); } break; - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_READY: { + case NOTIFICATION_ENTER_TREE: { panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), get_class_name())); _update_child_rects(); } break; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 6ab3cdcb69..3f1f16cd51 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -742,7 +742,7 @@ int RichTextLabel::_draw_line(ItemFrame *p_frame, int p_line, const Vector2 &p_o bool trim_glyphs_ltr = (visible_characters >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_LTR) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && !lrtl)); bool trim_glyphs_rtl = (visible_characters >= 0) && ((visible_chars_behavior == TextServer::VC_GLYPHS_RTL) || ((visible_chars_behavior == TextServer::VC_GLYPHS_AUTO) && lrtl)); int total_glyphs = (trim_glyphs_ltr || trim_glyphs_rtl) ? get_total_glyph_count() : 0; - int visible_glyphs = total_glyphs * percent_visible; + int visible_glyphs = total_glyphs * visible_ratio; Vector<int> list_index; Vector<ItemList *> list_items; @@ -4940,19 +4940,19 @@ TextServer::AutowrapMode RichTextLabel::get_autowrap_mode() const { return autowrap_mode; } -void RichTextLabel::set_percent_visible(float p_percent) { - if (percent_visible != p_percent) { +void RichTextLabel::set_visible_ratio(float p_ratio) { + if (visible_ratio != p_ratio) { _stop_thread(); - if (percent_visible >= 1.0) { + if (visible_ratio >= 1.0) { visible_characters = -1; - percent_visible = 1.0; - } else if (percent_visible < 0.0) { + visible_ratio = 1.0; + } else if (visible_ratio < 0.0) { visible_characters = 0; - percent_visible = 0.0; + visible_ratio = 0.0; } else { - visible_characters = get_total_character_count() * p_percent; - percent_visible = p_percent; + visible_characters = get_total_character_count() * p_ratio; + visible_ratio = p_ratio; } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { @@ -4963,8 +4963,8 @@ void RichTextLabel::set_percent_visible(float p_percent) { } } -float RichTextLabel::get_percent_visible() const { - return percent_visible; +float RichTextLabel::get_visible_ratio() const { + return visible_ratio; } void RichTextLabel::set_effects(Array p_effects) { @@ -5139,8 +5139,8 @@ void RichTextLabel::_bind_methods() { ClassDB::bind_method(D_METHOD("get_visible_characters_behavior"), &RichTextLabel::get_visible_characters_behavior); ClassDB::bind_method(D_METHOD("set_visible_characters_behavior", "behavior"), &RichTextLabel::set_visible_characters_behavior); - ClassDB::bind_method(D_METHOD("set_percent_visible", "percent_visible"), &RichTextLabel::set_percent_visible); - ClassDB::bind_method(D_METHOD("get_percent_visible"), &RichTextLabel::get_percent_visible); + ClassDB::bind_method(D_METHOD("set_visible_ratio", "ratio"), &RichTextLabel::set_visible_ratio); + ClassDB::bind_method(D_METHOD("get_visible_ratio"), &RichTextLabel::get_visible_ratio); ClassDB::bind_method(D_METHOD("get_character_line", "character"), &RichTextLabel::get_character_line); ClassDB::bind_method(D_METHOD("get_character_paragraph", "character"), &RichTextLabel::get_character_paragraph); @@ -5189,10 +5189,10 @@ void RichTextLabel::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hint_underlined"), "set_hint_underline", "is_hint_underlined"); ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); - // Note: "visible_characters" and "percent_visible" should be set after "text" to be correctly applied. + // Note: "visible_characters" and "visible_ratio" should be set after "text" to be correctly applied. ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters", PROPERTY_HINT_RANGE, "-1,128000,1"), "set_visible_characters", "get_visible_characters"); ADD_PROPERTY(PropertyInfo(Variant::INT, "visible_characters_behavior", PROPERTY_HINT_ENUM, "Characters Before Shaping,Characters After Shaping,Glyphs (Layout Direction),Glyphs (Left-to-Right),Glyphs (Right-to-Left)"), "set_visible_characters_behavior", "get_visible_characters_behavior"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "percent_visible", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_percent_visible", "get_percent_visible"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "visible_ratio", PROPERTY_HINT_RANGE, "0,1,0.001"), "set_visible_ratio", "get_visible_ratio"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "context_menu_enabled"), "set_context_menu_enabled", "is_context_menu_enabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shortcut_keys_enabled"), "set_shortcut_keys_enabled", "is_shortcut_keys_enabled"); @@ -5264,11 +5264,11 @@ void RichTextLabel::set_visible_characters(int p_visible) { visible_characters = p_visible; if (p_visible == -1) { - percent_visible = 1; + visible_ratio = 1; } else { int total_char_count = get_total_character_count(); if (total_char_count > 0) { - percent_visible = (float)p_visible / (float)total_char_count; + visible_ratio = (float)p_visible / (float)total_char_count; } } if (visible_chars_behavior == TextServer::VC_CHARS_BEFORE_SHAPING) { diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 95e55bf1a1..79f9c62539 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -440,7 +440,7 @@ private: void _menu_option(int p_option); int visible_characters = -1; - float percent_visible = 1.0; + float visible_ratio = 1.0; TextServer::VisibleCharactersBehavior visible_chars_behavior = TextServer::VC_CHARS_BEFORE_SHAPING; bool _is_click_inside_selection() const; @@ -660,8 +660,8 @@ public: int get_total_character_count() const; int get_total_glyph_count() const; - void set_percent_visible(float p_percent); - float get_percent_visible() const; + void set_visible_ratio(float p_ratio); + float get_visible_ratio() const; TextServer::VisibleCharactersBehavior get_visible_characters_behavior() const; void set_visible_characters_behavior(TextServer::VisibleCharactersBehavior p_behavior); diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp index 8fd547813d..f58cb0fe70 100644 --- a/scene/gui/scroll_container.cpp +++ b/scene/gui/scroll_container.cpp @@ -317,10 +317,9 @@ void ScrollContainer::_reposition_children() { void ScrollContainer::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: - case NOTIFICATION_THEME_CHANGED: case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: - case NOTIFICATION_TRANSLATION_CHANGED: { + case NOTIFICATION_TRANSLATION_CHANGED: + case NOTIFICATION_THEME_CHANGED: { _updating_scrollbars = true; call_deferred(SNAME("_update_scrollbar_position")); } break; diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp index 517c83545c..65c4a09c84 100644 --- a/scene/gui/spin_box.cpp +++ b/scene/gui/spin_box.cpp @@ -41,12 +41,16 @@ Size2 SpinBox::get_minimum_size() const { void SpinBox::_value_changed(double p_value) { String value = TS->format_number(String::num(get_value(), Math::range_step_decimals(get_step()))); - if (!prefix.is_empty()) { - value = prefix + " " + value; - } - if (!suffix.is_empty()) { - value += " " + suffix; + + if (!line_edit->has_focus()) { + if (!prefix.is_empty()) { + value = prefix + " " + value; + } + if (!suffix.is_empty()) { + value += " " + suffix; + } } + line_edit->set_text(value); Range::_value_changed(p_value); } @@ -105,8 +109,9 @@ void SpinBox::_range_click_timeout() { void SpinBox::_release_mouse() { if (drag.enabled) { drag.enabled = false; - Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_HIDDEN); warp_mouse(drag.capture_pos); + Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE); } } @@ -181,8 +186,14 @@ void SpinBox::gui_input(const Ref<InputEvent> &p_event) { } } +void SpinBox::_line_edit_focus_enter() { + int col = line_edit->get_caret_column(); + _value_changed(0); // Update the LineEdit's text. + line_edit->set_caret_column(col); +} + void SpinBox::_line_edit_focus_exit() { - // discontinue because the focus_exit was caused by right-click context menu + // Discontinue because the focus_exit was caused by right-click context menu. if (line_edit->is_menu_visible()) { return; } @@ -346,6 +357,7 @@ SpinBox::SpinBox() { line_edit->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_LEFT); line_edit->connect("text_submitted", callable_mp(this, &SpinBox::_text_submitted), CONNECT_DEFERRED); + line_edit->connect("focus_entered", callable_mp(this, &SpinBox::_line_edit_focus_enter), CONNECT_DEFERRED); line_edit->connect("focus_exited", callable_mp(this, &SpinBox::_line_edit_focus_exit), CONNECT_DEFERRED); line_edit->connect("gui_input", callable_mp(this, &SpinBox::_line_edit_input)); diff --git a/scene/gui/spin_box.h b/scene/gui/spin_box.h index 0aae9efe78..3fcb85ac99 100644 --- a/scene/gui/spin_box.h +++ b/scene/gui/spin_box.h @@ -64,6 +64,7 @@ class SpinBox : public Range { double diff_y = 0.0; } drag; + void _line_edit_focus_enter(); void _line_edit_focus_exit(); inline void _adjust_width_for_icon(const Ref<Texture2D> &icon); diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp index b6073ce265..3e60db0846 100644 --- a/scene/gui/split_container.cpp +++ b/scene/gui/split_container.cpp @@ -97,16 +97,12 @@ void SplitContainer::_resort() { // Compute the final middle separation. middle_sep = no_offset_middle_sep; - if (prev_no_offset_middle_sep != INT_MAX) { - split_offset -= middle_sep - prev_no_offset_middle_sep; - } - prev_no_offset_middle_sep = middle_sep; - if (!collapsed) { int clamped_split_offset = CLAMP(split_offset, ms_first[axis] - no_offset_middle_sep, (get_size()[axis] - ms_second[axis] - sep) - no_offset_middle_sep); middle_sep += clamped_split_offset; if (should_clamp_split_offset) { split_offset = clamped_split_offset; + should_clamp_split_offset = false; } } diff --git a/scene/gui/split_container.h b/scene/gui/split_container.h index dd15362199..a69ffe4de9 100644 --- a/scene/gui/split_container.h +++ b/scene/gui/split_container.h @@ -47,7 +47,6 @@ private: bool should_clamp_split_offset = false; int split_offset = 0; int middle_sep = 0; - int prev_no_offset_middle_sep = INT_MAX; bool vertical = false; bool dragging = false; int drag_from = 0; diff --git a/scene/gui/video_stream_player.cpp b/scene/gui/video_stream_player.cpp index 7baa4d44aa..4024d4c80e 100644 --- a/scene/gui/video_stream_player.cpp +++ b/scene/gui/video_stream_player.cpp @@ -362,7 +362,7 @@ void VideoStreamPlayer::set_volume_db(float p_db) { if (p_db < -79) { set_volume(0); } else { - set_volume(Math::db2linear(p_db)); + set_volume(Math::db_to_linear(p_db)); } } @@ -370,7 +370,7 @@ float VideoStreamPlayer::get_volume_db() const { if (volume == 0) { return -80; } else { - return Math::linear2db(volume); + return Math::linear_to_db(volume); } } diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index dcf506aafa..515f4d88a6 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -587,6 +587,12 @@ void CanvasItem::draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, RenderingServer::get_singleton()->canvas_item_add_msdf_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate, p_outline, p_pixel_range); } +void CanvasItem::draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate) { + ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); + ERR_FAIL_COND(p_texture.is_null()); + RenderingServer::get_singleton()->canvas_item_add_lcd_texture_rect_region(canvas_item, p_rect, p_texture->get_rid(), p_src_rect, p_modulate); +} + void CanvasItem::draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); @@ -919,6 +925,7 @@ void CanvasItem::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_texture_rect", "texture", "rect", "tile", "modulate", "transpose"), &CanvasItem::draw_texture_rect, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("draw_texture_rect_region", "texture", "rect", "src_rect", "modulate", "transpose", "clip_uv"), &CanvasItem::draw_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("draw_msdf_texture_rect_region", "texture", "rect", "src_rect", "modulate", "outline", "pixel_range"), &CanvasItem::draw_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1, 1)), DEFVAL(0.0), DEFVAL(4.0)); + ClassDB::bind_method(D_METHOD("draw_lcd_texture_rect_region", "texture", "rect", "src_rect", "modulate"), &CanvasItem::draw_lcd_texture_rect_region, DEFVAL(Color(1, 1, 1, 1))); ClassDB::bind_method(D_METHOD("draw_style_box", "style_box", "rect"), &CanvasItem::draw_style_box); ClassDB::bind_method(D_METHOD("draw_primitive", "points", "colors", "uvs", "texture", "width"), &CanvasItem::draw_primitive, DEFVAL(Ref<Texture2D>()), DEFVAL(1.0)); ClassDB::bind_method(D_METHOD("draw_polygon", "points", "colors", "uvs", "texture"), &CanvasItem::draw_polygon, DEFVAL(PackedVector2Array()), DEFVAL(Ref<Texture2D>())); diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 38e0be1683..1e0d4552ce 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -226,6 +226,7 @@ public: void draw_texture_rect(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void draw_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void draw_msdf_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), double p_outline = 0.0, double p_pixel_range = 4.0); + void draw_lcd_texture_rect_region(const Ref<Texture2D> &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)); void draw_style_box(const Ref<StyleBox> &p_style_box, const Rect2 &p_rect); void draw_primitive(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, Ref<Texture2D> p_texture = Ref<Texture2D>(), real_t p_width = 1); void draw_polygon(const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), Ref<Texture2D> p_texture = Ref<Texture2D>()); diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 9773218574..cc3d14e5be 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -948,6 +948,21 @@ String Node::validate_child_name(Node *p_child) { } #endif +String Node::adjust_name_casing(const String &p_name) { + switch (GLOBAL_GET("editor/node_naming/name_casing").operator int()) { + case NAME_CASING_PASCAL_CASE: + return p_name.capitalize().replace(" ", ""); + case NAME_CASING_CAMEL_CASE: { + String name = p_name.capitalize().replace(" ", ""); + name[0] = name.to_lower()[0]; + return name; + } + case NAME_CASING_SNAKE_CASE: + return p_name.capitalize().replace(" ", "_").to_lower(); + } + return p_name; +} + void Node::_validate_child_name(Node *p_child, bool p_force_human_readable) { /* Make sure the name is unique */ @@ -1021,19 +1036,8 @@ void Node::_generate_serial_child_name(const Node *p_child, StringName &name) co //no name and a new name is needed, create one. name = p_child->get_class(); - // Adjust casing according to project setting. The current type name is expected to be in PascalCase. - switch (ProjectSettings::get_singleton()->get("editor/node_naming/name_casing").operator int()) { - case NAME_CASING_PASCAL_CASE: - break; - case NAME_CASING_CAMEL_CASE: { - String n = name; - n[0] = n.to_lower()[0]; - name = n; - } break; - case NAME_CASING_SNAKE_CASE: - name = String(name).camelcase_to_underscore(true); - break; - } + // Adjust casing according to project setting. + name = adjust_name_casing(name); } //quickly test if proposed name exists diff --git a/scene/main/node.h b/scene/main/node.h index 52ccf3d825..703c580d3f 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -459,6 +459,7 @@ public: #ifdef TOOLS_ENABLED String validate_child_name(Node *p_child); #endif + static String adjust_name_casing(const String &p_name); void queue_delete(); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 36cc8ebfa2..a5a4e29186 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -1104,7 +1104,7 @@ Vector2 Viewport::get_mouse_position() const { void Viewport::warp_mouse(const Vector2 &p_position) { Transform2D xform = get_screen_transform(); - Vector2 gpos = xform.xform(p_position).round(); + Vector2 gpos = xform.xform(p_position); Input::get_singleton()->warp_mouse(gpos); } @@ -1709,15 +1709,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) { is_tooltip_shown = true; } } else { - Variant t = gui.tooltip_popup->call("get_tooltip_text"); - - if (t.get_type() == Variant::STRING) { - if (tooltip == String(t)) { - is_tooltip_shown = true; - } - } else { - is_tooltip_shown = true; // Nothing to compare against, likely using custom control, so if it changes there is nothing we can do. - } + is_tooltip_shown = true; // Nothing to compare against, likely using custom control, so if it changes there is nothing we can do. } } else { _gui_cancel_tooltip(); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index a0ec2d54dd..83083cd65a 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -563,7 +563,7 @@ public: bool is_input_disabled() const; Vector2 get_mouse_position() const; - void warp_mouse(const Vector2 &p_position); + virtual void warp_mouse(const Vector2 &p_position); void set_physics_object_picking(bool p_enable); bool get_physics_object_picking(); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index bf50ca0956..1b7aa787e7 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -848,21 +848,13 @@ void Window::_notification(int p_what) { RS::get_singleton()->viewport_set_active(get_viewport_rid(), true); } - if (theme.is_null()) { - Control *parent_c = cast_to<Control>(get_parent()); - if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { - theme_owner = parent_c->data.theme_owner; - theme_owner_window = parent_c->data.theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } else { - Window *parent_w = cast_to<Window>(get_parent()); - if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { - theme_owner = parent_w->theme_owner; - theme_owner_window = parent_w->theme_owner_window; - notification(NOTIFICATION_THEME_CHANGED); - } - } - } + // Need to defer here, because theme owner information might be set in + // add_child_notify, which doesn't get called until right after this. + call_deferred(SNAME("notification"), NOTIFICATION_THEME_CHANGED); + } break; + + case NOTIFICATION_THEME_CHANGED: { + emit_signal(SceneStringNames::get_singleton()->theme_changed); } break; case NOTIFICATION_READY: { @@ -974,6 +966,18 @@ DisplayServer::WindowID Window::get_window_id() const { return window_id; } +void Window::warp_mouse(const Vector2 &p_position) { + Transform2D xform = get_screen_transform(); + Vector2 gpos = xform.xform(p_position); + + if (transient_parent && !transient_parent->is_embedding_subwindows()) { + Transform2D window_trans = Transform2D().translated(get_position() + (transient_parent->get_visible_rect().size - transient_parent->get_real_size())); + gpos = window_trans.xform(gpos); + } + + Input::get_singleton()->warp_mouse(gpos); +} + void Window::set_wrap_controls(bool p_enable) { wrap_controls = p_enable; if (wrap_controls) { @@ -1250,16 +1254,10 @@ Rect2i Window::get_usable_parent_rect() const { } void Window::add_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && child_c->data.theme.is_null() && (theme_owner || theme_owner_window)) { - Control::_propagate_theme_changed(child_c, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && child_w->theme.is_null() && (theme_owner || theme_owner_window)) { - Control::_propagate_theme_changed(child_w, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff + // We propagate when this node uses a custom theme, so it can pass it on to its children. + if (theme_owner || theme_owner_window) { + // `p_notify` is false here as `NOTIFICATION_THEME_CHANGED` will be handled by `NOTIFICATION_ENTER_TREE`. + Control::_propagate_theme_changed(this, theme_owner, theme_owner_window, false, true); } if (is_inside_tree() && wrap_controls) { @@ -1268,16 +1266,9 @@ void Window::add_child_notify(Node *p_child) { } void Window::remove_child_notify(Node *p_child) { - Control *child_c = Object::cast_to<Control>(p_child); - - if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) { - Control::_propagate_theme_changed(child_c, nullptr, nullptr); - } - - Window *child_w = Object::cast_to<Window>(p_child); - - if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) { - Control::_propagate_theme_changed(child_w, nullptr, nullptr); + // If the removed child isn't inheriting any theme items through this node, then there's no need to propagate. + if (theme_owner || theme_owner_window) { + Control::_propagate_theme_changed(this, nullptr, nullptr, false, true); } if (is_inside_tree() && wrap_controls) { @@ -1290,34 +1281,47 @@ void Window::set_theme(const Ref<Theme> &p_theme) { return; } + if (theme.is_valid()) { + theme->disconnect("changed", callable_mp(this, &Window::_theme_changed)); + } + theme = p_theme; + if (theme.is_valid()) { + Control::_propagate_theme_changed(this, nullptr, this, is_inside_tree(), true); + theme->connect("changed", callable_mp(this, &Window::_theme_changed), CONNECT_DEFERRED); + return; + } - if (!p_theme.is_null()) { - theme_owner = nullptr; - theme_owner_window = this; - Control::_propagate_theme_changed(this, nullptr, this); - } else { - Control *parent_c = cast_to<Control>(get_parent()); - if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window); - } else { - Window *parent_w = cast_to<Window>(get_parent()); - if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { - Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window); - } else { - Control::_propagate_theme_changed(this, nullptr, nullptr); - } - } + Control *parent_c = Object::cast_to<Control>(get_parent()); + if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window, is_inside_tree(), true); + return; } + + Window *parent_w = cast_to<Window>(get_parent()); + if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) { + Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window, is_inside_tree(), true); + return; + } + + Control::_propagate_theme_changed(this, nullptr, nullptr, is_inside_tree(), true); } Ref<Theme> Window::get_theme() const { return theme; } +void Window::_theme_changed() { + if (is_inside_tree()) { + Control::_propagate_theme_changed(this, nullptr, this, true, false); + } +} + void Window::set_theme_type_variation(const StringName &p_theme_type) { theme_type_variation = p_theme_type; - Control::_propagate_theme_changed(this, theme_owner, theme_owner_window); + if (is_inside_tree()) { + notification(NOTIFICATION_THEME_CHANGED); + } } StringName Window::get_theme_type_variation() const { @@ -1681,6 +1685,7 @@ void Window::_bind_methods() { ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_flag", "get_flag", FLAG_TRANSPARENT); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unfocusable"), "set_flag", "get_flag", FLAG_NO_FOCUS); ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "popup_window"), "set_flag", "get_flag", FLAG_POPUP); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "extend_to_title"), "set_flag", "get_flag", FLAG_EXTEND_TO_TITLE); ADD_GROUP("Limits", ""); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size", PROPERTY_HINT_NONE, "suffix:px"), "set_min_size", "get_min_size"); @@ -1712,6 +1717,7 @@ void Window::_bind_methods() { ADD_SIGNAL(MethodInfo("theme_changed")); BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED); + BIND_CONSTANT(NOTIFICATION_THEME_CHANGED); BIND_ENUM_CONSTANT(MODE_WINDOWED); BIND_ENUM_CONSTANT(MODE_MINIMIZED); @@ -1725,6 +1731,7 @@ void Window::_bind_methods() { BIND_ENUM_CONSTANT(FLAG_TRANSPARENT); BIND_ENUM_CONSTANT(FLAG_NO_FOCUS); BIND_ENUM_CONSTANT(FLAG_POPUP); + BIND_ENUM_CONSTANT(FLAG_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(FLAG_MAX); BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED); diff --git a/scene/main/window.h b/scene/main/window.h index aa32edbb04..ebaf8fea75 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -56,6 +56,7 @@ public: FLAG_TRANSPARENT = DisplayServer::WINDOW_FLAG_TRANSPARENT, FLAG_NO_FOCUS = DisplayServer::WINDOW_FLAG_NO_FOCUS, FLAG_POPUP = DisplayServer::WINDOW_FLAG_POPUP, + FLAG_EXTEND_TO_TITLE = DisplayServer::WINDOW_FLAG_EXTEND_TO_TITLE, FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX, }; @@ -167,6 +168,7 @@ public: enum { NOTIFICATION_VISIBILITY_CHANGED = 30, NOTIFICATION_POST_POPUP = 31, + // This doesn't need to be paired with `NOTIFICATION_ENTER_TREE`. NOTIFICATION_THEME_CHANGED = 32 }; @@ -239,6 +241,8 @@ public: void set_use_font_oversampling(bool p_oversampling); bool is_using_font_oversampling() const; + void warp_mouse(const Vector2 &p_position) override; + void set_wrap_controls(bool p_enable); bool is_wrapping_controls() const; void child_controls_changed(); @@ -253,6 +257,7 @@ public: void set_theme(const Ref<Theme> &p_theme); Ref<Theme> get_theme() const; + void _theme_changed(); void set_theme_type_variation(const StringName &p_theme_type); StringName get_theme_type_variation() const; diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp index 62573ed3e8..5243d4bdca 100644 --- a/scene/register_scene_types.cpp +++ b/scene/register_scene_types.cpp @@ -162,7 +162,7 @@ #include "scene/resources/multimesh.h" #include "scene/resources/navigation_mesh.h" #include "scene/resources/packed_scene.h" -#include "scene/resources/particles_material.h" +#include "scene/resources/particle_process_material.h" #include "scene/resources/physics_material.h" #include "scene/resources/polygon_path_finder.h" #include "scene/resources/primitive_meshes.h" @@ -248,7 +248,7 @@ #include "scene/3d/shape_cast_3d.h" #include "scene/3d/skeleton_3d.h" #include "scene/3d/skeleton_ik_3d.h" -#include "scene/3d/soft_dynamic_body_3d.h" +#include "scene/3d/soft_body_3d.h" #include "scene/3d/spring_arm_3d.h" #include "scene/3d/sprite_3d.h" #include "scene/3d/vehicle_body_3d.h" @@ -533,13 +533,13 @@ void register_scene_types() { GDREGISTER_ABSTRACT_CLASS(PhysicsBody3D); GDREGISTER_CLASS(StaticBody3D); GDREGISTER_CLASS(AnimatableBody3D); - GDREGISTER_CLASS(RigidDynamicBody3D); + GDREGISTER_CLASS(RigidBody3D); GDREGISTER_CLASS(KinematicCollision3D); GDREGISTER_CLASS(CharacterBody3D); GDREGISTER_CLASS(SpringArm3D); GDREGISTER_CLASS(PhysicalBone3D); - GDREGISTER_CLASS(SoftDynamicBody3D); + GDREGISTER_CLASS(SoftBody3D); GDREGISTER_CLASS(SkeletonIK3D); GDREGISTER_CLASS(BoneAttachment3D); @@ -611,6 +611,7 @@ void register_scene_types() { GDREGISTER_CLASS(VisualShaderNodeColorFunc); GDREGISTER_CLASS(VisualShaderNodeTransformFunc); GDREGISTER_CLASS(VisualShaderNodeUVFunc); + GDREGISTER_CLASS(VisualShaderNodeUVPolarCoord); GDREGISTER_CLASS(VisualShaderNodeDotProduct); GDREGISTER_CLASS(VisualShaderNodeVectorLen); GDREGISTER_CLASS(VisualShaderNodeDeterminant); @@ -649,6 +650,7 @@ void register_scene_types() { GDREGISTER_CLASS(VisualShaderNodeTexture2DArrayUniform); GDREGISTER_CLASS(VisualShaderNodeTexture3DUniform); GDREGISTER_CLASS(VisualShaderNodeCubemapUniform); + GDREGISTER_CLASS(VisualShaderNodeLinearSceneDepth); GDREGISTER_CLASS(VisualShaderNodeIf); GDREGISTER_CLASS(VisualShaderNodeSwitch); GDREGISTER_CLASS(VisualShaderNodeFresnel); @@ -658,6 +660,10 @@ void register_scene_types() { GDREGISTER_CLASS(VisualShaderNodeCompare); GDREGISTER_CLASS(VisualShaderNodeMultiplyAdd); GDREGISTER_CLASS(VisualShaderNodeBillboard); + GDREGISTER_CLASS(VisualShaderNodeDistanceFade); + GDREGISTER_CLASS(VisualShaderNodeProximityFade); + GDREGISTER_CLASS(VisualShaderNodeRandomRange); + GDREGISTER_CLASS(VisualShaderNodeRemap); GDREGISTER_ABSTRACT_CLASS(VisualShaderNodeVarying); GDREGISTER_CLASS(VisualShaderNodeVaryingSetter); GDREGISTER_CLASS(VisualShaderNodeVaryingGetter); @@ -704,7 +710,7 @@ void register_scene_types() { GDREGISTER_ABSTRACT_CLASS(PhysicsBody2D); GDREGISTER_CLASS(StaticBody2D); GDREGISTER_CLASS(AnimatableBody2D); - GDREGISTER_CLASS(RigidDynamicBody2D); + GDREGISTER_CLASS(RigidBody2D); GDREGISTER_CLASS(CharacterBody2D); GDREGISTER_CLASS(KinematicCollision2D); GDREGISTER_CLASS(Area2D); @@ -761,9 +767,9 @@ void register_scene_types() { /* REGISTER RESOURCES */ GDREGISTER_ABSTRACT_CLASS(Shader); - GDREGISTER_CLASS(ParticlesMaterial); - SceneTree::add_idle_callback(ParticlesMaterial::flush_changes); - ParticlesMaterial::init_shaders(); + GDREGISTER_CLASS(ParticleProcessMaterial); + SceneTree::add_idle_callback(ParticleProcessMaterial::flush_changes); + ParticleProcessMaterial::init_shaders(); GDREGISTER_VIRTUAL_CLASS(Mesh); GDREGISTER_CLASS(ArrayMesh); @@ -1019,6 +1025,7 @@ void register_scene_types() { ClassDB::add_compatibility_class("PanoramaSky", "Sky"); ClassDB::add_compatibility_class("Particles", "GPUParticles3D"); ClassDB::add_compatibility_class("Particles2D", "GPUParticles2D"); + ClassDB::add_compatibility_class("ParticlesMaterial", "ParticleProcessMaterial"); ClassDB::add_compatibility_class("Path", "Path3D"); ClassDB::add_compatibility_class("PathFollow", "PathFollow3D"); ClassDB::add_compatibility_class("PhysicalBone", "PhysicalBone3D"); @@ -1041,14 +1048,16 @@ void register_scene_types() { ClassDB::add_compatibility_class("RayShape", "SeparationRayShape3D"); ClassDB::add_compatibility_class("RayShape2D", "SeparationRayShape2D"); ClassDB::add_compatibility_class("RemoteTransform", "RemoteTransform3D"); - ClassDB::add_compatibility_class("RigidBody", "RigidDynamicBody3D"); - ClassDB::add_compatibility_class("RigidBody2D", "RigidDynamicBody2D"); + ClassDB::add_compatibility_class("RigidBody", "RigidBody3D"); + ClassDB::add_compatibility_class("RigidDynamicBody2D", "RigidBody2D"); + ClassDB::add_compatibility_class("RigidDynamicBody3D", "RigidBody3D"); ClassDB::add_compatibility_class("Shape", "Shape3D"); ClassDB::add_compatibility_class("ShortCut", "Shortcut"); ClassDB::add_compatibility_class("Skeleton", "Skeleton3D"); ClassDB::add_compatibility_class("SkeletonIK", "SkeletonIK3D"); ClassDB::add_compatibility_class("SliderJoint", "SliderJoint3D"); - ClassDB::add_compatibility_class("SoftBody", "SoftDynamicBody3D"); + ClassDB::add_compatibility_class("SoftBody", "SoftBody3D"); + ClassDB::add_compatibility_class("SoftDynamicBody3D", "SoftBody3D"); ClassDB::add_compatibility_class("Spatial", "Node3D"); ClassDB::add_compatibility_class("SpatialGizmo", "Node3DGizmo"); ClassDB::add_compatibility_class("SpatialMaterial", "StandardMaterial3D"); @@ -1132,8 +1141,8 @@ void initialize_theme() { String font_path = GLOBAL_DEF_RST("gui/theme/custom_font", ""); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/custom_font", PropertyInfo(Variant::STRING, "gui/theme/custom_font", PROPERTY_HINT_FILE, "*.tres,*.res", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); - bool font_antialiased = (bool)GLOBAL_DEF_RST("gui/theme/default_font_antialiased", true); - ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiased", PropertyInfo(Variant::BOOL, "gui/theme/default_font_antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); + TextServer::FontAntialiasing font_antialiasing = (TextServer::FontAntialiasing)(int)GLOBAL_DEF_RST("gui/theme/default_font_antialiasing", 1); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_antialiasing", PropertyInfo(Variant::INT, "gui/theme/default_font_antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); TextServer::Hinting font_hinting = (TextServer::Hinting)(int)GLOBAL_DEF_RST("gui/theme/default_font_hinting", TextServer::HINTING_LIGHT); ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/default_font_hinting", PropertyInfo(Variant::INT, "gui/theme/default_font_hinting", PROPERTY_HINT_ENUM, "None,Light,Normal", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_RESTART_IF_CHANGED)); @@ -1144,6 +1153,10 @@ void initialize_theme() { const bool font_msdf = GLOBAL_DEF_RST("gui/theme/default_font_multichannel_signed_distance_field", false); const bool font_generate_mipmaps = GLOBAL_DEF_RST("gui/theme/default_font_generate_mipmaps", false); + GLOBAL_DEF_RST("gui/theme/lcd_subpixel_layout", 1); + ProjectSettings::get_singleton()->set_custom_property_info("gui/theme/lcd_subpixel_layout", PropertyInfo(Variant::INT, "gui/theme/lcd_subpixel_layout", PROPERTY_HINT_ENUM, "Disabled,Horizontal RGB,Horizontal BGR,Vertical RGB,Vertical BGR")); + ProjectSettings::get_singleton()->set_restart_if_changed("gui/theme/lcd_subpixel_layout", false); + Ref<Font> font; if (!font_path.is_empty()) { font = ResourceLoader::load(font_path); @@ -1154,7 +1167,7 @@ void initialize_theme() { // Always make the default theme to avoid invalid default font/icon/style in the given theme. if (RenderingServer::get_singleton()) { - make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiased, font_msdf, font_generate_mipmaps); + make_default_theme(default_theme_scale, font, font_subpixel_positioning, font_hinting, font_antialiasing, font_msdf, font_generate_mipmaps); } if (!theme_path.is_empty()) { @@ -1209,7 +1222,7 @@ void unregister_scene_types() { ProceduralSkyMaterial::cleanup_shader(); #endif // _3D_DISABLED - ParticlesMaterial::finish_shaders(); + ParticleProcessMaterial::finish_shaders(); CanvasItemMaterial::finish_shaders(); ColorPicker::finish_shaders(); SceneStringNames::free(); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index da59c4dbd1..823617328e 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2323,100 +2323,23 @@ Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, real_t p } real_t Animation::_interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const { - return p_a * (1.0 - p_c) + p_b * p_c; + return Math::lerp(p_a, p_b, p_c); } -// Cubic interpolation for anytype. - -Vector3 Animation::_cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c) const { - return p_a.cubic_interpolate(p_b, p_pre_a, p_post_b, p_c); -} - -Quaternion Animation::_cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const { - return p_a.spherical_cubic_interpolate(p_b, p_pre_a, p_post_b, p_c); -} - -Variant Animation::_cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const { +Variant Animation::_interpolate_angle(const Variant &p_a, const Variant &p_b, real_t p_c) const { Variant::Type type_a = p_a.get_type(); Variant::Type type_b = p_b.get_type(); - Variant::Type type_pa = p_pre_a.get_type(); - Variant::Type type_pb = p_post_b.get_type(); - - //make int and real play along - uint32_t vformat = 1 << type_a; vformat |= 1 << type_b; - vformat |= 1 << type_pa; - vformat |= 1 << type_pb; - if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { - //mix of real and int real_t a = p_a; real_t b = p_b; - real_t pa = p_pre_a; - real_t pb = p_post_b; - - return Math::cubic_interpolate(a, b, pa, pb, p_c); - } else if ((vformat & (vformat - 1))) { - return p_a; //can't interpolate, mix of types - } - - switch (type_a) { - case Variant::VECTOR2: { - Vector2 a = p_a; - Vector2 b = p_b; - Vector2 pa = p_pre_a; - Vector2 pb = p_post_b; - - return a.cubic_interpolate(b, pa, pb, p_c); - } - case Variant::RECT2: { - Rect2 a = p_a; - Rect2 b = p_b; - Rect2 pa = p_pre_a; - Rect2 pb = p_post_b; - - return Rect2( - a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c), - a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); - } - case Variant::VECTOR3: { - Vector3 a = p_a; - Vector3 b = p_b; - Vector3 pa = p_pre_a; - Vector3 pb = p_post_b; - - return a.cubic_interpolate(b, pa, pb, p_c); - } - case Variant::QUATERNION: { - Quaternion a = p_a; - Quaternion b = p_b; - Quaternion pa = p_pre_a; - Quaternion pb = p_post_b; - - return a.spherical_cubic_interpolate(b, pa, pb, p_c); - } - case Variant::AABB: { - AABB a = p_a; - AABB b = p_b; - AABB pa = p_pre_a; - AABB pb = p_post_b; - - return AABB( - a.position.cubic_interpolate(b.position, pa.position, pb.position, p_c), - a.size.cubic_interpolate(b.size, pa.size, pb.size, p_c)); - } - default: { - return _interpolate(p_a, p_b, p_c); - } + return Math::fposmod((float)Math::lerp_angle(a, b, p_c), (float)Math_TAU); } -} - -real_t Animation::_cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const { return _interpolate(p_a, p_b, p_c); } -// Cubic interpolation in time for anytype. +// Cubic interpolation for anytype. Vector3 Animation::_cubic_interpolate_in_time(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { return p_a.cubic_interpolate_in_time(p_b, p_pre_a, p_post_b, p_c, p_b_t, p_pre_a_t, p_post_b_t); @@ -2503,6 +2426,25 @@ Variant Animation::_cubic_interpolate_in_time(const Variant &p_pre_a, const Vari } real_t Animation::_cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + return Math::cubic_interpolate_in_time(p_a, p_b, p_pre_a, p_post_b, p_c, p_b_t, p_pre_a_t, p_post_b_t); +} + +Variant Animation::_cubic_interpolate_angle_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const { + Variant::Type type_a = p_a.get_type(); + Variant::Type type_b = p_b.get_type(); + Variant::Type type_pa = p_pre_a.get_type(); + Variant::Type type_pb = p_post_b.get_type(); + uint32_t vformat = 1 << type_a; + vformat |= 1 << type_b; + vformat |= 1 << type_pa; + vformat |= 1 << type_pb; + if (vformat == ((1 << Variant::INT) | (1 << Variant::FLOAT)) || vformat == (1 << Variant::FLOAT)) { + real_t a = p_a; + real_t b = p_b; + real_t pa = p_pre_a; + real_t pb = p_post_b; + return Math::fposmod((float)Math::cubic_interpolate_angle_in_time(a, b, pa, pb, p_c, p_b_t, p_pre_a_t, p_post_b_t), (float)Math_TAU); + } return _interpolate(p_a, p_b, p_c); } @@ -2685,8 +2627,11 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol case INTERPOLATION_LINEAR: { return _interpolate(p_keys[idx].value, p_keys[next].value, c); } break; + case INTERPOLATION_LINEAR_ANGLE: { + return _interpolate_angle(p_keys[idx].value, p_keys[next].value, c); + } break; case INTERPOLATION_CUBIC: - case INTERPOLATION_CUBIC_IN_TIME: { + case INTERPOLATION_CUBIC_ANGLE: { int pre = 0; int post = 0; if (!p_backward) { @@ -2725,25 +2670,27 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol } } + real_t pre_t = 0.0; + real_t to_t = 0.0; + real_t post_t = 0.0; if (loop_mode == LOOP_LINEAR && p_loop_wrap) { - if (p_interp == INTERPOLATION_CUBIC) { - return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); - } - return _cubic_interpolate_in_time( - p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, - pre > idx ? -length + p_keys[pre].time - p_keys[idx].time : p_keys[pre].time - p_keys[idx].time, - next < idx ? length + p_keys[next].time - p_keys[idx].time : p_keys[next].time - p_keys[idx].time, - next < idx || post <= idx ? length + p_keys[post].time - p_keys[idx].time : p_keys[post].time - p_keys[idx].time); + pre_t = pre > idx ? -length + p_keys[pre].time - p_keys[idx].time : p_keys[pre].time - p_keys[idx].time; + to_t = next < idx ? length + p_keys[next].time - p_keys[idx].time : p_keys[next].time - p_keys[idx].time; + post_t = next < idx || post <= idx ? length + p_keys[post].time - p_keys[idx].time : p_keys[post].time - p_keys[idx].time; + } else { + pre_t = p_keys[pre].time - p_keys[idx].time; + to_t = p_keys[next].time - p_keys[idx].time; + post_t = p_keys[post].time - p_keys[idx].time; } - if (p_interp == INTERPOLATION_CUBIC) { - return _cubic_interpolate(p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c); + if (p_interp == INTERPOLATION_CUBIC_ANGLE) { + return _cubic_interpolate_angle_in_time( + p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, + pre_t, to_t, post_t); } return _cubic_interpolate_in_time( p_keys[pre].value, p_keys[idx].value, p_keys[next].value, p_keys[post].value, c, - p_keys[pre].time - p_keys[idx].time, - p_keys[next].time - p_keys[idx].time, - p_keys[post].time - p_keys[idx].time); + pre_t, to_t, post_t); } break; default: return p_keys[idx].value; @@ -4073,7 +4020,8 @@ void Animation::_bind_methods() { BIND_ENUM_CONSTANT(INTERPOLATION_NEAREST); BIND_ENUM_CONSTANT(INTERPOLATION_LINEAR); BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC); - BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC_IN_TIME); + BIND_ENUM_CONSTANT(INTERPOLATION_LINEAR_ANGLE); + BIND_ENUM_CONSTANT(INTERPOLATION_CUBIC_ANGLE); BIND_ENUM_CONSTANT(UPDATE_CONTINUOUS); BIND_ENUM_CONSTANT(UPDATE_DISCRETE); @@ -4100,28 +4048,27 @@ void Animation::clear() { emit_signal(SceneStringNames::get_singleton()->tracks_changed); } -bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) { +bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) { // Remove overlapping keys. if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) { return true; } - if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) { + if (abs(t0.value - t1.value) < p_allowed_precision_error && abs(t1.value - t2.value) < p_allowed_precision_error) { return true; } // Calc velocities. - Vector3 vc0 = (t1.value - t0.value) / (t1.time - t0.time); - Vector3 vc1 = (t2.value - t1.value) / (t2.time - t1.time); - real_t v0 = vc0.length(); - real_t v1 = vc1.length(); + double v0 = (t1.value - t0.value) / (t1.time - t0.time); + double v1 = (t2.value - t1.value) / (t2.time - t1.time); // Avoid zero div but check equality. if (abs(v0 - v1) < p_allowed_precision_error) { return true; } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { return false; } - // Check axis. - if (vc0.normalized().dot(vc1.normalized()) >= 1.0 - p_allowed_angular_error * 2.0) { - real_t ratio = v0 < v1 ? v0 / v1 : v1 / v0; + if (!signbit(v0 * v1)) { + v0 = abs(v0); + v1 = abs(v1); + double ratio = v0 < v1 ? v0 / v1 : v1 / v0; if (ratio >= 1.0 - p_allowed_velocity_err) { return true; } @@ -4129,7 +4076,7 @@ bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<V return false; } -bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) { +bool Animation::_vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) { // Remove overlapping keys. if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) { return true; @@ -4137,20 +4084,22 @@ bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) { return true; } + // Calc velocities. + Vector2 vc0 = (t1.value - t0.value) / (t1.time - t0.time); + Vector2 vc1 = (t2.value - t1.value) / (t2.time - t1.time); + double v0 = vc0.length(); + double v1 = vc1.length(); + // Avoid zero div but check equality. + if (abs(v0 - v1) < p_allowed_precision_error) { + return true; + } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { + return false; + } // Check axis. - Quaternion q0 = t0.value * t1.value * t0.value.inverse(); - Quaternion q1 = t1.value * t2.value * t1.value.inverse(); - if (q0.get_axis().dot(q1.get_axis()) >= 1.0 - p_allowed_angular_error * 2.0) { - // Calc velocities. - real_t v0 = Math::acos(t0.value.dot(t1.value)) / (t1.time - t0.time); - real_t v1 = Math::acos(t1.value.dot(t2.value)) / (t2.time - t1.time); - // Avoid zero div but check equality. - if (abs(v0 - v1) < p_allowed_precision_error) { - return true; - } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { - return false; - } - real_t ratio = v0 < v1 ? v0 / v1 : v1 / v0; + if (vc0.normalized().dot(vc1.normalized()) >= 1.0 - p_allowed_angular_error * 2.0) { + v0 = abs(v0); + v1 = abs(v1); + double ratio = v0 < v1 ? v0 / v1 : v1 / v0; if (ratio >= 1.0 - p_allowed_velocity_err) { return true; } @@ -4158,25 +4107,64 @@ bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const return false; } -bool Animation::_float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error) { +bool Animation::_vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) { // Remove overlapping keys. if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) { return true; } - if (abs(t0.value - t1.value) < p_allowed_precision_error && abs(t1.value - t2.value) < p_allowed_precision_error) { + if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) { return true; } // Calc velocities. - real_t v0 = (t1.value - t0.value) / (t1.time - t0.time); - real_t v1 = (t2.value - t1.value) / (t2.time - t1.time); + Vector3 vc0 = (t1.value - t0.value) / (t1.time - t0.time); + Vector3 vc1 = (t2.value - t1.value) / (t2.time - t1.time); + double v0 = vc0.length(); + double v1 = vc1.length(); // Avoid zero div but check equality. if (abs(v0 - v1) < p_allowed_precision_error) { return true; } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { return false; } - if (!signbit(v0 * v1)) { - real_t ratio = v0 < v1 ? v0 / v1 : v1 / v0; + // Check axis. + if (vc0.normalized().dot(vc1.normalized()) >= 1.0 - p_allowed_angular_error * 2.0) { + v0 = abs(v0); + v1 = abs(v1); + double ratio = v0 < v1 ? v0 / v1 : v1 / v0; + if (ratio >= 1.0 - p_allowed_velocity_err) { + return true; + } + } + return false; +} + +bool Animation::_quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error) { + // Remove overlapping keys. + if (Math::is_equal_approx(t0.time, t1.time) || Math::is_equal_approx(t1.time, t2.time)) { + return true; + } + if ((t0.value - t1.value).length() < p_allowed_precision_error && (t1.value - t2.value).length() < p_allowed_precision_error) { + return true; + } + // Check axis. + Quaternion q0 = t0.value * t1.value * t0.value.inverse(); + Quaternion q1 = t1.value * t2.value * t1.value.inverse(); + if (q0.get_axis().dot(q1.get_axis()) >= 1.0 - p_allowed_angular_error * 2.0) { + double a0 = Math::acos(t0.value.dot(t1.value)); + double a1 = Math::acos(t1.value.dot(t2.value)); + if (a0 + a1 >= Math_PI) { + return false; // Rotation is more than 180 deg, keep key. + } + // Calc velocities. + double v0 = a0 / (t1.time - t0.time); + double v1 = a1 / (t2.time - t1.time); + // Avoid zero div but check equality. + if (abs(v0 - v1) < p_allowed_precision_error) { + return true; + } else if (abs(v0) < p_allowed_precision_error || abs(v1) < p_allowed_precision_error) { + return false; + } + double ratio = v0 < v1 ? v0 / v1 : v1 / v0; if (ratio >= 1.0 - p_allowed_velocity_err) { return true; } @@ -4288,6 +4276,125 @@ void Animation::_blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity } } +void Animation::_value_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error) { + ERR_FAIL_INDEX(p_idx, tracks.size()); + ERR_FAIL_COND(tracks[p_idx]->type != TYPE_VALUE); + ValueTrack *tt = static_cast<ValueTrack *>(tracks[p_idx]); + if (tt->values.size() == 0) { + return; + } + Variant::Type type = tt->values[0].value.get_type(); + + // Special case for angle interpolation. + bool is_using_angle = tt->interpolation == Animation::INTERPOLATION_LINEAR_ANGLE || tt->interpolation == Animation::INTERPOLATION_CUBIC_ANGLE; + int i = 0; + while (i < tt->values.size() - 2) { + bool erase = false; + switch (type) { + case Variant::FLOAT: { + TKey<float> t0; + TKey<float> t1; + TKey<float> t2; + t0.time = tt->values[i].time; + t1.time = tt->values[i + 1].time; + t2.time = tt->values[i + 2].time; + t0.value = tt->values[i].value; + t1.value = tt->values[i + 1].value; + t2.value = tt->values[i + 2].value; + if (is_using_angle) { + float diff1 = fmod(t1.value - t0.value, Math_TAU); + t1.value = t0.value + fmod(2.0 * diff1, Math_TAU) - diff1; + float diff2 = fmod(t2.value - t1.value, Math_TAU); + t2.value = t1.value + fmod(2.0 * diff2, Math_TAU) - diff2; + if (abs(abs(diff1) + abs(diff2)) >= Math_PI) { + break; // Rotation is more than 180 deg, keep key. + } + } + erase = _float_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_precision_error); + } break; + case Variant::VECTOR2: { + TKey<Vector2> t0; + TKey<Vector2> t1; + TKey<Vector2> t2; + t0.time = tt->values[i].time; + t1.time = tt->values[i + 1].time; + t2.time = tt->values[i + 2].time; + t0.value = tt->values[i].value; + t1.value = tt->values[i + 1].value; + t2.value = tt->values[i + 2].value; + erase = _vector2_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); + } break; + case Variant::VECTOR3: { + TKey<Vector3> t0; + TKey<Vector3> t1; + TKey<Vector3> t2; + t0.time = tt->values[i].time; + t1.time = tt->values[i + 1].time; + t2.time = tt->values[i + 2].time; + t0.value = tt->values[i].value; + t1.value = tt->values[i + 1].value; + t2.value = tt->values[i + 2].value; + erase = _vector3_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); + } break; + case Variant::QUATERNION: { + TKey<Quaternion> t0; + TKey<Quaternion> t1; + TKey<Quaternion> t2; + t0.time = tt->values[i].time; + t1.time = tt->values[i + 1].time; + t2.time = tt->values[i + 2].time; + t0.value = tt->values[i].value; + t1.value = tt->values[i + 1].value; + t2.value = tt->values[i + 2].value; + erase = _quaternion_track_optimize_key(t0, t1, t2, p_allowed_velocity_err, p_allowed_angular_err, p_allowed_precision_error); + } break; + default: { + } break; + } + + if (erase) { + tt->values.remove_at(i + 1); + } else { + i++; + } + } + + if (tt->values.size() == 2) { + bool single_key = false; + switch (type) { + case Variant::FLOAT: { + float val_0 = tt->values[0].value; + float val_1 = tt->values[1].value; + if (is_using_angle) { + float diff1 = fmod(val_1 - val_0, Math_TAU); + val_1 = val_0 + fmod(2.0 * diff1, Math_TAU) - diff1; + } + single_key = abs(val_0 - val_1) < p_allowed_precision_error; + } break; + case Variant::VECTOR2: { + Vector2 val_0 = tt->values[0].value; + Vector2 val_1 = tt->values[1].value; + single_key = (val_0 - val_1).length() < p_allowed_precision_error; + } break; + case Variant::VECTOR3: { + Vector3 val_0 = tt->values[0].value; + Vector3 val_1 = tt->values[1].value; + single_key = (val_0 - val_1).length() < p_allowed_precision_error; + } break; + case Variant::QUATERNION: { + Quaternion val_0 = tt->values[0].value; + Quaternion val_1 = tt->values[1].value; + single_key = (val_0 - val_1).length() < p_allowed_precision_error; + } break; + default: { + } break; + } + if (single_key) { + tt->values.remove_at(1); + } + } +} + void Animation::optimize(real_t p_allowed_velocity_err, real_t p_allowed_angular_err, int p_precision) { real_t precision = Math::pow(0.1, p_precision); for (int i = 0; i < tracks.size(); i++) { @@ -4302,6 +4409,8 @@ void Animation::optimize(real_t p_allowed_velocity_err, real_t p_allowed_angular _scale_track_optimize(i, p_allowed_velocity_err, p_allowed_angular_err, precision); } else if (tracks[i]->type == TYPE_BLEND_SHAPE) { _blend_shape_track_optimize(i, p_allowed_velocity_err, precision); + } else if (tracks[i]->type == TYPE_VALUE) { + _value_track_optimize(i, p_allowed_velocity_err, p_allowed_angular_err, precision); } } } diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 5e88980397..46a88df130 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -57,7 +57,8 @@ public: INTERPOLATION_NEAREST, INTERPOLATION_LINEAR, INTERPOLATION_CUBIC, - INTERPOLATION_CUBIC_IN_TIME, + INTERPOLATION_LINEAR_ANGLE, + INTERPOLATION_CUBIC_ANGLE, }; enum UpdateMode { @@ -237,16 +238,13 @@ private: _FORCE_INLINE_ Quaternion _interpolate(const Quaternion &p_a, const Quaternion &p_b, real_t p_c) const; _FORCE_INLINE_ Variant _interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const; _FORCE_INLINE_ real_t _interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const; - - _FORCE_INLINE_ Vector3 _cubic_interpolate(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c) const; - _FORCE_INLINE_ Quaternion _cubic_interpolate(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c) const; - _FORCE_INLINE_ Variant _cubic_interpolate(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c) const; - _FORCE_INLINE_ real_t _cubic_interpolate(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c) const; + _FORCE_INLINE_ Variant _interpolate_angle(const Variant &p_a, const Variant &p_b, real_t p_c) const; _FORCE_INLINE_ Vector3 _cubic_interpolate_in_time(const Vector3 &p_pre_a, const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; _FORCE_INLINE_ Quaternion _cubic_interpolate_in_time(const Quaternion &p_pre_a, const Quaternion &p_a, const Quaternion &p_b, const Quaternion &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; _FORCE_INLINE_ Variant _cubic_interpolate_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; _FORCE_INLINE_ real_t _cubic_interpolate_in_time(const real_t &p_pre_a, const real_t &p_a, const real_t &p_b, const real_t &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; + _FORCE_INLINE_ Variant _cubic_interpolate_angle_in_time(const Variant &p_pre_a, const Variant &p_a, const Variant &p_b, const Variant &p_post_b, real_t p_c, real_t p_pre_a_t, real_t p_b_t, real_t p_post_b_t) const; template <class T> _FORCE_INLINE_ T _interpolate(const Vector<TKey<T>> &p_keys, double p_time, InterpolationType p_interp, bool p_loop_wrap, bool *p_ok, bool p_backward = false) const; @@ -368,14 +366,16 @@ private: return idxr; } + bool _float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error); + bool _vector2_track_optimize_key(const TKey<Vector2> t0, const TKey<Vector2> t1, const TKey<Vector2> t2, real_t p_alowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); bool _vector3_track_optimize_key(const TKey<Vector3> t0, const TKey<Vector3> t1, const TKey<Vector3> t2, real_t p_alowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); bool _quaternion_track_optimize_key(const TKey<Quaternion> t0, const TKey<Quaternion> t1, const TKey<Quaternion> t2, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); - bool _float_track_optimize_key(const TKey<float> t0, const TKey<float> t1, const TKey<float> t2, real_t p_allowed_velocity_err, real_t p_allowed_precision_error); void _position_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); void _rotation_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_error, real_t p_allowed_precision_error); void _scale_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); void _blend_shape_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_precision_error); + void _value_track_optimize(int p_idx, real_t p_allowed_velocity_err, real_t p_allowed_angular_err, real_t p_allowed_precision_error); protected: bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/resources/capsule_shape_3d.cpp b/scene/resources/capsule_shape_3d.cpp index 214004824f..b0454004a0 100644 --- a/scene/resources/capsule_shape_3d.cpp +++ b/scene/resources/capsule_shape_3d.cpp @@ -40,8 +40,8 @@ Vector<Vector3> CapsuleShape3D::get_debug_mesh_lines() const { Vector3 d(0, height * 0.5 - radius, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 1835604285..ee53578517 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -763,7 +763,7 @@ void Curve2D::_bake_segment2d(RBMap<real_t, Vector2> &r_bake, real_t p_begin, re Vector2 nb = (end - mid).normalized(); real_t dp = na.dot(nb); - if (dp < Math::cos(Math::deg2rad(p_tol))) { + if (dp < Math::cos(Math::deg_to_rad(p_tol))) { r_bake[mp] = mid; } @@ -1352,7 +1352,7 @@ void Curve3D::_bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, re Vector3 nb = (end - mid).normalized(); real_t dp = na.dot(nb); - if (dp < Math::cos(Math::deg2rad(p_tol))) { + if (dp < Math::cos(Math::deg_to_rad(p_tol))) { r_bake[mp] = mid; } if (p_depth < p_max_depth) { diff --git a/scene/resources/cylinder_shape_3d.cpp b/scene/resources/cylinder_shape_3d.cpp index 345df5ffed..a5951db8ea 100644 --- a/scene/resources/cylinder_shape_3d.cpp +++ b/scene/resources/cylinder_shape_3d.cpp @@ -40,8 +40,8 @@ Vector<Vector3> CylinderShape3D::get_debug_mesh_lines() const { Vector3 d(0, height * 0.5, 0); for (int i = 0; i < 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * radius; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * radius; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 6d99073fa4..5bfa1adfe5 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -1053,7 +1053,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const default_style = make_flat_stylebox(Color(1, 0.365, 0.365), 4, 4, 4, 4, 0, false, 2); } -void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, bool p_font_antialiased, bool p_font_msdf, bool p_font_generate_mipmaps) { +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel, TextServer::Hinting p_font_hinting, TextServer::FontAntialiasing p_font_antialiasing, bool p_font_msdf, bool p_font_generate_mipmaps) { Ref<Theme> t; t.instantiate(); @@ -1077,7 +1077,7 @@ void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPos dynamic_font->set_data_ptr(_font_OpenSans_SemiBold, _font_OpenSans_SemiBold_size); dynamic_font->set_subpixel_positioning(p_font_subpixel); dynamic_font->set_hinting(p_font_hinting); - dynamic_font->set_antialiased(p_font_antialiased); + dynamic_font->set_antialiasing(p_font_antialiasing); dynamic_font->set_multichannel_signed_distance_field(p_font_msdf); dynamic_font->set_generate_mipmaps(p_font_generate_mipmaps); diff --git a/scene/resources/default_theme/default_theme.h b/scene/resources/default_theme/default_theme.h index 9b070a90cc..15be5e676f 100644 --- a/scene/resources/default_theme/default_theme.h +++ b/scene/resources/default_theme/default_theme.h @@ -36,7 +36,7 @@ const int default_font_size = 16; void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const Ref<Font> &bold_font, const Ref<Font> &bold_italics_font, const Ref<Font> &italics_font, Ref<Texture2D> &default_icon, Ref<StyleBox> &default_style, float p_scale); -void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, bool p_font_antialiased = true, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); +void make_default_theme(float p_scale, Ref<Font> p_font, TextServer::SubpixelPositioning p_font_subpixel = TextServer::SUBPIXEL_POSITIONING_AUTO, TextServer::Hinting p_font_hinting = TextServer::HINTING_LIGHT, TextServer::FontAntialiasing p_font_antialiased = TextServer::FONT_ANTIALIASING_GRAY, bool p_font_msdf = false, bool p_font_generate_mipmaps = false); void clear_default_theme(); #endif // DEFAULT_THEME_H diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index f8651fecd6..be57d9c965 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -576,7 +576,7 @@ _FORCE_INLINE_ void FontFile::_ensure_rid(int p_cache_index) const { if (unlikely(!cache[p_cache_index].is_valid())) { cache.write[p_cache_index] = TS->create_font(); TS->font_set_data_ptr(cache[p_cache_index], data_ptr, data_size); - TS->font_set_antialiased(cache[p_cache_index], antialiased); + TS->font_set_antialiasing(cache[p_cache_index], antialiasing); TS->font_set_generate_mipmaps(cache[p_cache_index], mipmaps); TS->font_set_multichannel_signed_distance_field(cache[p_cache_index], msdf); TS->font_set_msdf_pixel_range(cache[p_cache_index], msdf_pixel_range); @@ -875,8 +875,8 @@ void FontFile::_bind_methods() { ClassDB::bind_method(D_METHOD("set_font_style_name", "name"), &FontFile::set_font_style_name); ClassDB::bind_method(D_METHOD("set_font_style", "style"), &FontFile::set_font_style); - ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &FontFile::set_antialiased); - ClassDB::bind_method(D_METHOD("is_antialiased"), &FontFile::is_antialiased); + ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &FontFile::set_antialiasing); + ClassDB::bind_method(D_METHOD("get_antialiasing"), &FontFile::get_antialiasing); ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &FontFile::set_generate_mipmaps); ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &FontFile::get_generate_mipmaps); @@ -996,7 +996,7 @@ void FontFile::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_BYTE_ARRAY, "data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_data", "get_data"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_generate_mipmaps", "get_generate_mipmaps"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_antialiased", "is_antialiased"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "font_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_name", "get_font_name"); ADD_PROPERTY(PropertyInfo(Variant::STRING, "style_name", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_font_style_name", "get_font_style_name"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic,Fixed Size", PROPERTY_USAGE_STORAGE), "set_font_style", "get_font_style"); @@ -1318,7 +1318,7 @@ void FontFile::reset_state() { data_size = 0; cache.clear(); - antialiased = true; + antialiasing = TextServer::FONT_ANTIALIASING_GRAY; mipmaps = false; msdf = false; force_autohinter = false; @@ -1337,7 +1337,7 @@ void FontFile::reset_state() { Error FontFile::load_bitmap_font(const String &p_path) { reset_state(); - antialiased = false; + antialiasing = TextServer::FONT_ANTIALIASING_NONE; mipmaps = false; msdf = false; force_autohinter = false; @@ -1817,11 +1817,9 @@ void FontFile::set_data_ptr(const uint8_t *p_data, size_t p_size) { data_ptr = p_data; data_size = p_size; - if (data_ptr != nullptr) { - for (int i = 0; i < cache.size(); i++) { - if (cache[i].is_valid()) { - TS->font_set_data_ptr(cache[i], data_ptr, data_size); - } + for (int i = 0; i < cache.size(); i++) { + if (cache[i].is_valid()) { + TS->font_set_data_ptr(cache[i], data_ptr, data_size); } } } @@ -1831,11 +1829,9 @@ void FontFile::set_data(const PackedByteArray &p_data) { data_ptr = data.ptr(); data_size = data.size(); - if (data_ptr != nullptr) { - for (int i = 0; i < cache.size(); i++) { - if (cache[i].is_valid()) { - TS->font_set_data_ptr(cache[i], data_ptr, data_size); - } + for (int i = 0; i < cache.size(); i++) { + if (cache[i].is_valid()) { + TS->font_set_data_ptr(cache[i], data_ptr, data_size); } } } @@ -1864,19 +1860,19 @@ void FontFile::set_font_style(BitField<TextServer::FontStyle> p_style) { TS->font_set_style(cache[0], p_style); } -void FontFile::set_antialiased(bool p_antialiased) { - if (antialiased != p_antialiased) { - antialiased = p_antialiased; +void FontFile::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) { + if (antialiasing != p_antialiasing) { + antialiasing = p_antialiasing; for (int i = 0; i < cache.size(); i++) { _ensure_rid(i); - TS->font_set_antialiased(cache[i], antialiased); + TS->font_set_antialiasing(cache[i], antialiasing); } emit_changed(); } } -bool FontFile::is_antialiased() const { - return antialiased; +TextServer::FontAntialiasing FontFile::get_antialiasing() const { + return antialiasing; } void FontFile::set_generate_mipmaps(bool p_generate_mipmaps) { @@ -2699,8 +2695,8 @@ FontVariation::~FontVariation() { /*************************************************************************/ void SystemFont::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_antialiased", "antialiased"), &SystemFont::set_antialiased); - ClassDB::bind_method(D_METHOD("is_antialiased"), &SystemFont::is_antialiased); + ClassDB::bind_method(D_METHOD("set_antialiasing", "antialiasing"), &SystemFont::set_antialiasing); + ClassDB::bind_method(D_METHOD("get_antialiasing"), &SystemFont::get_antialiasing); ClassDB::bind_method(D_METHOD("set_generate_mipmaps", "generate_mipmaps"), &SystemFont::set_generate_mipmaps); ClassDB::bind_method(D_METHOD("get_generate_mipmaps"), &SystemFont::get_generate_mipmaps); @@ -2727,7 +2723,7 @@ void SystemFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "font_names"), "set_font_names", "get_font_names"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_style", PROPERTY_HINT_FLAGS, "Bold,Italic"), "set_font_style", "get_font_style"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "antialiased"), "set_antialiased", "is_antialiased"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "antialiasing", PROPERTY_HINT_ENUM, "None,Grayscale,LCD sub-pixel", PROPERTY_USAGE_STORAGE), "set_antialiasing", "get_antialiasing"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "generate_mipmaps"), "set_generate_mipmaps", "get_generate_mipmaps"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "force_autohinter"), "set_force_autohinter", "is_force_autohinter"); ADD_PROPERTY(PropertyInfo(Variant::INT, "hinting", PROPERTY_HINT_ENUM, "None,Light,Normal"), "set_hinting", "get_hinting"); @@ -2804,7 +2800,7 @@ void SystemFont::_update_base_font() { } // Apply font rendering settings. - file->set_antialiased(antialiased); + file->set_antialiasing(antialiasing); file->set_generate_mipmaps(mipmaps); file->set_force_autohinter(force_autohinter); file->set_hinting(hinting); @@ -2841,7 +2837,7 @@ void SystemFont::reset_state() { ftr_weight = 0; ftr_italic = 0; style = 0; - antialiased = true; + antialiasing = TextServer::FONT_ANTIALIASING_GRAY; mipmaps = false; force_autohinter = false; hinting = TextServer::HINTING_LIGHT; @@ -2907,18 +2903,18 @@ Ref<Font> SystemFont::_get_base_font_or_default() const { return Ref<Font>(); } -void SystemFont::set_antialiased(bool p_antialiased) { - if (antialiased != p_antialiased) { - antialiased = p_antialiased; +void SystemFont::set_antialiasing(TextServer::FontAntialiasing p_antialiasing) { + if (antialiasing != p_antialiasing) { + antialiasing = p_antialiasing; if (base_font.is_valid()) { - base_font->set_antialiased(antialiased); + base_font->set_antialiasing(antialiasing); } emit_changed(); } } -bool SystemFont::is_antialiased() const { - return antialiased; +TextServer::FontAntialiasing SystemFont::get_antialiasing() const { + return antialiasing; } void SystemFont::set_generate_mipmaps(bool p_generate_mipmaps) { diff --git a/scene/resources/font.h b/scene/resources/font.h index decbcfbb69..5cf596b41d 100644 --- a/scene/resources/font.h +++ b/scene/resources/font.h @@ -141,7 +141,7 @@ class FontFile : public Font { size_t data_size = 0; PackedByteArray data; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool msdf = false; int msdf_pixel_range = 16; @@ -192,8 +192,8 @@ public: virtual void set_font_style_name(const String &p_name); virtual void set_font_style(BitField<TextServer::FontStyle> p_style); - virtual void set_antialiased(bool p_antialiased); - virtual bool is_antialiased() const; + virtual void set_antialiasing(TextServer::FontAntialiasing p_antialiasing); + virtual TextServer::FontAntialiasing get_antialiasing() const; virtual void set_generate_mipmaps(bool p_generate_mipmaps); virtual bool get_generate_mipmaps() const; @@ -398,7 +398,7 @@ class SystemFont : public Font { int ftr_weight = 0; int ftr_italic = 0; - bool antialiased = true; + TextServer::FontAntialiasing antialiasing = TextServer::FONT_ANTIALIASING_GRAY; bool mipmaps = false; bool force_autohinter = false; TextServer::Hinting hinting = TextServer::HINTING_LIGHT; @@ -417,8 +417,8 @@ protected: public: virtual Ref<Font> _get_base_font_or_default() const; - virtual void set_antialiased(bool p_antialiased); - virtual bool is_antialiased() const; + virtual void set_antialiasing(TextServer::FontAntialiasing p_antialiasing); + virtual TextServer::FontAntialiasing get_antialiasing() const; virtual void set_generate_mipmaps(bool p_generate_mipmaps); virtual bool get_generate_mipmaps() const; diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index 293fdd6f05..3638d1862c 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -301,9 +301,9 @@ void ImporterMesh::generate_lods(float p_normal_merge_angle, float p_normal_spli } } - float normal_merge_threshold = Math::cos(Math::deg2rad(p_normal_merge_angle)); - float normal_pre_split_threshold = Math::cos(Math::deg2rad(MIN(180.0f, p_normal_split_angle * 2.0f))); - float normal_split_threshold = Math::cos(Math::deg2rad(p_normal_split_angle)); + float normal_merge_threshold = Math::cos(Math::deg_to_rad(p_normal_merge_angle)); + float normal_pre_split_threshold = Math::cos(Math::deg_to_rad(MIN(180.0f, p_normal_split_angle * 2.0f))); + float normal_split_threshold = Math::cos(Math::deg_to_rad(p_normal_split_angle)); const Vector3 *normals_ptr = normals.ptr(); HashMap<Vector3, LocalVector<Pair<int, int>>> unique_vertices; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 0e1b18d584..33334801c3 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -279,25 +279,36 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { Ref<Resource> res = value; if (res.is_valid()) { if (res->is_local_to_scene()) { - HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = resources_local_to_scene.find(res); - - if (E) { - value = E->value; + // In a situation where a local-to-scene resource is used in a child node of a non-editable instance, + // we need to avoid the parent scene from overriding the resource potentially also used in the root + // of the instantiated scene. That would to the instance having two different instances of the resource. + // Since at this point it's too late to propagate the resource instance in the parent scene to all the relevant + // nodes in the instance (and that would require very complex bookkepping), what we do instead is + // tampering the resource object already there with the values from the node in the parent scene and + // then tell this node to reference that resource. + if (n.instance >= 0) { + Ref<Resource> node_res = node->get(snames[nprops[j].name]); + if (node_res.is_valid()) { + node_res->copy_from(res); + node_res->configure_for_local_scene(node, resources_local_to_scene); + value = node_res; + } } else { + HashMap<Ref<Resource>, Ref<Resource>>::Iterator E = resources_local_to_scene.find(res); Node *base = i == 0 ? node : ret_nodes[0]; - - if (p_edit_state == GEN_EDIT_STATE_MAIN || p_edit_state == GEN_EDIT_STATE_MAIN_INHERITED) { - //for the main scene, use the resource as is - res->configure_for_local_scene(base, resources_local_to_scene); - resources_local_to_scene[res] = res; - + if (E) { + value = E->value; } else { - //for instances, a copy must be made - Node *base2 = i == 0 ? node : ret_nodes[0]; - Ref<Resource> local_dupe = res->duplicate_for_local_scene(base2, resources_local_to_scene); - resources_local_to_scene[res] = local_dupe; - res = local_dupe; - value = local_dupe; + if (p_edit_state == GEN_EDIT_STATE_MAIN) { + //for the main scene, use the resource as is + res->configure_for_local_scene(base, resources_local_to_scene); + resources_local_to_scene[res] = res; + } else { + //for instances, a copy must be made + Ref<Resource> local_dupe = res->duplicate_for_local_scene(base, resources_local_to_scene); + resources_local_to_scene[res] = local_dupe; + value = local_dupe; + } } } //must make a copy, because this res is local to scene @@ -398,7 +409,9 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { } for (KeyValue<Ref<Resource>, Ref<Resource>> &E : resources_local_to_scene) { - E.value->setup_local_to_scene(); + if (E.value->get_local_scene() == ret_nodes[0]) { + E.value->setup_local_to_scene(); + } } //do connections diff --git a/scene/resources/particles_material.cpp b/scene/resources/particle_process_material.cpp index 29a06622a3..ed19101de4 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particle_process_material.cpp @@ -1,5 +1,5 @@ /*************************************************************************/ -/* particles_material.cpp */ +/* particle_process_material.cpp */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,17 +28,17 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /*************************************************************************/ -#include "particles_material.h" +#include "particle_process_material.h" #include "core/version.h" -Mutex ParticlesMaterial::material_mutex; -SelfList<ParticlesMaterial>::List *ParticlesMaterial::dirty_materials = nullptr; -HashMap<ParticlesMaterial::MaterialKey, ParticlesMaterial::ShaderData, ParticlesMaterial::MaterialKey> ParticlesMaterial::shader_map; -ParticlesMaterial::ShaderNames *ParticlesMaterial::shader_names = nullptr; +Mutex ParticleProcessMaterial::material_mutex; +SelfList<ParticleProcessMaterial>::List *ParticleProcessMaterial::dirty_materials = nullptr; +HashMap<ParticleProcessMaterial::MaterialKey, ParticleProcessMaterial::ShaderData, ParticleProcessMaterial::MaterialKey> ParticleProcessMaterial::shader_map; +ParticleProcessMaterial::ShaderNames *ParticleProcessMaterial::shader_names = nullptr; -void ParticlesMaterial::init_shaders() { - dirty_materials = memnew(SelfList<ParticlesMaterial>::List); +void ParticleProcessMaterial::init_shaders() { + dirty_materials = memnew(SelfList<ParticleProcessMaterial>::List); shader_names = memnew(ShaderNames); @@ -121,14 +121,14 @@ void ParticlesMaterial::init_shaders() { shader_names->collision_bounce = "collision_bounce"; } -void ParticlesMaterial::finish_shaders() { +void ParticleProcessMaterial::finish_shaders() { memdelete(dirty_materials); dirty_materials = nullptr; memdelete(shader_names); } -void ParticlesMaterial::_update_shader() { +void ParticleProcessMaterial::_update_shader() { dirty_materials->remove(&element); MaterialKey mk = _compute_key(); @@ -155,7 +155,7 @@ void ParticlesMaterial::_update_shader() { //must create a shader! // Add a comment to describe the shader origin (useful when converting to ShaderMaterial). - String code = "// NOTE: Shader automatically converted from " VERSION_NAME " " VERSION_FULL_CONFIG "'s ParticlesMaterial.\n\n"; + String code = "// NOTE: Shader automatically converted from " VERSION_NAME " " VERSION_FULL_CONFIG "'s ParticleProcessMaterial.\n\n"; code += "shader_type particles;\n"; @@ -908,7 +908,7 @@ void ParticlesMaterial::_update_shader() { RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } -void ParticlesMaterial::flush_changes() { +void ParticleProcessMaterial::flush_changes() { MutexLock lock(material_mutex); while (dirty_materials->first()) { @@ -916,7 +916,7 @@ void ParticlesMaterial::flush_changes() { } } -void ParticlesMaterial::_queue_shader_change() { +void ParticleProcessMaterial::_queue_shader_change() { MutexLock lock(material_mutex); if (is_initialized && !element.in_list()) { @@ -924,40 +924,40 @@ void ParticlesMaterial::_queue_shader_change() { } } -bool ParticlesMaterial::_is_shader_dirty() const { +bool ParticleProcessMaterial::_is_shader_dirty() const { MutexLock lock(material_mutex); return element.in_list(); } -void ParticlesMaterial::set_direction(Vector3 p_direction) { +void ParticleProcessMaterial::set_direction(Vector3 p_direction) { direction = p_direction; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->direction, direction); } -Vector3 ParticlesMaterial::get_direction() const { +Vector3 ParticleProcessMaterial::get_direction() const { return direction; } -void ParticlesMaterial::set_spread(float p_spread) { +void ParticleProcessMaterial::set_spread(float p_spread) { spread = p_spread; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); } -float ParticlesMaterial::get_spread() const { +float ParticleProcessMaterial::get_spread() const { return spread; } -void ParticlesMaterial::set_flatness(float p_flatness) { +void ParticleProcessMaterial::set_flatness(float p_flatness) { flatness = p_flatness; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); } -float ParticlesMaterial::get_flatness() const { +float ParticleProcessMaterial::get_flatness() const { return flatness; } -void ParticlesMaterial::set_param_min(Parameter p_param, float p_value) { +void ParticleProcessMaterial::set_param_min(Parameter p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params_min[p_param] = p_value; @@ -1016,13 +1016,13 @@ void ParticlesMaterial::set_param_min(Parameter p_param, float p_value) { } } -float ParticlesMaterial::get_param_min(Parameter p_param) const { +float ParticleProcessMaterial::get_param_min(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return params_min[p_param]; } -void ParticlesMaterial::set_param_max(Parameter p_param, float p_value) { +void ParticleProcessMaterial::set_param_max(Parameter p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params_max[p_param] = p_value; @@ -1081,7 +1081,7 @@ void ParticlesMaterial::set_param_max(Parameter p_param, float p_value) { } } -float ParticlesMaterial::get_param_max(Parameter p_param) const { +float ParticleProcessMaterial::get_param_max(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, 0); return params_max[p_param]; @@ -1096,7 +1096,7 @@ static void _adjust_curve_range(const Ref<Texture2D> &p_texture, float p_min, fl curve_tex->ensure_default_setup(p_min, p_max); } -void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture) { +void ParticleProcessMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D> &p_texture) { ERR_FAIL_INDEX(p_param, PARAM_MAX); tex_parameters[p_param] = p_texture; @@ -1167,22 +1167,22 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Ref<Texture2D _queue_shader_change(); } -Ref<Texture2D> ParticlesMaterial::get_param_texture(Parameter p_param) const { +Ref<Texture2D> ParticleProcessMaterial::get_param_texture(Parameter p_param) const { ERR_FAIL_INDEX_V(p_param, PARAM_MAX, Ref<Texture2D>()); return tex_parameters[p_param]; } -void ParticlesMaterial::set_color(const Color &p_color) { +void ParticleProcessMaterial::set_color(const Color &p_color) { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); color = p_color; } -Color ParticlesMaterial::get_color() const { +Color ParticleProcessMaterial::get_color() const { return color; } -void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) { +void ParticleProcessMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) { color_ramp = p_texture; RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, tex_rid); @@ -1190,11 +1190,11 @@ void ParticlesMaterial::set_color_ramp(const Ref<Texture2D> &p_texture) { notify_property_list_changed(); } -Ref<Texture2D> ParticlesMaterial::get_color_ramp() const { +Ref<Texture2D> ParticleProcessMaterial::get_color_ramp() const { return color_ramp; } -void ParticlesMaterial::set_color_initial_ramp(const Ref<Texture2D> &p_texture) { +void ParticleProcessMaterial::set_color_initial_ramp(const Ref<Texture2D> &p_texture) { color_initial_ramp = p_texture; RID tex_rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_initial_ramp, tex_rid); @@ -1202,11 +1202,11 @@ void ParticlesMaterial::set_color_initial_ramp(const Ref<Texture2D> &p_texture) notify_property_list_changed(); } -Ref<Texture2D> ParticlesMaterial::get_color_initial_ramp() const { +Ref<Texture2D> ParticleProcessMaterial::get_color_initial_ramp() const { return color_initial_ramp; } -void ParticlesMaterial::set_particle_flag(ParticleFlags p_particle_flag, bool p_enable) { +void ParticleProcessMaterial::set_particle_flag(ParticleFlags p_particle_flag, bool p_enable) { ERR_FAIL_INDEX(p_particle_flag, PARTICLE_FLAG_MAX); particle_flags[p_particle_flag] = p_enable; _queue_shader_change(); @@ -1215,165 +1215,165 @@ void ParticlesMaterial::set_particle_flag(ParticleFlags p_particle_flag, bool p_ } } -bool ParticlesMaterial::get_particle_flag(ParticleFlags p_particle_flag) const { +bool ParticleProcessMaterial::get_particle_flag(ParticleFlags p_particle_flag) const { ERR_FAIL_INDEX_V(p_particle_flag, PARTICLE_FLAG_MAX, false); return particle_flags[p_particle_flag]; } -void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { +void ParticleProcessMaterial::set_emission_shape(EmissionShape p_shape) { ERR_FAIL_INDEX(p_shape, EMISSION_SHAPE_MAX); emission_shape = p_shape; notify_property_list_changed(); _queue_shader_change(); } -void ParticlesMaterial::set_emission_sphere_radius(real_t p_radius) { +void ParticleProcessMaterial::set_emission_sphere_radius(real_t p_radius) { emission_sphere_radius = p_radius; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); } -void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { +void ParticleProcessMaterial::set_emission_box_extents(Vector3 p_extents) { emission_box_extents = p_extents; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); } -void ParticlesMaterial::set_emission_point_texture(const Ref<Texture2D> &p_points) { +void ParticleProcessMaterial::set_emission_point_texture(const Ref<Texture2D> &p_points) { emission_point_texture = p_points; RID tex_rid = p_points.is_valid() ? p_points->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, tex_rid); } -void ParticlesMaterial::set_emission_normal_texture(const Ref<Texture2D> &p_normals) { +void ParticleProcessMaterial::set_emission_normal_texture(const Ref<Texture2D> &p_normals) { emission_normal_texture = p_normals; RID tex_rid = p_normals.is_valid() ? p_normals->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, tex_rid); } -void ParticlesMaterial::set_emission_color_texture(const Ref<Texture2D> &p_colors) { +void ParticleProcessMaterial::set_emission_color_texture(const Ref<Texture2D> &p_colors) { emission_color_texture = p_colors; RID tex_rid = p_colors.is_valid() ? p_colors->get_rid() : RID(); RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, tex_rid); _queue_shader_change(); } -void ParticlesMaterial::set_emission_point_count(int p_count) { +void ParticleProcessMaterial::set_emission_point_count(int p_count) { emission_point_count = p_count; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); } -void ParticlesMaterial::set_emission_ring_axis(Vector3 p_axis) { +void ParticleProcessMaterial::set_emission_ring_axis(Vector3 p_axis) { emission_ring_axis = p_axis; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_axis, p_axis); } -void ParticlesMaterial::set_emission_ring_height(real_t p_height) { +void ParticleProcessMaterial::set_emission_ring_height(real_t p_height) { emission_ring_height = p_height; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_height, p_height); } -void ParticlesMaterial::set_emission_ring_radius(real_t p_radius) { +void ParticleProcessMaterial::set_emission_ring_radius(real_t p_radius) { emission_ring_radius = p_radius; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_radius, p_radius); } -void ParticlesMaterial::set_emission_ring_inner_radius(real_t p_radius) { +void ParticleProcessMaterial::set_emission_ring_inner_radius(real_t p_radius) { emission_ring_inner_radius = p_radius; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_ring_inner_radius, p_radius); } -ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { +ParticleProcessMaterial::EmissionShape ParticleProcessMaterial::get_emission_shape() const { return emission_shape; } -real_t ParticlesMaterial::get_emission_sphere_radius() const { +real_t ParticleProcessMaterial::get_emission_sphere_radius() const { return emission_sphere_radius; } -Vector3 ParticlesMaterial::get_emission_box_extents() const { +Vector3 ParticleProcessMaterial::get_emission_box_extents() const { return emission_box_extents; } -Ref<Texture2D> ParticlesMaterial::get_emission_point_texture() const { +Ref<Texture2D> ParticleProcessMaterial::get_emission_point_texture() const { return emission_point_texture; } -Ref<Texture2D> ParticlesMaterial::get_emission_normal_texture() const { +Ref<Texture2D> ParticleProcessMaterial::get_emission_normal_texture() const { return emission_normal_texture; } -Ref<Texture2D> ParticlesMaterial::get_emission_color_texture() const { +Ref<Texture2D> ParticleProcessMaterial::get_emission_color_texture() const { return emission_color_texture; } -int ParticlesMaterial::get_emission_point_count() const { +int ParticleProcessMaterial::get_emission_point_count() const { return emission_point_count; } -Vector3 ParticlesMaterial::get_emission_ring_axis() const { +Vector3 ParticleProcessMaterial::get_emission_ring_axis() const { return emission_ring_axis; } -real_t ParticlesMaterial::get_emission_ring_height() const { +real_t ParticleProcessMaterial::get_emission_ring_height() const { return emission_ring_height; } -real_t ParticlesMaterial::get_emission_ring_radius() const { +real_t ParticleProcessMaterial::get_emission_ring_radius() const { return emission_ring_radius; } -real_t ParticlesMaterial::get_emission_ring_inner_radius() const { +real_t ParticleProcessMaterial::get_emission_ring_inner_radius() const { return emission_ring_inner_radius; } -void ParticlesMaterial::set_turbulence_enabled(const bool p_turbulence_enabled) { +void ParticleProcessMaterial::set_turbulence_enabled(const bool p_turbulence_enabled) { turbulence_enabled = p_turbulence_enabled; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_enabled, turbulence_enabled); _queue_shader_change(); notify_property_list_changed(); } -bool ParticlesMaterial::get_turbulence_enabled() const { +bool ParticleProcessMaterial::get_turbulence_enabled() const { return turbulence_enabled; } -void ParticlesMaterial::set_turbulence_noise_strength(float p_turbulence_noise_strength) { +void ParticleProcessMaterial::set_turbulence_noise_strength(float p_turbulence_noise_strength) { turbulence_noise_strength = p_turbulence_noise_strength; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_strength, p_turbulence_noise_strength); } -float ParticlesMaterial::get_turbulence_noise_strength() const { +float ParticleProcessMaterial::get_turbulence_noise_strength() const { return turbulence_noise_strength; } -void ParticlesMaterial::set_turbulence_noise_scale(float p_turbulence_noise_scale) { +void ParticleProcessMaterial::set_turbulence_noise_scale(float p_turbulence_noise_scale) { turbulence_noise_scale = p_turbulence_noise_scale; float shader_turbulence_noise_scale = (pow(p_turbulence_noise_scale, 0.25) * 5.6234 / 10.0) * 4.0 - 3.0; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_scale, shader_turbulence_noise_scale); } -float ParticlesMaterial::get_turbulence_noise_scale() const { +float ParticleProcessMaterial::get_turbulence_noise_scale() const { return turbulence_noise_scale; } -void ParticlesMaterial::set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random) { +void ParticleProcessMaterial::set_turbulence_noise_speed_random(float p_turbulence_noise_speed_random) { turbulence_noise_speed_random = p_turbulence_noise_speed_random; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed_random, p_turbulence_noise_speed_random); } -float ParticlesMaterial::get_turbulence_noise_speed_random() const { +float ParticleProcessMaterial::get_turbulence_noise_speed_random() const { return turbulence_noise_speed_random; } -void ParticlesMaterial::set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed) { +void ParticleProcessMaterial::set_turbulence_noise_speed(const Vector3 &p_turbulence_noise_speed) { turbulence_noise_speed = p_turbulence_noise_speed; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->turbulence_noise_speed, turbulence_noise_speed); } -Vector3 ParticlesMaterial::get_turbulence_noise_speed() const { +Vector3 ParticleProcessMaterial::get_turbulence_noise_speed() const { return turbulence_noise_speed; } -void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { +void ParticleProcessMaterial::set_gravity(const Vector3 &p_gravity) { gravity = p_gravity; Vector3 gset = gravity; if (gset == Vector3()) { @@ -1382,25 +1382,25 @@ void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); } -Vector3 ParticlesMaterial::get_gravity() const { +Vector3 ParticleProcessMaterial::get_gravity() const { return gravity; } -void ParticlesMaterial::set_lifetime_randomness(double p_lifetime) { +void ParticleProcessMaterial::set_lifetime_randomness(double p_lifetime) { lifetime_randomness = p_lifetime; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->lifetime_randomness, lifetime_randomness); } -double ParticlesMaterial::get_lifetime_randomness() const { +double ParticleProcessMaterial::get_lifetime_randomness() const { return lifetime_randomness; } -RID ParticlesMaterial::get_shader_rid() const { +RID ParticleProcessMaterial::get_shader_rid() const { ERR_FAIL_COND_V(!shader_map.has(current_key), RID()); return shader_map[current_key].shader; } -void ParticlesMaterial::_validate_property(PropertyInfo &p_property) const { +void ParticleProcessMaterial::_validate_property(PropertyInfo &p_property) const { if (p_property.name == "emission_sphere_radius" && (emission_shape != EMISSION_SHAPE_SPHERE && emission_shape != EMISSION_SHAPE_SPHERE_SURFACE)) { p_property.usage = PROPERTY_USAGE_NONE; } @@ -1460,203 +1460,203 @@ void ParticlesMaterial::_validate_property(PropertyInfo &p_property) const { } } -void ParticlesMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { +void ParticleProcessMaterial::set_sub_emitter_mode(SubEmitterMode p_sub_emitter_mode) { sub_emitter_mode = p_sub_emitter_mode; _queue_shader_change(); notify_property_list_changed(); } -ParticlesMaterial::SubEmitterMode ParticlesMaterial::get_sub_emitter_mode() const { +ParticleProcessMaterial::SubEmitterMode ParticleProcessMaterial::get_sub_emitter_mode() const { return sub_emitter_mode; } -void ParticlesMaterial::set_sub_emitter_frequency(double p_frequency) { +void ParticleProcessMaterial::set_sub_emitter_frequency(double p_frequency) { sub_emitter_frequency = p_frequency; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_frequency, 1.0 / p_frequency); //pass delta instead of frequency, since its easier to compute } -double ParticlesMaterial::get_sub_emitter_frequency() const { +double ParticleProcessMaterial::get_sub_emitter_frequency() const { return sub_emitter_frequency; } -void ParticlesMaterial::set_sub_emitter_amount_at_end(int p_amount) { +void ParticleProcessMaterial::set_sub_emitter_amount_at_end(int p_amount) { sub_emitter_amount_at_end = p_amount; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_amount_at_end, p_amount); } -int ParticlesMaterial::get_sub_emitter_amount_at_end() const { +int ParticleProcessMaterial::get_sub_emitter_amount_at_end() const { return sub_emitter_amount_at_end; } -void ParticlesMaterial::set_sub_emitter_keep_velocity(bool p_enable) { +void ParticleProcessMaterial::set_sub_emitter_keep_velocity(bool p_enable) { sub_emitter_keep_velocity = p_enable; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->sub_emitter_keep_velocity, p_enable); } -bool ParticlesMaterial::get_sub_emitter_keep_velocity() const { +bool ParticleProcessMaterial::get_sub_emitter_keep_velocity() const { return sub_emitter_keep_velocity; } -void ParticlesMaterial::set_attractor_interaction_enabled(bool p_enable) { +void ParticleProcessMaterial::set_attractor_interaction_enabled(bool p_enable) { attractor_interaction_enabled = p_enable; _queue_shader_change(); } -bool ParticlesMaterial::is_attractor_interaction_enabled() const { +bool ParticleProcessMaterial::is_attractor_interaction_enabled() const { return attractor_interaction_enabled; } -void ParticlesMaterial::set_collision_mode(CollisionMode p_collision_mode) { +void ParticleProcessMaterial::set_collision_mode(CollisionMode p_collision_mode) { collision_mode = p_collision_mode; _queue_shader_change(); notify_property_list_changed(); } -ParticlesMaterial::CollisionMode ParticlesMaterial::get_collision_mode() const { +ParticleProcessMaterial::CollisionMode ParticleProcessMaterial::get_collision_mode() const { return collision_mode; } -void ParticlesMaterial::set_collision_use_scale(bool p_scale) { +void ParticleProcessMaterial::set_collision_use_scale(bool p_scale) { collision_scale = p_scale; _queue_shader_change(); } -bool ParticlesMaterial::is_collision_using_scale() const { +bool ParticleProcessMaterial::is_collision_using_scale() const { return collision_scale; } -void ParticlesMaterial::set_collision_friction(float p_friction) { +void ParticleProcessMaterial::set_collision_friction(float p_friction) { collision_friction = p_friction; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->collision_friction, p_friction); } -float ParticlesMaterial::get_collision_friction() const { +float ParticleProcessMaterial::get_collision_friction() const { return collision_friction; } -void ParticlesMaterial::set_collision_bounce(float p_bounce) { +void ParticleProcessMaterial::set_collision_bounce(float p_bounce) { collision_bounce = p_bounce; RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->collision_bounce, p_bounce); } -float ParticlesMaterial::get_collision_bounce() const { +float ParticleProcessMaterial::get_collision_bounce() const { return collision_bounce; } -Shader::Mode ParticlesMaterial::get_shader_mode() const { +Shader::Mode ParticleProcessMaterial::get_shader_mode() const { return Shader::MODE_PARTICLES; } -void ParticlesMaterial::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_direction", "degrees"), &ParticlesMaterial::set_direction); - ClassDB::bind_method(D_METHOD("get_direction"), &ParticlesMaterial::get_direction); +void ParticleProcessMaterial::_bind_methods() { + ClassDB::bind_method(D_METHOD("set_direction", "degrees"), &ParticleProcessMaterial::set_direction); + ClassDB::bind_method(D_METHOD("get_direction"), &ParticleProcessMaterial::get_direction); - ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticlesMaterial::set_spread); - ClassDB::bind_method(D_METHOD("get_spread"), &ParticlesMaterial::get_spread); + ClassDB::bind_method(D_METHOD("set_spread", "degrees"), &ParticleProcessMaterial::set_spread); + ClassDB::bind_method(D_METHOD("get_spread"), &ParticleProcessMaterial::get_spread); - ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticlesMaterial::set_flatness); - ClassDB::bind_method(D_METHOD("get_flatness"), &ParticlesMaterial::get_flatness); + ClassDB::bind_method(D_METHOD("set_flatness", "amount"), &ParticleProcessMaterial::set_flatness); + ClassDB::bind_method(D_METHOD("get_flatness"), &ParticleProcessMaterial::get_flatness); - ClassDB::bind_method(D_METHOD("set_param_min", "param", "value"), &ParticlesMaterial::set_param_min); - ClassDB::bind_method(D_METHOD("get_param_min", "param"), &ParticlesMaterial::get_param_min); + ClassDB::bind_method(D_METHOD("set_param_min", "param", "value"), &ParticleProcessMaterial::set_param_min); + ClassDB::bind_method(D_METHOD("get_param_min", "param"), &ParticleProcessMaterial::get_param_min); - ClassDB::bind_method(D_METHOD("set_param_max", "param", "value"), &ParticlesMaterial::set_param_max); - ClassDB::bind_method(D_METHOD("get_param_max", "param"), &ParticlesMaterial::get_param_max); + ClassDB::bind_method(D_METHOD("set_param_max", "param", "value"), &ParticleProcessMaterial::set_param_max); + ClassDB::bind_method(D_METHOD("get_param_max", "param"), &ParticleProcessMaterial::get_param_max); - ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticlesMaterial::set_param_texture); - ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticlesMaterial::get_param_texture); + ClassDB::bind_method(D_METHOD("set_param_texture", "param", "texture"), &ParticleProcessMaterial::set_param_texture); + ClassDB::bind_method(D_METHOD("get_param_texture", "param"), &ParticleProcessMaterial::get_param_texture); - ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticlesMaterial::set_color); - ClassDB::bind_method(D_METHOD("get_color"), &ParticlesMaterial::get_color); + ClassDB::bind_method(D_METHOD("set_color", "color"), &ParticleProcessMaterial::set_color); + ClassDB::bind_method(D_METHOD("get_color"), &ParticleProcessMaterial::get_color); - ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &ParticlesMaterial::set_color_ramp); - ClassDB::bind_method(D_METHOD("get_color_ramp"), &ParticlesMaterial::get_color_ramp); + ClassDB::bind_method(D_METHOD("set_color_ramp", "ramp"), &ParticleProcessMaterial::set_color_ramp); + ClassDB::bind_method(D_METHOD("get_color_ramp"), &ParticleProcessMaterial::get_color_ramp); - ClassDB::bind_method(D_METHOD("set_color_initial_ramp", "ramp"), &ParticlesMaterial::set_color_initial_ramp); - ClassDB::bind_method(D_METHOD("get_color_initial_ramp"), &ParticlesMaterial::get_color_initial_ramp); + ClassDB::bind_method(D_METHOD("set_color_initial_ramp", "ramp"), &ParticleProcessMaterial::set_color_initial_ramp); + ClassDB::bind_method(D_METHOD("get_color_initial_ramp"), &ParticleProcessMaterial::get_color_initial_ramp); - ClassDB::bind_method(D_METHOD("set_particle_flag", "particle_flag", "enable"), &ParticlesMaterial::set_particle_flag); - ClassDB::bind_method(D_METHOD("get_particle_flag", "particle_flag"), &ParticlesMaterial::get_particle_flag); + ClassDB::bind_method(D_METHOD("set_particle_flag", "particle_flag", "enable"), &ParticleProcessMaterial::set_particle_flag); + ClassDB::bind_method(D_METHOD("get_particle_flag", "particle_flag"), &ParticleProcessMaterial::get_particle_flag); - ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticlesMaterial::set_emission_shape); - ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticlesMaterial::get_emission_shape); + ClassDB::bind_method(D_METHOD("set_emission_shape", "shape"), &ParticleProcessMaterial::set_emission_shape); + ClassDB::bind_method(D_METHOD("get_emission_shape"), &ParticleProcessMaterial::get_emission_shape); - ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticlesMaterial::set_emission_sphere_radius); - ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticlesMaterial::get_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("set_emission_sphere_radius", "radius"), &ParticleProcessMaterial::set_emission_sphere_radius); + ClassDB::bind_method(D_METHOD("get_emission_sphere_radius"), &ParticleProcessMaterial::get_emission_sphere_radius); - ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticlesMaterial::set_emission_box_extents); - ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticlesMaterial::get_emission_box_extents); + ClassDB::bind_method(D_METHOD("set_emission_box_extents", "extents"), &ParticleProcessMaterial::set_emission_box_extents); + ClassDB::bind_method(D_METHOD("get_emission_box_extents"), &ParticleProcessMaterial::get_emission_box_extents); - ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture"), &ParticlesMaterial::set_emission_point_texture); - ClassDB::bind_method(D_METHOD("get_emission_point_texture"), &ParticlesMaterial::get_emission_point_texture); + ClassDB::bind_method(D_METHOD("set_emission_point_texture", "texture"), &ParticleProcessMaterial::set_emission_point_texture); + ClassDB::bind_method(D_METHOD("get_emission_point_texture"), &ParticleProcessMaterial::get_emission_point_texture); - ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture"), &ParticlesMaterial::set_emission_normal_texture); - ClassDB::bind_method(D_METHOD("get_emission_normal_texture"), &ParticlesMaterial::get_emission_normal_texture); + ClassDB::bind_method(D_METHOD("set_emission_normal_texture", "texture"), &ParticleProcessMaterial::set_emission_normal_texture); + ClassDB::bind_method(D_METHOD("get_emission_normal_texture"), &ParticleProcessMaterial::get_emission_normal_texture); - ClassDB::bind_method(D_METHOD("set_emission_color_texture", "texture"), &ParticlesMaterial::set_emission_color_texture); - ClassDB::bind_method(D_METHOD("get_emission_color_texture"), &ParticlesMaterial::get_emission_color_texture); + ClassDB::bind_method(D_METHOD("set_emission_color_texture", "texture"), &ParticleProcessMaterial::set_emission_color_texture); + ClassDB::bind_method(D_METHOD("get_emission_color_texture"), &ParticleProcessMaterial::get_emission_color_texture); - ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticlesMaterial::set_emission_point_count); - ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticlesMaterial::get_emission_point_count); + ClassDB::bind_method(D_METHOD("set_emission_point_count", "point_count"), &ParticleProcessMaterial::set_emission_point_count); + ClassDB::bind_method(D_METHOD("get_emission_point_count"), &ParticleProcessMaterial::get_emission_point_count); - ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &ParticlesMaterial::set_emission_ring_axis); - ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &ParticlesMaterial::get_emission_ring_axis); + ClassDB::bind_method(D_METHOD("set_emission_ring_axis", "axis"), &ParticleProcessMaterial::set_emission_ring_axis); + ClassDB::bind_method(D_METHOD("get_emission_ring_axis"), &ParticleProcessMaterial::get_emission_ring_axis); - ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &ParticlesMaterial::set_emission_ring_height); - ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &ParticlesMaterial::get_emission_ring_height); + ClassDB::bind_method(D_METHOD("set_emission_ring_height", "height"), &ParticleProcessMaterial::set_emission_ring_height); + ClassDB::bind_method(D_METHOD("get_emission_ring_height"), &ParticleProcessMaterial::get_emission_ring_height); - ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &ParticlesMaterial::set_emission_ring_radius); - ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &ParticlesMaterial::get_emission_ring_radius); + ClassDB::bind_method(D_METHOD("set_emission_ring_radius", "radius"), &ParticleProcessMaterial::set_emission_ring_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_radius"), &ParticleProcessMaterial::get_emission_ring_radius); - ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticlesMaterial::set_emission_ring_inner_radius); - ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticlesMaterial::get_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("set_emission_ring_inner_radius", "inner_radius"), &ParticleProcessMaterial::set_emission_ring_inner_radius); + ClassDB::bind_method(D_METHOD("get_emission_ring_inner_radius"), &ParticleProcessMaterial::get_emission_ring_inner_radius); - ClassDB::bind_method(D_METHOD("get_turbulence_enabled"), &ParticlesMaterial::get_turbulence_enabled); - ClassDB::bind_method(D_METHOD("set_turbulence_enabled", "turbulence_enabled"), &ParticlesMaterial::set_turbulence_enabled); + ClassDB::bind_method(D_METHOD("get_turbulence_enabled"), &ParticleProcessMaterial::get_turbulence_enabled); + ClassDB::bind_method(D_METHOD("set_turbulence_enabled", "turbulence_enabled"), &ParticleProcessMaterial::set_turbulence_enabled); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_strength"), &ParticlesMaterial::get_turbulence_noise_strength); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_strength", "turbulence_noise_strength"), &ParticlesMaterial::set_turbulence_noise_strength); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_strength"), &ParticleProcessMaterial::get_turbulence_noise_strength); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_strength", "turbulence_noise_strength"), &ParticleProcessMaterial::set_turbulence_noise_strength); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_scale"), &ParticlesMaterial::get_turbulence_noise_scale); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_scale", "turbulence_noise_scale"), &ParticlesMaterial::set_turbulence_noise_scale); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_scale"), &ParticleProcessMaterial::get_turbulence_noise_scale); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_scale", "turbulence_noise_scale"), &ParticleProcessMaterial::set_turbulence_noise_scale); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed_random"), &ParticlesMaterial::get_turbulence_noise_speed_random); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed_random", "turbulence_noise_speed_random"), &ParticlesMaterial::set_turbulence_noise_speed_random); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed_random"), &ParticleProcessMaterial::get_turbulence_noise_speed_random); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed_random", "turbulence_noise_speed_random"), &ParticleProcessMaterial::set_turbulence_noise_speed_random); - ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed"), &ParticlesMaterial::get_turbulence_noise_speed); - ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed", "turbulence_noise_speed"), &ParticlesMaterial::set_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("get_turbulence_noise_speed"), &ParticleProcessMaterial::get_turbulence_noise_speed); + ClassDB::bind_method(D_METHOD("set_turbulence_noise_speed", "turbulence_noise_speed"), &ParticleProcessMaterial::set_turbulence_noise_speed); - ClassDB::bind_method(D_METHOD("get_gravity"), &ParticlesMaterial::get_gravity); - ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticlesMaterial::set_gravity); + ClassDB::bind_method(D_METHOD("get_gravity"), &ParticleProcessMaterial::get_gravity); + ClassDB::bind_method(D_METHOD("set_gravity", "accel_vec"), &ParticleProcessMaterial::set_gravity); - ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "randomness"), &ParticlesMaterial::set_lifetime_randomness); - ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &ParticlesMaterial::get_lifetime_randomness); + ClassDB::bind_method(D_METHOD("set_lifetime_randomness", "randomness"), &ParticleProcessMaterial::set_lifetime_randomness); + ClassDB::bind_method(D_METHOD("get_lifetime_randomness"), &ParticleProcessMaterial::get_lifetime_randomness); - ClassDB::bind_method(D_METHOD("get_sub_emitter_mode"), &ParticlesMaterial::get_sub_emitter_mode); - ClassDB::bind_method(D_METHOD("set_sub_emitter_mode", "mode"), &ParticlesMaterial::set_sub_emitter_mode); + ClassDB::bind_method(D_METHOD("get_sub_emitter_mode"), &ParticleProcessMaterial::get_sub_emitter_mode); + ClassDB::bind_method(D_METHOD("set_sub_emitter_mode", "mode"), &ParticleProcessMaterial::set_sub_emitter_mode); - ClassDB::bind_method(D_METHOD("get_sub_emitter_frequency"), &ParticlesMaterial::get_sub_emitter_frequency); - ClassDB::bind_method(D_METHOD("set_sub_emitter_frequency", "hz"), &ParticlesMaterial::set_sub_emitter_frequency); + ClassDB::bind_method(D_METHOD("get_sub_emitter_frequency"), &ParticleProcessMaterial::get_sub_emitter_frequency); + ClassDB::bind_method(D_METHOD("set_sub_emitter_frequency", "hz"), &ParticleProcessMaterial::set_sub_emitter_frequency); - ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_end"), &ParticlesMaterial::get_sub_emitter_amount_at_end); - ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_end", "amount"), &ParticlesMaterial::set_sub_emitter_amount_at_end); + ClassDB::bind_method(D_METHOD("get_sub_emitter_amount_at_end"), &ParticleProcessMaterial::get_sub_emitter_amount_at_end); + ClassDB::bind_method(D_METHOD("set_sub_emitter_amount_at_end", "amount"), &ParticleProcessMaterial::set_sub_emitter_amount_at_end); - ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticlesMaterial::get_sub_emitter_keep_velocity); - ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticlesMaterial::set_sub_emitter_keep_velocity); + ClassDB::bind_method(D_METHOD("get_sub_emitter_keep_velocity"), &ParticleProcessMaterial::get_sub_emitter_keep_velocity); + ClassDB::bind_method(D_METHOD("set_sub_emitter_keep_velocity", "enable"), &ParticleProcessMaterial::set_sub_emitter_keep_velocity); - ClassDB::bind_method(D_METHOD("set_attractor_interaction_enabled", "enabled"), &ParticlesMaterial::set_attractor_interaction_enabled); - ClassDB::bind_method(D_METHOD("is_attractor_interaction_enabled"), &ParticlesMaterial::is_attractor_interaction_enabled); + ClassDB::bind_method(D_METHOD("set_attractor_interaction_enabled", "enabled"), &ParticleProcessMaterial::set_attractor_interaction_enabled); + ClassDB::bind_method(D_METHOD("is_attractor_interaction_enabled"), &ParticleProcessMaterial::is_attractor_interaction_enabled); - ClassDB::bind_method(D_METHOD("set_collision_mode", "mode"), &ParticlesMaterial::set_collision_mode); - ClassDB::bind_method(D_METHOD("get_collision_mode"), &ParticlesMaterial::get_collision_mode); + ClassDB::bind_method(D_METHOD("set_collision_mode", "mode"), &ParticleProcessMaterial::set_collision_mode); + ClassDB::bind_method(D_METHOD("get_collision_mode"), &ParticleProcessMaterial::get_collision_mode); - ClassDB::bind_method(D_METHOD("set_collision_use_scale", "radius"), &ParticlesMaterial::set_collision_use_scale); - ClassDB::bind_method(D_METHOD("is_collision_using_scale"), &ParticlesMaterial::is_collision_using_scale); + ClassDB::bind_method(D_METHOD("set_collision_use_scale", "radius"), &ParticleProcessMaterial::set_collision_use_scale); + ClassDB::bind_method(D_METHOD("is_collision_using_scale"), &ParticleProcessMaterial::is_collision_using_scale); - ClassDB::bind_method(D_METHOD("set_collision_friction", "friction"), &ParticlesMaterial::set_collision_friction); - ClassDB::bind_method(D_METHOD("get_collision_friction"), &ParticlesMaterial::get_collision_friction); + ClassDB::bind_method(D_METHOD("set_collision_friction", "friction"), &ParticleProcessMaterial::set_collision_friction); + ClassDB::bind_method(D_METHOD("get_collision_friction"), &ParticleProcessMaterial::get_collision_friction); - ClassDB::bind_method(D_METHOD("set_collision_bounce", "bounce"), &ParticlesMaterial::set_collision_bounce); - ClassDB::bind_method(D_METHOD("get_collision_bounce"), &ParticlesMaterial::get_collision_bounce); + ClassDB::bind_method(D_METHOD("set_collision_bounce", "bounce"), &ParticleProcessMaterial::set_collision_bounce); + ClassDB::bind_method(D_METHOD("get_collision_bounce"), &ParticleProcessMaterial::get_collision_bounce); ADD_GROUP("Time", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "lifetime_randomness", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_lifetime_randomness", "get_lifetime_randomness"); @@ -1806,7 +1806,7 @@ void ParticlesMaterial::_bind_methods() { BIND_ENUM_CONSTANT(COLLISION_MAX); } -ParticlesMaterial::ParticlesMaterial() : +ParticleProcessMaterial::ParticleProcessMaterial() : element(this) { set_direction(Vector3(1, 0, 0)); set_spread(45); @@ -1879,7 +1879,7 @@ ParticlesMaterial::ParticlesMaterial() : _queue_shader_change(); } -ParticlesMaterial::~ParticlesMaterial() { +ParticleProcessMaterial::~ParticleProcessMaterial() { MutexLock lock(material_mutex); if (shader_map.has(current_key)) { diff --git a/scene/resources/particles_material.h b/scene/resources/particle_process_material.h index 2e94e7e01a..fe4741d6e5 100644 --- a/scene/resources/particles_material.h +++ b/scene/resources/particle_process_material.h @@ -1,5 +1,5 @@ /*************************************************************************/ -/* particles_material.h */ +/* particle_process_material.h */ /*************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -31,8 +31,8 @@ #include "core/templates/rid.h" #include "scene/resources/material.h" -#ifndef PARTICLES_MATERIAL_H -#define PARTICLES_MATERIAL_H +#ifndef PARTICLE_PROCESS_MATERIAL_H +#define PARTICLE_PROCESS_MATERIAL_H /* TODO: @@ -41,8 +41,8 @@ -Proper trails */ -class ParticlesMaterial : public Material { - GDCLASS(ParticlesMaterial, Material); +class ParticleProcessMaterial : public Material { + GDCLASS(ParticleProcessMaterial, Material); public: enum Parameter { @@ -170,7 +170,7 @@ private: } static Mutex material_mutex; - static SelfList<ParticlesMaterial>::List *dirty_materials; + static SelfList<ParticleProcessMaterial>::List *dirty_materials; struct ShaderNames { StringName direction; @@ -254,7 +254,7 @@ private: static ShaderNames *shader_names; - SelfList<ParticlesMaterial> element; + SelfList<ParticleProcessMaterial> element; void _update_shader(); _FORCE_INLINE_ void _queue_shader_change(); @@ -425,14 +425,14 @@ public: virtual Shader::Mode get_shader_mode() const override; - ParticlesMaterial(); - ~ParticlesMaterial(); + ParticleProcessMaterial(); + ~ParticleProcessMaterial(); }; -VARIANT_ENUM_CAST(ParticlesMaterial::Parameter) -VARIANT_ENUM_CAST(ParticlesMaterial::ParticleFlags) -VARIANT_ENUM_CAST(ParticlesMaterial::EmissionShape) -VARIANT_ENUM_CAST(ParticlesMaterial::SubEmitterMode) -VARIANT_ENUM_CAST(ParticlesMaterial::CollisionMode) +VARIANT_ENUM_CAST(ParticleProcessMaterial::Parameter) +VARIANT_ENUM_CAST(ParticleProcessMaterial::ParticleFlags) +VARIANT_ENUM_CAST(ParticleProcessMaterial::EmissionShape) +VARIANT_ENUM_CAST(ParticleProcessMaterial::SubEmitterMode) +VARIANT_ENUM_CAST(ParticleProcessMaterial::CollisionMode) -#endif // PARTICLES_MATERIAL_H +#endif // PARTICLE_PROCESS_MATERIAL_H diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 7847acb318..e993936350 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -2458,9 +2458,7 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { dirty_text = false; dirty_font = false; - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - TS->shaped_text_fit_to_width(text_rid, width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); - } + dirty_lines = true; } else if (dirty_font) { int spans = TS->shaped_get_span_count(text_rid); for (int i = 0; i < spans; i++) { @@ -2471,81 +2469,138 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { } dirty_font = false; + dirty_lines = true; + } + + if (dirty_lines) { + for (int i = 0; i < lines_rid.size(); i++) { + TS->free_rid(lines_rid[i]); + } + lines_rid.clear(); + + BitField<TextServer::LineBreakFlag> autowrap_flags = TextServer::BREAK_MANDATORY; + switch (autowrap_mode) { + case TextServer::AUTOWRAP_WORD_SMART: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_ADAPTIVE | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_WORD: + autowrap_flags = TextServer::BREAK_WORD_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_ARBITRARY: + autowrap_flags = TextServer::BREAK_GRAPHEME_BOUND | TextServer::BREAK_MANDATORY; + break; + case TextServer::AUTOWRAP_OFF: + break; + } + PackedInt32Array line_breaks = TS->shaped_text_get_line_breaks(text_rid, width, 0, autowrap_flags); + + float max_line_w = 0.0; + for (int i = 0; i < line_breaks.size(); i = i + 2) { + RID line = TS->shaped_text_substr(text_rid, line_breaks[i], line_breaks[i + 1] - line_breaks[i]); + max_line_w = MAX(max_line_w, TS->shaped_text_get_width(line)); + lines_rid.push_back(line); + } + if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - TS->shaped_text_fit_to_width(text_rid, width, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); + for (int i = 0; i < lines_rid.size() - 1; i++) { + TS->shaped_text_fit_to_width(lines_rid[i], (width > 0) ? width : max_line_w, TextServer::JUSTIFICATION_WORD_BOUND | TextServer::JUSTIFICATION_KASHIDA); + } } + dirty_lines = false; } - Vector2 offset; - const Glyph *glyphs = TS->shaped_text_get_glyphs(text_rid); - int gl_size = TS->shaped_text_get_glyph_count(text_rid); - float line_width = TS->shaped_text_get_width(text_rid) * pixel_size; - - switch (horizontal_alignment) { - case HORIZONTAL_ALIGNMENT_LEFT: - offset.x = 0.0; - break; - case HORIZONTAL_ALIGNMENT_FILL: - case HORIZONTAL_ALIGNMENT_CENTER: { - offset.x = -line_width / 2.0; + float total_h = 0.0; + for (int i = 0; i < lines_rid.size(); i++) { + total_h += (TS->shaped_text_get_size(lines_rid[i]).y + line_spacing) * pixel_size; + } + + float vbegin = 0.0; + switch (vertical_alignment) { + case VERTICAL_ALIGNMENT_FILL: + case VERTICAL_ALIGNMENT_TOP: { + // Nothing. + } break; + case VERTICAL_ALIGNMENT_CENTER: { + vbegin = (total_h - line_spacing * pixel_size) / 2.0; } break; - case HORIZONTAL_ALIGNMENT_RIGHT: { - offset.x = -line_width; + case VERTICAL_ALIGNMENT_BOTTOM: { + vbegin = (total_h - line_spacing * pixel_size); } break; } - bool has_depth = !Math::is_zero_approx(depth); - - // Generate glyph data, precalculate size of the arrays and mesh bounds for UV. - int64_t p_size = 0; - int64_t i_size = 0; + Vector<Vector3> vertices; + Vector<Vector3> normals; + Vector<float> tangents; + Vector<Vector2> uvs; + Vector<int32_t> indices; Vector2 min_p = Vector2(INFINITY, INFINITY); Vector2 max_p = Vector2(-INFINITY, -INFINITY); - Vector2 offset_pre = offset; - for (int i = 0; i < gl_size; i++) { - if (glyphs[i].index == 0) { - offset.x += glyphs[i].advance * pixel_size * glyphs[i].repeat; - continue; + int32_t p_size = 0; + int32_t i_size = 0; + + Vector2 offset = Vector2(0, vbegin + lbl_offset.y * pixel_size); + for (int i = 0; i < lines_rid.size(); i++) { + const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); + int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]); + float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_LEFT: + offset.x = 0.0; + break; + case HORIZONTAL_ALIGNMENT_FILL: + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = -line_width / 2.0; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + offset.x = -line_width; + } break; } - if (glyphs[i].font_rid != RID()) { - GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index); - _generate_glyph_mesh_data(key, glyphs[i]); - GlyphMeshData &gl_data = cache[key]; - - p_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); - i_size += glyphs[i].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); - - if (has_depth) { - for (int j = 0; j < gl_data.contours.size(); j++) { - p_size += glyphs[i].repeat * gl_data.contours[j].size() * 4; - i_size += glyphs[i].repeat * gl_data.contours[j].size() * 6; - } - } + offset.x += lbl_offset.x * pixel_size; + offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size; - for (int j = 0; j < glyphs[i].repeat; j++) { - min_p.x = MIN(gl_data.min_p.x + offset_pre.x, min_p.x); - min_p.y = MIN(gl_data.min_p.y + offset_pre.y, min_p.y); - max_p.x = MAX(gl_data.max_p.x + offset_pre.x, max_p.x); - max_p.y = MAX(gl_data.max_p.y + offset_pre.y, max_p.y); + bool has_depth = !Math::is_zero_approx(depth); - offset_pre.x += glyphs[i].advance * pixel_size; + for (int j = 0; j < gl_size; j++) { + if (glyphs[j].index == 0) { + offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat; + continue; } - } else { - p_size += glyphs[i].repeat * 4; - i_size += glyphs[i].repeat * 6; + if (glyphs[j].font_rid != RID()) { + GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index); + _generate_glyph_mesh_data(key, glyphs[j]); + GlyphMeshData &gl_data = cache[key]; + + p_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); + i_size += glyphs[j].repeat * gl_data.triangles.size() * ((has_depth) ? 2 : 1); + + if (has_depth) { + for (int k = 0; k < gl_data.contours.size(); k++) { + p_size += glyphs[j].repeat * gl_data.contours[k].size() * 4; + i_size += glyphs[j].repeat * gl_data.contours[k].size() * 6; + } + } + + for (int r = 0; r < glyphs[j].repeat; r++) { + min_p.x = MIN(gl_data.min_p.x + offset.x, min_p.x); + min_p.y = MIN(gl_data.min_p.y - offset.y, min_p.y); + max_p.x = MAX(gl_data.max_p.x + offset.x, max_p.x); + max_p.y = MAX(gl_data.max_p.y - offset.y, max_p.y); - offset_pre.x += glyphs[i].advance * pixel_size * glyphs[i].repeat; + offset.x += glyphs[j].advance * pixel_size; + } + } else { + p_size += glyphs[j].repeat * 4; + i_size += glyphs[j].repeat * 6; + + offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat; + } } + offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size; } - Vector<Vector3> vertices; - Vector<Vector3> normals; - Vector<float> tangents; - Vector<Vector2> uvs; - Vector<int32_t> indices; - vertices.resize(p_size); normals.resize(p_size); uvs.resize(p_size); @@ -2561,149 +2616,176 @@ void TextMesh::_create_mesh_array(Array &p_arr) const { // Generate mesh. int32_t p_idx = 0; int32_t i_idx = 0; - for (int i = 0; i < gl_size; i++) { - if (glyphs[i].index == 0) { - offset.x += glyphs[i].advance * pixel_size * glyphs[i].repeat; - continue; + + offset = Vector2(0, vbegin + lbl_offset.y * pixel_size); + for (int i = 0; i < lines_rid.size(); i++) { + const Glyph *glyphs = TS->shaped_text_get_glyphs(lines_rid[i]); + int gl_size = TS->shaped_text_get_glyph_count(lines_rid[i]); + float line_width = TS->shaped_text_get_width(lines_rid[i]) * pixel_size; + + switch (horizontal_alignment) { + case HORIZONTAL_ALIGNMENT_LEFT: + offset.x = 0.0; + break; + case HORIZONTAL_ALIGNMENT_FILL: + case HORIZONTAL_ALIGNMENT_CENTER: { + offset.x = -line_width / 2.0; + } break; + case HORIZONTAL_ALIGNMENT_RIGHT: { + offset.x = -line_width; + } break; } - if (glyphs[i].font_rid != RID()) { - GlyphMeshKey key = GlyphMeshKey(glyphs[i].font_rid.get_id(), glyphs[i].index); - _generate_glyph_mesh_data(key, glyphs[i]); - const GlyphMeshData &gl_data = cache[key]; - - int64_t ts = gl_data.triangles.size(); - const Vector2 *ts_ptr = gl_data.triangles.ptr(); - - for (int j = 0; j < glyphs[i].repeat; j++) { - for (int k = 0; k < ts; k += 3) { - // Add front face. - for (int l = 0; l < 3; l++) { - Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0); - vertices_ptr[p_idx] = point; - normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0); - if (has_depth) { - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(0.4))); - } else { - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.0), real_t(1.0))); - } - tangents_ptr[p_idx * 4 + 0] = 1.0; - tangents_ptr[p_idx * 4 + 1] = 0.0; - tangents_ptr[p_idx * 4 + 2] = 0.0; - tangents_ptr[p_idx * 4 + 3] = 1.0; - indices_ptr[i_idx++] = p_idx; - p_idx++; - } - if (has_depth) { - // Add back face. - for (int l = 2; l >= 0; l--) { - Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0); + offset.x += lbl_offset.x * pixel_size; + offset.y -= TS->shaped_text_get_ascent(lines_rid[i]) * pixel_size; + + bool has_depth = !Math::is_zero_approx(depth); + + // Generate glyph data, precalculate size of the arrays and mesh bounds for UV. + for (int j = 0; j < gl_size; j++) { + if (glyphs[j].index == 0) { + offset.x += glyphs[j].advance * pixel_size * glyphs[j].repeat; + continue; + } + if (glyphs[j].font_rid != RID()) { + GlyphMeshKey key = GlyphMeshKey(glyphs[j].font_rid.get_id(), glyphs[j].index); + _generate_glyph_mesh_data(key, glyphs[j]); + const GlyphMeshData &gl_data = cache[key]; + + int64_t ts = gl_data.triangles.size(); + const Vector2 *ts_ptr = gl_data.triangles.ptr(); + + for (int r = 0; r < glyphs[j].repeat; r++) { + for (int k = 0; k < ts; k += 3) { + // Add front face. + for (int l = 0; l < 3; l++) { + Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, depth / 2.0); vertices_ptr[p_idx] = point; - normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0); - uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -min_p.y, -max_p.y, real_t(0.4), real_t(0.8))); - tangents_ptr[p_idx * 4 + 0] = -1.0; + normals_ptr[p_idx] = Vector3(0.0, 0.0, 1.0); + if (has_depth) { + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); + } else { + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); + } + tangents_ptr[p_idx * 4 + 0] = 1.0; tangents_ptr[p_idx * 4 + 1] = 0.0; tangents_ptr[p_idx * 4 + 2] = 0.0; tangents_ptr[p_idx * 4 + 3] = 1.0; indices_ptr[i_idx++] = p_idx; p_idx++; } - } - } - // Add sides. - if (has_depth) { - for (int k = 0; k < gl_data.contours.size(); k++) { - int64_t ps = gl_data.contours[k].size(); - const ContourPoint *ps_ptr = gl_data.contours[k].ptr(); - const ContourInfo &ps_info = gl_data.contours_info[k]; - real_t length = 0.0; - for (int l = 0; l < ps; l++) { - int prev = (l == 0) ? (ps - 1) : (l - 1); - int next = (l + 1 == ps) ? 0 : (l + 1); - Vector2 d1; - Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized(); - if (ps_ptr[l].sharp) { - d1 = d2; - } else { - d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized(); + if (has_depth) { + // Add back face. + for (int l = 2; l >= 0; l--) { + Vector3 point = Vector3(ts_ptr[k + l].x + offset.x, -ts_ptr[k + l].y + offset.y, -depth / 2.0); + vertices_ptr[p_idx] = point; + normals_ptr[p_idx] = Vector3(0.0, 0.0, -1.0); + uvs_ptr[p_idx] = Vector2(Math::range_lerp(point.x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(point.y, -max_p.y, -min_p.y, real_t(0.8), real_t(0.4))); + tangents_ptr[p_idx * 4 + 0] = -1.0; + tangents_ptr[p_idx * 4 + 1] = 0.0; + tangents_ptr[p_idx * 4 + 2] = 0.0; + tangents_ptr[p_idx * 4 + 3] = 1.0; + indices_ptr[i_idx++] = p_idx; + p_idx++; } - real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length(); - - Vector3 quad_faces[4] = { - Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0), - Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0), - Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0), - Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0), - }; - for (int m = 0; m < 4; m++) { - const Vector2 &d = ((m % 2) == 0) ? d1 : d2; - real_t u_pos = ((m % 2) == 0) ? length : length + seg_len; - vertices_ptr[p_idx + m] = quad_faces[m]; - normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0); - if (m < 2) { - uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9); + } + } + // Add sides. + if (has_depth) { + for (int k = 0; k < gl_data.contours.size(); k++) { + int64_t ps = gl_data.contours[k].size(); + const ContourPoint *ps_ptr = gl_data.contours[k].ptr(); + const ContourInfo &ps_info = gl_data.contours_info[k]; + real_t length = 0.0; + for (int l = 0; l < ps; l++) { + int prev = (l == 0) ? (ps - 1) : (l - 1); + int next = (l + 1 == ps) ? 0 : (l + 1); + Vector2 d1; + Vector2 d2 = (ps_ptr[next].point - ps_ptr[l].point).normalized(); + if (ps_ptr[l].sharp) { + d1 = d2; } else { - uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0); + d1 = (ps_ptr[l].point - ps_ptr[prev].point).normalized(); + } + real_t seg_len = (ps_ptr[next].point - ps_ptr[l].point).length(); + + Vector3 quad_faces[4] = { + Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, -depth / 2.0), + Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, -depth / 2.0), + Vector3(ps_ptr[l].point.x + offset.x, -ps_ptr[l].point.y + offset.y, depth / 2.0), + Vector3(ps_ptr[next].point.x + offset.x, -ps_ptr[next].point.y + offset.y, depth / 2.0), + }; + for (int m = 0; m < 4; m++) { + const Vector2 &d = ((m % 2) == 0) ? d1 : d2; + real_t u_pos = ((m % 2) == 0) ? length : length + seg_len; + vertices_ptr[p_idx + m] = quad_faces[m]; + normals_ptr[p_idx + m] = Vector3(d.y, d.x, 0.0); + if (m < 2) { + uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.8 : 0.9); + } else { + uvs_ptr[p_idx + m] = Vector2(Math::range_lerp(u_pos, 0, ps_info.length, real_t(0.0), real_t(1.0)), (ps_info.ccw) ? 0.9 : 1.0); + } + tangents_ptr[(p_idx + m) * 4 + 0] = d.x; + tangents_ptr[(p_idx + m) * 4 + 1] = -d.y; + tangents_ptr[(p_idx + m) * 4 + 2] = 0.0; + tangents_ptr[(p_idx + m) * 4 + 3] = 1.0; } - tangents_ptr[(p_idx + m) * 4 + 0] = d.x; - tangents_ptr[(p_idx + m) * 4 + 1] = -d.y; - tangents_ptr[(p_idx + m) * 4 + 2] = 0.0; - tangents_ptr[(p_idx + m) * 4 + 3] = 1.0; - } - indices_ptr[i_idx++] = p_idx; - indices_ptr[i_idx++] = p_idx + 1; - indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 2; - indices_ptr[i_idx++] = p_idx + 1; - indices_ptr[i_idx++] = p_idx + 3; - indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 3; + indices_ptr[i_idx++] = p_idx + 2; - length += seg_len; - p_idx += 4; + length += seg_len; + p_idx += 4; + } } } + offset.x += glyphs[j].advance * pixel_size; } - offset.x += glyphs[i].advance * pixel_size; - } - } else { - // Add fallback quad for missing glyphs. - for (int j = 0; j < glyphs[i].repeat; j++) { - Size2 sz = TS->get_hex_code_box_size(glyphs[i].font_size, glyphs[i].index) * pixel_size; - Vector3 quad_faces[4] = { - Vector3(offset.x, offset.y, 0.0), - Vector3(offset.x, sz.y + offset.y, 0.0), - Vector3(sz.x + offset.x, sz.y + offset.y, 0.0), - Vector3(sz.x + offset.x, offset.y, 0.0), - }; - for (int k = 0; k < 4; k++) { - vertices_ptr[p_idx + k] = quad_faces[k]; - normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0); - if (has_depth) { - uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -min_p.y, -max_p.y, real_t(0.0), real_t(0.4))); - } else { - uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -min_p.y, -max_p.y, real_t(0.0), real_t(1.0))); + } else { + // Add fallback quad for missing glyphs. + for (int r = 0; r < glyphs[j].repeat; r++) { + Size2 sz = TS->get_hex_code_box_size(glyphs[j].font_size, glyphs[j].index) * pixel_size; + Vector3 quad_faces[4] = { + Vector3(offset.x, offset.y, 0.0), + Vector3(offset.x, sz.y + offset.y, 0.0), + Vector3(sz.x + offset.x, sz.y + offset.y, 0.0), + Vector3(sz.x + offset.x, offset.y, 0.0), + }; + for (int k = 0; k < 4; k++) { + vertices_ptr[p_idx + k] = quad_faces[k]; + normals_ptr[p_idx + k] = Vector3(0.0, 0.0, 1.0); + if (has_depth) { + uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(0.4), real_t(0.0))); + } else { + uvs_ptr[p_idx + k] = Vector2(Math::range_lerp(quad_faces[k].x, min_p.x, max_p.x, real_t(0.0), real_t(1.0)), Math::range_lerp(quad_faces[k].y, -max_p.y, -min_p.y, real_t(1.0), real_t(0.0))); + } + tangents_ptr[(p_idx + k) * 4 + 0] = 1.0; + tangents_ptr[(p_idx + k) * 4 + 1] = 0.0; + tangents_ptr[(p_idx + k) * 4 + 2] = 0.0; + tangents_ptr[(p_idx + k) * 4 + 3] = 1.0; } - tangents_ptr[(p_idx + k) * 4 + 0] = 1.0; - tangents_ptr[(p_idx + k) * 4 + 1] = 0.0; - tangents_ptr[(p_idx + k) * 4 + 2] = 0.0; - tangents_ptr[(p_idx + k) * 4 + 3] = 1.0; - } - indices_ptr[i_idx++] = p_idx; - indices_ptr[i_idx++] = p_idx + 1; - indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx; + indices_ptr[i_idx++] = p_idx + 1; + indices_ptr[i_idx++] = p_idx + 2; - indices_ptr[i_idx++] = p_idx + 0; - indices_ptr[i_idx++] = p_idx + 2; - indices_ptr[i_idx++] = p_idx + 3; - p_idx += 4; + indices_ptr[i_idx++] = p_idx + 0; + indices_ptr[i_idx++] = p_idx + 2; + indices_ptr[i_idx++] = p_idx + 3; + p_idx += 4; - offset.x += glyphs[i].advance * pixel_size; + offset.x += glyphs[j].advance * pixel_size; + } } } + offset.y -= (TS->shaped_text_get_descent(lines_rid[i]) + line_spacing) * pixel_size; } - if (p_size == 0) { + if (indices.is_empty()) { // If empty, add single triangle to suppress errors. vertices.push_back(Vector3()); normals.push_back(Vector3()); @@ -2728,6 +2810,9 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_horizontal_alignment", "alignment"), &TextMesh::set_horizontal_alignment); ClassDB::bind_method(D_METHOD("get_horizontal_alignment"), &TextMesh::get_horizontal_alignment); + ClassDB::bind_method(D_METHOD("set_vertical_alignment", "alignment"), &TextMesh::set_vertical_alignment); + ClassDB::bind_method(D_METHOD("get_vertical_alignment"), &TextMesh::get_vertical_alignment); + ClassDB::bind_method(D_METHOD("set_text", "text"), &TextMesh::set_text); ClassDB::bind_method(D_METHOD("get_text"), &TextMesh::get_text); @@ -2737,6 +2822,12 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_font_size", "font_size"), &TextMesh::set_font_size); ClassDB::bind_method(D_METHOD("get_font_size"), &TextMesh::get_font_size); + ClassDB::bind_method(D_METHOD("set_line_spacing", "line_spacing"), &TextMesh::set_line_spacing); + ClassDB::bind_method(D_METHOD("get_line_spacing"), &TextMesh::get_line_spacing); + + ClassDB::bind_method(D_METHOD("set_autowrap_mode", "autowrap_mode"), &TextMesh::set_autowrap_mode); + ClassDB::bind_method(D_METHOD("get_autowrap_mode"), &TextMesh::get_autowrap_mode); + ClassDB::bind_method(D_METHOD("set_depth", "depth"), &TextMesh::set_depth); ClassDB::bind_method(D_METHOD("get_depth"), &TextMesh::get_depth); @@ -2746,6 +2837,9 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("set_pixel_size", "pixel_size"), &TextMesh::set_pixel_size); ClassDB::bind_method(D_METHOD("get_pixel_size"), &TextMesh::get_pixel_size); + ClassDB::bind_method(D_METHOD("set_offset", "offset"), &TextMesh::set_offset); + ClassDB::bind_method(D_METHOD("get_offset"), &TextMesh::get_offset); + ClassDB::bind_method(D_METHOD("set_curve_step", "curve_step"), &TextMesh::set_curve_step); ClassDB::bind_method(D_METHOD("get_curve_step"), &TextMesh::get_curve_step); @@ -2768,17 +2862,21 @@ void TextMesh::_bind_methods() { ClassDB::bind_method(D_METHOD("_request_update"), &TextMesh::_request_update); ADD_GROUP("Text", ""); - ADD_PROPERTY(PropertyInfo(Variant::STRING, "text"), "set_text", "get_text"); + ADD_PROPERTY(PropertyInfo(Variant::STRING, "text", PROPERTY_HINT_MULTILINE_TEXT, ""), "set_text", "get_text"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_font", "get_font"); ADD_PROPERTY(PropertyInfo(Variant::INT, "font_size", PROPERTY_HINT_RANGE, "1,256,1,or_greater,suffix:px"), "set_font_size", "get_font_size"); ADD_PROPERTY(PropertyInfo(Variant::INT, "horizontal_alignment", PROPERTY_HINT_ENUM, "Left,Center,Right,Fill"), "set_horizontal_alignment", "get_horizontal_alignment"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "vertical_alignment", PROPERTY_HINT_ENUM, "Top,Center,Bottom"), "set_vertical_alignment", "get_vertical_alignment"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uppercase"), "set_uppercase", "is_uppercase"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "autowrap_mode", PROPERTY_HINT_ENUM, "Off,Arbitrary,Word,Word (Smart)"), "set_autowrap_mode", "get_autowrap_mode"); ADD_GROUP("Mesh", ""); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "pixel_size", PROPERTY_HINT_RANGE, "0.0001,128,0.0001,suffix:m"), "set_pixel_size", "get_pixel_size"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "curve_step", PROPERTY_HINT_RANGE, "0.1,10,0.1,suffix:px"), "set_curve_step", "get_curve_step"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "depth", PROPERTY_HINT_RANGE, "0.0,100.0,0.001,or_greater,suffix:m"), "set_depth", "get_depth"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "width", PROPERTY_HINT_NONE, "suffix:m"), "set_width", "get_width"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "offset", PROPERTY_HINT_NONE, "suffix:px"), "set_offset", "get_offset"); ADD_GROUP("BiDi", ""); ADD_PROPERTY(PropertyInfo(Variant::INT, "text_direction", PROPERTY_HINT_ENUM, "Auto,Left-to-Right,Right-to-Left"), "set_text_direction", "get_text_direction"); @@ -2807,6 +2905,11 @@ TextMesh::TextMesh() { } TextMesh::~TextMesh() { + for (int i = 0; i < lines_rid.size(); i++) { + TS->free_rid(lines_rid[i]); + } + lines_rid.clear(); + TS->free_rid(text_rid); } @@ -2814,7 +2917,7 @@ void TextMesh::set_horizontal_alignment(HorizontalAlignment p_alignment) { ERR_FAIL_INDEX((int)p_alignment, 4); if (horizontal_alignment != p_alignment) { if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL || p_alignment == HORIZONTAL_ALIGNMENT_FILL) { - dirty_text = true; + dirty_lines = true; } horizontal_alignment = p_alignment; _request_update(); @@ -2825,6 +2928,18 @@ HorizontalAlignment TextMesh::get_horizontal_alignment() const { return horizontal_alignment; } +void TextMesh::set_vertical_alignment(VerticalAlignment p_alignment) { + ERR_FAIL_INDEX((int)p_alignment, 4); + if (vertical_alignment != p_alignment) { + vertical_alignment = p_alignment; + _request_update(); + } +} + +VerticalAlignment TextMesh::get_vertical_alignment() const { + return vertical_alignment; +} + void TextMesh::set_text(const String &p_string) { if (text != p_string) { text = p_string; @@ -2909,6 +3024,29 @@ int TextMesh::get_font_size() const { return font_size; } +void TextMesh::set_line_spacing(float p_line_spacing) { + if (line_spacing != p_line_spacing) { + line_spacing = p_line_spacing; + _request_update(); + } +} + +float TextMesh::get_line_spacing() const { + return line_spacing; +} + +void TextMesh::set_autowrap_mode(TextServer::AutowrapMode p_mode) { + if (autowrap_mode != p_mode) { + autowrap_mode = p_mode; + dirty_lines = true; + _request_update(); + } +} + +TextServer::AutowrapMode TextMesh::get_autowrap_mode() const { + return autowrap_mode; +} + void TextMesh::set_depth(real_t p_depth) { if (depth != p_depth) { depth = MAX(p_depth, 0.0); @@ -2923,9 +3061,7 @@ real_t TextMesh::get_depth() const { void TextMesh::set_width(real_t p_width) { if (width != p_width) { width = p_width; - if (horizontal_alignment == HORIZONTAL_ALIGNMENT_FILL) { - dirty_text = true; - } + dirty_lines = true; _request_update(); } } @@ -2946,6 +3082,17 @@ real_t TextMesh::get_pixel_size() const { return pixel_size; } +void TextMesh::set_offset(const Point2 &p_offset) { + if (lbl_offset != p_offset) { + lbl_offset = p_offset; + _request_update(); + } +} + +Point2 TextMesh::get_offset() const { + return lbl_offset; +} + void TextMesh::set_curve_step(real_t p_step) { if (curve_step != p_step) { curve_step = CLAMP(p_step, 0.1, 10.0); diff --git a/scene/resources/primitive_meshes.h b/scene/resources/primitive_meshes.h index 3cf161db00..280477ebfa 100644 --- a/scene/resources/primitive_meshes.h +++ b/scene/resources/primitive_meshes.h @@ -534,14 +534,21 @@ private: mutable HashMap<GlyphMeshKey, GlyphMeshData, GlyphMeshKeyHasher> cache; RID text_rid; + mutable Vector<RID> lines_rid; + String text; String xl_text; int font_size = 16; Ref<Font> font_override; + + TextServer::AutowrapMode autowrap_mode = TextServer::AUTOWRAP_OFF; float width = 500.0; + float line_spacing = 0.f; + Point2 lbl_offset; HorizontalAlignment horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER; + VerticalAlignment vertical_alignment = VERTICAL_ALIGNMENT_CENTER; bool uppercase = false; String language; TextServer::Direction text_direction = TextServer::DIRECTION_AUTO; @@ -552,6 +559,7 @@ private: real_t pixel_size = 0.01; real_t curve_step = 0.5; + mutable bool dirty_lines = true; mutable bool dirty_text = true; mutable bool dirty_font = true; mutable bool dirty_cache = true; @@ -574,6 +582,9 @@ public: void set_horizontal_alignment(HorizontalAlignment p_alignment); HorizontalAlignment get_horizontal_alignment() const; + void set_vertical_alignment(VerticalAlignment p_alignment); + VerticalAlignment get_vertical_alignment() const; + void set_text(const String &p_string); String get_text() const; @@ -584,6 +595,12 @@ public: void set_font_size(int p_size); int get_font_size() const; + void set_line_spacing(float p_size); + float get_line_spacing() const; + + void set_autowrap_mode(TextServer::AutowrapMode p_mode); + TextServer::AutowrapMode get_autowrap_mode() const; + void set_text_direction(TextServer::Direction p_text_direction); TextServer::Direction get_text_direction() const; @@ -610,6 +627,9 @@ public: void set_pixel_size(real_t p_amount); real_t get_pixel_size() const; + + void set_offset(const Point2 &p_offset); + Point2 get_offset() const; }; VARIANT_ENUM_CAST(RibbonTrailMesh::Shape) diff --git a/scene/resources/skeleton_modification_2d_ccdik.cpp b/scene/resources/skeleton_modification_2d_ccdik.cpp index 7adaf1452c..96961a1fe4 100644 --- a/scene/resources/skeleton_modification_2d_ccdik.cpp +++ b/scene/resources/skeleton_modification_2d_ccdik.cpp @@ -52,9 +52,9 @@ bool SkeletonModification2DCCDIK::_set(const StringName &p_path, const Variant & } else if (what == "enable_constraint") { set_ccdik_joint_enable_constraint(which, p_value); } else if (what == "constraint_angle_min") { - set_ccdik_joint_constraint_angle_min(which, Math::deg2rad(float(p_value))); + set_ccdik_joint_constraint_angle_min(which, Math::deg_to_rad(float(p_value))); } else if (what == "constraint_angle_max") { - set_ccdik_joint_constraint_angle_max(which, Math::deg2rad(float(p_value))); + set_ccdik_joint_constraint_angle_max(which, Math::deg_to_rad(float(p_value))); } else if (what == "constraint_angle_invert") { set_ccdik_joint_constraint_angle_invert(which, p_value); } else if (what == "constraint_in_localspace") { @@ -96,9 +96,9 @@ bool SkeletonModification2DCCDIK::_get(const StringName &p_path, Variant &r_ret) } else if (what == "enable_constraint") { r_ret = get_ccdik_joint_enable_constraint(which); } else if (what == "constraint_angle_min") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_min(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_min(which)); } else if (what == "constraint_angle_max") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_max(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_max(which)); } else if (what == "constraint_angle_invert") { r_ret = get_ccdik_joint_constraint_angle_invert(which); } else if (what == "constraint_in_localspace") { diff --git a/scene/resources/skeleton_modification_2d_lookat.cpp b/scene/resources/skeleton_modification_2d_lookat.cpp index 23e1c579dc..d3cfffb1de 100644 --- a/scene/resources/skeleton_modification_2d_lookat.cpp +++ b/scene/resources/skeleton_modification_2d_lookat.cpp @@ -41,15 +41,15 @@ bool SkeletonModification2DLookAt::_set(const StringName &p_path, const Variant if (path.begins_with("enable_constraint")) { set_enable_constraint(p_value); } else if (path.begins_with("constraint_angle_min")) { - set_constraint_angle_min(Math::deg2rad(float(p_value))); + set_constraint_angle_min(Math::deg_to_rad(float(p_value))); } else if (path.begins_with("constraint_angle_max")) { - set_constraint_angle_max(Math::deg2rad(float(p_value))); + set_constraint_angle_max(Math::deg_to_rad(float(p_value))); } else if (path.begins_with("constraint_angle_invert")) { set_constraint_angle_invert(p_value); } else if (path.begins_with("constraint_in_localspace")) { set_constraint_in_localspace(p_value); } else if (path.begins_with("additional_rotation")) { - set_additional_rotation(Math::deg2rad(float(p_value))); + set_additional_rotation(Math::deg_to_rad(float(p_value))); } #ifdef TOOLS_ENABLED @@ -67,15 +67,15 @@ bool SkeletonModification2DLookAt::_get(const StringName &p_path, Variant &r_ret if (path.begins_with("enable_constraint")) { r_ret = get_enable_constraint(); } else if (path.begins_with("constraint_angle_min")) { - r_ret = Math::rad2deg(get_constraint_angle_min()); + r_ret = Math::rad_to_deg(get_constraint_angle_min()); } else if (path.begins_with("constraint_angle_max")) { - r_ret = Math::rad2deg(get_constraint_angle_max()); + r_ret = Math::rad_to_deg(get_constraint_angle_max()); } else if (path.begins_with("constraint_angle_invert")) { r_ret = get_constraint_angle_invert(); } else if (path.begins_with("constraint_in_localspace")) { r_ret = get_constraint_in_localspace(); } else if (path.begins_with("additional_rotation")) { - r_ret = Math::rad2deg(get_additional_rotation()); + r_ret = Math::rad_to_deg(get_additional_rotation()); } #ifdef TOOLS_ENABLED diff --git a/scene/resources/skeleton_modification_3d_ccdik.cpp b/scene/resources/skeleton_modification_3d_ccdik.cpp index f19be47db2..3251ee4189 100644 --- a/scene/resources/skeleton_modification_3d_ccdik.cpp +++ b/scene/resources/skeleton_modification_3d_ccdik.cpp @@ -50,9 +50,9 @@ bool SkeletonModification3DCCDIK::_set(const StringName &p_path, const Variant & } else if (what == "enable_joint_constraint") { set_ccdik_joint_enable_constraint(which, p_value); } else if (what == "joint_constraint_angle_min") { - set_ccdik_joint_constraint_angle_min(which, Math::deg2rad(real_t(p_value))); + set_ccdik_joint_constraint_angle_min(which, Math::deg_to_rad(real_t(p_value))); } else if (what == "joint_constraint_angle_max") { - set_ccdik_joint_constraint_angle_max(which, Math::deg2rad(real_t(p_value))); + set_ccdik_joint_constraint_angle_max(which, Math::deg_to_rad(real_t(p_value))); } else if (what == "joint_constraint_angles_invert") { set_ccdik_joint_constraint_invert(which, p_value); } @@ -79,9 +79,9 @@ bool SkeletonModification3DCCDIK::_get(const StringName &p_path, Variant &r_ret) } else if (what == "enable_joint_constraint") { r_ret = get_ccdik_joint_enable_constraint(which); } else if (what == "joint_constraint_angle_min") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_min(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_min(which)); } else if (what == "joint_constraint_angle_max") { - r_ret = Math::rad2deg(get_ccdik_joint_constraint_angle_max(which)); + r_ret = Math::rad_to_deg(get_ccdik_joint_constraint_angle_max(which)); } else if (what == "joint_constraint_angles_invert") { r_ret = get_ccdik_joint_constraint_invert(which); } diff --git a/scene/resources/skeleton_modification_3d_fabrik.cpp b/scene/resources/skeleton_modification_3d_fabrik.cpp index b62dda3f4f..4099208f44 100644 --- a/scene/resources/skeleton_modification_3d_fabrik.cpp +++ b/scene/resources/skeleton_modification_3d_fabrik.cpp @@ -58,7 +58,7 @@ bool SkeletonModification3DFABRIK::_set(const StringName &p_path, const Variant } else if (what == "use_target_basis") { set_fabrik_joint_use_target_basis(which, p_value); } else if (what == "roll") { - set_fabrik_joint_roll(which, Math::deg2rad(real_t(p_value))); + set_fabrik_joint_roll(which, Math::deg_to_rad(real_t(p_value))); } return true; } @@ -91,7 +91,7 @@ bool SkeletonModification3DFABRIK::_get(const StringName &p_path, Variant &r_ret } else if (what == "use_target_basis") { r_ret = get_fabrik_joint_use_target_basis(which); } else if (what == "roll") { - r_ret = Math::rad2deg(get_fabrik_joint_roll(which)); + r_ret = Math::rad_to_deg(get_fabrik_joint_roll(which)); } return true; } diff --git a/scene/resources/skeleton_modification_3d_jiggle.cpp b/scene/resources/skeleton_modification_3d_jiggle.cpp index 3e36c241f7..64f26f3fda 100644 --- a/scene/resources/skeleton_modification_3d_jiggle.cpp +++ b/scene/resources/skeleton_modification_3d_jiggle.cpp @@ -58,7 +58,7 @@ bool SkeletonModification3DJiggle::_set(const StringName &p_path, const Variant } else if (what == "gravity") { set_jiggle_joint_gravity(which, p_value); } else if (what == "roll") { - set_jiggle_joint_roll(which, Math::deg2rad(real_t(p_value))); + set_jiggle_joint_roll(which, Math::deg_to_rad(real_t(p_value))); } return true; } else { @@ -98,7 +98,7 @@ bool SkeletonModification3DJiggle::_get(const StringName &p_path, Variant &r_ret } else if (what == "gravity") { r_ret = get_jiggle_joint_gravity(which); } else if (what == "roll") { - r_ret = Math::rad2deg(get_jiggle_joint_roll(which)); + r_ret = Math::rad_to_deg(get_jiggle_joint_roll(which)); } return true; } else { diff --git a/scene/resources/skeleton_modification_3d_lookat.cpp b/scene/resources/skeleton_modification_3d_lookat.cpp index 3e8c1e3a77..69167cb308 100644 --- a/scene/resources/skeleton_modification_3d_lookat.cpp +++ b/scene/resources/skeleton_modification_3d_lookat.cpp @@ -39,9 +39,9 @@ bool SkeletonModification3DLookAt::_set(const StringName &p_path, const Variant set_lock_rotation_plane(p_value); } else if (p_path == "additional_rotation") { Vector3 tmp = p_value; - tmp.x = Math::deg2rad(tmp.x); - tmp.y = Math::deg2rad(tmp.y); - tmp.z = Math::deg2rad(tmp.z); + tmp.x = Math::deg_to_rad(tmp.x); + tmp.y = Math::deg_to_rad(tmp.y); + tmp.z = Math::deg_to_rad(tmp.z); set_additional_rotation(tmp); } @@ -55,9 +55,9 @@ bool SkeletonModification3DLookAt::_get(const StringName &p_path, Variant &r_ret r_ret = get_lock_rotation_plane(); } else if (p_path == "additional_rotation") { Vector3 tmp = get_additional_rotation(); - tmp.x = Math::rad2deg(tmp.x); - tmp.y = Math::rad2deg(tmp.y); - tmp.z = Math::rad2deg(tmp.z); + tmp.x = Math::rad_to_deg(tmp.x); + tmp.y = Math::rad_to_deg(tmp.y); + tmp.z = Math::rad_to_deg(tmp.z); r_ret = tmp; } diff --git a/scene/resources/skeleton_modification_3d_twoboneik.cpp b/scene/resources/skeleton_modification_3d_twoboneik.cpp index acc5ff716c..366fcc30b7 100644 --- a/scene/resources/skeleton_modification_3d_twoboneik.cpp +++ b/scene/resources/skeleton_modification_3d_twoboneik.cpp @@ -54,13 +54,13 @@ bool SkeletonModification3DTwoBoneIK::_set(const StringName &p_path, const Varia } else if (path == "joint_one/bone_idx") { set_joint_one_bone_idx(p_value); } else if (path == "joint_one/roll") { - set_joint_one_roll(Math::deg2rad(real_t(p_value))); + set_joint_one_roll(Math::deg_to_rad(real_t(p_value))); } else if (path == "joint_two/bone_name") { set_joint_two_bone_name(p_value); } else if (path == "joint_two/bone_idx") { set_joint_two_bone_idx(p_value); } else if (path == "joint_two/roll") { - set_joint_two_roll(Math::deg2rad(real_t(p_value))); + set_joint_two_roll(Math::deg_to_rad(real_t(p_value))); } return true; @@ -88,13 +88,13 @@ bool SkeletonModification3DTwoBoneIK::_get(const StringName &p_path, Variant &r_ } else if (path == "joint_one/bone_idx") { r_ret = get_joint_one_bone_idx(); } else if (path == "joint_one/roll") { - r_ret = Math::rad2deg(get_joint_one_roll()); + r_ret = Math::rad_to_deg(get_joint_one_roll()); } else if (path == "joint_two/bone_name") { r_ret = get_joint_two_bone_name(); } else if (path == "joint_two/bone_idx") { r_ret = get_joint_two_bone_idx(); } else if (path == "joint_two/roll") { - r_ret = Math::rad2deg(get_joint_two_roll()); + r_ret = Math::rad_to_deg(get_joint_two_roll()); } return true; diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index 5d1a223cc7..737c50e570 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -128,7 +128,7 @@ float ProceduralSkyMaterial::get_ground_energy() const { void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { sun_angle_max = p_angle; - RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max)); + RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg_to_rad(sun_angle_max)); } float ProceduralSkyMaterial::get_sun_angle_max() const { diff --git a/scene/resources/sphere_shape_3d.cpp b/scene/resources/sphere_shape_3d.cpp index 92efe3ce6f..340d0fe370 100644 --- a/scene/resources/sphere_shape_3d.cpp +++ b/scene/resources/sphere_shape_3d.cpp @@ -38,8 +38,8 @@ Vector<Vector3> SphereShape3D::get_debug_mesh_lines() const { Vector<Vector3> points; for (int i = 0; i <= 360; i++) { - float ra = Math::deg2rad((float)i); - float rb = Math::deg2rad((float)i + 1); + float ra = Math::deg_to_rad((float)i); + float rb = Math::deg_to_rad((float)i + 1); Point2 a = Vector2(Math::sin(ra), Math::cos(ra)) * r; Point2 b = Vector2(Math::sin(rb), Math::cos(rb)) * r; diff --git a/scene/resources/visual_shader_nodes.cpp b/scene/resources/visual_shader_nodes.cpp index 2911d726b4..3b2b58516d 100644 --- a/scene/resources/visual_shader_nodes.cpp +++ b/scene/resources/visual_shader_nodes.cpp @@ -1606,6 +1606,51 @@ VisualShaderNodeCubemap::VisualShaderNodeCubemap() { simple_decl = false; } +////////////// Linear Depth + +String VisualShaderNodeLinearSceneDepth::get_caption() const { + return "LinearSceneDepth"; +} + +int VisualShaderNodeLinearSceneDepth::get_input_port_count() const { + return 0; +} + +VisualShaderNodeLinearSceneDepth::PortType VisualShaderNodeLinearSceneDepth::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeLinearSceneDepth::get_input_port_name(int p_port) const { + return ""; +} + +int VisualShaderNodeLinearSceneDepth::get_output_port_count() const { + return 1; +} + +VisualShaderNodeLinearSceneDepth::PortType VisualShaderNodeLinearSceneDepth::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeLinearSceneDepth::get_output_port_name(int p_port) const { + return "linear depth"; +} + +String VisualShaderNodeLinearSceneDepth::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + + code += " float _log_depth = texture(DEPTH_TEXTURE, SCREEN_UV).x;\n"; + code += " vec3 _depth_ndc = vec3(SCREEN_UV * 2.0 - 1.0, _log_depth);\n"; + code += " vec4 _depth_view = INV_PROJECTION_MATRIX * vec4(_depth_ndc, 1.0);\n"; + code += " _depth_view.xyz /= _depth_view.w;"; + code += vformat(" %s = -_depth_view.z;", p_output_vars[0]); + + return code; +} + +VisualShaderNodeLinearSceneDepth::VisualShaderNodeLinearSceneDepth() { +} + ////////////// Float Op String VisualShaderNodeFloatOp::get_caption() const { @@ -3090,6 +3135,107 @@ VisualShaderNodeUVFunc::VisualShaderNodeUVFunc() { set_input_port_default_value(2, Vector2()); // offset } +////////////// UV PolarCoord + +String VisualShaderNodeUVPolarCoord::get_caption() const { + return "UVPolarCoord"; +} + +int VisualShaderNodeUVPolarCoord::get_input_port_count() const { + return 4; +} + +VisualShaderNodeUVPolarCoord::PortType VisualShaderNodeUVPolarCoord::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR_2D; // uv + case 1: + return PORT_TYPE_VECTOR_2D; // center + case 2: + return PORT_TYPE_SCALAR; // zoom + case 3: + return PORT_TYPE_SCALAR; // repeat + default: + break; + } + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeUVPolarCoord::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "uv"; + case 1: + return "scale"; + case 2: + return "zoom strength"; + case 3: + return "repeat"; + default: + break; + } + return ""; +} + +bool VisualShaderNodeUVPolarCoord::is_input_port_default(int p_port, Shader::Mode p_mode) const { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + if (p_port == 0) { + return true; + } + } + return false; +} + +int VisualShaderNodeUVPolarCoord::get_output_port_count() const { + return 1; +} + +VisualShaderNodeUVPolarCoord::PortType VisualShaderNodeUVPolarCoord::get_output_port_type(int p_port) const { + return PORT_TYPE_VECTOR_2D; +} + +String VisualShaderNodeUVPolarCoord::get_output_port_name(int p_port) const { + return "uv"; +} + +String VisualShaderNodeUVPolarCoord::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + + String uv; + if (p_input_vars[0].is_empty()) { + if (p_mode == Shader::MODE_CANVAS_ITEM || p_mode == Shader::MODE_SPATIAL) { + uv = "UV"; + } else { + uv = "vec2(0.0)"; + } + } else { + uv = vformat("%s", p_input_vars[0]); + } + String center = vformat("%s", p_input_vars[1]); + String zoom = vformat("%s", p_input_vars[2]); + String repeat = vformat("%s", p_input_vars[3]); + + if (p_mode == Shader::MODE_CANVAS_ITEM) { + code += vformat(" vec2 __dir = %s - %s;\n", uv, center); + code += " float __radius = length(__dir) * 2.0;\n"; + code += " float __angle = atan(__dir.y, __dir.x) * 1.0/(PI * 2.0);\n"; + code += vformat(" %s = mod(vec2(__radius * %s, __angle * %s), 1.0);\n", p_output_vars[0], zoom, repeat); + } else { + code += vformat(" vec2 __dir = %s - %s;\n", uv, center); + code += " float __radius = length(__dir) * 2.0;\n"; + code += " float __angle = atan(__dir.y, __dir.x) * 1.0/(PI * 2.0);\n"; + code += vformat(" %s = vec2(__radius * %s, __angle * %s);\n", p_output_vars[0], zoom, repeat); + } + + return code; +} + +VisualShaderNodeUVPolarCoord::VisualShaderNodeUVPolarCoord() { + set_input_port_default_value(1, Vector2(0.5, 0.5)); // center + set_input_port_default_value(2, 1.0); // zoom + set_input_port_default_value(3, 1.0); // repeat +} + ////////////// Dot Product String VisualShaderNodeDotProduct::get_caption() const { @@ -7010,3 +7156,261 @@ void VisualShaderNodeBillboard::_bind_methods() { VisualShaderNodeBillboard::VisualShaderNodeBillboard() { simple_decl = false; } + +////////////// DistanceFade + +String VisualShaderNodeDistanceFade::get_caption() const { + return "DistanceFade"; +} + +int VisualShaderNodeDistanceFade::get_input_port_count() const { + return 2; +} + +VisualShaderNodeDistanceFade::PortType VisualShaderNodeDistanceFade::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_SCALAR; + case 1: + return PORT_TYPE_SCALAR; + } + + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeDistanceFade::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "min"; + case 1: + return "max"; + } + + return ""; +} + +int VisualShaderNodeDistanceFade::get_output_port_count() const { + return 1; +} + +VisualShaderNodeDistanceFade::PortType VisualShaderNodeDistanceFade::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeDistanceFade::get_output_port_name(int p_port) const { + return "amount"; +} + +String VisualShaderNodeDistanceFade::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + code += vformat(" %s = clamp(smoothstep(%s, %s,-VERTEX.z),0.0,1.0);\n", p_output_vars[0], p_input_vars[0], p_input_vars[1]); + return code; +} + +VisualShaderNodeDistanceFade::VisualShaderNodeDistanceFade() { + set_input_port_default_value(0, 0.0); + set_input_port_default_value(1, 10.0); +} + +////////////// ProximityFade + +String VisualShaderNodeProximityFade::get_caption() const { + return "ProximityFade"; +} + +int VisualShaderNodeProximityFade::get_input_port_count() const { + return 1; +} + +VisualShaderNodeProximityFade::PortType VisualShaderNodeProximityFade::get_input_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeProximityFade::get_input_port_name(int p_port) const { + return "distance"; +} + +int VisualShaderNodeProximityFade::get_output_port_count() const { + return 1; +} + +VisualShaderNodeProximityFade::PortType VisualShaderNodeProximityFade::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeProximityFade::get_output_port_name(int p_port) const { + return "fade"; +} + +String VisualShaderNodeProximityFade::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + + String proximity_fade_distance = vformat("%s", p_input_vars[0]); + code += " float __depth_tex = textureLod(DEPTH_TEXTURE, SCREEN_UV, 0.0).r;\n"; + code += " vec4 __depth_world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, __depth_tex, 1.0);\n"; + code += " __depth_world_pos.xyz /= __depth_world_pos.z;\n"; + code += vformat(" %s = clamp(1.0 - smoothstep(__depth_world_pos.z + %s, __depth_world_pos.z, VERTEX.z), 0.0, 1.0);\n", p_output_vars[0], p_input_vars[0]); + + return code; +} + +VisualShaderNodeProximityFade::VisualShaderNodeProximityFade() { + set_input_port_default_value(0, 1.0); +} + +////////////// Random Range + +String VisualShaderNodeRandomRange::get_caption() const { + return "RandomRange"; +} + +int VisualShaderNodeRandomRange::get_input_port_count() const { + return 3; +} + +VisualShaderNodeRandomRange::PortType VisualShaderNodeRandomRange::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_VECTOR_3D; + case 1: + return PORT_TYPE_SCALAR; + case 2: + return PORT_TYPE_SCALAR; + default: + break; + } + + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeRandomRange::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "seed"; + case 1: + return "min"; + case 2: + return "max"; + default: + break; + } + + return ""; +} + +int VisualShaderNodeRandomRange::get_output_port_count() const { + return 1; +} + +VisualShaderNodeRandomRange::PortType VisualShaderNodeRandomRange::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeRandomRange::get_output_port_name(int p_port) const { + return "value"; +} + +String VisualShaderNodeRandomRange::generate_global_per_node(Shader::Mode p_mode, int p_id) const { + String code; + + code += "\n\n"; + code += "// 3D Noise with friendly permission by Inigo Quilez\n"; + code += "vec3 hash_noise_range( vec3 p ) {\n"; + code += " p *= mat3(vec3(127.1, 311.7, -53.7), vec3(269.5, 183.3, 77.1), vec3(-301.7, 27.3, 215.3));\n"; + code += " return 2.0 * fract(fract(p)*4375.55) -1.;\n"; + code += "}\n"; + code += "\n"; + + return code; +} + +String VisualShaderNodeRandomRange::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + + code += vformat(" %s = mix(%s, %s, hash_noise_range(%s).x);\n", p_output_vars[0], p_input_vars[1], p_input_vars[2], p_input_vars[0]); + + return code; +} + +VisualShaderNodeRandomRange::VisualShaderNodeRandomRange() { + set_input_port_default_value(0, Vector3(1.0, 1.0, 1.0)); + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 1.0); +} + +////////////// Remap + +String VisualShaderNodeRemap::get_caption() const { + return "Remap"; +} + +int VisualShaderNodeRemap::get_input_port_count() const { + return 5; +} + +VisualShaderNodeRemap::PortType VisualShaderNodeRemap::get_input_port_type(int p_port) const { + switch (p_port) { + case 0: + return PORT_TYPE_SCALAR; + case 1: + return PORT_TYPE_SCALAR; + case 2: + return PORT_TYPE_SCALAR; + case 3: + return PORT_TYPE_SCALAR; + case 4: + return PORT_TYPE_SCALAR; + default: + break; + } + + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeRemap::get_input_port_name(int p_port) const { + switch (p_port) { + case 0: + return "value"; + case 1: + return "input min"; + case 2: + return "input max"; + case 3: + return "output min"; + case 4: + return "output max"; + default: + break; + } + + return ""; +} + +int VisualShaderNodeRemap::get_output_port_count() const { + return 1; +} + +VisualShaderNodeRemap::PortType VisualShaderNodeRemap::get_output_port_type(int p_port) const { + return PORT_TYPE_SCALAR; +} + +String VisualShaderNodeRemap::get_output_port_name(int p_port) const { + return "value"; +} + +String VisualShaderNodeRemap::generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview) const { + String code; + + code += vformat(" float _input_range = %s - %s;\n", p_input_vars[2], p_input_vars[1]); + code += vformat(" float _output_range = %s - %s;\n", p_input_vars[4], p_input_vars[3]); + code += vformat(" %s = %s + _output_range * ((%s - %s) / _input_range);\n", p_output_vars[0], p_input_vars[3], p_input_vars[0], p_input_vars[1]); + + return code; +} + +VisualShaderNodeRemap::VisualShaderNodeRemap() { + set_input_port_default_value(1, 0.0); + set_input_port_default_value(2, 1.0); + set_input_port_default_value(3, 0.0); + set_input_port_default_value(4, 1.0); +} diff --git a/scene/resources/visual_shader_nodes.h b/scene/resources/visual_shader_nodes.h index ffcb41072d..c603a10eae 100644 --- a/scene/resources/visual_shader_nodes.h +++ b/scene/resources/visual_shader_nodes.h @@ -622,6 +622,27 @@ VARIANT_ENUM_CAST(VisualShaderNodeCubemap::TextureType) VARIANT_ENUM_CAST(VisualShaderNodeCubemap::Source) /////////////////////////////////////// + +class VisualShaderNodeLinearSceneDepth : public VisualShaderNode { + GDCLASS(VisualShaderNodeLinearSceneDepth, VisualShaderNode); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + VisualShaderNodeLinearSceneDepth(); +}; + +/////////////////////////////////////// /// OPS /////////////////////////////////////// @@ -1231,6 +1252,30 @@ public: VARIANT_ENUM_CAST(VisualShaderNodeUVFunc::Function) /////////////////////////////////////// +/// UV POLARCOORD +/////////////////////////////////////// + +class VisualShaderNodeUVPolarCoord : public VisualShaderNode { + GDCLASS(VisualShaderNodeUVPolarCoord, VisualShaderNode); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + virtual bool is_input_port_default(int p_port, Shader::Mode p_mode) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + VisualShaderNodeUVPolarCoord(); +}; + +/////////////////////////////////////// /// DOT /////////////////////////////////////// @@ -2574,4 +2619,85 @@ public: VARIANT_ENUM_CAST(VisualShaderNodeBillboard::BillboardType) +/////////////////////////////////////// +/// DistanceFade +/////////////////////////////////////// + +class VisualShaderNodeDistanceFade : public VisualShaderNode { + GDCLASS(VisualShaderNodeDistanceFade, VisualShaderNode); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + VisualShaderNodeDistanceFade(); +}; + +class VisualShaderNodeProximityFade : public VisualShaderNode { + GDCLASS(VisualShaderNodeProximityFade, VisualShaderNode); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + VisualShaderNodeProximityFade(); +}; + +class VisualShaderNodeRandomRange : public VisualShaderNode { + GDCLASS(VisualShaderNodeRandomRange, VisualShaderNode); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_global_per_node(Shader::Mode p_mode, int p_id) const override; + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + VisualShaderNodeRandomRange(); +}; + +class VisualShaderNodeRemap : public VisualShaderNode { + GDCLASS(VisualShaderNodeRemap, VisualShaderNode); + +public: + virtual String get_caption() const override; + + virtual int get_input_port_count() const override; + virtual PortType get_input_port_type(int p_port) const override; + virtual String get_input_port_name(int p_port) const override; + + virtual int get_output_port_count() const override; + virtual PortType get_output_port_type(int p_port) const override; + virtual String get_output_port_name(int p_port) const override; + + virtual String generate_code(Shader::Mode p_mode, VisualShader::Type p_type, int p_id, const String *p_input_vars, const String *p_output_vars, bool p_for_preview = false) const override; + + VisualShaderNodeRemap(); +}; + #endif // VISUAL_SHADER_NODES_H diff --git a/servers/audio/audio_stream.cpp b/servers/audio/audio_stream.cpp index 80485845c9..4252131161 100644 --- a/servers/audio/audio_stream.cpp +++ b/servers/audio/audio_stream.cpp @@ -782,7 +782,7 @@ void AudioStreamPlaybackRandomizer::start(float p_from_pos) { float range_to = randomizer->random_volume_offset_db; float volume_offset_db = range_from + Math::randf() * (range_to - range_from); - volume_scale = Math::db2linear(volume_offset_db); + volume_scale = Math::db_to_linear(volume_offset_db); } if (playing.is_valid()) { diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp index 87d46f8bbe..2889562173 100644 --- a/servers/audio/effects/audio_effect_amplify.cpp +++ b/servers/audio/effects/audio_effect_amplify.cpp @@ -33,8 +33,8 @@ void AudioEffectAmplifyInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { //multiply volume interpolating to avoid clicks if this changes float volume_db = base->volume_db; - float vol = Math::db2linear(mix_volume_db); - float vol_inc = (Math::db2linear(volume_db) - vol) / float(p_frame_count); + float vol = Math::db_to_linear(mix_volume_db); + float vol_inc = (Math::db_to_linear(volume_db) - vol) / float(p_frame_count); for (int i = 0; i < p_frame_count; i++) { p_dst_frames[i] = p_src_frames[i] * vol; diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp index 54c08ef644..69b416f5f7 100644 --- a/servers/audio/effects/audio_effect_chorus.cpp +++ b/servers/audio/effects/audio_effect_chorus.cpp @@ -95,7 +95,7 @@ void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames, A //vol modifier - AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db2linear(v.level); + AudioFrame vol_modifier = AudioFrame(base->wet, base->wet) * Math::db_to_linear(v.level); vol_modifier.l *= CLAMP(1.0 - v.pan, 0, 1); vol_modifier.r *= CLAMP(1.0 + v.pan, 0, 1); diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp index 0e1accba16..43b210e450 100644 --- a/servers/audio/effects/audio_effect_compressor.cpp +++ b/servers/audio/effects/audio_effect_compressor.cpp @@ -32,7 +32,7 @@ #include "servers/audio_server.h" void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { - float threshold = Math::db2linear(base->threshold); + float threshold = Math::db_to_linear(base->threshold); float sample_rate = AudioServer::get_singleton()->get_mix_rate(); float ratatcoef = exp(-1 / (0.00001f * sample_rate)); @@ -42,7 +42,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi float atcoef = exp(-1 / (attime * sample_rate)); float relcoef = exp(-1 / (reltime * sample_rate)); - float makeup = Math::db2linear(base->gain); + float makeup = Math::db_to_linear(base->gain); float mix = base->mix; float gr_meter_decay = exp(1 / (1 * sample_rate)); @@ -64,7 +64,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi float peak = MAX(s.l, s.r); - float overdb = 2.08136898f * Math::linear2db(peak / threshold); + float overdb = 2.08136898f * Math::linear_to_db(peak / threshold); if (overdb < 0.0) { //we only care about what goes over to compress overdb = 0.0; @@ -94,7 +94,7 @@ void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames, Audi } float gr = -overdb * (cratio - 1) / cratio; - float grv = Math::db2linear(gr); + float grv = Math::db_to_linear(gr); runmax = maxover + relcoef * (runmax - maxover); // highest peak for setting att/rel decays in reltime maxover = runmax; diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp index ae8c58f654..f71ff05b23 100644 --- a/servers/audio/effects/audio_effect_delay.cpp +++ b/servers/audio/effects/audio_effect_delay.cpp @@ -53,13 +53,13 @@ void AudioEffectDelayInstance::_process_chunk(const AudioFrame *p_src_frames, Au float mix_rate = AudioServer::get_singleton()->get_mix_rate(); - float tap_1_level_f = base->tap_1_active ? Math::db2linear(base->tap_1_level) : 0.0; + float tap_1_level_f = base->tap_1_active ? Math::db_to_linear(base->tap_1_level) : 0.0; int tap_1_delay_frames = int((base->tap_1_delay_ms / 1000.0) * mix_rate); - float tap_2_level_f = base->tap_2_active ? Math::db2linear(base->tap_2_level) : 0.0; + float tap_2_level_f = base->tap_2_active ? Math::db_to_linear(base->tap_2_level) : 0.0; int tap_2_delay_frames = int((base->tap_2_delay_ms / 1000.0) * mix_rate); - float feedback_level_f = base->feedback_active ? Math::db2linear(base->feedback_level) : 0.0; + float feedback_level_f = base->feedback_active ? Math::db_to_linear(base->feedback_level) : 0.0; unsigned int feedback_delay_frames = int((base->feedback_delay_ms / 1000.0) * mix_rate); AudioFrame tap1_vol = AudioFrame(tap_1_level_f, tap_1_level_f); diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp index 6820d796a4..5987ed7bb2 100644 --- a/servers/audio/effects/audio_effect_distortion.cpp +++ b/servers/audio/effects/audio_effect_distortion.cpp @@ -41,8 +41,8 @@ void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames, Audi float lpf_ic = 1.0 - lpf_c; float drive_f = base->drive; - float pregain_f = Math::db2linear(base->pre_gain); - float postgain_f = Math::db2linear(base->post_gain); + float pregain_f = Math::db_to_linear(base->pre_gain); + float postgain_f = Math::db_to_linear(base->post_gain); float atan_mult = pow(10, drive_f * drive_f * 3.0) - 1.0 + 0.001; float atan_div = 1.0 / (atanf(atan_mult) * (1.0 + drive_f * 8)); diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp index 500abd3a6f..14ece8d93e 100644 --- a/servers/audio/effects/audio_effect_eq.cpp +++ b/servers/audio/effects/audio_effect_eq.cpp @@ -38,7 +38,7 @@ void AudioEffectEQInstance::process(const AudioFrame *p_src_frames, AudioFrame * EQ::BandProcess *proc_r = bands[1].ptrw(); float *bgain = gains.ptrw(); for (int i = 0; i < band_count; i++) { - bgain[i] = Math::db2linear(base->gain[i]); + bgain[i] = Math::db_to_linear(base->gain[i]); } for (int i = 0; i < p_frame_count; i++) { diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp index 7bcd68d48b..99653cf5b6 100644 --- a/servers/audio/effects/audio_effect_limiter.cpp +++ b/servers/audio/effects/audio_effect_limiter.cpp @@ -32,11 +32,11 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFrame *p_dst_frames, int p_frame_count) { float threshdb = base->threshold; - float ceiling = Math::db2linear(base->ceiling); + float ceiling = Math::db_to_linear(base->ceiling); float ceildb = base->ceiling; - float makeup = Math::db2linear(ceildb - threshdb); + float makeup = Math::db_to_linear(ceildb - threshdb); float sc = -base->soft_clip; - float scv = Math::db2linear(sc); + float scv = Math::db_to_linear(sc); float peakdb = ceildb + 25; float scmult = Math::abs((ceildb - sc) / (peakdb - sc)); @@ -49,14 +49,14 @@ void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames, AudioFr float sign1 = (spl1 < 0.0 ? -1.0 : 1.0); float abs0 = Math::abs(spl0); float abs1 = Math::abs(spl1); - float overdb0 = Math::linear2db(abs0) - ceildb; - float overdb1 = Math::linear2db(abs1) - ceildb; + float overdb0 = Math::linear_to_db(abs0) - ceildb; + float overdb1 = Math::linear_to_db(abs1) - ceildb; if (abs0 > scv) { - spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult)); + spl0 = sign0 * (scv + Math::db_to_linear(overdb0 * scmult)); } if (abs1 > scv) { - spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult)); + spl1 = sign1 * (scv + Math::db_to_linear(overdb1 * scmult)); } spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0); diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp index 64695557aa..1254a6740a 100644 --- a/servers/audio_server.cpp +++ b/servers/audio_server.cpp @@ -547,7 +547,7 @@ void AudioServer::_mix_step() { AudioFrame peak = AudioFrame(0, 0); - float volume = Math::db2linear(bus->volume_db); + float volume = Math::db_to_linear(bus->volume_db); if (solo_mode) { if (!bus->soloed) { @@ -573,12 +573,12 @@ void AudioServer::_mix_step() { } } - bus->channels.write[k].peak_volume = AudioFrame(Math::linear2db(peak.l + AUDIO_PEAK_OFFSET), Math::linear2db(peak.r + AUDIO_PEAK_OFFSET)); + bus->channels.write[k].peak_volume = AudioFrame(Math::linear_to_db(peak.l + AUDIO_PEAK_OFFSET), Math::linear_to_db(peak.r + AUDIO_PEAK_OFFSET)); if (!bus->channels[k].used) { //see if any audio is contained, because channel was not used - if (MAX(peak.r, peak.l) > Math::db2linear(channel_disable_threshold_db)) { + if (MAX(peak.r, peak.l) > Math::db_to_linear(channel_disable_threshold_db)) { bus->channels.write[k].last_mix_with_audio = mix_frames; } else if (mix_frames - bus->channels[k].last_mix_with_audio > channel_disable_frames) { bus->channels.write[k].active = false; diff --git a/servers/display_server.cpp b/servers/display_server.cpp index 0c05570b23..22f42ca343 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -663,6 +663,8 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("window_set_flag", "flag", "enabled", "window_id"), &DisplayServer::window_set_flag, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_get_flag", "flag", "window_id"), &DisplayServer::window_get_flag, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_get_safe_title_margins", "window_id"), &DisplayServer::window_get_safe_title_margins, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_request_attention", "window_id"), &DisplayServer::window_request_attention, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_move_to_foreground", "window_id"), &DisplayServer::window_move_to_foreground, DEFVAL(MAIN_WINDOW_ID)); @@ -677,6 +679,9 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("window_set_vsync_mode", "vsync_mode", "window_id"), &DisplayServer::window_set_vsync_mode, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_get_vsync_mode", "window_id"), &DisplayServer::window_get_vsync_mode, DEFVAL(MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("window_maximize_on_title_dbl_click"), &DisplayServer::window_maximize_on_title_dbl_click); + ClassDB::bind_method(D_METHOD("window_minimize_on_title_dbl_click"), &DisplayServer::window_minimize_on_title_dbl_click); + ClassDB::bind_method(D_METHOD("ime_get_selection"), &DisplayServer::ime_get_selection); ClassDB::bind_method(D_METHOD("ime_get_text"), &DisplayServer::ime_get_text); @@ -733,6 +738,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(FEATURE_SWAP_BUFFERS); BIND_ENUM_CONSTANT(FEATURE_CLIPBOARD_PRIMARY); BIND_ENUM_CONSTANT(FEATURE_TEXT_TO_SPEECH); + BIND_ENUM_CONSTANT(FEATURE_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); @@ -792,6 +798,7 @@ void DisplayServer::_bind_methods() { BIND_ENUM_CONSTANT(WINDOW_FLAG_TRANSPARENT); BIND_ENUM_CONSTANT(WINDOW_FLAG_NO_FOCUS); BIND_ENUM_CONSTANT(WINDOW_FLAG_POPUP); + BIND_ENUM_CONSTANT(WINDOW_FLAG_EXTEND_TO_TITLE); BIND_ENUM_CONSTANT(WINDOW_FLAG_MAX); BIND_ENUM_CONSTANT(WINDOW_EVENT_MOUSE_ENTER); diff --git a/servers/display_server.h b/servers/display_server.h index 4e52c58633..0b162fe491 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -122,6 +122,7 @@ public: FEATURE_KEEP_SCREEN_ON, FEATURE_CLIPBOARD_PRIMARY, FEATURE_TEXT_TO_SPEECH, + FEATURE_EXTEND_TO_TITLE, }; virtual bool has_feature(Feature p_feature) const = 0; @@ -289,6 +290,7 @@ public: WINDOW_FLAG_TRANSPARENT, WINDOW_FLAG_NO_FOCUS, WINDOW_FLAG_POPUP, + WINDOW_FLAG_EXTEND_TO_TITLE, WINDOW_FLAG_MAX, }; @@ -300,6 +302,7 @@ public: WINDOW_FLAG_TRANSPARENT_BIT = (1 << WINDOW_FLAG_TRANSPARENT), WINDOW_FLAG_NO_FOCUS_BIT = (1 << WINDOW_FLAG_NO_FOCUS), WINDOW_FLAG_POPUP_BIT = (1 << WINDOW_FLAG_POPUP), + WINDOW_FLAG_EXTEND_TO_TITLE_BIT = (1 << WINDOW_FLAG_EXTEND_TO_TITLE), }; virtual WindowID create_sub_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()); @@ -371,6 +374,8 @@ public: virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) = 0; virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0; + virtual Vector2i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const { return Vector2i(); }; + virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const = 0; virtual bool can_any_window_draw() const = 0; @@ -378,6 +383,9 @@ public: virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID); virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID); + virtual bool window_maximize_on_title_dbl_click() const { return false; } + virtual bool window_minimize_on_title_dbl_click() const { return false; } + // necessary for GL focus, may be able to use one of the existing functions for this, not sure yet virtual void gl_window_make_current(DisplayServer::WindowID p_window_id); diff --git a/servers/physics_2d/godot_body_2d.cpp b/servers/physics_2d/godot_body_2d.cpp index 268beb1a55..ef6a6b1ae2 100644 --- a/servers/physics_2d/godot_body_2d.cpp +++ b/servers/physics_2d/godot_body_2d.cpp @@ -44,7 +44,7 @@ void GodotBody2D::update_mass_properties() { //update shapes and motions switch (mode) { - case PhysicsServer2D::BODY_MODE_DYNAMIC: { + case PhysicsServer2D::BODY_MODE_RIGID: { real_t total_area = 0; for (int i = 0; i < get_shape_count(); i++) { if (is_shape_disabled(i)) { @@ -113,7 +113,7 @@ void GodotBody2D::update_mass_properties() { _inv_inertia = 0; _inv_mass = 0; } break; - case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: { _inv_inertia = 0; _inv_mass = 1.0 / mass; @@ -160,7 +160,7 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian real_t mass_value = p_value; ERR_FAIL_COND(mass_value <= 0); mass = mass_value; - if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (mode >= PhysicsServer2D::BODY_MODE_RIGID) { _mass_properties_changed(); } } break; @@ -168,13 +168,13 @@ void GodotBody2D::set_param(PhysicsServer2D::BodyParameter p_param, const Varian real_t inertia_value = p_value; if (inertia_value <= 0.0) { calculate_inertia = true; - if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer2D::BODY_MODE_RIGID) { _mass_properties_changed(); } } else { calculate_inertia = false; inertia = inertia_value; - if (mode == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer2D::BODY_MODE_RIGID) { _inv_inertia = 1.0 / inertia; } } @@ -267,7 +267,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) { first_time_kinematic = true; } } break; - case PhysicsServer2D::BODY_MODE_DYNAMIC: { + case PhysicsServer2D::BODY_MODE_RIGID: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; if (!calculate_inertia) { _inv_inertia = 1.0 / inertia; @@ -277,7 +277,7 @@ void GodotBody2D::set_mode(PhysicsServer2D::BodyMode p_mode) { set_active(true); } break; - case PhysicsServer2D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer2D::BODY_MODE_RIGID_LINEAR: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = 0; angular_velocity = 0; @@ -358,7 +358,7 @@ void GodotBody2D::set_state(PhysicsServer2D::BodyState p_state, const Variant &p } break; case PhysicsServer2D::BODY_STATE_CAN_SLEEP: { can_sleep = p_variant; - if (mode >= PhysicsServer2D::BODY_MODE_DYNAMIC && !active && !can_sleep) { + if (mode >= PhysicsServer2D::BODY_MODE_RIGID && !active && !can_sleep) { set_active(true); } @@ -661,7 +661,7 @@ void GodotBody2D::wakeup_neighbours() { continue; } GodotBody2D *b = n[i]; - if (b->mode < PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (b->mode < PhysicsServer2D::BODY_MODE_RIGID) { continue; } diff --git a/servers/physics_2d/godot_body_2d.h b/servers/physics_2d/godot_body_2d.h index 4b87a69d5c..409940d4f8 100644 --- a/servers/physics_2d/godot_body_2d.h +++ b/servers/physics_2d/godot_body_2d.h @@ -42,7 +42,7 @@ class GodotConstraint2D; class GodotPhysicsDirectBodyState2D; class GodotBody2D : public GodotCollisionObject2D { - PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_DYNAMIC; + PhysicsServer2D::BodyMode mode = PhysicsServer2D::BODY_MODE_RIGID; Vector2 biased_linear_velocity; real_t biased_angular_velocity = 0.0; diff --git a/servers/physics_2d/godot_space_2d.cpp b/servers/physics_2d/godot_space_2d.cpp index 4166191be8..afcc5af951 100644 --- a/servers/physics_2d/godot_space_2d.cpp +++ b/servers/physics_2d/godot_space_2d.cpp @@ -643,7 +643,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) { const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj); - if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) { //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); //compute displacement from linear velocity @@ -948,7 +948,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D:: if (col_obj->get_type() == GodotCollisionObject2D::TYPE_BODY) { const GodotBody2D *b = static_cast<const GodotBody2D *>(col_obj); - if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_DYNAMIC) { + if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) { //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); //compute displacement from linear velocity @@ -1218,7 +1218,7 @@ GodotPhysicsDirectSpaceState2D *GodotSpace2D::get_direct_state() { GodotSpace2D::GodotSpace2D() { body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_linear", 2.0); - body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg2rad(8.0)); + body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/2d/sleep_threshold_angular", Math::deg_to_rad(8.0)); body_time_to_sleep = GLOBAL_DEF("physics/2d/time_before_sleep", 0.5); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/2d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); diff --git a/servers/physics_2d/godot_step_2d.cpp b/servers/physics_2d/godot_step_2d.cpp index 0603458acd..46718c8819 100644 --- a/servers/physics_2d/godot_step_2d.cpp +++ b/servers/physics_2d/godot_step_2d.cpp @@ -42,7 +42,7 @@ void GodotStep2D::_populate_island(GodotBody2D *p_body, LocalVector<GodotBody2D p_body->set_island_step(_step); if (p_body->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) { - // Only dynamic bodies are tested for activation. + // Only rigid bodies are tested for activation. p_body_island.push_back(p_body); } diff --git a/servers/physics_3d/godot_body_3d.cpp b/servers/physics_3d/godot_body_3d.cpp index 4c89106839..b632f7f461 100644 --- a/servers/physics_3d/godot_body_3d.cpp +++ b/servers/physics_3d/godot_body_3d.cpp @@ -56,7 +56,7 @@ void GodotBody3D::update_mass_properties() { // Update shapes and motions. switch (mode) { - case PhysicsServer3D::BODY_MODE_DYNAMIC: { + case PhysicsServer3D::BODY_MODE_RIGID: { real_t total_area = 0; for (int i = 0; i < get_shape_count(); i++) { if (is_shape_disabled(i)) { @@ -154,7 +154,7 @@ void GodotBody3D::update_mass_properties() { _inv_inertia = Vector3(); _inv_mass = 0; } break; - case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: { _inv_inertia_tensor.set_zero(); _inv_mass = 1.0 / mass; @@ -201,7 +201,7 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian real_t mass_value = p_value; ERR_FAIL_COND(mass_value <= 0); mass = mass_value; - if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode >= PhysicsServer3D::BODY_MODE_RIGID) { _mass_properties_changed(); } } break; @@ -209,12 +209,12 @@ void GodotBody3D::set_param(PhysicsServer3D::BodyParameter p_param, const Varian inertia = p_value; if ((inertia.x <= 0.0) || (inertia.y <= 0.0) || (inertia.z <= 0.0)) { calculate_inertia = true; - if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer3D::BODY_MODE_RIGID) { _mass_properties_changed(); } } else { calculate_inertia = false; - if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer3D::BODY_MODE_RIGID) { principal_inertia_axes_local = Basis(); _inv_inertia = inertia.inverse(); _update_transform_dependent(); @@ -263,7 +263,7 @@ Variant GodotBody3D::get_param(PhysicsServer3D::BodyParameter p_param) const { return mass; } break; case PhysicsServer3D::BODY_PARAM_INERTIA: { - if (mode == PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (mode == PhysicsServer3D::BODY_MODE_RIGID) { return _inv_inertia.inverse(); } else { return Vector3(); @@ -315,7 +315,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) { _update_transform_dependent(); } break; - case PhysicsServer3D::BODY_MODE_DYNAMIC: { + case PhysicsServer3D::BODY_MODE_RIGID: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; if (!calculate_inertia) { principal_inertia_axes_local = Basis(); @@ -327,7 +327,7 @@ void GodotBody3D::set_mode(PhysicsServer3D::BodyMode p_mode) { set_active(true); } break; - case PhysicsServer3D::BODY_MODE_DYNAMIC_LINEAR: { + case PhysicsServer3D::BODY_MODE_RIGID_LINEAR: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = Vector3(); angular_velocity = Vector3(); @@ -407,7 +407,7 @@ void GodotBody3D::set_state(PhysicsServer3D::BodyState p_state, const Variant &p } break; case PhysicsServer3D::BODY_STATE_CAN_SLEEP: { can_sleep = p_variant; - if (mode >= PhysicsServer3D::BODY_MODE_DYNAMIC && !active && !can_sleep) { + if (mode >= PhysicsServer3D::BODY_MODE_RIGID && !active && !can_sleep) { set_active(true); } @@ -744,7 +744,7 @@ void GodotBody3D::wakeup_neighbours() { continue; } GodotBody3D *b = n[i]; - if (b->mode < PhysicsServer3D::BODY_MODE_DYNAMIC) { + if (b->mode < PhysicsServer3D::BODY_MODE_RIGID) { continue; } diff --git a/servers/physics_3d/godot_body_3d.h b/servers/physics_3d/godot_body_3d.h index 93bd5a0071..2153ca4e91 100644 --- a/servers/physics_3d/godot_body_3d.h +++ b/servers/physics_3d/godot_body_3d.h @@ -40,7 +40,7 @@ class GodotConstraint3D; class GodotPhysicsDirectBodyState3D; class GodotBody3D : public GodotCollisionObject3D { - PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_DYNAMIC; + PhysicsServer3D::BodyMode mode = PhysicsServer3D::BODY_MODE_RIGID; Vector3 linear_velocity; Vector3 angular_velocity; diff --git a/servers/physics_3d/godot_collision_solver_3d.cpp b/servers/physics_3d/godot_collision_solver_3d.cpp index b2d3e4d876..094d77a582 100644 --- a/servers/physics_3d/godot_collision_solver_3d.cpp +++ b/servers/physics_3d/godot_collision_solver_3d.cpp @@ -38,7 +38,7 @@ #define collision_solver sat_calculate_penetration //#define collision_solver gjk_epa_calculate_penetration -bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { +bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin) { const GodotWorldBoundaryShape3D *world_boundary = static_cast<const GodotWorldBoundaryShape3D *>(p_shape_A); if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_WORLD_BOUNDARY) { return false; @@ -70,6 +70,7 @@ bool GodotCollisionSolver3D::solve_static_world_boundary(const GodotShape3D *p_s bool found = false; for (int i = 0; i < support_count; i++) { + supports[i] += p_margin * supports[i].normalized(); supports[i] = p_transform_B.xform(supports[i]); if (p.distance_to(supports[i]) >= 0) { continue; @@ -379,9 +380,9 @@ bool GodotCollisionSolver3D::solve_static(const GodotShape3D *p_shape_A, const T } if (swap) { - return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); + return solve_static_world_boundary(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_A); } else { - return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); + return solve_static_world_boundary(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_B); } } else if (type_A == PhysicsServer3D::SHAPE_SEPARATION_RAY) { @@ -456,8 +457,17 @@ bool GodotCollisionSolver3D::solve_distance_world_boundary(const GodotShape3D *p Vector3 supports[max_supports]; int support_count; GodotShape3D::FeatureType support_type; + Vector3 support_direction = p_transform_B.basis.xform_inv(-p.normal).normalized(); - p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count, support_type); + p_shape_B->get_supports(support_direction, max_supports, supports, support_count, support_type); + + if (support_count == 0) { // This is a poor man's way to detect shapes that don't implement get_supports, such as GodotMotionShape3D. + Vector3 support_B = p_transform_B.xform(p_shape_B->get_support(support_direction)); + r_point_A = p.project(support_B); + r_point_B = support_B; + bool collided = p.distance_to(support_B) <= 0; + return collided; + } if (support_type == GodotShape3D::FEATURE_CIRCLE) { ERR_FAIL_COND_V(support_count != 3, false); diff --git a/servers/physics_3d/godot_collision_solver_3d.h b/servers/physics_3d/godot_collision_solver_3d.h index a6a0ebfead..e7d67903e9 100644 --- a/servers/physics_3d/godot_collision_solver_3d.h +++ b/servers/physics_3d/godot_collision_solver_3d.h @@ -42,7 +42,7 @@ private: static void soft_body_contact_callback(const Vector3 &p_point_A, int p_index_A, const Vector3 &p_point_B, int p_index_B, void *p_userdata); static bool soft_body_concave_callback(void *p_userdata, GodotShape3D *p_convex); static bool concave_callback(void *p_userdata, GodotShape3D *p_convex); - static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool solve_static_world_boundary(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0); static bool solve_separation_ray(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin = 0); static bool solve_soft_body(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); static bool solve_concave(const GodotShape3D *p_shape_A, const Transform3D &p_transform_A, const GodotShape3D *p_shape_B, const Transform3D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0); diff --git a/servers/physics_3d/godot_space_3d.cpp b/servers/physics_3d/godot_space_3d.cpp index 074232dd66..76d59202c9 100644 --- a/servers/physics_3d/godot_space_3d.cpp +++ b/servers/physics_3d/godot_space_3d.cpp @@ -1249,7 +1249,7 @@ GodotPhysicsDirectSpaceState3D *GodotSpace3D::get_direct_state() { GodotSpace3D::GodotSpace3D() { body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); - body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg2rad(8.0)); + body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", Math::deg_to_rad(8.0)); body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); diff --git a/servers/physics_3d/godot_step_3d.cpp b/servers/physics_3d/godot_step_3d.cpp index f384c829a4..bfedcd29c0 100644 --- a/servers/physics_3d/godot_step_3d.cpp +++ b/servers/physics_3d/godot_step_3d.cpp @@ -44,7 +44,7 @@ void GodotStep3D::_populate_island(GodotBody3D *p_body, LocalVector<GodotBody3D p_body->set_island_step(_step); if (p_body->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC) { - // Only dynamic bodies are tested for activation. + // Only rigid bodies are tested for activation. p_body_island.push_back(p_body); } diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp index bfb5cd8106..ca9c9c8fc4 100644 --- a/servers/physics_server_2d.cpp +++ b/servers/physics_server_2d.cpp @@ -817,8 +817,8 @@ void PhysicsServer2D::_bind_methods() { BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR); BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h index d0c5a7189b..071ff5ffe9 100644 --- a/servers/physics_server_2d.h +++ b/servers/physics_server_2d.h @@ -348,8 +348,8 @@ public: enum BodyMode { BODY_MODE_STATIC, BODY_MODE_KINEMATIC, - BODY_MODE_DYNAMIC, - BODY_MODE_DYNAMIC_LINEAR, + BODY_MODE_RIGID, + BODY_MODE_RIGID_LINEAR, }; virtual RID body_create() = 0; diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp index 6dd5be9ea8..fc32e1f665 100644 --- a/servers/physics_server_3d.cpp +++ b/servers/physics_server_3d.cpp @@ -988,8 +988,8 @@ void PhysicsServer3D::_bind_methods() { BIND_ENUM_CONSTANT(BODY_MODE_STATIC); BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC); - BIND_ENUM_CONSTANT(BODY_MODE_DYNAMIC_LINEAR); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID_LINEAR); BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h index d5c4d9713b..6237ed67aa 100644 --- a/servers/physics_server_3d.h +++ b/servers/physics_server_3d.h @@ -381,8 +381,8 @@ public: enum BodyMode { BODY_MODE_STATIC, BODY_MODE_KINEMATIC, - BODY_MODE_DYNAMIC, - BODY_MODE_DYNAMIC_LINEAR, + BODY_MODE_RIGID, + BODY_MODE_RIGID_LINEAR, }; enum BodyDampMode { diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 86e5e4802b..aa9772a483 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -1183,6 +1183,38 @@ void RendererCanvasCull::canvas_item_add_msdf_texture_rect_region(RID p_item, co rect->px_range = p_px_range; } +void RendererCanvasCull::canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate) { + Item *canvas_item = canvas_item_owner.get_or_null(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect *rect = canvas_item->alloc_command<Item::CommandRect>(); + ERR_FAIL_COND(!rect); + rect->modulate = p_modulate; + rect->rect = p_rect; + + rect->texture = p_texture; + + rect->source = p_src_rect; + rect->flags = RendererCanvasRender::CANVAS_RECT_REGION | RendererCanvasRender::CANVAS_RECT_LCD; + + if (p_rect.size.x < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_src_rect.size.x < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_H; + rect->source.size.x = -rect->source.size.x; + } + if (p_rect.size.y < 0) { + rect->flags |= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_src_rect.size.y < 0) { + rect->flags ^= RendererCanvasRender::CANVAS_RECT_FLIP_V; + rect->source.size.y = -rect->source.size.y; + } +} + void RendererCanvasCull::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, bool p_clip_uv) { Item *canvas_item = canvas_item_owner.get_or_null(p_item); ERR_FAIL_COND(!canvas_item); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index e8c54310c9..0d6a4006f8 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -225,6 +225,7 @@ public: void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false); void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false); void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0); + void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)); void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0); void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()); diff --git a/servers/rendering/renderer_canvas_render.h b/servers/rendering/renderer_canvas_render.h index 11a7d34291..6791ed9626 100644 --- a/servers/rendering/renderer_canvas_render.h +++ b/servers/rendering/renderer_canvas_render.h @@ -46,6 +46,7 @@ public: CANVAS_RECT_CLIP_UV = 32, CANVAS_RECT_IS_GROUP = 64, CANVAS_RECT_MSDF = 128, + CANVAS_RECT_LCD = 256, }; struct Light { @@ -193,7 +194,7 @@ public: Rect2 rect; Color modulate; Rect2 source; - uint8_t flags; + uint16_t flags; float outline; float px_range; diff --git a/servers/rendering/renderer_rd/cluster_builder_rd.h b/servers/rendering/renderer_rd/cluster_builder_rd.h index 17ca1986c6..ef17ceb98c 100644 --- a/servers/rendering/renderer_rd/cluster_builder_rd.h +++ b/servers/rendering/renderer_rd/cluster_builder_rd.h @@ -269,7 +269,7 @@ public: //spot radius *= shared->cone_overfit; // overfit icosphere - real_t len = Math::tan(Math::deg2rad(p_spot_aperture)) * radius; + real_t len = Math::tan(Math::deg_to_rad(p_spot_aperture)) * radius; //approximate, probably better to use a cone support function float max_d = -1e20; float min_d = 1e20; @@ -293,7 +293,7 @@ public: float dist = base_plane.distance_to(Vector3()); if (dist >= 0 && dist < radius) { //inside, check angle - float angle = Math::rad2deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z)))); + float angle = Math::rad_to_deg(Math::acos((-xform.origin.normalized()).dot(-xform.basis.get_column(Vector3::AXIS_Z)))); e.touches_near = angle < p_spot_aperture * 1.05; //overfit aperture a little due to cone overfit } else { e.touches_near = false; diff --git a/servers/rendering/renderer_rd/effects/ss_effects.cpp b/servers/rendering/renderer_rd/effects/ss_effects.cpp index 0f896a8aa7..874409b885 100644 --- a/servers/rendering/renderer_rd/effects/ss_effects.cpp +++ b/servers/rendering/renderer_rd/effects/ss_effects.cpp @@ -1604,7 +1604,7 @@ void SSEffects::screen_space_reflection(SSRRenderBuffers &p_ssr_buffers, const R ScreenSpaceReflectionFilterPushConstant push_constant; push_constant.view_index = v; push_constant.orthogonal = p_projections[v].is_orthogonal(); - push_constant.edge_tolerance = Math::sin(Math::deg2rad(15.0)); + push_constant.edge_tolerance = Math::sin(Math::deg_to_rad(15.0)); push_constant.proj_info[0] = -2.0f / (p_screen_size.width * p_projections[v].matrix[0][0]); push_constant.proj_info[1] = -2.0f / (p_screen_size.height * p_projections[v].matrix[1][1]); push_constant.proj_info[2] = (1.0f - p_projections[v].matrix[0][2]) / p_projections[v].matrix[0][0]; diff --git a/servers/rendering/renderer_rd/environment/gi.cpp b/servers/rendering/renderer_rd/environment/gi.cpp index eaef5ba39c..66e984174c 100644 --- a/servers/rendering/renderer_rd/environment/gi.cpp +++ b/servers/rendering/renderer_rd/environment/gi.cpp @@ -1924,7 +1924,7 @@ void GI::SDFGI::pre_process_gi(const Transform3D &p_transform, RenderDataRD *p_r lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; @@ -2362,7 +2362,7 @@ void GI::SDFGI::render_static_lights(RID p_render_buffers, uint32_t p_cascade_co lights[idx].has_shadow = RSG::light_storage->light_has_shadow(li->light); lights[idx].attenuation = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_ATTENUATION); lights[idx].radius = RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_RANGE); - lights[idx].cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); + lights[idx].cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ANGLE))); lights[idx].inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(li->light, RS::LIGHT_PARAM_SPOT_ATTENUATION); idx++; @@ -2800,7 +2800,7 @@ void GI::VoxelGIInstance::update(bool p_update_light_instances, const Vector<RID l.color[1] = color.g; l.color[2] = color.b; - l.cos_spot_angle = Math::cos(Math::deg2rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); + l.cos_spot_angle = Math::cos(Math::deg_to_rad(RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE))); l.inv_spot_attenuation = 1.0f / RSG::light_storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); Transform3D xform = p_scene_render->light_instance_get_base_transform(light_instance); diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index d3601274b5..1d6b158d65 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -1232,7 +1232,7 @@ void SkyRD::setup(RID p_env, RID p_render_buffers, const PagedArray<RID> &p_ligh // I know tan(0) is 0, but let's not risk it with numerical precision. // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); } else { angular_diameter = 0.0; } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index 38a2340d40..67c929b724 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -494,7 +494,11 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend } //bind pipeline - { + if (rect->flags & CANVAS_RECT_LCD) { + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD_LCD_BLEND].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + RD::get_singleton()->draw_list_set_blend_constants(p_draw_list, rect->modulate); + } else { RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); } @@ -556,6 +560,8 @@ void RendererCanvasRenderRD::_render_item(RD::DrawListID p_draw_list, RID p_rend push_constant.msdf[1] = rect->outline; // Outline size. push_constant.msdf[2] = 0.f; // Reserved. push_constant.msdf[3] = 0.f; // Reserved. + } else if (rect->flags & CANVAS_RECT_LCD) { + push_constant.flags |= FLAGS_USE_LCD; } push_constant.modulation[0] = rect->modulate.r * base_color.r; @@ -1594,7 +1600,7 @@ void RendererCanvasRenderRD::light_update_shadow(RID p_rid, int p_shadow_index, real_t farp = p_far; real_t aspect = 1.0; - real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5)); + real_t ymax = nearp * Math::tan(Math::deg_to_rad(fov * 0.5)); real_t ymin = -ymax; real_t xmin = ymin * aspect; real_t xmax = ymax * aspect; @@ -2113,6 +2119,18 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::PipelineColorBlendState blend_state; blend_state.attachments.push_back(attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + //update pipelines for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { @@ -2128,10 +2146,12 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2141,8 +2161,11 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2152,11 +2175,17 @@ void RendererCanvasRenderRD::CanvasShaderData::set_code(const String &p_code) { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]); - pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } @@ -2363,6 +2392,18 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { blend_state.attachments.push_back(blend_attachment); + RD::PipelineColorBlendState::Attachment attachment_lcd; + attachment_lcd.enable_blend = true; + attachment_lcd.alpha_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.color_blend_op = RD::BLEND_OP_ADD; + attachment_lcd.src_color_blend_factor = RD::BLEND_FACTOR_CONSTANT_COLOR; + attachment_lcd.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_COLOR; + attachment_lcd.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment_lcd.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + RD::PipelineColorBlendState blend_state_lcd; + blend_state_lcd.attachments.push_back(attachment_lcd); + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { @@ -2376,10 +2417,12 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { RD::RENDER_PRIMITIVE_LINES, RD::RENDER_PRIMITIVE_LINESTRIPS, RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, }; ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit + { + //non lit SHADER_VARIANT_QUAD, SHADER_VARIANT_NINEPATCH, SHADER_VARIANT_PRIMITIVE, @@ -2389,8 +2432,11 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD, + }, + { + //lit SHADER_VARIANT_QUAD_LIGHT, SHADER_VARIANT_NINEPATCH_LIGHT, SHADER_VARIANT_PRIMITIVE_LIGHT, @@ -2400,11 +2446,17 @@ RendererCanvasRenderRD::RendererCanvasRenderRD() { SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_QUAD_LIGHT, + }, }; RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); - shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + if (j == PIPELINE_VARIANT_QUAD_LCD_BLEND) { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state_lcd, RD::DYNAMIC_STATE_BLEND_CONSTANTS); + } else { + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } } } } diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h index bcbbbaa1a0..54077a5b9a 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.h @@ -85,6 +85,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27), FLAGS_USE_MSDF = (1 << 28), + FLAGS_USE_LCD = (1 << 29), }; enum { @@ -122,6 +123,7 @@ class RendererCanvasRenderRD : public RendererCanvasRender { PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_POINTS, + PIPELINE_VARIANT_QUAD_LCD_BLEND, PIPELINE_VARIANT_MAX }; enum PipelineLightMode { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index d8499681ad..7adc36c57c 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -2459,6 +2459,19 @@ void RendererSceneRenderRD::render_buffers_configure(RID p_render_buffers, RID p p_internal_width = p_width; } + if (p_use_taa) { + // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. + // This restores sharpness in still images to be roughly at the same level as without TAA, + // but moving scenes will still be blurrier. + p_texture_mipmap_bias -= 0.5; + } + + if (p_screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { + // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness. + // If both TAA and FXAA are enabled, combine their negative LOD biases together. + p_texture_mipmap_bias -= 0.25; + } + material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias); update_uniform_sets(); @@ -2862,7 +2875,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const float size = light_storage->light_get_param(base, RS::LIGHT_PARAM_SIZE); - light_data.size = 1.0 - Math::cos(Math::deg2rad(size)); //angle to cosine offset + light_data.size = 1.0 - Math::cos(Math::deg_to_rad(size)); //angle to cosine offset if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_PSSM_SPLITS) { WARN_PRINT_ONCE("The DirectionalLight3D PSSM splits debug draw mode is not reimplemented yet."); @@ -2877,7 +2890,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // I know tan(0) is 0, but let's not risk it with numerical precision. // technically this will keep expanding until reaching the sun, but all we care // is expand until we reach the radius of the near plane (there can't be more occluders than that) - angular_diameter = Math::tan(Math::deg2rad(angular_diameter)); + angular_diameter = Math::tan(Math::deg_to_rad(angular_diameter)); if (light_storage->light_has_shadow(base) && light_storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_BLUR) > 0.0) { // Only enable PCSS-like soft shadows if blurring is enabled. // Otherwise, performance would decrease with no visual difference. @@ -3092,7 +3105,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const light_data.inv_spot_attenuation = 1.0f / light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION); float spot_angle = light_storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE); - light_data.cos_spot_angle = Math::cos(Math::deg2rad(spot_angle)); + light_data.cos_spot_angle = Math::cos(Math::deg_to_rad(spot_angle)); light_data.mask = light_storage->light_get_cull_mask(base); @@ -3193,7 +3206,7 @@ void RendererSceneRenderRD::_setup_lights(const PagedArray<RID> &p_lights, const // Only enable PCSS-like soft shadows if blurring is enabled. // Otherwise, performance would decrease with no visual difference. Projection cm = li->shadow_transform[0].camera; - float half_np = cm.get_z_near() * Math::tan(Math::deg2rad(spot_angle)); + float half_np = cm.get_z_near() * Math::tan(Math::deg_to_rad(spot_angle)); light_data.soft_shadow_size = (size * 0.5 / radius) / (half_np / cm.get_z_near()) * rect.size.width; } else { light_data.soft_shadow_size = 0.0; diff --git a/servers/rendering/renderer_rd/shaders/canvas.glsl b/servers/rendering/renderer_rd/shaders/canvas.glsl index f8e9020f9f..459d798a80 100644 --- a/servers/rendering/renderer_rd/shaders/canvas.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas.glsl @@ -509,7 +509,13 @@ void main() { float a = clamp(d * px_size + 0.5, 0.0, 1.0); color.a = a * color.a; } - + } else if (bool(draw_data.flags & FLAGS_USE_LCD)) { + vec4 lcd_sample = texture(sampler2D(color_texture, texture_sampler), uv); + if (lcd_sample.a == 1.0) { + color.rgb = lcd_sample.rgb * color.a; + } else { + color = vec4(0.0, 0.0, 0.0, 0.0); + } } else { #else { diff --git a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl index 2ea6965c09..1b627a3e81 100644 --- a/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl +++ b/servers/rendering/renderer_rd/shaders/canvas_uniforms_inc.glsl @@ -25,6 +25,7 @@ #define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) #define FLAGS_USE_MSDF (1 << 28) +#define FLAGS_USE_LCD (1 << 29) #define SAMPLER_NEAREST_CLAMP 0 #define SAMPLER_LINEAR_CLAMP 1 diff --git a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp index 882afdfa54..7b58cc08dd 100644 --- a/servers/rendering/renderer_rd/storage_rd/light_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/light_storage.cpp @@ -352,7 +352,7 @@ AABB LightStorage::light_get_aabb(RID p_light) const { switch (light->type) { case RS::LIGHT_SPOT: { float len = light->param[RS::LIGHT_PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; + float size = Math::tan(Math::deg_to_rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); }; case RS::LIGHT_OMNI: { diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index ba644e7eb9..022b027644 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -134,7 +134,7 @@ void process() { material_storage->material_initialize(particles_shader.default_material); material_storage->material_set_shader(particles_shader.default_material, particles_shader.default_shader); - ParticlesMaterialData *md = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + ParticleProcessMaterialData *md = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); particles_shader.default_shader_rd = particles_shader.shader.version_get_shader(md->shader_data->version, 0); Vector<RD::Uniform> uniforms; @@ -1072,9 +1072,9 @@ void ParticlesStorage::_particles_process(Particles *p_particles, double p_delta RD::get_singleton()->buffer_update(p_particles->frame_params_buffer, 0, sizeof(ParticlesFrameParams) * p_particles->trail_params.size(), p_particles->trail_params.ptr()); - ParticlesMaterialData *m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + ParticleProcessMaterialData *m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(p_particles->process_material, MaterialStorage::SHADER_TYPE_PARTICLES)); if (!m) { - m = static_cast<ParticlesMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); + m = static_cast<ParticleProcessMaterialData *>(material_storage->material_get_data(particles_shader.default_material, MaterialStorage::SHADER_TYPE_PARTICLES)); } ERR_FAIL_COND(!m); @@ -1696,16 +1696,16 @@ MaterialStorage::ShaderData *ParticlesStorage::_create_particles_shader_func() { return shader_data; } -bool ParticlesStorage::ParticlesMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { +bool ParticlesStorage::ParticleProcessMaterialData::update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { return update_parameters_uniform_set(p_parameters, p_uniform_dirty, p_textures_dirty, shader_data->uniforms, shader_data->ubo_offsets.ptr(), shader_data->texture_uniforms, shader_data->default_texture_params, shader_data->ubo_size, uniform_set, ParticlesStorage::get_singleton()->particles_shader.shader.version_get_shader(shader_data->version, 0), 3); } -ParticlesStorage::ParticlesMaterialData::~ParticlesMaterialData() { +ParticlesStorage::ParticleProcessMaterialData::~ParticleProcessMaterialData() { free_parameters_uniform_set(uniform_set); } MaterialStorage::MaterialData *ParticlesStorage::_create_particles_material_func(ParticlesShaderData *p_shader) { - ParticlesMaterialData *material_data = memnew(ParticlesMaterialData); + ParticleProcessMaterialData *material_data = memnew(ParticleProcessMaterialData); material_data->shader_data = p_shader; //update will happen later anyway so do nothing. return material_data; diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.h b/servers/rendering/renderer_rd/storage_rd/particles_storage.h index 97d100e2da..299fdc6ec8 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.h @@ -354,14 +354,14 @@ private: return ParticlesStorage::get_singleton()->_create_particles_shader_func(); } - struct ParticlesMaterialData : public MaterialStorage::MaterialData { + struct ParticleProcessMaterialData : public MaterialStorage::MaterialData { ParticlesShaderData *shader_data = nullptr; RID uniform_set; virtual void set_render_priority(int p_priority) {} virtual void set_next_pass(RID p_pass) {} virtual bool update_parameters(const HashMap<StringName, Variant> &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~ParticlesMaterialData(); + virtual ~ParticleProcessMaterialData(); }; MaterialStorage::MaterialData *_create_particles_material_func(ParticlesShaderData *p_shader); diff --git a/servers/rendering/renderer_scene_cull.cpp b/servers/rendering/renderer_scene_cull.cpp index 9f5eb85c2f..80c4ecea2d 100644 --- a/servers/rendering/renderer_scene_cull.cpp +++ b/servers/rendering/renderer_scene_cull.cpp @@ -2146,7 +2146,7 @@ void RendererSceneCull::_light_instance_setup_directional_shadow(int p_shadow_in if (soft_shadow_angle > 0.0) { float z_range = (z_vec.dot(center) + radius + pancake_size) - z_min_cam; - soft_shadow_expand = Math::tan(Math::deg2rad(soft_shadow_angle)) * z_range; + soft_shadow_expand = Math::tan(Math::deg_to_rad(soft_shadow_angle)) * z_range; x_max += soft_shadow_expand; y_max += soft_shadow_expand; @@ -3125,8 +3125,8 @@ void RendererSceneCull::_render_scene(const RendererSceneRender::CameraData *p_c float radius = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); float angle = RSG::light_storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE); - float w = radius * Math::sin(Math::deg2rad(angle)); - float d = radius * Math::cos(Math::deg2rad(angle)); + float w = radius * Math::sin(Math::deg_to_rad(angle)); + float d = radius * Math::cos(Math::deg_to_rad(angle)); Vector3 base = ins->transform.origin - ins->transform.basis.get_column(2).normalized() * d; diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp index c07a783302..2fefdbff52 100644 --- a/servers/rendering/rendering_device.cpp +++ b/servers/rendering/rendering_device.cpp @@ -429,6 +429,7 @@ void RenderingDevice::_bind_methods() { ClassDB::bind_method(D_METHOD("draw_list_begin", "framebuffer", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::draw_list_begin, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); ClassDB::bind_method(D_METHOD("draw_list_begin_split", "framebuffer", "splits", "initial_color_action", "final_color_action", "initial_depth_action", "final_depth_action", "clear_color_values", "clear_depth", "clear_stencil", "region", "storage_textures"), &RenderingDevice::_draw_list_begin_split, DEFVAL(Vector<Color>()), DEFVAL(1.0), DEFVAL(0), DEFVAL(Rect2()), DEFVAL(TypedArray<RID>())); + ClassDB::bind_method(D_METHOD("draw_list_set_blend_constants", "draw_list", "color"), &RenderingDevice::draw_list_set_blend_constants); ClassDB::bind_method(D_METHOD("draw_list_bind_render_pipeline", "draw_list", "render_pipeline"), &RenderingDevice::draw_list_bind_render_pipeline); ClassDB::bind_method(D_METHOD("draw_list_bind_uniform_set", "draw_list", "uniform_set", "set_index"), &RenderingDevice::draw_list_bind_uniform_set); ClassDB::bind_method(D_METHOD("draw_list_bind_vertex_array", "draw_list", "vertex_array"), &RenderingDevice::draw_list_bind_vertex_array); diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h index a864cfa74c..6dadcab383 100644 --- a/servers/rendering/rendering_device.h +++ b/servers/rendering/rendering_device.h @@ -1129,6 +1129,7 @@ public: virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector<Color> &p_clear_color_values = Vector<Color>(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2(), const Vector<RID> &p_storage_textures = Vector<RID>()) = 0; + virtual void draw_list_set_blend_constants(DrawListID p_list, const Color &p_color) = 0; virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0; virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0; virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0; diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index cc79d09503..9b174d5879 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -831,6 +831,7 @@ public: FUNC6(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool) FUNC7(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, bool) FUNC7(canvas_item_add_msdf_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, int, float) + FUNC5(canvas_item_add_lcd_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &) FUNC10(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &) FUNC6(canvas_item_add_primitive, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID, float) FUNC5(canvas_item_add_polygon, RID, const Vector<Point2> &, const Vector<Color> &, const Vector<Point2> &, RID) diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp index a410cf0ed8..30b6faa360 100644 --- a/servers/rendering_server.cpp +++ b/servers/rendering_server.cpp @@ -2580,6 +2580,7 @@ void RenderingServer::_bind_methods() { ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false)); ClassDB::bind_method(D_METHOD("canvas_item_add_msdf_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "outline_size", "px_range"), &RenderingServer::canvas_item_add_msdf_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(0), DEFVAL(1.0)); + ClassDB::bind_method(D_METHOD("canvas_item_add_lcd_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate"), &RenderingServer::canvas_item_add_lcd_texture_rect_region); ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(true)); ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1))); ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0)); diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 59887d7d37..56295a2c5f 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1326,6 +1326,7 @@ public: virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false) = 0; virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, bool p_clip_uv = false) = 0; virtual void canvas_item_add_msdf_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), int p_outline_size = 0, float p_px_range = 1.0) = 0; + virtual void canvas_item_add_lcd_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1)) = 0; virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1)) = 0; virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs, RID p_texture, float p_width = 1.0) = 0; virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2> &p_points, const Vector<Color> &p_colors, const Vector<Point2> &p_uvs = Vector<Point2>(), RID p_texture = RID()) = 0; diff --git a/servers/text/text_server_extension.cpp b/servers/text/text_server_extension.cpp index 855267e428..74ae2bfff0 100644 --- a/servers/text/text_server_extension.cpp +++ b/servers/text/text_server_extension.cpp @@ -69,8 +69,8 @@ void TextServerExtension::_bind_methods() { GDVIRTUAL_BIND(font_set_style_name, "font_rid", "name_style"); GDVIRTUAL_BIND(font_get_style_name, "font_rid"); - GDVIRTUAL_BIND(font_set_antialiased, "font_rid", "antialiased"); - GDVIRTUAL_BIND(font_is_antialiased, "font_rid"); + GDVIRTUAL_BIND(font_set_antialiasing, "font_rid", "antialiasing"); + GDVIRTUAL_BIND(font_get_antialiasing, "font_rid"); GDVIRTUAL_BIND(font_set_generate_mipmaps, "font_rid", "generate_mipmaps"); GDVIRTUAL_BIND(font_get_generate_mipmaps, "font_rid"); @@ -478,16 +478,16 @@ String TextServerExtension::font_get_name(const RID &p_font_rid) const { return String(); } -void TextServerExtension::font_set_antialiased(const RID &p_font_rid, bool p_antialiased) { - GDVIRTUAL_CALL(font_set_antialiased, p_font_rid, p_antialiased); +void TextServerExtension::font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) { + GDVIRTUAL_CALL(font_set_antialiasing, p_font_rid, p_antialiasing); } -bool TextServerExtension::font_is_antialiased(const RID &p_font_rid) const { - bool ret; - if (GDVIRTUAL_CALL(font_is_antialiased, p_font_rid, ret)) { +TextServer::FontAntialiasing TextServerExtension::font_get_antialiasing(RID p_font_rid) const { + TextServer::FontAntialiasing ret; + if (GDVIRTUAL_CALL(font_get_antialiasing, p_font_rid, ret)) { return ret; } - return false; + return TextServer::FONT_ANTIALIASING_NONE; } void TextServerExtension::font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) { diff --git a/servers/text/text_server_extension.h b/servers/text/text_server_extension.h index 7e1ed22390..6a2c199898 100644 --- a/servers/text/text_server_extension.h +++ b/servers/text/text_server_extension.h @@ -108,10 +108,10 @@ public: GDVIRTUAL2(font_set_style_name, RID, const String &); GDVIRTUAL1RC(String, font_get_style_name, RID); - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) override; - virtual bool font_is_antialiased(const RID &p_font_rid) const override; - GDVIRTUAL2(font_set_antialiased, RID, bool); - GDVIRTUAL1RC(bool, font_is_antialiased, RID); + virtual void font_set_antialiasing(RID p_font_rid, TextServer::FontAntialiasing p_antialiasing) override; + virtual TextServer::FontAntialiasing font_get_antialiasing(RID p_font_rid) const override; + GDVIRTUAL2(font_set_antialiasing, RID, TextServer::FontAntialiasing); + GDVIRTUAL1RC(TextServer::FontAntialiasing, font_get_antialiasing, RID); virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) override; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const override; diff --git a/servers/text_server.cpp b/servers/text_server.cpp index 66b32dba84..393160fe9e 100644 --- a/servers/text_server.cpp +++ b/servers/text_server.cpp @@ -223,8 +223,8 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("font_set_style_name", "font_rid", "name"), &TextServer::font_set_style_name); ClassDB::bind_method(D_METHOD("font_get_style_name", "font_rid"), &TextServer::font_get_style_name); - ClassDB::bind_method(D_METHOD("font_set_antialiased", "font_rid", "antialiased"), &TextServer::font_set_antialiased); - ClassDB::bind_method(D_METHOD("font_is_antialiased", "font_rid"), &TextServer::font_is_antialiased); + ClassDB::bind_method(D_METHOD("font_set_antialiasing", "font_rid", "antialiasing"), &TextServer::font_set_antialiasing); + ClassDB::bind_method(D_METHOD("font_get_antialiasing", "font_rid"), &TextServer::font_get_antialiasing); ClassDB::bind_method(D_METHOD("font_set_generate_mipmaps", "font_rid", "generate_mipmaps"), &TextServer::font_set_generate_mipmaps); ClassDB::bind_method(D_METHOD("font_get_generate_mipmaps", "font_rid"), &TextServer::font_get_generate_mipmaps); @@ -458,6 +458,17 @@ void TextServer::_bind_methods() { ClassDB::bind_method(D_METHOD("parse_structured_text", "parser_type", "args", "text"), &TextServer::parse_structured_text); + /* Font AA */ + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_NONE); + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_GRAY); + BIND_ENUM_CONSTANT(FONT_ANTIALIASING_LCD); + + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_NONE); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HRGB); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_HBGR); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VRGB); + BIND_ENUM_CONSTANT(FONT_LCD_SUBPIXEL_LAYOUT_VBGR); + /* Direction */ BIND_ENUM_CONSTANT(DIRECTION_AUTO); BIND_ENUM_CONSTANT(DIRECTION_LTR); diff --git a/servers/text_server.h b/servers/text_server.h index 9ffc2984d1..9304771d1b 100644 --- a/servers/text_server.h +++ b/servers/text_server.h @@ -47,6 +47,21 @@ class TextServer : public RefCounted { GDCLASS(TextServer, RefCounted); public: + enum FontAntialiasing { + FONT_ANTIALIASING_NONE, + FONT_ANTIALIASING_GRAY, + FONT_ANTIALIASING_LCD, + }; + + enum FontLCDSubpixelLayout { + FONT_LCD_SUBPIXEL_LAYOUT_NONE, + FONT_LCD_SUBPIXEL_LAYOUT_HRGB, + FONT_LCD_SUBPIXEL_LAYOUT_HBGR, + FONT_LCD_SUBPIXEL_LAYOUT_VRGB, + FONT_LCD_SUBPIXEL_LAYOUT_VBGR, + FONT_LCD_SUBPIXEL_LAYOUT_MAX, + }; + enum Direction { DIRECTION_AUTO, DIRECTION_LTR, @@ -233,8 +248,8 @@ public: virtual void font_set_style_name(const RID &p_font_rid, const String &p_name) = 0; virtual String font_get_style_name(const RID &p_font_rid) const = 0; - virtual void font_set_antialiased(const RID &p_font_rid, bool p_antialiased) = 0; - virtual bool font_is_antialiased(const RID &p_font_rid) const = 0; + virtual void font_set_antialiasing(RID p_font_rid, FontAntialiasing p_antialiasing) = 0; + virtual FontAntialiasing font_get_antialiasing(RID p_font_rid) const = 0; virtual void font_set_generate_mipmaps(const RID &p_font_rid, bool p_generate_mipmaps) = 0; virtual bool font_get_generate_mipmaps(const RID &p_font_rid) const = 0; @@ -572,6 +587,8 @@ VARIANT_ENUM_CAST(TextServer::ContourPointTag); VARIANT_ENUM_CAST(TextServer::SpacingType); VARIANT_BITFIELD_CAST(TextServer::FontStyle); VARIANT_ENUM_CAST(TextServer::StructuredTextParser); +VARIANT_ENUM_CAST(TextServer::FontAntialiasing); +VARIANT_ENUM_CAST(TextServer::FontLCDSubpixelLayout); GDVIRTUAL_NATIVE_PTR(Glyph); GDVIRTUAL_NATIVE_PTR(CaretInfo); diff --git a/tests/core/math/test_quaternion.h b/tests/core/math/test_quaternion.h index 94eef6c463..1b80ffba0b 100644 --- a/tests/core/math/test_quaternion.h +++ b/tests/core/math/test_quaternion.h @@ -41,9 +41,9 @@ namespace TestQuaternion { Quaternion quat_euler_yxz_deg(Vector3 angle) { - double yaw = Math::deg2rad(angle[1]); - double pitch = Math::deg2rad(angle[0]); - double roll = Math::deg2rad(angle[2]); + double yaw = Math::deg_to_rad(angle[1]); + double pitch = Math::deg_to_rad(angle[0]); + double roll = Math::deg_to_rad(angle[2]); // Generate YXZ (Z-then-X-then-Y) Quaternion using single-axis Euler // constructor and quaternion product, both tested separately. @@ -77,7 +77,7 @@ TEST_CASE("[Quaternion] Construct x,y,z,w") { TEST_CASE("[Quaternion] Construct AxisAngle 1") { // Easy to visualize: 120 deg about X-axis. - Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0)); + Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0)); // 0.866 isn't close enough; doctest::Approx doesn't cut much slack! CHECK(q[0] == doctest::Approx(0.866025)); // Sine of half the angle. @@ -88,7 +88,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 1") { TEST_CASE("[Quaternion] Construct AxisAngle 2") { // Easy to visualize: 30 deg about Y-axis. - Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0)); + Quaternion q(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0)); CHECK(q[0] == doctest::Approx(0.0)); CHECK(q[1] == doctest::Approx(0.258819)); // Sine of half the angle. @@ -98,7 +98,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 2") { TEST_CASE("[Quaternion] Construct AxisAngle 3") { // Easy to visualize: 60 deg about Z-axis. - Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0)); + Quaternion q(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0)); CHECK(q[0] == doctest::Approx(0.0)); CHECK(q[1] == doctest::Approx(0.0)); @@ -109,7 +109,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 3") { TEST_CASE("[Quaternion] Construct AxisAngle 4") { // More complex & hard to visualize, so test w/ data from online calculator. Vector3 axis(1.0, 2.0, 0.5); - Quaternion q(axis.normalized(), Math::deg2rad(35.0)); + Quaternion q(axis.normalized(), Math::deg_to_rad(35.0)); CHECK(q[0] == doctest::Approx(0.131239)); CHECK(q[1] == doctest::Approx(0.262478)); @@ -119,7 +119,7 @@ TEST_CASE("[Quaternion] Construct AxisAngle 4") { TEST_CASE("[Quaternion] Construct from Quaternion") { Vector3 axis(1.0, 2.0, 0.5); - Quaternion q_src(axis.normalized(), Math::deg2rad(35.0)); + Quaternion q_src(axis.normalized(), Math::deg_to_rad(35.0)); Quaternion q(q_src); CHECK(q[0] == doctest::Approx(0.131239)); @@ -129,9 +129,9 @@ TEST_CASE("[Quaternion] Construct from Quaternion") { } TEST_CASE("[Quaternion] Construct Euler SingleAxis") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); Vector3 euler_y(0.0, yaw, 0.0); Quaternion q_y(euler_y); @@ -156,9 +156,9 @@ TEST_CASE("[Quaternion] Construct Euler SingleAxis") { } TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); // Generate YXZ comparision data (Z-then-X-then-Y) using single-axis Euler // constructor and quaternion product, both tested separately. @@ -187,9 +187,9 @@ TEST_CASE("[Quaternion] Construct Euler YXZ dynamic axes") { } TEST_CASE("[Quaternion] Construct Basis Euler") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); Vector3 euler_yxz(pitch, yaw, roll); Quaternion q_yxz(euler_yxz); Basis basis_axes(euler_yxz); @@ -199,7 +199,7 @@ TEST_CASE("[Quaternion] Construct Basis Euler") { TEST_CASE("[Quaternion] Construct Basis Axes") { // Arbitrary Euler angles. - Vector3 euler_yxz(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34)); + Vector3 euler_yxz(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34)); // Basis vectors from online calculation of rotation matrix. Vector3 i_unit(0.5545787, 0.1823950, 0.8118957); Vector3 j_unit(-0.5249245, 0.8337420, 0.1712555); @@ -248,9 +248,9 @@ TEST_CASE("[Quaternion] Product (book)") { } TEST_CASE("[Quaternion] Product") { - double yaw = Math::deg2rad(45.0); - double pitch = Math::deg2rad(30.0); - double roll = Math::deg2rad(10.0); + double yaw = Math::deg_to_rad(45.0); + double pitch = Math::deg_to_rad(30.0); + double roll = Math::deg_to_rad(10.0); Vector3 euler_y(0.0, yaw, 0.0); Quaternion q_y(euler_y); @@ -292,7 +292,7 @@ TEST_CASE("[Quaternion] Product") { TEST_CASE("[Quaternion] xform unit vectors") { // Easy to visualize: 120 deg about X-axis. // Transform the i, j, & k unit vectors. - Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg2rad(120.0)); + Quaternion q(Vector3(1.0, 0.0, 0.0), Math::deg_to_rad(120.0)); Vector3 i_t = q.xform(Vector3(1.0, 0.0, 0.0)); Vector3 j_t = q.xform(Vector3(0.0, 1.0, 0.0)); Vector3 k_t = q.xform(Vector3(0.0, 0.0, 1.0)); @@ -305,7 +305,7 @@ TEST_CASE("[Quaternion] xform unit vectors") { CHECK(k_t.length_squared() == doctest::Approx(1.0)); // Easy to visualize: 30 deg about Y-axis. - q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg2rad(30.0)); + q = Quaternion(Vector3(0.0, 1.0, 0.0), Math::deg_to_rad(30.0)); i_t = q.xform(Vector3(1.0, 0.0, 0.0)); j_t = q.xform(Vector3(0.0, 1.0, 0.0)); k_t = q.xform(Vector3(0.0, 0.0, 1.0)); @@ -318,7 +318,7 @@ TEST_CASE("[Quaternion] xform unit vectors") { CHECK(k_t.length_squared() == doctest::Approx(1.0)); // Easy to visualize: 60 deg about Z-axis. - q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg2rad(60.0)); + q = Quaternion(Vector3(0.0, 0.0, 1.0), Math::deg_to_rad(60.0)); i_t = q.xform(Vector3(1.0, 0.0, 0.0)); j_t = q.xform(Vector3(0.0, 1.0, 0.0)); k_t = q.xform(Vector3(0.0, 0.0, 1.0)); @@ -333,7 +333,7 @@ TEST_CASE("[Quaternion] xform unit vectors") { TEST_CASE("[Quaternion] xform vector") { // Arbitrary quaternion rotates an arbitrary vector. - Vector3 euler_yzx(Math::deg2rad(31.41), Math::deg2rad(-49.16), Math::deg2rad(12.34)); + Vector3 euler_yzx(Math::deg_to_rad(31.41), Math::deg_to_rad(-49.16), Math::deg_to_rad(12.34)); Basis basis_axes(euler_yzx); Quaternion q(basis_axes); diff --git a/tests/scene/test_code_edit.h b/tests/scene/test_code_edit.h index 4fc88f398f..be2e18bdf4 100644 --- a/tests/scene/test_code_edit.h +++ b/tests/scene/test_code_edit.h @@ -2943,6 +2943,10 @@ TEST_CASE("[SceneTree][CodeEdit] completion") { code_edit->set_code_completion_enabled(true); CHECK(code_edit->get_code_completion_selected_index() == -1); + // Need to flush here since `NOTIFICATION_THEME_CHANGED` is called deferred from `NOTIFICATION_ENTER_TREE`, + // and `update_code_completion_options` requires access to the theme's font size. + MessageQueue::get_singleton()->flush(); + code_edit->update_code_completion_options(); code_edit->set_code_completion_selected_index(1); CHECK(code_edit->get_code_completion_selected_index() == -1); diff --git a/thirdparty/README.md b/thirdparty/README.md index 4514217dd8..ffc8137819 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -345,6 +345,9 @@ File extracted from upstream release tarball: - Added 2 files `godot_core_mbedtls_platform.c` and `godot_core_mbedtls_config.h` providing configuration for light bundling with core. +Some changes have been made in order to fix Windows on ARM build errors. +They are marked with `// -- GODOT start --` and `// -- GODOT end --` + ## meshoptimizer @@ -375,6 +378,9 @@ Files extracted from upstream repository: - `minimp3_ex.h` - `LICENSE` +Some changes have been made in order to fix Windows on ARM build errors. +They are marked with `// -- GODOT start --` and `// -- GODOT end --` + ## miniupnpc diff --git a/thirdparty/mbedtls/library/timing.c b/thirdparty/mbedtls/library/timing.c index 57bc9bcc12..78bfa10cfb 100644 --- a/thirdparty/mbedtls/library/timing.c +++ b/thirdparty/mbedtls/library/timing.c @@ -195,8 +195,10 @@ unsigned long mbedtls_timing_hardclock( void ) #endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && __GNUC__ && __ia64__ */ -#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ +// -- GODOT start -- +#if !defined(HAVE_HARDCLOCK) && defined(_WIN32) && \ !defined(EFIX64) && !defined(EFI32) +// -- GODOT end -- #define HAVE_HARDCLOCK diff --git a/thirdparty/minimp3/minimp3.h b/thirdparty/minimp3/minimp3.h index 3220ae1a85..2a9975cc86 100644 --- a/thirdparty/minimp3/minimp3.h +++ b/thirdparty/minimp3/minimp3.h @@ -1566,7 +1566,18 @@ static void mp3d_synth(float *xl, mp3d_sample_t *dstl, int nch, float *lins) #else /* MINIMP3_FLOAT_OUTPUT */ +// -- GODOT start -- +#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_ARM)) + static f4 g_scale; + g_scale = vsetq_lane_f32(1.0f/32768.0f, g_scale, 0); + g_scale = vsetq_lane_f32(1.0f/32768.0f, g_scale, 1); + g_scale = vsetq_lane_f32(1.0f/32768.0f, g_scale, 2); + g_scale = vsetq_lane_f32(1.0f/32768.0f, g_scale, 3); +#else static const f4 g_scale = { 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f, 1.0f/32768.0f }; +#endif +// -- GODOT end -- + a = VMUL(a, g_scale); b = VMUL(b, g_scale); #if HAVE_SSE @@ -1813,7 +1824,19 @@ void mp3dec_f32_to_s16(const float *in, int16_t *out, int num_samples) int aligned_count = num_samples & ~7; for(; i < aligned_count; i += 8) { + +// -- GODOT start -- +#if defined(_MSC_VER) && (defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_ARM)) + static f4 g_scale; + g_scale = vsetq_lane_f32(32768.0f, g_scale, 0); + g_scale = vsetq_lane_f32(32768.0f, g_scale, 1); + g_scale = vsetq_lane_f32(32768.0f, g_scale, 2); + g_scale = vsetq_lane_f32(32768.0f, g_scale, 3); +#else static const f4 g_scale = { 32768.0f, 32768.0f, 32768.0f, 32768.0f }; +#endif +// -- GODOT end -- + f4 a = VMUL(VLD(&in[i ]), g_scale); f4 b = VMUL(VLD(&in[i+4]), g_scale); #if HAVE_SSE |