diff options
Diffstat (limited to 'scene')
| -rw-r--r-- | scene/2d/animated_sprite_2d.cpp | 54 | ||||
| -rw-r--r-- | scene/2d/animated_sprite_2d.h | 3 | ||||
| -rw-r--r-- | scene/3d/lightmap_gi.cpp | 5 | ||||
| -rw-r--r-- | scene/3d/lightmap_gi.h | 8 | ||||
| -rw-r--r-- | scene/3d/sprite_3d.cpp | 52 | ||||
| -rw-r--r-- | scene/3d/sprite_3d.h | 3 | ||||
| -rw-r--r-- | scene/animation/animation_player.cpp | 7 | ||||
| -rw-r--r-- | scene/animation/animation_tree.cpp | 15 | ||||
| -rw-r--r-- | scene/animation/tween.cpp | 272 | ||||
| -rw-r--r-- | scene/animation/tween.h | 1 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.cpp | 55 | ||||
| -rw-r--r-- | scene/gui/rich_text_label.h | 11 | ||||
| -rw-r--r-- | scene/main/viewport.cpp | 47 | ||||
| -rw-r--r-- | scene/main/viewport.h | 2 | ||||
| -rw-r--r-- | scene/main/window.cpp | 18 | ||||
| -rw-r--r-- | scene/main/window.h | 2 | ||||
| -rw-r--r-- | scene/resources/animation.cpp | 464 | ||||
| -rw-r--r-- | scene/resources/animation.h | 6 | ||||
| -rw-r--r-- | scene/resources/material.cpp | 30 | ||||
| -rw-r--r-- | scene/resources/material.h | 11 | ||||
| -rw-r--r-- | scene/resources/skeleton_profile.cpp | 4 |
21 files changed, 673 insertions, 397 deletions
diff --git a/scene/2d/animated_sprite_2d.cpp b/scene/2d/animated_sprite_2d.cpp index 7fe464d2f4..afa4633848 100644 --- a/scene/2d/animated_sprite_2d.cpp +++ b/scene/2d/animated_sprite_2d.cpp @@ -63,9 +63,13 @@ Rect2 AnimatedSprite2D::_edit_get_rect() const { } bool AnimatedSprite2D::_edit_use_rect() const { - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { return false; } + if (frame < 0 || frame >= frames->get_frame_count(animation)) { + return false; + } + Ref<Texture2D> t; if (animation) { t = frames->get_frame(animation, frame); @@ -79,7 +83,10 @@ Rect2 AnimatedSprite2D::get_anchorable_rect() const { } Rect2 AnimatedSprite2D::_get_rect() const { - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { + return Rect2(); + } + if (frame < 0 || frame >= frames->get_frame_count(animation)) { return Rect2(); } @@ -161,29 +168,22 @@ void AnimatedSprite2D::_validate_property(PropertyInfo &p_property) const { void AnimatedSprite2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_INTERNAL_PROCESS: { - if (frames.is_null()) { + if (frames.is_null() || !frames->has_animation(animation)) { return; } - if (!frames->has_animation(animation)) { - return; - } - if (frame < 0) { - return; + + double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale); + if (speed == 0) { + return; // Do nothing. } + int last_frame = frames->get_frame_count(animation) - 1; double remaining = get_process_delta_time(); - while (remaining) { - double speed = frames->get_animation_speed(animation) * speed_scale; - if (speed == 0) { - return; // Do nothing. - } - if (timeout <= 0) { timeout = _get_frame_duration(); - int last_frame = frames->get_frame_count(animation) - 1; - if (!backwards) { + if (!playing_backwards) { // Forward. if (frame >= last_frame) { if (frames->get_animation_loop(animation)) { @@ -229,13 +229,7 @@ void AnimatedSprite2D::_notification(int p_what) { } break; case NOTIFICATION_DRAW: { - if (frames.is_null()) { - return; - } - if (frame < 0) { - return; - } - if (!frames->has_animation(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { return; } @@ -327,9 +321,14 @@ int AnimatedSprite2D::get_frame() const { } void AnimatedSprite2D::set_speed_scale(double p_speed_scale) { + if (speed_scale == p_speed_scale) { + return; + } + double elapsed = _get_frame_duration() - timeout; - speed_scale = MAX(p_speed_scale, 0.0f); + speed_scale = p_speed_scale; + playing_backwards = signbit(speed_scale) != backwards; // We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed. _reset_timeout(); @@ -398,12 +397,13 @@ bool AnimatedSprite2D::is_playing() const { return playing; } -void AnimatedSprite2D::play(const StringName &p_animation, const bool p_backwards) { +void AnimatedSprite2D::play(const StringName &p_animation, bool p_backwards) { backwards = p_backwards; + playing_backwards = signbit(speed_scale) != backwards; if (p_animation) { set_animation(p_animation); - if (frames.is_valid() && backwards && get_frame() == 0) { + if (frames.is_valid() && playing_backwards && get_frame() == 0) { set_frame(frames->get_frame_count(p_animation) - 1); } } @@ -418,7 +418,7 @@ void AnimatedSprite2D::stop() { double AnimatedSprite2D::_get_frame_duration() { if (frames.is_valid() && frames->has_animation(animation)) { - double speed = frames->get_animation_speed(animation) * speed_scale; + double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale); if (speed > 0) { return 1.0 / speed; } diff --git a/scene/2d/animated_sprite_2d.h b/scene/2d/animated_sprite_2d.h index 0a19e250d8..be1cc5353e 100644 --- a/scene/2d/animated_sprite_2d.h +++ b/scene/2d/animated_sprite_2d.h @@ -39,6 +39,7 @@ class AnimatedSprite2D : public Node2D { Ref<SpriteFrames> frames; bool playing = false; + bool playing_backwards = false; bool backwards = false; StringName animation = "default"; int frame = 0; @@ -81,7 +82,7 @@ public: void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; - void play(const StringName &p_animation = StringName(), const bool p_backwards = false); + void play(const StringName &p_animation = StringName(), bool p_backwards = false); void stop(); void set_playing(bool p_playing); diff --git a/scene/3d/lightmap_gi.cpp b/scene/3d/lightmap_gi.cpp index b0bccc4571..555884f445 100644 --- a/scene/3d/lightmap_gi.cpp +++ b/scene/3d/lightmap_gi.cpp @@ -1418,7 +1418,8 @@ float LightmapGI::get_bias() const { } void LightmapGI::set_max_texture_size(int p_size) { - ERR_FAIL_COND(p_size < 2048); + ERR_FAIL_COND_MSG(p_size < 2048, vformat("The LightmapGI maximum texture size supplied (%d) is too small. The minimum allowed value is 2048.", p_size)); + ERR_FAIL_COND_MSG(p_size > 16384, vformat("The LightmapGI maximum texture size supplied (%d) is too large. The maximum allowed value is 16384.", p_size)); max_texture_size = p_size; } @@ -1506,7 +1507,7 @@ void LightmapGI::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size"), "set_max_texture_size", "get_max_texture_size"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size", PROPERTY_HINT_RANGE, "2048,16384,1"), "set_max_texture_size", "get_max_texture_size"); ADD_GROUP("Environment", "environment_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode"); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky"); diff --git a/scene/3d/lightmap_gi.h b/scene/3d/lightmap_gi.h index 0062a4a093..1d282e92c8 100644 --- a/scene/3d/lightmap_gi.h +++ b/scene/3d/lightmap_gi.h @@ -142,16 +142,16 @@ public: private: BakeQuality bake_quality = BAKE_QUALITY_MEDIUM; bool use_denoiser = true; - int bounces = 1; + int bounces = 3; float bias = 0.0005; int max_texture_size = 16384; bool interior = false; - EnvironmentMode environment_mode = ENVIRONMENT_MODE_DISABLED; + EnvironmentMode environment_mode = ENVIRONMENT_MODE_SCENE; Ref<Sky> environment_custom_sky; - Color environment_custom_color = Color(0.2, 0.7, 1.0); + Color environment_custom_color = Color(1, 1, 1); float environment_custom_energy = 1.0; bool directional = false; - GenerateProbes gen_probes = GENERATE_PROBES_DISABLED; + GenerateProbes gen_probes = GENERATE_PROBES_SUBDIV_8; Ref<CameraAttributes> camera_attributes; Ref<LightmapGIData> light_data; diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index 7a89bf81bb..380172f396 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -447,7 +447,7 @@ void Sprite3D::_draw() { if (get_base() != get_mesh()) { set_base(get_mesh()); } - if (!texture.is_valid()) { + if (texture.is_null()) { set_base(RID()); return; } @@ -807,15 +807,7 @@ void AnimatedSprite3D::_draw() { set_base(get_mesh()); } - if (frames.is_null()) { - return; - } - - if (frame < 0) { - return; - } - - if (!frames->has_animation(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { return; } @@ -1050,29 +1042,22 @@ void AnimatedSprite3D::_validate_property(PropertyInfo &p_property) const { void AnimatedSprite3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_INTERNAL_PROCESS: { - if (frames.is_null()) { - return; - } - if (!frames->has_animation(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { return; } - if (frame < 0) { - return; + + double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale); + if (speed == 0) { + return; // Do nothing. } + int last_frame = frames->get_frame_count(animation) - 1; double remaining = get_process_delta_time(); - while (remaining) { - double speed = frames->get_animation_speed(animation) * speed_scale; - if (speed == 0) { - return; // Do nothing. - } - if (timeout <= 0) { timeout = _get_frame_duration(); - int last_frame = frames->get_frame_count(animation) - 1; - if (!backwards) { + if (!playing_backwards) { // Forward. if (frame >= last_frame) { if (frames->get_animation_loop(animation)) { @@ -1177,9 +1162,14 @@ int AnimatedSprite3D::get_frame() const { } void AnimatedSprite3D::set_speed_scale(double p_speed_scale) { + if (speed_scale == p_speed_scale) { + return; + } + double elapsed = _get_frame_duration() - timeout; - speed_scale = MAX(p_speed_scale, 0.0f); + speed_scale = p_speed_scale; + playing_backwards = signbit(speed_scale) != backwards; // We adapt the timeout so that the animation speed adapts as soon as the speed scale is changed. _reset_timeout(); @@ -1191,7 +1181,10 @@ double AnimatedSprite3D::get_speed_scale() const { } Rect2 AnimatedSprite3D::get_item_rect() const { - if (!frames.is_valid() || !frames->has_animation(animation) || frame < 0 || frame >= frames->get_frame_count(animation)) { + if (frames.is_null() || !frames->has_animation(animation)) { + return Rect2(0, 0, 1, 1); + } + if (frame < 0 || frame >= frames->get_frame_count(animation)) { return Rect2(0, 0, 1, 1); } @@ -1236,12 +1229,13 @@ bool AnimatedSprite3D::is_playing() const { return playing; } -void AnimatedSprite3D::play(const StringName &p_animation, const bool p_backwards) { +void AnimatedSprite3D::play(const StringName &p_animation, bool p_backwards) { backwards = p_backwards; + playing_backwards = signbit(speed_scale) != backwards; if (p_animation) { set_animation(p_animation); - if (frames.is_valid() && backwards && get_frame() == 0) { + if (frames.is_valid() && playing_backwards && get_frame() == 0) { set_frame(frames->get_frame_count(p_animation) - 1); } } @@ -1256,7 +1250,7 @@ void AnimatedSprite3D::stop() { double AnimatedSprite3D::_get_frame_duration() { if (frames.is_valid() && frames->has_animation(animation)) { - double speed = frames->get_animation_speed(animation) * speed_scale; + double speed = frames->get_animation_speed(animation) * Math::abs(speed_scale); if (speed > 0) { return 1.0 / speed; } diff --git a/scene/3d/sprite_3d.h b/scene/3d/sprite_3d.h index e6a546a76d..f6ad1bbdb8 100644 --- a/scene/3d/sprite_3d.h +++ b/scene/3d/sprite_3d.h @@ -209,6 +209,7 @@ class AnimatedSprite3D : public SpriteBase3D { Ref<SpriteFrames> frames; bool playing = false; + bool playing_backwards = false; bool backwards = false; StringName animation = "default"; int frame = 0; @@ -237,7 +238,7 @@ public: void set_sprite_frames(const Ref<SpriteFrames> &p_frames); Ref<SpriteFrames> get_sprite_frames() const; - void play(const StringName &p_animation = StringName(), const bool p_backwards = false); + void play(const StringName &p_animation = StringName(), bool p_backwards = false); void stop(); void set_playing(bool p_playing); diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp index 72710cf802..ce9406883d 100644 --- a/scene/animation/animation_player.cpp +++ b/scene/animation/animation_player.cpp @@ -650,15 +650,14 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double double c = Math::ease(p_time / first_key_time, transition); Variant first_value = a->track_get_key_value(i, first_key); first_value = _post_process_key_value(a, i, first_value, nc->node); - Variant interp_value; - Variant::interpolate(pa->capture, first_value, c, interp_value); + Variant interp_value = Animation::interpolate_variant(pa->capture, first_value, c); if (pa->accum_pass != accum_pass) { ERR_CONTINUE(cache_update_prop_size >= NODE_CACHE_UPDATE_MAX); cache_update_prop[cache_update_prop_size++] = pa; pa->value_accum = interp_value; pa->accum_pass = accum_pass; } else { - Variant::interpolate(pa->value_accum, interp_value, p_interp, pa->value_accum); + pa->value_accum = Animation::interpolate_variant(pa->value_accum, interp_value, p_interp); } continue; //handled @@ -679,7 +678,7 @@ void AnimationPlayer::_animation_process_animation(AnimationData *p_anim, double pa->value_accum = value; pa->accum_pass = accum_pass; } else { - Variant::interpolate(pa->value_accum, value, p_interp, pa->value_accum); + pa->value_accum = Animation::interpolate_variant(pa->value_accum, value, p_interp); } } else if (p_is_current && p_delta != 0) { diff --git a/scene/animation/animation_tree.cpp b/scene/animation/animation_tree.cpp index c1e674dad5..776706d7f3 100644 --- a/scene/animation/animation_tree.cpp +++ b/scene/animation/animation_tree.cpp @@ -1383,8 +1383,13 @@ void AnimationTree::_process_graph(double p_delta) { } 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); + if (t->init_value.get_type() == Variant::BOOL) { + value = Animation::subtract_variant(value.operator real_t(), t->init_value.operator real_t()); + t->value = Animation::blend_variant(t->value.operator real_t(), value.operator real_t(), blend); + } else { + value = Animation::subtract_variant(value, t->init_value); + t->value = Animation::blend_variant(t->value, value, blend); + } } } else { if (blend < CMP_EPSILON) { @@ -1703,7 +1708,11 @@ void AnimationTree::_process_graph(double p_delta) { case Animation::TYPE_VALUE: { TrackCacheValue *t = static_cast<TrackCacheValue *>(track); - t->object->set_indexed(t->subpath, t->value); + if (t->init_value.get_type() == Variant::BOOL) { + t->object->set_indexed(t->subpath, t->value.operator real_t() >= 0.5); + } else { + t->object->set_indexed(t->subpath, t->value); + } } break; case Animation::TYPE_BEZIER: { diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp index 5b18d4e457..b02f1959b7 100644 --- a/scene/animation/tween.cpp +++ b/scene/animation/tween.cpp @@ -32,6 +32,7 @@ #include "scene/animation/easing_equations.h" #include "scene/main/node.h" +#include "scene/resources/animation.h" Tween::interpolater Tween::interpolaters[Tween::TRANS_MAX][Tween::EASE_MAX] = { { &linear::in, &linear::in, &linear::in, &linear::in }, // Linear is the same for each easing. @@ -314,6 +315,7 @@ bool Tween::step(float p_delta) { running = false; dead = true; emit_signal(SNAME("finished")); + break; } else { emit_signal(SNAME("loop_finished"), loops_done); current_step = 0; @@ -375,264 +377,14 @@ Variant Tween::interpolate_variant(Variant p_initial_val, Variant p_delta_val, f ERR_FAIL_INDEX_V(p_trans, TransitionType::TRANS_MAX, Variant()); ERR_FAIL_INDEX_V(p_ease, EaseType::EASE_MAX, Variant()); -// Helper macro to run equation on sub-elements of the value (e.g. x and y of Vector2). -#define APPLY_EQUATION(element) \ - r.element = run_equation(p_trans, p_ease, p_time, i.element, d.element, p_duration); - - switch (p_initial_val.get_type()) { - case Variant::BOOL: { - return (run_equation(p_trans, p_ease, p_time, p_initial_val, p_delta_val, p_duration)) >= 0.5; - } - - case Variant::INT: { - return (int)run_equation(p_trans, p_ease, p_time, (int)p_initial_val, (int)p_delta_val, p_duration); - } - - case Variant::FLOAT: { - return run_equation(p_trans, p_ease, p_time, (real_t)p_initial_val, (real_t)p_delta_val, p_duration); - } - - case Variant::VECTOR2: { - Vector2 i = p_initial_val; - Vector2 d = p_delta_val; - Vector2 r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - return r; - } - - case Variant::VECTOR2I: { - Vector2i i = p_initial_val; - Vector2i d = p_delta_val; - Vector2i r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - return r; - } - - case Variant::RECT2: { - Rect2 i = p_initial_val; - Rect2 d = p_delta_val; - Rect2 r; - - APPLY_EQUATION(position.x); - APPLY_EQUATION(position.y); - APPLY_EQUATION(size.x); - APPLY_EQUATION(size.y); - return r; - } - - case Variant::RECT2I: { - Rect2i i = p_initial_val; - Rect2i d = p_delta_val; - Rect2i r; - - APPLY_EQUATION(position.x); - APPLY_EQUATION(position.y); - APPLY_EQUATION(size.x); - APPLY_EQUATION(size.y); - return r; - } - - case Variant::VECTOR3: { - Vector3 i = p_initial_val; - Vector3 d = p_delta_val; - Vector3 r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - APPLY_EQUATION(z); - return r; - } - - case Variant::VECTOR3I: { - Vector3i i = p_initial_val; - Vector3i d = p_delta_val; - Vector3i r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - APPLY_EQUATION(z); - return r; - } - - case Variant::TRANSFORM2D: { - Transform2D i = p_initial_val; - Transform2D d = p_delta_val; - Transform2D r; - - APPLY_EQUATION(columns[0][0]); - APPLY_EQUATION(columns[0][1]); - APPLY_EQUATION(columns[1][0]); - APPLY_EQUATION(columns[1][1]); - APPLY_EQUATION(columns[2][0]); - APPLY_EQUATION(columns[2][1]); - return r; - } - case Variant::VECTOR4: { - Vector4 i = p_initial_val; - Vector4 d = p_delta_val; - Vector4 r; - - APPLY_EQUATION(x); - APPLY_EQUATION(y); - APPLY_EQUATION(z); - APPLY_EQUATION(w); - return r; - } - - case Variant::QUATERNION: { - Quaternion i = p_initial_val; - Quaternion d = p_delta_val; - Quaternion r = i * d; - r = i.slerp(r, run_equation(p_trans, p_ease, p_time, 0.0, 1.0, p_duration)); - return r; - } - - case Variant::AABB: { - AABB i = p_initial_val; - AABB d = p_delta_val; - AABB r; - - APPLY_EQUATION(position.x); - APPLY_EQUATION(position.y); - APPLY_EQUATION(position.z); - APPLY_EQUATION(size.x); - APPLY_EQUATION(size.y); - APPLY_EQUATION(size.z); - return r; - } - - case Variant::BASIS: { - Basis i = p_initial_val; - Basis d = p_delta_val; - Basis r; - - APPLY_EQUATION(rows[0][0]); - APPLY_EQUATION(rows[0][1]); - APPLY_EQUATION(rows[0][2]); - APPLY_EQUATION(rows[1][0]); - APPLY_EQUATION(rows[1][1]); - APPLY_EQUATION(rows[1][2]); - APPLY_EQUATION(rows[2][0]); - APPLY_EQUATION(rows[2][1]); - APPLY_EQUATION(rows[2][2]); - return r; - } - - case Variant::TRANSFORM3D: { - Transform3D i = p_initial_val; - Transform3D d = p_delta_val; - Transform3D r; - - APPLY_EQUATION(basis.rows[0][0]); - APPLY_EQUATION(basis.rows[0][1]); - APPLY_EQUATION(basis.rows[0][2]); - APPLY_EQUATION(basis.rows[1][0]); - APPLY_EQUATION(basis.rows[1][1]); - APPLY_EQUATION(basis.rows[1][2]); - APPLY_EQUATION(basis.rows[2][0]); - APPLY_EQUATION(basis.rows[2][1]); - APPLY_EQUATION(basis.rows[2][2]); - APPLY_EQUATION(origin.x); - APPLY_EQUATION(origin.y); - APPLY_EQUATION(origin.z); - return r; - } - - case Variant::COLOR: { - Color i = p_initial_val; - Color d = p_delta_val; - Color r; - - APPLY_EQUATION(r); - APPLY_EQUATION(g); - APPLY_EQUATION(b); - APPLY_EQUATION(a); - return r; - } - - default: { - return p_initial_val; - } - }; -#undef APPLY_EQUATION -} - -Variant Tween::calculate_delta_value(Variant p_intial_val, Variant p_final_val) { - ERR_FAIL_COND_V_MSG(p_intial_val.get_type() != p_final_val.get_type(), p_intial_val, "Type mismatch between initial and final value: " + Variant::get_type_name(p_intial_val.get_type()) + " and " + Variant::get_type_name(p_final_val.get_type())); - - switch (p_intial_val.get_type()) { - case Variant::BOOL: { - return (int)p_final_val - (int)p_intial_val; - } - - case Variant::RECT2: { - Rect2 i = p_intial_val; - Rect2 f = p_final_val; - return Rect2(f.position - i.position, f.size - i.size); - } - - case Variant::RECT2I: { - Rect2i i = p_intial_val; - Rect2i f = p_final_val; - return Rect2i(f.position - i.position, f.size - i.size); - } - - case Variant::TRANSFORM2D: { - Transform2D i = p_intial_val; - Transform2D f = p_final_val; - return Transform2D(f.columns[0][0] - i.columns[0][0], - f.columns[0][1] - i.columns[0][1], - f.columns[1][0] - i.columns[1][0], - f.columns[1][1] - i.columns[1][1], - f.columns[2][0] - i.columns[2][0], - f.columns[2][1] - i.columns[2][1]); - } - - case Variant::AABB: { - AABB i = p_intial_val; - AABB f = p_final_val; - return AABB(f.position - i.position, f.size - i.size); - } - - case Variant::BASIS: { - Basis i = p_intial_val; - Basis f = p_final_val; - return Basis(f.rows[0][0] - i.rows[0][0], - f.rows[0][1] - i.rows[0][1], - f.rows[0][2] - i.rows[0][2], - f.rows[1][0] - i.rows[1][0], - f.rows[1][1] - i.rows[1][1], - f.rows[1][2] - i.rows[1][2], - f.rows[2][0] - i.rows[2][0], - f.rows[2][1] - i.rows[2][1], - f.rows[2][2] - i.rows[2][2]); - } - - case Variant::TRANSFORM3D: { - Transform3D i = p_intial_val; - Transform3D f = p_final_val; - return Transform3D(f.basis.rows[0][0] - i.basis.rows[0][0], - f.basis.rows[0][1] - i.basis.rows[0][1], - f.basis.rows[0][2] - i.basis.rows[0][2], - f.basis.rows[1][0] - i.basis.rows[1][0], - f.basis.rows[1][1] - i.basis.rows[1][1], - f.basis.rows[1][2] - i.basis.rows[1][2], - f.basis.rows[2][0] - i.basis.rows[2][0], - f.basis.rows[2][1] - i.basis.rows[2][1], - f.basis.rows[2][2] - i.basis.rows[2][2], - f.origin.x - i.origin.x, - f.origin.y - i.origin.y, - f.origin.z - i.origin.z); - } + // Special case for bool. + if (p_initial_val.get_type() == Variant::BOOL) { + return run_equation(p_trans, p_ease, p_time, p_initial_val, p_delta_val, p_duration) >= 0.5; + } - default: { - return Variant::evaluate(Variant::OP_SUBTRACT, p_final_val, p_intial_val); - } - }; + Variant ret = Animation::add_variant(p_initial_val, p_delta_val); + ret = Animation::interpolate_variant(p_initial_val, ret, run_equation(p_trans, p_ease, p_time, 0.0, 1.0, p_duration)); + return ret; } void Tween::_bind_methods() { @@ -748,10 +500,10 @@ void PropertyTweener::start() { } if (relative) { - final_val = Variant::evaluate(Variant::Operator::OP_ADD, initial_val, base_final_val); + final_val = Animation::add_variant(initial_val, base_final_val); } - delta_val = tween->calculate_delta_value(initial_val, final_val); + delta_val = Animation::subtract_variant(final_val, initial_val); } bool PropertyTweener::step(float &r_delta) { @@ -973,7 +725,7 @@ void MethodTweener::_bind_methods() { MethodTweener::MethodTweener(Callable p_callback, Variant p_from, Variant p_to, float p_duration) { callback = p_callback; initial_val = p_from; - delta_val = tween->calculate_delta_value(p_from, p_to); + delta_val = Animation::subtract_variant(p_to, p_from); final_val = p_to; duration = p_duration; } diff --git a/scene/animation/tween.h b/scene/animation/tween.h index b57ec2e5e7..da7a8b5d71 100644 --- a/scene/animation/tween.h +++ b/scene/animation/tween.h @@ -164,7 +164,6 @@ public: static real_t run_equation(TransitionType p_trans_type, EaseType p_ease_type, real_t t, real_t b, real_t c, real_t d); static Variant interpolate_variant(Variant p_initial_val, Variant p_delta_val, float p_time, float p_duration, Tween::TransitionType p_trans, Tween::EaseType p_ease); - Variant calculate_delta_value(Variant p_intial_val, Variant p_final_val); bool step(float p_delta); bool can_process(bool p_tree_paused) const; diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index 64a0402149..3a238e9edd 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -2188,6 +2188,30 @@ RichTextLabel::ItemFont *RichTextLabel::_find_font(Item *p_item) { while (fontitem) { if (fontitem->type == ITEM_FONT) { ItemFont *fi = static_cast<ItemFont *>(fontitem); + switch (fi->def_font) { + case NORMAL_FONT: { + fi->font = theme_cache.normal_font; + fi->font_size = theme_cache.normal_font_size; + } break; + case BOLD_FONT: { + fi->font = theme_cache.bold_font; + fi->font_size = theme_cache.bold_font_size; + } break; + case ITALICS_FONT: { + fi->font = theme_cache.italics_font; + fi->font_size = theme_cache.italics_font_size; + } break; + case BOLD_ITALICS_FONT: { + fi->font = theme_cache.bold_italics_font; + fi->font_size = theme_cache.bold_italics_font_size; + } break; + case MONO_FONT: { + fi->font = theme_cache.mono_font; + fi->font_size = theme_cache.mono_font_size; + } break; + default: { + } break; + } return fi; } @@ -3004,6 +3028,17 @@ void RichTextLabel::push_dropcap(const String &p_string, const Ref<Font> &p_font _add_item(item, false); } +void RichTextLabel::_push_def_font(DefaultFont p_font) { + _stop_thread(); + MutexLock data_lock(data_mutex); + + ERR_FAIL_COND(current->type == ITEM_TABLE); + ItemFont *item = memnew(ItemFont); + + item->def_font = p_font; + _add_item(item, true); +} + void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) { _stop_thread(); MutexLock data_lock(data_mutex); @@ -3020,31 +3055,31 @@ void RichTextLabel::push_font(const Ref<Font> &p_font, int p_size) { void RichTextLabel::push_normal() { ERR_FAIL_COND(theme_cache.normal_font.is_null()); - push_font(theme_cache.normal_font, theme_cache.normal_font_size); + _push_def_font(NORMAL_FONT); } void RichTextLabel::push_bold() { ERR_FAIL_COND(theme_cache.bold_font.is_null()); - push_font(theme_cache.bold_font, theme_cache.bold_font_size); + _push_def_font(BOLD_FONT); } void RichTextLabel::push_bold_italics() { ERR_FAIL_COND(theme_cache.bold_italics_font.is_null()); - push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size); + _push_def_font(BOLD_ITALICS_FONT); } void RichTextLabel::push_italics() { ERR_FAIL_COND(theme_cache.italics_font.is_null()); - push_font(theme_cache.italics_font, theme_cache.italics_font_size); + _push_def_font(ITALICS_FONT); } void RichTextLabel::push_mono() { ERR_FAIL_COND(theme_cache.mono_font.is_null()); - push_font(theme_cache.mono_font, theme_cache.mono_font_size); + _push_def_font(MONO_FONT); } void RichTextLabel::push_font_size(int p_font_size) { @@ -3635,9 +3670,9 @@ void RichTextLabel::append_text(const String &p_bbcode) { //use bold font in_bold = true; if (in_italics) { - push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size); + _push_def_font(BOLD_ITALICS_FONT); } else { - push_font(theme_cache.bold_font, theme_cache.bold_font_size); + _push_def_font(BOLD_FONT); } pos = brk_end + 1; tag_stack.push_front(tag); @@ -3645,15 +3680,15 @@ void RichTextLabel::append_text(const String &p_bbcode) { //use italics font in_italics = true; if (in_bold) { - push_font(theme_cache.bold_italics_font, theme_cache.bold_italics_font_size); + _push_def_font(BOLD_ITALICS_FONT); } else { - push_font(theme_cache.italics_font, theme_cache.italics_font_size); + _push_def_font(ITALICS_FONT); } pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag == "code") { //use monospace font - push_font(theme_cache.mono_font, theme_cache.mono_font_size); + _push_def_font(MONO_FONT); pos = brk_end + 1; tag_stack.push_front(tag); } else if (tag.begins_with("table=")) { diff --git a/scene/gui/rich_text_label.h b/scene/gui/rich_text_label.h index 8bc28a9ecf..2a5ec4b5d5 100644 --- a/scene/gui/rich_text_label.h +++ b/scene/gui/rich_text_label.h @@ -82,6 +82,15 @@ public: MENU_SELECT_ALL, }; + enum DefaultFont { + NORMAL_FONT, + BOLD_FONT, + ITALICS_FONT, + BOLD_ITALICS_FONT, + MONO_FONT, + CUSTOM_FONT, + }; + protected: virtual void _update_theme_item_cache() override; void _notification(int p_what); @@ -178,6 +187,7 @@ private: }; struct ItemFont : public Item { + DefaultFont def_font = CUSTOM_FONT; Ref<Font> font; int font_size = 0; ItemFont() { type = ITEM_FONT; } @@ -560,6 +570,7 @@ public: void add_newline(); bool remove_line(const int p_line); void push_dropcap(const String &p_string, const Ref<Font> &p_font, int p_size, const Rect2 &p_dropcap_margins = Rect2(), const Color &p_color = Color(1, 1, 1), int p_ol_size = 0, const Color &p_ol_color = Color(0, 0, 0, 0)); + void _push_def_font(DefaultFont p_font); void push_font(const Ref<Font> &p_font, int p_size = 0); void push_font_size(int p_font_size); void push_outline_size(int p_font_size); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 5295de5c09..879d494909 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -795,11 +795,20 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, stretch_transform = p_stretch_transform; to_screen_rect = p_to_screen_rect; - if (p_allocated) { - RS::get_singleton()->viewport_set_size(viewport, size.width, size.height); - } else { - RS::get_singleton()->viewport_set_size(viewport, 0, 0); - } +#ifndef _3D_DISABLED + if (!use_xr) { +#endif + + if (p_allocated) { + RS::get_singleton()->viewport_set_size(viewport, size.width, size.height); + } else { + RS::get_singleton()->viewport_set_size(viewport, 0, 0); + } + +#ifndef _3D_DISABLED + } // if (!use_xr) +#endif + _update_global_transform(); update_configuration_warnings(); @@ -813,6 +822,19 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override, } Size2i Viewport::_get_size() const { +#ifndef _3D_DISABLED + if (use_xr) { + if (XRServer::get_singleton() != nullptr) { + Ref<XRInterface> xr_interface = XRServer::get_singleton()->get_primary_interface(); + if (xr_interface.is_valid() && xr_interface->is_initialized()) { + Size2 xr_size = xr_interface->get_render_target_size(); + return (Size2i)xr_size; + } + } + return Size2i(); + } +#endif // _3D_DISABLED + return size; } @@ -3612,9 +3634,20 @@ void Viewport::_propagate_exit_world_3d(Node *p_node) { } void Viewport::set_use_xr(bool p_use_xr) { - use_xr = p_use_xr; + if (use_xr != p_use_xr) { + use_xr = p_use_xr; - RS::get_singleton()->viewport_set_use_xr(viewport, use_xr); + RS::get_singleton()->viewport_set_use_xr(viewport, use_xr); + + if (!use_xr) { + // Set viewport to previous size when exiting XR. + if (size_allocated) { + RS::get_singleton()->viewport_set_size(viewport, size.width, size.height); + } else { + RS::get_singleton()->viewport_set_size(viewport, 0, 0); + } + } + } } bool Viewport::is_using_xr() { diff --git a/scene/main/viewport.h b/scene/main/viewport.h index afea3ea56c..c7c474c70f 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -568,7 +568,7 @@ public: bool is_input_disabled() const; Vector2 get_mouse_position() const; - virtual void warp_mouse(const Vector2 &p_position); + 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 04f56bb874..ebe9587b31 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -986,18 +986,6 @@ 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) { @@ -1153,7 +1141,7 @@ void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio Rect2 parent_rect; if (is_embedded()) { - parent_rect = get_parent_viewport()->get_visible_rect(); + parent_rect = _get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1179,7 +1167,7 @@ void Window::popup_centered(const Size2i &p_minsize) { Rect2 parent_rect; if (is_embedded()) { - parent_rect = get_parent_viewport()->get_visible_rect(); + parent_rect = _get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); @@ -1207,7 +1195,7 @@ void Window::popup_centered_ratio(float p_ratio) { Rect2 parent_rect; if (is_embedded()) { - parent_rect = get_parent_viewport()->get_visible_rect(); + parent_rect = _get_embedder()->get_visible_rect(); } else { DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id(); int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id); diff --git a/scene/main/window.h b/scene/main/window.h index 8113117103..8c6ca65436 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -254,8 +254,6 @@ 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(); diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index 9d5bc18c96..a52bfe97e7 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -2317,9 +2317,7 @@ Quaternion Animation::_interpolate(const Quaternion &p_a, const Quaternion &p_b, } Variant Animation::_interpolate(const Variant &p_a, const Variant &p_b, real_t p_c) const { - Variant dst; - Variant::interpolate(p_a, p_b, p_c, dst); - return dst; + return interpolate_variant(p_a, p_b, p_c); } real_t Animation::_interpolate(const real_t &p_a, const real_t &p_b, real_t p_c) const { @@ -5563,6 +5561,466 @@ bool Animation::_fetch_compressed_by_index(uint32_t p_compressed_track, int p_in return false; } +// Helper math functions for Variant. +Variant Animation::add_variant(const Variant &a, const Variant &b) { + if (a.get_type() != b.get_type()) { + return a; + } + + switch (a.get_type()) { + case Variant::NIL: { + return Variant(); + } + case Variant::BOOL: { + return (a.operator real_t()) + (b.operator real_t()); // It is cast for interpolation. + } + case Variant::RECT2: { + const Rect2 ra = a.operator Rect2(); + const Rect2 rb = b.operator Rect2(); + return Rect2(ra.position + rb.position, ra.size + rb.size); + } + case Variant::RECT2I: { + const Rect2i ra = a.operator Rect2i(); + const Rect2i rb = b.operator Rect2i(); + return Rect2i(ra.position + rb.position, ra.size + rb.size); + } + case Variant::PLANE: { + const Plane pa = a.operator Plane(); + const Plane pb = b.operator Plane(); + return Plane(pa.normal + pb.normal, pa.d + pb.d); + } + case Variant::AABB: { + const ::AABB aa = a.operator ::AABB(); + const ::AABB ab = b.operator ::AABB(); + return ::AABB(aa.position + ab.position, aa.size + ab.size); + } + case Variant::QUATERNION: { + return (a.operator Quaternion()) * (b.operator Quaternion()); + } + case Variant::TRANSFORM2D: { + return (a.operator Transform2D()) * (b.operator Transform2D()); + } + case Variant::TRANSFORM3D: { + return (a.operator Transform3D()) * (b.operator Transform3D()); + } + default: { + return Variant::evaluate(Variant::OP_ADD, a, b); + } + } +} + +Variant Animation::subtract_variant(const Variant &a, const Variant &b) { + if (a.get_type() != b.get_type()) { + return a; + } + + switch (a.get_type()) { + case Variant::NIL: { + return Variant(); + } + case Variant::BOOL: { + return (a.operator real_t()) - (b.operator real_t()); // It is cast for interpolation. + } + case Variant::RECT2: { + const Rect2 ra = a.operator Rect2(); + const Rect2 rb = b.operator Rect2(); + return Rect2(ra.position - rb.position, ra.size - rb.size); + } + case Variant::RECT2I: { + const Rect2i ra = a.operator Rect2i(); + const Rect2i rb = b.operator Rect2i(); + return Rect2i(ra.position - rb.position, ra.size - rb.size); + } + case Variant::PLANE: { + const Plane pa = a.operator Plane(); + const Plane pb = b.operator Plane(); + return Plane(pa.normal - pb.normal, pa.d - pb.d); + } + case Variant::AABB: { + const ::AABB aa = a.operator ::AABB(); + const ::AABB ab = b.operator ::AABB(); + return ::AABB(aa.position - ab.position, aa.size - ab.size); + } + case Variant::QUATERNION: { + return (b.operator Quaternion()).inverse() * (a.operator Quaternion()); + } + case Variant::TRANSFORM2D: { + return (b.operator Transform2D()).inverse() * (a.operator Transform2D()); + } + case Variant::TRANSFORM3D: { + return (b.operator Transform3D()).inverse() * (a.operator Transform3D()); + } + default: { + return Variant::evaluate(Variant::OP_SUBTRACT, a, b); + } + } +} + +Variant Animation::blend_variant(const Variant &a, const Variant &b, float c) { + if (a.get_type() != b.get_type()) { + if (a.is_num() && b.is_num()) { + real_t va = a; + real_t vb = b; + return va + vb * c; + } + return a; + } + + switch (a.get_type()) { + case Variant::NIL: { + return Variant(); + } + case Variant::INT: { + return int((a.operator int64_t()) + (b.operator int64_t()) * c + 0.5); + } + case Variant::FLOAT: { + return (a.operator double()) + (b.operator double()) * c; + } + case Variant::VECTOR2: { + return (a.operator Vector2()) + (b.operator Vector2()) * c; + } + case Variant::VECTOR2I: { + const Vector2i va = a.operator Vector2i(); + const Vector2i vb = b.operator Vector2i(); + return Vector2i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5)); + } + case Variant::RECT2: { + const Rect2 ra = a.operator Rect2(); + const Rect2 rb = b.operator Rect2(); + return Rect2(ra.position + rb.position * c, ra.size + rb.size * c); + } + case Variant::RECT2I: { + const Rect2i ra = a.operator Rect2i(); + const Rect2i rb = b.operator Rect2i(); + return Rect2i(int32_t(ra.position.x + rb.position.x * c + 0.5), int32_t(ra.position.y + rb.position.y * c + 0.5), int32_t(ra.size.x + rb.size.x * c + 0.5), int32_t(ra.size.y + rb.size.y * c + 0.5)); + } + case Variant::VECTOR3: { + return (a.operator Vector3()) + (b.operator Vector3()) * c; + } + case Variant::VECTOR3I: { + const Vector3i va = a.operator Vector3i(); + const Vector3i vb = b.operator Vector3i(); + return Vector3i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5), int32_t(va.z + vb.z * c + 0.5)); + } + case Variant::VECTOR4: { + return (a.operator Vector4()) + (b.operator Vector4()) * c; + } + case Variant::VECTOR4I: { + const Vector4i va = a.operator Vector4i(); + const Vector4i vb = b.operator Vector4i(); + return Vector4i(int32_t(va.x + vb.x * c + 0.5), int32_t(va.y + vb.y * c + 0.5), int32_t(va.z + vb.z * c + 0.5), int32_t(va.w + vb.w * c + 0.5)); + } + case Variant::PLANE: { + const Plane pa = a.operator Plane(); + const Plane pb = b.operator Plane(); + return Plane(pa.normal + pb.normal * c, pa.d + pb.d * c); + } + case Variant::COLOR: { + return (a.operator Color()) + (b.operator Color()) * c; + } + case Variant::AABB: { + const ::AABB aa = a.operator ::AABB(); + const ::AABB ab = b.operator ::AABB(); + return ::AABB(aa.position + ab.position * c, aa.size + ab.size * c); + } + case Variant::BASIS: { + return (a.operator Basis()) + (b.operator Basis()) * c; + } + case Variant::QUATERNION: { + return (a.operator Quaternion()) * Quaternion().slerp((b.operator Quaternion()), c); + } + case Variant::TRANSFORM2D: { + return (a.operator Transform2D()) * Transform2D().interpolate_with((b.operator Transform2D()), c); + } + case Variant::TRANSFORM3D: { + return (a.operator Transform3D()) * Transform3D().interpolate_with((b.operator Transform3D()), c); + } + default: { + return c < 0.5 ? a : b; + } + } +} + +Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float c) { + if (a.get_type() != b.get_type()) { + if (a.is_num() && b.is_num()) { + real_t va = a; + real_t vb = b; + return va + (vb - va) * c; + } + return a; + } + + switch (a.get_type()) { + case Variant::NIL: { + return Variant(); + } + case Variant::INT: { + const int64_t va = a.operator int64_t(); + return int(va + ((b.operator int64_t()) - va) * c); + } + case Variant::FLOAT: { + const real_t va = a.operator real_t(); + return va + ((b.operator real_t()) - va) * c; + } + case Variant::VECTOR2: { + return (a.operator Vector2()).lerp(b.operator Vector2(), c); + } + case Variant::VECTOR2I: { + const Vector2i va = a.operator Vector2i(); + const Vector2i vb = b.operator Vector2i(); + return Vector2i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c)); + } + case Variant::RECT2: { + const Rect2 ra = a.operator Rect2(); + const Rect2 rb = b.operator Rect2(); + return Rect2(ra.position.lerp(rb.position, c), ra.size.lerp(rb.size, c)); + } + case Variant::RECT2I: { + const Rect2i ra = a.operator Rect2i(); + const Rect2i rb = b.operator Rect2i(); + return Rect2i(int32_t(ra.position.x + (rb.position.x - ra.position.x) * c), int32_t(ra.position.y + (rb.position.y - ra.position.y) * c), int32_t(ra.size.x + (rb.size.x - ra.size.x) * c), int32_t(ra.size.y + (rb.size.y - ra.size.y) * c)); + } + case Variant::VECTOR3: { + return (a.operator Vector3()).lerp(b.operator Vector3(), c); + } + case Variant::VECTOR3I: { + const Vector3i va = a.operator Vector3i(); + const Vector3i vb = b.operator Vector3i(); + return Vector3i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c), int32_t(va.z + (vb.z - va.z) * c)); + } + case Variant::VECTOR4: { + return (a.operator Vector4()).lerp(b.operator Vector4(), c); + } + case Variant::VECTOR4I: { + const Vector4i va = a.operator Vector4i(); + const Vector4i vb = b.operator Vector4i(); + return Vector4i(int32_t(va.x + (vb.x - va.x) * c), int32_t(va.y + (vb.y - va.y) * c), int32_t(va.z + (vb.z - va.z) * c), int32_t(va.w + (vb.w - va.w) * c)); + } + case Variant::PLANE: { + const Plane pa = a.operator Plane(); + const Plane pb = b.operator Plane(); + return Plane(pa.normal.lerp(pb.normal, c), pa.d + (pb.d - pa.d) * c); + } + case Variant::COLOR: { + return (a.operator Color()).lerp(b.operator Color(), c); + } + case Variant::AABB: { + const ::AABB aa = a.operator ::AABB(); + const ::AABB ab = b.operator ::AABB(); + return ::AABB(aa.position.lerp(ab.position, c), aa.size.lerp(ab.size, c)); + } + case Variant::BASIS: { + return (a.operator Basis()).lerp(b.operator Basis(), c); + } + case Variant::QUATERNION: { + return (a.operator Quaternion()).slerp(b.operator Quaternion(), c); + } + case Variant::TRANSFORM2D: { + return (a.operator Transform2D()).interpolate_with(b.operator Transform2D(), c); + } + case Variant::TRANSFORM3D: { + return (a.operator Transform3D()).interpolate_with(b.operator Transform3D(), c); + } + case Variant::STRING: { + // This is pretty funny and bizarre, but artists like to use it for typewriter effects. + const String sa = a.operator String(); + const String sb = b.operator String(); + String dst; + int sa_len = sa.length(); + int sb_len = sb.length(); + int csize = sa_len + (sb_len - sa_len) * c; + if (csize == 0) { + return ""; + } + dst.resize(csize + 1); + dst[csize] = 0; + int split = csize / 2; + + for (int i = 0; i < csize; i++) { + char32_t chr = ' '; + + if (i < split) { + if (i < sa.length()) { + chr = sa[i]; + } else if (i < sb.length()) { + chr = sb[i]; + } + + } else { + if (i < sb.length()) { + chr = sb[i]; + } else if (i < sa.length()) { + chr = sa[i]; + } + } + + dst[i] = chr; + } + + return dst; + } + case Variant::PACKED_INT32_ARRAY: { + const Vector<int32_t> *arr_a = Object::cast_to<Vector<int32_t>>(a); + const Vector<int32_t> *arr_b = Object::cast_to<Vector<int32_t>>(b); + int32_t sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + return a; + } else { + Vector<int32_t> v; + v.resize(sz); + { + int32_t *vw = v.ptrw(); + const int32_t *ar = arr_a->ptr(); + const int32_t *br = arr_b->ptr(); + + Variant va; + for (int32_t i = 0; i < sz; i++) { + va = interpolate_variant(ar[i], br[i], c); + vw[i] = va; + } + } + return v; + } + } + case Variant::PACKED_INT64_ARRAY: { + const Vector<int64_t> *arr_a = Object::cast_to<Vector<int64_t>>(a); + const Vector<int64_t> *arr_b = Object::cast_to<Vector<int64_t>>(b); + int64_t sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + return a; + } else { + Vector<int64_t> v; + v.resize(sz); + { + int64_t *vw = v.ptrw(); + const int64_t *ar = arr_a->ptr(); + const int64_t *br = arr_b->ptr(); + + Variant va; + for (int64_t i = 0; i < sz; i++) { + va = interpolate_variant(ar[i], br[i], c); + vw[i] = va; + } + } + return v; + } + } + case Variant::PACKED_FLOAT32_ARRAY: { + const Vector<float> *arr_a = Object::cast_to<Vector<float>>(a); + const Vector<float> *arr_b = Object::cast_to<Vector<float>>(b); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + return a; + } else { + Vector<float> v; + v.resize(sz); + { + float *vw = v.ptrw(); + const float *ar = arr_a->ptr(); + const float *br = arr_b->ptr(); + + Variant va; + for (int i = 0; i < sz; i++) { + va = interpolate_variant(ar[i], br[i], c); + vw[i] = va; + } + } + return v; + } + } + case Variant::PACKED_FLOAT64_ARRAY: { + const Vector<double> *arr_a = Object::cast_to<Vector<double>>(a); + const Vector<double> *arr_b = Object::cast_to<Vector<double>>(b); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + return a; + } else { + Vector<double> v; + v.resize(sz); + { + double *vw = v.ptrw(); + const double *ar = arr_a->ptr(); + const double *br = arr_b->ptr(); + + Variant va; + for (int i = 0; i < sz; i++) { + va = interpolate_variant(ar[i], br[i], c); + vw[i] = va; + } + } + return v; + } + } + case Variant::PACKED_VECTOR2_ARRAY: { + const Vector<Vector2> *arr_a = Object::cast_to<Vector<Vector2>>(a); + const Vector<Vector2> *arr_b = Object::cast_to<Vector<Vector2>>(b); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + return a; + } else { + Vector<Vector2> v; + v.resize(sz); + { + Vector2 *vw = v.ptrw(); + const Vector2 *ar = arr_a->ptr(); + const Vector2 *br = arr_b->ptr(); + + for (int i = 0; i < sz; i++) { + vw[i] = ar[i].lerp(br[i], c); + } + } + return v; + } + } + case Variant::PACKED_VECTOR3_ARRAY: { + const Vector<Vector3> *arr_a = Object::cast_to<Vector<Vector3>>(a); + const Vector<Vector3> *arr_b = Object::cast_to<Vector<Vector3>>(b); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + return a; + } else { + Vector<Vector3> v; + v.resize(sz); + { + Vector3 *vw = v.ptrw(); + const Vector3 *ar = arr_a->ptr(); + const Vector3 *br = arr_b->ptr(); + + for (int i = 0; i < sz; i++) { + vw[i] = ar[i].lerp(br[i], c); + } + } + return v; + } + } + case Variant::PACKED_COLOR_ARRAY: { + const Vector<Color> *arr_a = Object::cast_to<Vector<Color>>(a); + const Vector<Color> *arr_b = Object::cast_to<Vector<Color>>(b); + int sz = arr_a->size(); + if (sz == 0 || arr_b->size() != sz) { + return a; + } else { + Vector<Color> v; + v.resize(sz); + { + Color *vw = v.ptrw(); + const Color *ar = arr_a->ptr(); + const Color *br = arr_b->ptr(); + + for (int i = 0; i < sz; i++) { + vw[i] = ar[i].lerp(br[i], c); + } + } + return v; + } + } + default: { + return c < 0.5 ? a : b; + } + } +} + Animation::Animation() {} Animation::~Animation() { diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 46a88df130..49c8fa4c22 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -496,6 +496,12 @@ public: void optimize(real_t p_allowed_velocity_err = 0.01, real_t p_allowed_angular_err = 0.01, int p_precision = 3); void compress(uint32_t p_page_size = 8192, uint32_t p_fps = 120, float p_split_tolerance = 4.0); // 4.0 seems to be the split tolerance sweet spot from many tests + // Helper math functions for Variant. + static Variant add_variant(const Variant &a, const Variant &b); + static Variant subtract_variant(const Variant &a, const Variant &b); + static Variant blend_variant(const Variant &a, const Variant &b, float c); + static Variant interpolate_variant(const Variant &a, const Variant &b, float c); + Animation(); ~Animation(); }; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index e47bfef576..c1e30dd93c 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -257,23 +257,25 @@ void ShaderMaterial::_get_property_list(List<PropertyInfo> *p_list) const { groups[last_group][last_subgroup].push_back(info); } - // Sort groups alphabetically. - List<UniformProp> props; + List<String> group_names; for (HashMap<String, HashMap<String, List<PropertyInfo>>>::Iterator group = groups.begin(); group; ++group) { - for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = group->value.begin(); subgroup; ++subgroup) { - for (List<PropertyInfo>::Element *item = subgroup->value.front(); item; item = item->next()) { - if (subgroup->key == "<None>") { - props.push_back({ group->key, item->get() }); - } else { - props.push_back({ group->key + "::" + subgroup->key, item->get() }); - } - } - } + group_names.push_back(group->key); } - props.sort_custom<UniformPropComparator>(); + group_names.sort(); - for (List<UniformProp>::Element *E = props.front(); E; E = E->next()) { - p_list->push_back(E->get().info); + for (const String &group_name : group_names) { + List<String> subgroup_names; + HashMap<String, List<PropertyInfo>> &subgroups = groups[group_name]; + for (HashMap<String, List<PropertyInfo>>::Iterator subgroup = subgroups.begin(); subgroup; ++subgroup) { + subgroup_names.push_back(subgroup->key); + } + subgroup_names.sort(); + for (const String &subgroup_name : subgroup_names) { + List<PropertyInfo> &prop_infos = subgroups[subgroup_name]; + for (List<PropertyInfo>::Element *item = prop_infos.front(); item; item = item->next()) { + p_list->push_back(item->get()); + } + } } } } diff --git a/scene/resources/material.h b/scene/resources/material.h index 6c81293ee3..dd9589c577 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -84,17 +84,6 @@ class ShaderMaterial : public Material { HashMap<StringName, Variant> param_cache; - struct UniformProp { - String str; - PropertyInfo info; - }; - - struct UniformPropComparator { - bool operator()(const UniformProp &p_a, const UniformProp &p_b) const { - return p_a.str.naturalnocasecmp_to(p_b.str) < 0; - } - }; - protected: bool _set(const StringName &p_name, const Variant &p_value); bool _get(const StringName &p_name, Variant &r_ret) const; diff --git a/scene/resources/skeleton_profile.cpp b/scene/resources/skeleton_profile.cpp index 1367ea86dd..61a0350440 100644 --- a/scene/resources/skeleton_profile.cpp +++ b/scene/resources/skeleton_profile.cpp @@ -566,7 +566,7 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() { bones.write[14].bone_name = "LeftThumbMetacarpal"; bones.write[14].bone_parent = "LeftHand"; - bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0.707, 0.577, 0.408, -0.707, 0.577, 0.408, -0.025, 0, 0); + bones.write[14].reference_pose = Transform3D(0, -0.577, 0.816, 0, 0.816, 0.577, -1, 0, 0, -0.025, 0.025, 0); bones.write[14].handle_offset = Vector2(0.4, 0.8); bones.write[14].group = "LeftHand"; @@ -686,7 +686,7 @@ SkeletonProfileHumanoid::SkeletonProfileHumanoid() { bones.write[33].bone_name = "RightThumbMetacarpal"; bones.write[33].bone_parent = "RightHand"; - bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, -0.707, 0.577, 0.408, 0.707, 0.577, 0.408, 0.025, 0, 0); + bones.write[33].reference_pose = Transform3D(0, 0.577, -0.816, 0, 0.816, 0.577, 1, 0, 0, 0.025, 0.025, 0); bones.write[33].handle_offset = Vector2(0.6, 0.8); bones.write[33].group = "RightHand"; |