diff options
Diffstat (limited to 'scene/resources')
-rw-r--r-- | scene/resources/animation.cpp | 709 | ||||
-rw-r--r-- | scene/resources/animation.h | 38 | ||||
-rw-r--r-- | scene/resources/animation_library.cpp | 13 | ||||
-rw-r--r-- | scene/resources/animation_library.h | 2 | ||||
-rw-r--r-- | scene/resources/bit_map.cpp | 101 | ||||
-rw-r--r-- | scene/resources/camera_attributes.cpp | 4 | ||||
-rw-r--r-- | scene/resources/curve.cpp | 245 | ||||
-rw-r--r-- | scene/resources/curve.h | 7 | ||||
-rw-r--r-- | scene/resources/default_theme/default_theme.cpp | 3 | ||||
-rw-r--r-- | scene/resources/font.cpp | 12 | ||||
-rw-r--r-- | scene/resources/importer_mesh.cpp | 4 | ||||
-rw-r--r-- | scene/resources/importer_mesh.h | 2 | ||||
-rw-r--r-- | scene/resources/label_settings.cpp | 6 | ||||
-rw-r--r-- | scene/resources/material.cpp | 15 | ||||
-rw-r--r-- | scene/resources/mesh.cpp | 106 | ||||
-rw-r--r-- | scene/resources/mesh.h | 9 | ||||
-rw-r--r-- | scene/resources/packed_scene.cpp | 53 | ||||
-rw-r--r-- | scene/resources/packed_scene.h | 3 | ||||
-rw-r--r-- | scene/resources/primitive_meshes.cpp | 8 | ||||
-rw-r--r-- | scene/resources/resource_format_text.cpp | 7 | ||||
-rw-r--r-- | scene/resources/style_box.cpp | 12 | ||||
-rw-r--r-- | scene/resources/texture.cpp | 126 | ||||
-rw-r--r-- | scene/resources/tile_set.cpp | 1 |
23 files changed, 642 insertions, 844 deletions
diff --git a/scene/resources/animation.cpp b/scene/resources/animation.cpp index ef619c9893..3967858d47 100644 --- a/scene/resources/animation.cpp +++ b/scene/resources/animation.cpp @@ -888,7 +888,6 @@ int Animation::add_track(TrackType p_type, int p_at_pos) { } } emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); return p_at_pos; } @@ -951,7 +950,6 @@ void Animation::remove_track(int p_track) { memdelete(t); tracks.remove_at(p_track); emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); } int Animation::get_track_count() const { @@ -967,7 +965,6 @@ void Animation::track_set_path(int p_track, const NodePath &p_path) { ERR_FAIL_INDEX(p_track, tracks.size()); tracks[p_track]->path = p_path; emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); } NodePath Animation::track_get_path(int p_track) const { @@ -2467,7 +2464,6 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol ERR_FAIL_COND_V(idx == -2, T()); - bool result = true; int next = 0; real_t c = 0.0; // prepare for all cases of interpolation @@ -2599,10 +2595,7 @@ T Animation::_interpolate(const Vector<TKey<T>> &p_keys, double p_time, Interpol } if (p_ok) { - *p_ok = result; - } - if (!result) { - return T(); + *p_ok = true; } real_t tr = p_keys[idx].transition; @@ -2712,106 +2705,6 @@ Variant Animation::value_track_interpolate(int p_track, double p_time) const { return Variant(); } -void Animation::_value_track_get_key_indices_in_range(const ValueTrack *vt, double from_time, double to_time, List<int> *p_indices) const { - if (from_time != length && to_time == length) { - to_time = length + CMP_EPSILON; //include a little more if at the end - } - int to = _find(vt->values, to_time); - - if (to >= 0 && from_time == to_time && vt->values[to].time == from_time) { - //find exact (0 delta), return if found - p_indices->push_back(to); - return; - } - // can't really send the events == time, will be sent in the next frame. - // if event>=len then it will probably never be requested by the anim player. - - if (to >= 0 && vt->values[to].time >= to_time) { - to--; - } - - if (to < 0) { - return; // not bother - } - - int from = _find(vt->values, from_time); - - // position in the right first event.+ - if (from < 0 || vt->values[from].time < from_time) { - from++; - } - - int max = vt->values.size(); - - for (int i = from; i <= to; i++) { - ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen - p_indices->push_back(i); - } -} - -void Animation::value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const { - ERR_FAIL_INDEX(p_track, tracks.size()); - Track *t = tracks[p_track]; - ERR_FAIL_COND(t->type != TYPE_VALUE); - - ValueTrack *vt = static_cast<ValueTrack *>(t); - - double from_time = p_time - p_delta; - double to_time = p_time; - - if (from_time > to_time) { - SWAP(from_time, to_time); - } - - switch (loop_mode) { - case LOOP_NONE: { - if (from_time < 0) { - from_time = 0; - } - if (from_time > length) { - from_time = length; - } - - if (to_time < 0) { - to_time = 0; - } - if (to_time > length) { - to_time = length; - } - } break; - case LOOP_LINEAR: { - from_time = Math::fposmod(from_time, length); - to_time = Math::fposmod(to_time, length); - - if (from_time > to_time) { - // handle loop by splitting - _value_track_get_key_indices_in_range(vt, from_time, length, p_indices); - _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices); - return; - } - } break; - case LOOP_PINGPONG: { - from_time = Math::pingpong(from_time, length); - to_time = Math::pingpong(to_time, length); - - if (p_pingponged == -1) { - // handle loop by splitting - _value_track_get_key_indices_in_range(vt, 0, from_time, p_indices); - _value_track_get_key_indices_in_range(vt, 0, to_time, p_indices); - return; - } - if (p_pingponged == 1) { - // handle loop by splitting - _value_track_get_key_indices_in_range(vt, from_time, length, p_indices); - _value_track_get_key_indices_in_range(vt, to_time, length, p_indices); - return; - } - } break; - } - - _value_track_get_key_indices_in_range(vt, from_time, to_time, p_indices); -} - void Animation::value_track_set_update_mode(int p_track, UpdateMode p_mode) { ERR_FAIL_INDEX(p_track, tracks.size()); Track *t = tracks[p_track]; @@ -2833,47 +2726,74 @@ Animation::UpdateMode Animation::value_track_get_update_mode(int p_track) const } template <class T> -void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const { - if (from_time != length && to_time == length) { - to_time = length + CMP_EPSILON; //include a little more if at the end +void Animation::_track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const { + int len = p_array.size(); + if (len == 0) { + return; } - int to = _find(p_array, to_time); + int from = 0; + int to = len - 1; - // can't really send the events == time, will be sent in the next frame. - // if event>=len then it will probably never be requested by the anim player. - - if (to >= 0 && p_array[to].time >= to_time) { - to--; + if (!p_is_backward) { + while (p_array[from].time < from_time || Math::is_equal_approx(p_array[from].time, from_time)) { + from++; + if (to < from) { + return; + } + } + while (p_array[to].time > to_time && !Math::is_equal_approx(p_array[to].time, to_time)) { + to--; + if (to < from) { + return; + } + } + } else { + while (p_array[from].time < from_time && !Math::is_equal_approx(p_array[from].time, from_time)) { + from++; + if (to < from) { + return; + } + } + while (p_array[to].time > to_time || Math::is_equal_approx(p_array[to].time, to_time)) { + to--; + if (to < from) { + return; + } + } } - if (to < 0) { - return; // not bother + if (from == to) { + p_indices->push_back(from); + return; } - int from = _find(p_array, from_time); - - // position in the right first event.+ - if (from < 0 || p_array[from].time < from_time) { - from++; + if (!p_is_backward) { + for (int i = from; i <= to; i++) { + p_indices->push_back(i); + } + } else { + for (int i = to; i >= to; i--) { + p_indices->push_back(i); + } } +} - int max = p_array.size(); +void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, Animation::LoopedFlag p_looped_flag) const { + ERR_FAIL_INDEX(p_track, tracks.size()); - for (int i = from; i <= to; i++) { - ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen - p_indices->push_back(i); + if (p_delta == 0) { + return; // Prevent to get key continuously. } -} -void Animation::track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const { - ERR_FAIL_INDEX(p_track, tracks.size()); const Track *t = tracks[p_track]; double from_time = p_time - p_delta; double to_time = p_time; + bool is_backward = false; if (from_time > to_time) { + is_backward = true; SWAP(from_time, to_time); } @@ -2902,7 +2822,10 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl } if (from_time > to_time) { - // handle loop by splitting + // Handle loop by splitting. + double anim_end = length + CMP_EPSILON; + double anim_start = -CMP_EPSILON; + switch (t->type) { case TYPE_POSITION_3D: { const PositionTrack *tt = static_cast<const PositionTrack *>(t); @@ -2910,8 +2833,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices); _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices); } else { - _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices); - _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(tt->positions, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(tt->positions, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(tt->positions, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(tt->positions, from_time, anim_end, p_indices, is_backward); + } } } break; case TYPE_ROTATION_3D: { @@ -2920,8 +2848,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices); _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices); } else { - _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices); - _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(rt->rotations, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(rt->rotations, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(rt->rotations, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(rt->rotations, from_time, anim_end, p_indices, is_backward); + } } } break; case TYPE_SCALE_3D: { @@ -2930,8 +2863,13 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices); _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices); } else { - _track_get_key_indices_in_range(st->scales, from_time, length, p_indices); - _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(st->scales, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(st->scales, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(st->scales, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(st->scales, from_time, anim_end, p_indices, is_backward); + } } } break; case TYPE_BLEND_SHAPE: { @@ -2940,38 +2878,83 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices); _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices); } else { - _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices); - _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(bst->blend_shapes, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(bst->blend_shapes, from_time, anim_end, p_indices, is_backward); + } } } break; case TYPE_VALUE: { const ValueTrack *vt = static_cast<const ValueTrack *>(t); - _track_get_key_indices_in_range(vt->values, from_time, length, p_indices); - _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(vt->values, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(vt->values, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(vt->values, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(vt->values, from_time, anim_end, p_indices, is_backward); + } } break; case TYPE_METHOD: { const MethodTrack *mt = static_cast<const MethodTrack *>(t); - _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices); - _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(mt->methods, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(mt->methods, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(mt->methods, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(mt->methods, from_time, anim_end, p_indices, is_backward); + } } break; case TYPE_BEZIER: { const BezierTrack *bz = static_cast<const BezierTrack *>(t); - _track_get_key_indices_in_range(bz->values, from_time, length, p_indices); - _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(bz->values, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(bz->values, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(bz->values, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(bz->values, from_time, anim_end, p_indices, is_backward); + } } break; case TYPE_AUDIO: { const AudioTrack *ad = static_cast<const AudioTrack *>(t); - _track_get_key_indices_in_range(ad->values, from_time, length, p_indices); - _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(ad->values, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(ad->values, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(ad->values, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(ad->values, from_time, anim_end, p_indices, is_backward); + } } break; case TYPE_ANIMATION: { const AnimationTrack *an = static_cast<const AnimationTrack *>(t); - _track_get_key_indices_in_range(an->values, from_time, length, p_indices); - _track_get_key_indices_in_range(an->values, 0, to_time, p_indices); + if (!is_backward) { + _track_get_key_indices_in_range(an->values, from_time, anim_end, p_indices, is_backward); + _track_get_key_indices_in_range(an->values, anim_start, to_time, p_indices, is_backward); + } else { + _track_get_key_indices_in_range(an->values, anim_start, to_time, p_indices, is_backward); + _track_get_key_indices_in_range(an->values, from_time, anim_end, p_indices, is_backward); + } } break; } return; } + + // Not from_time > to_time but most recent of looping... + if (p_looped_flag != Animation::LOOPED_FLAG_NONE) { + if (!is_backward && Math::is_equal_approx(from_time, 0)) { + int edge = track_find_key(p_track, 0, true); + if (edge >= 0) { + p_indices->push_back(edge); + } + } else if (is_backward && Math::is_equal_approx(to_time, length)) { + int edge = track_find_key(p_track, length, true); + if (edge >= 0) { + p_indices->push_back(edge); + } + } + } } break; case LOOP_PINGPONG: { if (from_time > length || from_time < 0) { @@ -2981,160 +2964,164 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl to_time = Math::pingpong(to_time, length); } - if ((int)Math::floor(abs(p_delta) / length) % 2 == 0) { - if (p_pingponged == -1) { - // handle loop by splitting - switch (t->type) { - case TYPE_POSITION_3D: { - const PositionTrack *tt = static_cast<const PositionTrack *>(t); - if (tt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, from_time, p_indices); - _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, to_time, p_indices); - } else { - _track_get_key_indices_in_range(tt->positions, 0, from_time, p_indices); - _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices); - } - } break; - case TYPE_ROTATION_3D: { - const RotationTrack *rt = static_cast<const RotationTrack *>(t); - if (rt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, from_time, p_indices); - _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, to_time, p_indices); - } else { - _track_get_key_indices_in_range(rt->rotations, 0, from_time, p_indices); - _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices); - } - } break; - case TYPE_SCALE_3D: { - const ScaleTrack *st = static_cast<const ScaleTrack *>(t); - if (st->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, from_time, p_indices); - _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices); - } else { - _track_get_key_indices_in_range(st->scales, 0, from_time, p_indices); - _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices); - } - } break; - case TYPE_BLEND_SHAPE: { - const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); - if (bst->compressed_track >= 0) { - _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, from_time, p_indices); - _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices); - } else { - _track_get_key_indices_in_range(bst->blend_shapes, 0, from_time, p_indices); - _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices); - } - } break; - case TYPE_VALUE: { - const ValueTrack *vt = static_cast<const ValueTrack *>(t); - _track_get_key_indices_in_range(vt->values, 0, from_time, p_indices); - _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices); - } break; - case TYPE_METHOD: { - const MethodTrack *mt = static_cast<const MethodTrack *>(t); - _track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices); - _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices); - } break; - case TYPE_BEZIER: { - const BezierTrack *bz = static_cast<const BezierTrack *>(t); - _track_get_key_indices_in_range(bz->values, 0, from_time, p_indices); - _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices); - } break; - case TYPE_AUDIO: { - const AudioTrack *ad = static_cast<const AudioTrack *>(t); - _track_get_key_indices_in_range(ad->values, 0, from_time, p_indices); - _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices); - } break; - case TYPE_ANIMATION: { - const AnimationTrack *an = static_cast<const AnimationTrack *>(t); - _track_get_key_indices_in_range(an->values, 0, from_time, p_indices); - _track_get_key_indices_in_range(an->values, 0, to_time, p_indices); - } break; - } - return; + if (p_looped_flag == Animation::LOOPED_FLAG_START) { + // Handle loop by splitting. + switch (t->type) { + case TYPE_POSITION_3D: { + const PositionTrack *tt = static_cast<const PositionTrack *>(t); + if (tt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(tt->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, CMP_EPSILON, to_time, p_indices); + } else { + _track_get_key_indices_in_range(tt->positions, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(tt->positions, 0, to_time, p_indices, false); + } + } break; + case TYPE_ROTATION_3D: { + const RotationTrack *rt = static_cast<const RotationTrack *>(t); + if (rt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(rt->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, CMP_EPSILON, to_time, p_indices); + } else { + _track_get_key_indices_in_range(rt->rotations, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(rt->rotations, 0, to_time, p_indices, false); + } + } break; + case TYPE_SCALE_3D: { + const ScaleTrack *st = static_cast<const ScaleTrack *>(t); + if (st->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(st->scales, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(st->scales, 0, to_time, p_indices, false); + } + } break; + case TYPE_BLEND_SHAPE: { + const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); + if (bst->compressed_track >= 0) { + _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, from_time, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, 0, to_time, p_indices); + } else { + _track_get_key_indices_in_range(bst->blend_shapes, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(bst->blend_shapes, 0, to_time, p_indices, false); + } + } break; + case TYPE_VALUE: { + const ValueTrack *vt = static_cast<const ValueTrack *>(t); + _track_get_key_indices_in_range(vt->values, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(vt->values, 0, to_time, p_indices, false); + } break; + case TYPE_METHOD: { + const MethodTrack *mt = static_cast<const MethodTrack *>(t); + _track_get_key_indices_in_range(mt->methods, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(mt->methods, 0, to_time, p_indices, false); + } break; + case TYPE_BEZIER: { + const BezierTrack *bz = static_cast<const BezierTrack *>(t); + _track_get_key_indices_in_range(bz->values, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(bz->values, 0, to_time, p_indices, false); + } break; + case TYPE_AUDIO: { + const AudioTrack *ad = static_cast<const AudioTrack *>(t); + _track_get_key_indices_in_range(ad->values, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(ad->values, 0, to_time, p_indices, false); + } break; + case TYPE_ANIMATION: { + const AnimationTrack *an = static_cast<const AnimationTrack *>(t); + _track_get_key_indices_in_range(an->values, 0, from_time, p_indices, true); + _track_get_key_indices_in_range(an->values, 0, to_time, p_indices, false); + } break; } - if (p_pingponged == 1) { - // handle loop by splitting - switch (t->type) { - case TYPE_POSITION_3D: { - const PositionTrack *tt = static_cast<const PositionTrack *>(t); - if (tt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, length, p_indices); - } else { - _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices); - _track_get_key_indices_in_range(tt->positions, to_time, length, p_indices); - } - } break; - case TYPE_ROTATION_3D: { - const RotationTrack *rt = static_cast<const RotationTrack *>(t); - if (rt->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, length, p_indices); - } else { - _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices); - _track_get_key_indices_in_range(rt->rotations, to_time, length, p_indices); - } - } break; - case TYPE_SCALE_3D: { - const ScaleTrack *st = static_cast<const ScaleTrack *>(t); - if (st->compressed_track >= 0) { - _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, length, p_indices); - } else { - _track_get_key_indices_in_range(st->scales, from_time, length, p_indices); - _track_get_key_indices_in_range(st->scales, to_time, length, p_indices); - } - } break; - case TYPE_BLEND_SHAPE: { - const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); - if (bst->compressed_track >= 0) { - _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices); - _get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, length, p_indices); - } else { - _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices); - _track_get_key_indices_in_range(bst->blend_shapes, to_time, length, p_indices); - } - } break; - case TYPE_VALUE: { - const ValueTrack *vt = static_cast<const ValueTrack *>(t); - _track_get_key_indices_in_range(vt->values, from_time, length, p_indices); - _track_get_key_indices_in_range(vt->values, to_time, length, p_indices); - } break; - case TYPE_METHOD: { - const MethodTrack *mt = static_cast<const MethodTrack *>(t); - _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices); - _track_get_key_indices_in_range(mt->methods, to_time, length, p_indices); - } break; - case TYPE_BEZIER: { - const BezierTrack *bz = static_cast<const BezierTrack *>(t); - _track_get_key_indices_in_range(bz->values, from_time, length, p_indices); - _track_get_key_indices_in_range(bz->values, to_time, length, p_indices); - } break; - case TYPE_AUDIO: { - const AudioTrack *ad = static_cast<const AudioTrack *>(t); - _track_get_key_indices_in_range(ad->values, from_time, length, p_indices); - _track_get_key_indices_in_range(ad->values, to_time, length, p_indices); - } break; - case TYPE_ANIMATION: { - const AnimationTrack *an = static_cast<const AnimationTrack *>(t); - _track_get_key_indices_in_range(an->values, from_time, length, p_indices); - _track_get_key_indices_in_range(an->values, to_time, length, p_indices); - } break; - } - return; + return; + } + if (p_looped_flag == Animation::LOOPED_FLAG_END) { + // Handle loop by splitting. + switch (t->type) { + case TYPE_POSITION_3D: { + const PositionTrack *tt = static_cast<const PositionTrack *>(t); + if (tt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(tt->compressed_track, to_time, length, p_indices); + } else { + _track_get_key_indices_in_range(tt->positions, from_time, length, p_indices, false); + _track_get_key_indices_in_range(tt->positions, to_time, length, p_indices, true); + } + } break; + case TYPE_ROTATION_3D: { + const RotationTrack *rt = static_cast<const RotationTrack *>(t); + if (rt->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(rt->compressed_track, to_time, length, p_indices); + } else { + _track_get_key_indices_in_range(rt->rotations, from_time, length, p_indices, false); + _track_get_key_indices_in_range(rt->rotations, to_time, length, p_indices, true); + } + } break; + case TYPE_SCALE_3D: { + const ScaleTrack *st = static_cast<const ScaleTrack *>(t); + if (st->compressed_track >= 0) { + _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<3>(st->compressed_track, to_time, length, p_indices); + } else { + _track_get_key_indices_in_range(st->scales, from_time, length, p_indices, false); + _track_get_key_indices_in_range(st->scales, to_time, length, p_indices, true); + } + } break; + case TYPE_BLEND_SHAPE: { + const BlendShapeTrack *bst = static_cast<const BlendShapeTrack *>(t); + if (bst->compressed_track >= 0) { + _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, length, p_indices); + _get_compressed_key_indices_in_range<1>(bst->compressed_track, to_time, length - CMP_EPSILON, p_indices); + } else { + _track_get_key_indices_in_range(bst->blend_shapes, from_time, length, p_indices, false); + _track_get_key_indices_in_range(bst->blend_shapes, to_time, length, p_indices, true); + } + } break; + case TYPE_VALUE: { + const ValueTrack *vt = static_cast<const ValueTrack *>(t); + _track_get_key_indices_in_range(vt->values, from_time, length, p_indices, false); + _track_get_key_indices_in_range(vt->values, to_time, length, p_indices, true); + } break; + case TYPE_METHOD: { + const MethodTrack *mt = static_cast<const MethodTrack *>(t); + _track_get_key_indices_in_range(mt->methods, from_time, length, p_indices, false); + _track_get_key_indices_in_range(mt->methods, to_time, length, p_indices, true); + } break; + case TYPE_BEZIER: { + const BezierTrack *bz = static_cast<const BezierTrack *>(t); + _track_get_key_indices_in_range(bz->values, from_time, length, p_indices, false); + _track_get_key_indices_in_range(bz->values, to_time, length, p_indices, true); + } break; + case TYPE_AUDIO: { + const AudioTrack *ad = static_cast<const AudioTrack *>(t); + _track_get_key_indices_in_range(ad->values, from_time, length, p_indices, false); + _track_get_key_indices_in_range(ad->values, to_time, length, p_indices, true); + } break; + case TYPE_ANIMATION: { + const AnimationTrack *an = static_cast<const AnimationTrack *>(t); + _track_get_key_indices_in_range(an->values, from_time, length, p_indices, false); + _track_get_key_indices_in_range(an->values, to_time, length, p_indices, true); + } break; } + return; + } + + // The edge will be pingponged in the next frame and processed there, so let's ignore it now... + if (!is_backward && Math::is_equal_approx(to_time, length)) { + to_time = length - CMP_EPSILON; + } else if (is_backward && Math::is_equal_approx(from_time, 0)) { + from_time = CMP_EPSILON; } } break; } - switch (t->type) { case TYPE_POSITION_3D: { const PositionTrack *tt = static_cast<const PositionTrack *>(t); if (tt->compressed_track >= 0) { _get_compressed_key_indices_in_range<3>(tt->compressed_track, from_time, to_time - from_time, p_indices); } else { - _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices); + _track_get_key_indices_in_range(tt->positions, from_time, to_time, p_indices, is_backward); } } break; case TYPE_ROTATION_3D: { @@ -3142,7 +3129,7 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl if (rt->compressed_track >= 0) { _get_compressed_key_indices_in_range<3>(rt->compressed_track, from_time, to_time - from_time, p_indices); } else { - _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices); + _track_get_key_indices_in_range(rt->rotations, from_time, to_time, p_indices, is_backward); } } break; case TYPE_SCALE_3D: { @@ -3150,7 +3137,7 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl if (st->compressed_track >= 0) { _get_compressed_key_indices_in_range<3>(st->compressed_track, from_time, to_time - from_time, p_indices); } else { - _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices); + _track_get_key_indices_in_range(st->scales, from_time, to_time, p_indices, is_backward); } } break; case TYPE_BLEND_SHAPE: { @@ -3158,136 +3145,32 @@ void Animation::track_get_key_indices_in_range(int p_track, double p_time, doubl if (bst->compressed_track >= 0) { _get_compressed_key_indices_in_range<1>(bst->compressed_track, from_time, to_time - from_time, p_indices); } else { - _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices); + _track_get_key_indices_in_range(bst->blend_shapes, from_time, to_time, p_indices, is_backward); } } break; case TYPE_VALUE: { const ValueTrack *vt = static_cast<const ValueTrack *>(t); - _track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices); + _track_get_key_indices_in_range(vt->values, from_time, to_time, p_indices, is_backward); } break; case TYPE_METHOD: { const MethodTrack *mt = static_cast<const MethodTrack *>(t); - _track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices); + _track_get_key_indices_in_range(mt->methods, from_time, to_time, p_indices, is_backward); } break; case TYPE_BEZIER: { const BezierTrack *bz = static_cast<const BezierTrack *>(t); - _track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices); + _track_get_key_indices_in_range(bz->values, from_time, to_time, p_indices, is_backward); } break; case TYPE_AUDIO: { const AudioTrack *ad = static_cast<const AudioTrack *>(t); - _track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices); + _track_get_key_indices_in_range(ad->values, from_time, to_time, p_indices, is_backward); } break; case TYPE_ANIMATION: { const AnimationTrack *an = static_cast<const AnimationTrack *>(t); - _track_get_key_indices_in_range(an->values, from_time, to_time, p_indices); + _track_get_key_indices_in_range(an->values, from_time, to_time, p_indices, is_backward); } break; } } -void Animation::_method_track_get_key_indices_in_range(const MethodTrack *mt, double from_time, double to_time, List<int> *p_indices) const { - if (from_time != length && to_time == length) { - to_time = length + CMP_EPSILON; //include a little more if at the end - } - - int to = _find(mt->methods, to_time); - - // can't really send the events == time, will be sent in the next frame. - // if event>=len then it will probably never be requested by the anim player. - - if (to >= 0 && mt->methods[to].time >= to_time) { - to--; - } - - if (to < 0) { - return; // not bother - } - - int from = _find(mt->methods, from_time); - - // position in the right first event.+ - if (from < 0 || mt->methods[from].time < from_time) { - from++; - } - - int max = mt->methods.size(); - - for (int i = from; i <= to; i++) { - ERR_CONTINUE(i < 0 || i >= max); // shouldn't happen - p_indices->push_back(i); - } -} - -void Animation::method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged) const { - ERR_FAIL_INDEX(p_track, tracks.size()); - Track *t = tracks[p_track]; - ERR_FAIL_COND(t->type != TYPE_METHOD); - - MethodTrack *mt = static_cast<MethodTrack *>(t); - - double from_time = p_time - p_delta; - double to_time = p_time; - - if (from_time > to_time) { - SWAP(from_time, to_time); - } - - switch (loop_mode) { - case LOOP_NONE: { - if (from_time < 0) { - from_time = 0; - } - if (from_time > length) { - from_time = length; - } - - if (to_time < 0) { - to_time = 0; - } - if (to_time > length) { - to_time = length; - } - } break; - case LOOP_LINEAR: { - if (from_time > length || from_time < 0) { - from_time = Math::fposmod(from_time, length); - } - if (to_time > length || to_time < 0) { - to_time = Math::fposmod(to_time, length); - } - - if (from_time > to_time) { - // handle loop by splitting - _method_track_get_key_indices_in_range(mt, from_time, length, p_indices); - _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices); - return; - } - } break; - case LOOP_PINGPONG: { - if (from_time > length || from_time < 0) { - from_time = Math::pingpong(from_time, length); - } - if (to_time > length || to_time < 0) { - to_time = Math::pingpong(to_time, length); - } - - if (p_pingponged == -1) { - _method_track_get_key_indices_in_range(mt, 0, from_time, p_indices); - _method_track_get_key_indices_in_range(mt, 0, to_time, p_indices); - return; - } - if (p_pingponged == 1) { - _method_track_get_key_indices_in_range(mt, from_time, length, p_indices); - _method_track_get_key_indices_in_range(mt, to_time, length, p_indices); - return; - } - } break; - default: - break; - } - - _method_track_get_key_indices_in_range(mt, from_time, to_time, p_indices); -} - Vector<Variant> Animation::method_track_get_params(int p_track, int p_key_idx) const { ERR_FAIL_INDEX_V(p_track, tracks.size(), Vector<Variant>()); Track *t = tracks[p_track]; @@ -3834,7 +3717,6 @@ void Animation::track_move_up(int p_track) { } emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); } void Animation::track_move_down(int p_track) { @@ -3843,7 +3725,6 @@ void Animation::track_move_down(int p_track) { } emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); } void Animation::track_move_to(int p_track, int p_to_index) { @@ -3859,7 +3740,6 @@ void Animation::track_move_to(int p_track, int p_to_index) { tracks.insert(p_to_index > p_track ? p_to_index - 1 : p_to_index, track); emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); } void Animation::track_swap(int p_track, int p_with_track) { @@ -3871,7 +3751,6 @@ void Animation::track_swap(int p_track, int p_with_track) { SWAP(tracks.write[p_track], tracks.write[p_with_track]); emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); } void Animation::set_step(real_t p_step) { @@ -3952,10 +3831,8 @@ void Animation::_bind_methods() { ClassDB::bind_method(D_METHOD("value_track_set_update_mode", "track_idx", "mode"), &Animation::value_track_set_update_mode); ClassDB::bind_method(D_METHOD("value_track_get_update_mode", "track_idx"), &Animation::value_track_get_update_mode); - ClassDB::bind_method(D_METHOD("value_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_value_track_get_key_indices); ClassDB::bind_method(D_METHOD("value_track_interpolate", "track_idx", "time_sec"), &Animation::value_track_interpolate); - ClassDB::bind_method(D_METHOD("method_track_get_key_indices", "track_idx", "time_sec", "delta"), &Animation::_method_track_get_key_indices); ClassDB::bind_method(D_METHOD("method_track_get_name", "track_idx", "key_idx"), &Animation::method_track_get_name); ClassDB::bind_method(D_METHOD("method_track_get_params", "track_idx", "key_idx"), &Animation::method_track_get_params); @@ -4001,8 +3878,6 @@ void Animation::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "loop_mode", PROPERTY_HINT_ENUM, "None,Linear,Ping-Pong"), "set_loop_mode", "get_loop_mode"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step", PROPERTY_HINT_RANGE, "0,4096,0.001,suffix:s"), "set_step", "get_step"); - ADD_SIGNAL(MethodInfo("tracks_changed")); - BIND_ENUM_CONSTANT(TYPE_VALUE); BIND_ENUM_CONSTANT(TYPE_POSITION_3D); BIND_ENUM_CONSTANT(TYPE_ROTATION_3D); @@ -4027,6 +3902,10 @@ void Animation::_bind_methods() { BIND_ENUM_CONSTANT(LOOP_NONE); BIND_ENUM_CONSTANT(LOOP_LINEAR); BIND_ENUM_CONSTANT(LOOP_PINGPONG); + + BIND_ENUM_CONSTANT(LOOPED_FLAG_NONE); + BIND_ENUM_CONSTANT(LOOPED_FLAG_END); + BIND_ENUM_CONSTANT(LOOPED_FLAG_START); } void Animation::clear() { @@ -4041,7 +3920,6 @@ void Animation::clear() { compression.pages.clear(); compression.fps = 120; emit_changed(); - emit_signal(SceneStringNames::get_singleton()->tracks_changed); } 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) { @@ -6011,7 +5889,8 @@ Variant Animation::interpolate_variant(const Variant &a, const Variant &b, float } } -Animation::Animation() {} +Animation::Animation() { +} Animation::~Animation() { for (int i = 0; i < tracks.size(); i++) { diff --git a/scene/resources/animation.h b/scene/resources/animation.h index 49c8fa4c22..e66af77018 100644 --- a/scene/resources/animation.h +++ b/scene/resources/animation.h @@ -74,6 +74,12 @@ public: LOOP_PINGPONG, }; + enum LoopedFlag { + LOOPED_FLAG_NONE, + LOOPED_FLAG_END, + LOOPED_FLAG_START, + }; + #ifdef TOOLS_ENABLED enum HandleMode { HANDLE_MODE_FREE, @@ -250,15 +256,11 @@ private: _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; template <class T> - _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices) const; - - _FORCE_INLINE_ void _value_track_get_key_indices_in_range(const ValueTrack *vt, double from_time, double to_time, List<int> *p_indices) const; - _FORCE_INLINE_ void _method_track_get_key_indices_in_range(const MethodTrack *mt, double from_time, double to_time, List<int> *p_indices) const; + _FORCE_INLINE_ void _track_get_key_indices_in_range(const Vector<T> &p_array, double from_time, double to_time, List<int> *p_indices, bool p_is_backward) const; double length = 1.0; real_t step = 0.1; LoopMode loop_mode = LOOP_NONE; - int pingponged = 0; /* Animation compression page format (version 1): * @@ -345,27 +347,6 @@ private: // bind helpers private: - Vector<int> _value_track_get_key_indices(int p_track, double p_time, double p_delta) const { - List<int> idxs; - value_track_get_key_indices(p_track, p_time, p_delta, &idxs); - Vector<int> idxr; - - for (int &E : idxs) { - idxr.push_back(E); - } - return idxr; - } - Vector<int> _method_track_get_key_indices(int p_track, double p_time, double p_delta) const { - List<int> idxs; - method_track_get_key_indices(p_track, p_time, p_delta, &idxs); - Vector<int> idxr; - - for (int &E : idxs) { - idxr.push_back(E); - } - 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); @@ -470,17 +451,15 @@ public: bool track_get_interpolation_loop_wrap(int p_track) const; Variant value_track_interpolate(int p_track, double p_time) const; - void value_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const; void value_track_set_update_mode(int p_track, UpdateMode p_mode); UpdateMode value_track_get_update_mode(int p_track) const; - void method_track_get_key_indices(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const; Vector<Variant> method_track_get_params(int p_track, int p_key_idx) const; StringName method_track_get_name(int p_track, int p_key_idx) const; void copy_track(int p_track, Ref<Animation> p_to_animation); - void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, int p_pingponged = 0) const; + void track_get_key_indices_in_range(int p_track, double p_time, double p_delta, List<int> *p_indices, Animation::LoopedFlag p_looped_flag = Animation::LOOPED_FLAG_NONE) const; void set_length(real_t p_length); real_t get_length() const; @@ -510,6 +489,7 @@ VARIANT_ENUM_CAST(Animation::TrackType); VARIANT_ENUM_CAST(Animation::InterpolationType); VARIANT_ENUM_CAST(Animation::UpdateMode); VARIANT_ENUM_CAST(Animation::LoopMode); +VARIANT_ENUM_CAST(Animation::LoopedFlag); #ifdef TOOLS_ENABLED VARIANT_ENUM_CAST(Animation::HandleMode); VARIANT_ENUM_CAST(Animation::HandleSetMode); diff --git a/scene/resources/animation_library.cpp b/scene/resources/animation_library.cpp index 427d418551..b37bfbae62 100644 --- a/scene/resources/animation_library.cpp +++ b/scene/resources/animation_library.cpp @@ -52,11 +52,13 @@ Error AnimationLibrary::add_animation(const StringName &p_name, const Ref<Animat ERR_FAIL_COND_V(p_animation.is_null(), ERR_INVALID_PARAMETER); if (animations.has(p_name)) { + animations.get(p_name)->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed)); animations.erase(p_name); emit_signal(SNAME("animation_removed"), p_name); } animations.insert(p_name, p_animation); + animations.get(p_name)->connect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed).bind(p_name)); emit_signal(SNAME("animation_added"), p_name); notify_property_list_changed(); return OK; @@ -65,6 +67,7 @@ Error AnimationLibrary::add_animation(const StringName &p_name, const Ref<Animat void AnimationLibrary::remove_animation(const StringName &p_name) { ERR_FAIL_COND_MSG(!animations.has(p_name), vformat("Animation not found: %s.", p_name)); + animations.get(p_name)->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed)); animations.erase(p_name); emit_signal(SNAME("animation_removed"), p_name); notify_property_list_changed(); @@ -75,6 +78,8 @@ void AnimationLibrary::rename_animation(const StringName &p_name, const StringNa ERR_FAIL_COND_MSG(!is_valid_animation_name(p_new_name), "Invalid animation name: '" + String(p_new_name) + "'."); ERR_FAIL_COND_MSG(animations.has(p_new_name), vformat("Animation name \"%s\" already exists in library.", p_new_name)); + animations.get(p_name)->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed)); + animations.get(p_name)->connect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed).bind(p_new_name)); animations.insert(p_new_name, animations[p_name]); animations.erase(p_name); emit_signal(SNAME("animation_renamed"), p_name, p_new_name); @@ -100,6 +105,10 @@ TypedArray<StringName> AnimationLibrary::_get_animation_list() const { return ret; } +void AnimationLibrary::_animation_changed(const StringName &p_name) { + emit_signal(SNAME("animation_changed"), p_name); +} + void AnimationLibrary::get_animation_list(List<StringName> *p_animations) const { List<StringName> anims; @@ -115,6 +124,9 @@ void AnimationLibrary::get_animation_list(List<StringName> *p_animations) const } void AnimationLibrary::_set_data(const Dictionary &p_data) { + for (KeyValue<StringName, Ref<Animation>> &K : animations) { + K.value->disconnect(SNAME("changed"), callable_mp(this, &AnimationLibrary::_animation_changed)); + } animations.clear(); List<Variant> keys; p_data.get_key_list(&keys); @@ -146,6 +158,7 @@ void AnimationLibrary::_bind_methods() { ADD_SIGNAL(MethodInfo("animation_added", PropertyInfo(Variant::STRING_NAME, "name"))); ADD_SIGNAL(MethodInfo("animation_removed", PropertyInfo(Variant::STRING_NAME, "name"))); ADD_SIGNAL(MethodInfo("animation_renamed", PropertyInfo(Variant::STRING_NAME, "name"), PropertyInfo(Variant::STRING_NAME, "to_name"))); + ADD_SIGNAL(MethodInfo("animation_changed", PropertyInfo(Variant::STRING_NAME, "name"))); } AnimationLibrary::AnimationLibrary() { } diff --git a/scene/resources/animation_library.h b/scene/resources/animation_library.h index d63807b6d7..54bd641b6d 100644 --- a/scene/resources/animation_library.h +++ b/scene/resources/animation_library.h @@ -42,6 +42,8 @@ class AnimationLibrary : public Resource { TypedArray<StringName> _get_animation_list() const; + void _animation_changed(const StringName &p_name); + friend class AnimationPlayer; //for faster access HashMap<StringName, Ref<Animation>> animations; diff --git a/scene/resources/bit_map.cpp b/scene/resources/bit_map.cpp index 4afc82576d..0df61871d8 100644 --- a/scene/resources/bit_map.cpp +++ b/scene/resources/bit_map.cpp @@ -169,14 +169,6 @@ Dictionary BitMap::_get_data() const { return d; } -struct CrossStackEntry { - Point2i cross; - Vector<int> ranges; - - _FORCE_INLINE_ bool operator==(const CrossStackEntry &p_other) const { return cross == p_other.cross; } - _FORCE_INLINE_ bool operator!=(const CrossStackEntry &p_other) const { return cross != p_other.cross; } -}; - Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2i &p_start) const { int stepx = 0; int stepy = 0; @@ -188,14 +180,11 @@ Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2 int cury = starty; unsigned int count = 0; - Vector<CrossStackEntry> cross_stack; - int cross_stack_size = 0; + HashMap<Point2i, int> cross_map; - // Add starting point to stack as the default entry. - cross_stack.push_back({ Point2i(-1, -1), Vector<int>({ 0 }) }); - cross_stack_size++; + Vector<Vector2> _points; + int points_size = 0; - Vector<Point2i> _points; Vector<Vector<Vector2>> ret; // Add starting entry at start of return. @@ -326,52 +315,25 @@ Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2 // Handle crossing points. if (sv == 6 || sv == 9) { - const int new_index = _points.size() - 1; - - // Add previous point to last stack entry. - cross_stack.write[cross_stack_size - 1].ranges.push_back(new_index); - - // Create temporary entry to maybe insert, for searching. - const CrossStackEntry new_entry = { _points[new_index], Vector<int>({ new_index }) }; - - // Attempt to find matching entry. - const int found = cross_stack.rfind(new_entry, cross_stack_size - 1); + const Point2i cur_pos(curx, cury); - if (found != -1) { - Vector<Vector2> tmp; + // Find if this point has occured before. + if (HashMap<Point2i, int>::Iterator found = cross_map.find(cur_pos)) { + // Add points after the previous crossing to the result. + ret.push_back(_points.slice(found->value + 1, points_size)); - // Iterate over entries between end of stack and found, adding ranges to result. - for (int i = found; i < cross_stack_size; i++) { - const Vector<int> &ranges = cross_stack[i].ranges; + // Remove points after crossing point. + points_size = found->value + 1; - for (int j = 0; j < ranges.size() / 2; j++) { - int first = ranges[2 * j]; - const int last = ranges[2 * j + 1]; - - int new_pos = tmp.size(); - - tmp.resize(tmp.size() + (last - first)); - - Vector2 *tmp_ptrw = tmp.ptrw(); - - for (; first < last; first++, new_pos++) { - tmp_ptrw[new_pos].x = (float)(_points[first].x - p_rect.position.x); - tmp_ptrw[new_pos].y = (float)(_points[first].y - p_rect.position.y); - } - } + // Erase trailing map elements. + while (cross_map.last() != found) { + cross_map.remove(cross_map.last()); } - ret.push_back(tmp); - - // Shrink stack. - cross_stack_size = found; - - // Add previous point to last stack entry. - cross_stack.write[cross_stack_size - 1].ranges.push_back(new_index); + cross_map.erase(cur_pos); } else { - cross_stack.resize(MAX(cross_stack_size + 1, cross_stack.size())); - cross_stack.set(cross_stack_size, new_entry); - cross_stack_size++; + // Add crossing point to map. + cross_map.insert(cur_pos, points_size - 1); } } @@ -381,10 +343,11 @@ Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2 curx += stepx; cury += stepy; if (stepx == prevx && stepy == prevy) { - _points.write[_points.size() - 1].x = curx; - _points.write[_points.size() - 1].y = cury; + _points.set(points_size - 1, Vector2(curx, cury) - p_rect.position); } else { - _points.push_back(Point2i(curx, cury)); + _points.resize(MAX(points_size + 1, _points.size())); + _points.set(points_size, Vector2(curx, cury) - p_rect.position); + points_size++; } count++; @@ -394,28 +357,10 @@ Vector<Vector<Vector2>> BitMap::_march_square(const Rect2i &p_rect, const Point2 ERR_FAIL_COND_V((int)count > width * height, Vector<Vector<Vector2>>()); } while (curx != startx || cury != starty); - // Add last position to last stack entry. - cross_stack.write[cross_stack_size - 1].ranges.push_back(_points.size()); - - for (int i = 0; i < cross_stack_size; i++) { - const Vector<int> &ranges = cross_stack[i].ranges; - - for (int j = 0; j < ranges.size() / 2; j++) { - int first = ranges[2 * j]; - const int last = ranges[2 * j + 1]; - - int new_pos = ret[0].size(); + // Add remaining points to result. + _points.resize(points_size); - ret.write[0].resize(ret[0].size() + (last - first)); - - Vector2 *tmp_ptrw = ret.write[0].ptrw(); - - for (; first < last; first++, new_pos++) { - tmp_ptrw[new_pos].x = (float)(_points[first].x - p_rect.position.x); - tmp_ptrw[new_pos].y = (float)(_points[first].y - p_rect.position.y); - } - } - } + ret.set(0, _points); return ret; } diff --git a/scene/resources/camera_attributes.cpp b/scene/resources/camera_attributes.cpp index 3c322f32b6..8e4876e01f 100644 --- a/scene/resources/camera_attributes.cpp +++ b/scene/resources/camera_attributes.cpp @@ -120,7 +120,7 @@ void CameraAttributes::_bind_methods() { ClassDB::bind_method(D_METHOD("set_auto_exposure_scale", "exposure_grey"), &CameraAttributes::set_auto_exposure_scale); ClassDB::bind_method(D_METHOD("get_auto_exposure_scale"), &CameraAttributes::get_auto_exposure_scale); - ADD_GROUP("Exposure", "exposure"); + ADD_GROUP("Exposure", "exposure_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_sensitivity", PROPERTY_HINT_RANGE, "0.1,32000.0,0.1,suffix:ISO"), "set_exposure_sensitivity", "get_exposure_sensitivity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_multiplier", PROPERTY_HINT_RANGE, "0.0,2048.0,0.001"), "set_exposure_multiplier", "get_exposure_multiplier"); @@ -472,7 +472,7 @@ void CameraAttributesPhysical::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_near", PROPERTY_HINT_RANGE, "0.001,10,0.001,or_greater,exp,suffix:m"), "set_near", "get_near"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "frustum_far", PROPERTY_HINT_RANGE, "0.01,4000,0.01,or_greater,exp,suffix:m"), "set_far", "get_far"); - ADD_GROUP("Exposure", "exposure"); + ADD_GROUP("Exposure", "exposure_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_aperture", PROPERTY_HINT_RANGE, "0.5,64.0,0.01,exp,suffix:f-stop"), "set_aperture", "get_aperture"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "exposure_shutter_speed", PROPERTY_HINT_RANGE, "0.1,8000.0,0.001,suffix:1/s"), "set_shutter_speed", "get_shutter_speed"); diff --git a/scene/resources/curve.cpp b/scene/resources/curve.cpp index 0c36abc148..9289c5da4a 100644 --- a/scene/resources/curve.cpp +++ b/scene/resources/curve.cpp @@ -1403,6 +1403,22 @@ void Curve3D::_bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, re } } +void Curve3D::_bake_segment3d_even_length(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_length) const { + Vector3 beg = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_begin); + Vector3 end = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, p_end); + + size_t length = beg.distance_to(end); + + if (length > p_length && p_depth < p_max_depth) { + real_t mp = (p_begin + p_end) * 0.5; + Vector3 mid = p_a.bezier_interpolate(p_a + p_out, p_b + p_in, p_b, mp); + r_bake[mp] = mid; + + _bake_segment3d(r_bake, p_begin, mp, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length); + _bake_segment3d(r_bake, mp, p_end, p_a, p_out, p_b, p_in, p_depth + 1, p_max_depth, p_length); + } +} + void Curve3D::_bake() const { if (!baked_cache_dirty) { return; @@ -1416,6 +1432,7 @@ void Curve3D::_bake() const { baked_tilt_cache.clear(); baked_dist_cache.clear(); + baked_forward_vector_cache.clear(); baked_up_vector_cache.clear(); return; } @@ -1427,10 +1444,12 @@ void Curve3D::_bake() const { baked_tilt_cache.set(0, points[0].tilt); baked_dist_cache.resize(1); baked_dist_cache.set(0, 0.0); + baked_forward_vector_cache.resize(1); + baked_forward_vector_cache.set(0, Vector3(0.0, 0.0, 1.0)); if (up_vector_enabled) { baked_up_vector_cache.resize(1); - baked_up_vector_cache.set(0, Vector3(0, 1, 0)); + baked_up_vector_cache.set(0, Vector3(0.0, 1.0, 0.0)); } else { baked_up_vector_cache.clear(); } @@ -1438,101 +1457,52 @@ void Curve3D::_bake() const { return; } - Vector3 position = points[0].position; - real_t dist = 0.0; - List<Plane> pointlist; // Abuse Plane for (position, dist) - List<real_t> distlist; - - // Start always from origin. - pointlist.push_back(Plane(position, points[0].tilt)); - distlist.push_back(0.0); - - // Step 1: Sample points - const real_t step = 0.1; // At least 10 substeps ought to be enough? - for (int i = 0; i < points.size() - 1; i++) { - real_t p = 0.0; - - while (p < 1.0) { - real_t np = p + step; - if (np > 1.0) { - np = 1.0; - } - - Vector3 npp = points[i].position.bezier_interpolate(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, np); - real_t d = position.distance_to(npp); - - if (d > bake_interval) { - // OK! between P and NP there _has_ to be Something, let's go searching! - - const int iterations = 10; // Lots of detail! - - real_t low = p; - real_t hi = np; - real_t mid = low + (hi - low) * 0.5; - - for (int j = 0; j < iterations; j++) { - npp = points[i].position.bezier_interpolate(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, mid); - d = position.distance_to(npp); - - if (bake_interval < d) { - hi = mid; - } else { - low = mid; - } - mid = low + (hi - low) * 0.5; - } - - position = npp; - p = mid; - Plane post; - post.normal = position; - post.d = Math::lerp(points[i].tilt, points[i + 1].tilt, mid); - dist += d; + // Step 1: Tesselate curve to (almost) even length segments + { + Vector<RBMap<real_t, Vector3>> midpoints = _tessellate_even_length(10, bake_interval); - pointlist.push_back(post); - distlist.push_back(dist); - } else { - p = np; - } + int pc = 1; + for (int i = 0; i < points.size() - 1; i++) { + pc++; + pc += midpoints[i].size(); } - Vector3 npp = points[i + 1].position; - real_t d = position.distance_to(npp); - - if (d > CMP_EPSILON) { // Avoid the degenerate case of two very close points. - position = npp; - Plane post; - post.normal = position; - post.d = points[i + 1].tilt; - - dist += d; + baked_point_cache.resize(pc); + baked_tilt_cache.resize(pc); + baked_dist_cache.resize(pc); + baked_forward_vector_cache.resize(pc); + + Vector3 *bpw = baked_point_cache.ptrw(); + real_t *btw = baked_tilt_cache.ptrw(); + Vector3 *bfw = baked_forward_vector_cache.ptrw(); + + // Collect positions and sample tilts and tangents for each baked points. + bpw[0] = points[0].position; + bfw[0] = points[0].position.bezier_derivative(points[0].position + points[0].out, points[1].position + points[1].in, points[1].position, 0.0).normalized(); + btw[0] = points[0].tilt; + int pidx = 0; + + for (int i = 0; i < points.size() - 1; i++) { + for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { + pidx++; + bpw[pidx] = E.value; + bfw[pidx] = points[i].position.bezier_derivative(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, E.key).normalized(); + btw[pidx] = Math::lerp(points[i].tilt, points[i + 1].tilt, E.key); + } - pointlist.push_back(post); - distlist.push_back(dist); + pidx++; + bpw[pidx] = points[i + 1].position; + bfw[pidx] = points[i].position.bezier_derivative(points[i].position + points[i].out, points[i + 1].position + points[i + 1].in, points[i + 1].position, 1.0).normalized(); + btw[pidx] = points[i + 1].tilt; } - } - - baked_max_ofs = dist; - - const int point_count = pointlist.size(); - { - baked_point_cache.resize(point_count); - Vector3 *w = baked_point_cache.ptrw(); - - baked_tilt_cache.resize(point_count); - real_t *wt = baked_tilt_cache.ptrw(); - - baked_dist_cache.resize(point_count); - real_t *wd = baked_dist_cache.ptrw(); - - int idx = 0; - for (const Plane &E : pointlist) { - w[idx] = E.normal; - wt[idx] = E.d; - wd[idx] = distlist[idx]; - idx++; + // Recalculate the baked distances. + real_t *bdw = baked_dist_cache.ptrw(); + bdw[0] = 0.0; + for (int i = 0; i < pc - 1; i++) { + bdw[i + 1] = bdw[i] + bpw[i].distance_to(bpw[i + 1]); } + baked_max_ofs = bdw[pc - 1]; } if (!up_vector_enabled) { @@ -1545,14 +1515,12 @@ void Curve3D::_bake() const { // See Dougan, Carl. "The parallel transport frame." Game Programming Gems 2 (2001): 215-219. // for an example discussing about why not the Frenet frame. { - PackedVector3Array forward_vectors; + int point_count = baked_point_cache.size(); baked_up_vector_cache.resize(point_count); - forward_vectors.resize(point_count); - Vector3 *up_write = baked_up_vector_cache.ptrw(); - Vector3 *forward_write = forward_vectors.ptrw(); + const Vector3 *forward_ptr = baked_forward_vector_cache.ptr(); const Vector3 *points_ptr = baked_point_cache.ptr(); Basis frame; // X-right, Y-up, Z-forward. @@ -1560,28 +1528,20 @@ void Curve3D::_bake() const { // Set the initial frame based on Y-up rule. { - Vector3 up(0, 1, 0); - Vector3 forward = (points_ptr[1] - points_ptr[0]).normalized(); - if (forward.is_equal_approx(Vector3())) { - forward = Vector3(1, 0, 0); - } + Vector3 forward = forward_ptr[0]; - if (abs(forward.dot(up)) > 1.0 - UNIT_EPSILON) { - frame_prev = Basis::looking_at(-forward, up); - } else { + if (abs(forward.dot(Vector3(0, 1, 0))) > 1.0 - UNIT_EPSILON) { frame_prev = Basis::looking_at(-forward, Vector3(1, 0, 0)); + } else { + frame_prev = Basis::looking_at(-forward, Vector3(0, 1, 0)); } up_write[0] = frame_prev.get_column(1); - forward_write[0] = frame_prev.get_column(2); } // Calculate the Parallel Transport Frame. for (int idx = 1; idx < point_count; idx++) { - Vector3 forward = (points_ptr[idx] - points_ptr[idx - 1]).normalized(); - if (forward.is_equal_approx(Vector3())) { - forward = frame_prev.get_column(2); - } + Vector3 forward = forward_ptr[idx]; Basis rotate; rotate.rotate_to_align(frame_prev.get_column(2), forward); @@ -1589,8 +1549,6 @@ void Curve3D::_bake() const { frame.orthonormalize(); // guard against float error accumulation up_write[idx] = frame.get_column(1); - forward_write[idx] = frame.get_column(2); - frame_prev = frame; } @@ -1601,8 +1559,8 @@ void Curve3D::_bake() const { is_loop = false; } - real_t dot = forward_write[0].dot(forward_write[point_count - 1]); - if (dot < 1.0 - 0.01) { // Alignment should not be too tight, or it dosen't work for coarse bake interval + real_t dot = forward_ptr[0].dot(forward_ptr[point_count - 1]); + if (dot < 1.0 - UNIT_EPSILON) { // Alignment should not be too tight, or it dosen't work for coarse bake interval. is_loop = false; } } @@ -1612,17 +1570,17 @@ void Curve3D::_bake() const { const Vector3 up_start = up_write[0]; const Vector3 up_end = up_write[point_count - 1]; - real_t sign = SIGN(up_end.cross(up_start).dot(forward_write[0])); + real_t sign = SIGN(up_end.cross(up_start).dot(forward_ptr[0])); real_t full_angle = Quaternion(up_end, up_start).get_angle(); - if (abs(full_angle) < UNIT_EPSILON) { + if (abs(full_angle) < CMP_EPSILON) { return; } else { const real_t *dists = baked_dist_cache.ptr(); for (int idx = 1; idx < point_count; idx++) { const real_t frac = dists[idx] / baked_max_ofs; const real_t angle = Math::lerp((real_t)0.0, full_angle, frac); - Basis twist(forward_write[idx] * sign, angle); + Basis twist(forward_ptr[idx] * sign, angle); up_write[idx] = twist.xform(up_write[idx]); } @@ -1720,22 +1678,14 @@ Basis Curve3D::_sample_posture(Interval p_interval, bool p_apply_tilt) const { int idx = p_interval.idx; real_t frac = p_interval.frac; - Vector3 forward_begin; - Vector3 forward_end; - if (idx == 0) { - forward_begin = (baked_point_cache[1] - baked_point_cache[0]).normalized(); - forward_end = (baked_point_cache[1] - baked_point_cache[0]).normalized(); - } else { - forward_begin = (baked_point_cache[idx] - baked_point_cache[idx - 1]).normalized(); - forward_end = (baked_point_cache[idx + 1] - baked_point_cache[idx]).normalized(); - } + Vector3 forward_begin = baked_forward_vector_cache[idx]; + Vector3 forward_end = baked_forward_vector_cache[idx + 1]; Vector3 up_begin; Vector3 up_end; if (up_vector_enabled) { - const Vector3 *up_ptr = baked_up_vector_cache.ptr(); - up_begin = up_ptr[idx]; - up_end = up_ptr[idx + 1]; + up_begin = baked_up_vector_cache[idx]; + up_end = baked_up_vector_cache[idx + 1]; } else { up_begin = Vector3(0.0, 1.0, 0.0); up_end = Vector3(0.0, 1.0, 0.0); @@ -2046,6 +1996,50 @@ PackedVector3Array Curve3D::tessellate(int p_max_stages, real_t p_tolerance) con return tess; } +Vector<RBMap<real_t, Vector3>> Curve3D::_tessellate_even_length(int p_max_stages, real_t p_length) const { + Vector<RBMap<real_t, Vector3>> midpoints; + ERR_FAIL_COND_V_MSG(points.size() < 2, midpoints, "Curve must have at least 2 control point"); + + midpoints.resize(points.size() - 1); + + for (int i = 0; i < points.size() - 1; i++) { + _bake_segment3d_even_length(midpoints.write[i], 0, 1, points[i].position, points[i].out, points[i + 1].position, points[i + 1].in, 0, p_max_stages, p_length); + } + return midpoints; +} + +PackedVector3Array Curve3D::tessellate_even_length(int p_max_stages, real_t p_length) const { + PackedVector3Array tess; + + Vector<RBMap<real_t, Vector3>> midpoints = _tessellate_even_length(p_max_stages, p_length); + if (midpoints.size() == 0) { + return tess; + } + + int pc = 1; + for (int i = 0; i < points.size() - 1; i++) { + pc++; + pc += midpoints[i].size(); + } + + tess.resize(pc); + Vector3 *bpw = tess.ptrw(); + bpw[0] = points[0].position; + int pidx = 0; + + for (int i = 0; i < points.size() - 1; i++) { + for (const KeyValue<real_t, Vector3> &E : midpoints[i]) { + pidx++; + bpw[pidx] = E.value; + } + + pidx++; + bpw[pidx] = points[i + 1].position; + } + + return tess; +} + bool Curve3D::_set(const StringName &p_name, const Variant &p_value) { Vector<String> components = String(p_name).split("/", true, 2); if (components.size() >= 2 && components[0].begins_with("point_") && components[0].trim_prefix("point_").is_valid_int()) { @@ -2146,6 +2140,7 @@ void Curve3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_closest_point", "to_point"), &Curve3D::get_closest_point); ClassDB::bind_method(D_METHOD("get_closest_offset", "to_point"), &Curve3D::get_closest_offset); ClassDB::bind_method(D_METHOD("tessellate", "max_stages", "tolerance_degrees"), &Curve3D::tessellate, DEFVAL(5), DEFVAL(4)); + ClassDB::bind_method(D_METHOD("tessellate_even_length", "max_stages", "tolerance_length"), &Curve3D::tessellate_even_length, DEFVAL(5), DEFVAL(0.2)); ClassDB::bind_method(D_METHOD("_get_data"), &Curve3D::_get_data); ClassDB::bind_method(D_METHOD("_set_data", "data"), &Curve3D::_set_data); diff --git a/scene/resources/curve.h b/scene/resources/curve.h index d0c813f262..88c3cf3ae6 100644 --- a/scene/resources/curve.h +++ b/scene/resources/curve.h @@ -242,6 +242,7 @@ class Curve3D : public Resource { mutable PackedVector3Array baked_point_cache; mutable Vector<real_t> baked_tilt_cache; mutable PackedVector3Array baked_up_vector_cache; + mutable PackedVector3Array baked_forward_vector_cache; mutable Vector<real_t> baked_dist_cache; mutable real_t baked_max_ofs = 0.0; @@ -262,6 +263,7 @@ class Curve3D : public Resource { bool up_vector_enabled = true; void _bake_segment3d(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_tol) const; + void _bake_segment3d_even_length(RBMap<real_t, Vector3> &r_bake, real_t p_begin, real_t p_end, const Vector3 &p_a, const Vector3 &p_out, const Vector3 &p_b, const Vector3 &p_in, int p_depth, int p_max_depth, real_t p_length) const; Dictionary _get_data() const; void _set_data(const Dictionary &p_data); @@ -272,6 +274,8 @@ class Curve3D : public Resource { void _add_point(const Vector3 &p_position, const Vector3 &p_in = Vector3(), const Vector3 &p_out = Vector3(), int p_atpos = -1); void _remove_point(int p_index); + Vector<RBMap<real_t, Vector3>> _tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const; + protected: static void _bind_methods(); @@ -309,7 +313,8 @@ public: Vector3 get_closest_point(const Vector3 &p_to_point) const; real_t get_closest_offset(const Vector3 &p_to_point) const; - PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; //useful for display + PackedVector3Array tessellate(int p_max_stages = 5, real_t p_tolerance = 4) const; // Useful for display. + PackedVector3Array tessellate_even_length(int p_max_stages = 5, real_t p_length = 0.2) const; // Useful for baking. Curve3D(); }; diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp index 894936acd7..f179b4b818 100644 --- a/scene/resources/default_theme/default_theme.cpp +++ b/scene/resources/default_theme/default_theme.cpp @@ -84,7 +84,8 @@ static Ref<ImageTexture> generate_icon(int p_index) { // with integer scales. const bool upsample = !Math::is_equal_approx(Math::round(scale), scale); ImageLoaderSVG img_loader; - img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>()); + Error err = img_loader.create_image_from_string(img, default_theme_icons_sources[p_index], scale, upsample, HashMap<Color, Color>()); + ERR_FAIL_COND_V_MSG(err != OK, Ref<ImageTexture>(), "Failed generating icon, unsupported or invalid SVG data in default theme."); #endif return ImageTexture::create_from_image(img); diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 84814d939b..af51d6539e 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -1016,7 +1016,7 @@ void FontFile::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_oversampling", "get_oversampling"); ADD_PROPERTY(PropertyInfo(Variant::INT, "fixed_size", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_fixed_size", "get_fixed_size"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_feature_overrides", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_STORAGE), "set_opentype_feature_overrides", "get_opentype_feature_overrides"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font"), PROPERTY_USAGE_STORAGE), "set_fallbacks", "get_fallbacks"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font"), PROPERTY_USAGE_STORAGE), "set_fallbacks", "get_fallbacks"); } bool FontFile::_set(const StringName &p_name, const Variant &p_value) { @@ -2603,18 +2603,18 @@ void FontVariation::_bind_methods() { ClassDB::bind_method(D_METHOD("set_spacing", "spacing", "value"), &FontVariation::set_spacing); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "base_font", PROPERTY_HINT_RESOURCE_TYPE, "Font"), "set_base_font", "get_base_font"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), "set_fallbacks", "get_fallbacks"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), "set_fallbacks", "get_fallbacks"); - ADD_GROUP("Variation", "variation"); + ADD_GROUP("Variation", "variation_"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "variation_opentype"), "set_variation_opentype", "get_variation_opentype"); ADD_PROPERTY(PropertyInfo(Variant::INT, "variation_face_index"), "set_variation_face_index", "get_variation_face_index"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "variation_embolden", PROPERTY_HINT_RANGE, "-2,2,0.01"), "set_variation_embolden", "get_variation_embolden"); ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "variation_transform", PROPERTY_HINT_NONE, "suffix:px"), "set_variation_transform", "get_variation_transform"); - ADD_GROUP("OpenType Features", "opentype"); + ADD_GROUP("OpenType Features", "opentype_"); ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "opentype_features"), "set_opentype_features", "get_opentype_features"); - ADD_GROUP("Extra Spacing", "spacing"); + ADD_GROUP("Extra Spacing", "spacing_"); ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_glyph", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_GLYPH); ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_space", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_SPACE); ADD_PROPERTYI(PropertyInfo(Variant::INT, "spacing_top", PROPERTY_HINT_NONE, "suffix:px"), "set_spacing", "get_spacing", TextServer::SPACING_TOP); @@ -2868,7 +2868,7 @@ void SystemFont::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "subpixel_positioning", PROPERTY_HINT_ENUM, "Disabled,Auto,One Half of a Pixel,One Quarter of a Pixel"), "set_subpixel_positioning", "get_subpixel_positioning"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "multichannel_signed_distance_field"), "set_multichannel_signed_distance_field", "is_multichannel_signed_distance_field"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "oversampling", PROPERTY_HINT_RANGE, "0,10,0.1"), "set_oversampling", "get_oversampling"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, vformat("%s/%s:%s", Variant::OBJECT, PROPERTY_HINT_RESOURCE_TYPE, "Font")), "set_fallbacks", "get_fallbacks"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "fallbacks", PROPERTY_HINT_ARRAY_TYPE, MAKE_RESOURCE_TYPE_HINT("Font")), "set_fallbacks", "get_fallbacks"); } void SystemFont::_update_rids() const { diff --git a/scene/resources/importer_mesh.cpp b/scene/resources/importer_mesh.cpp index cec5569345..d1278f9340 100644 --- a/scene/resources/importer_mesh.cpp +++ b/scene/resources/importer_mesh.cpp @@ -971,10 +971,10 @@ Vector<Ref<Shape3D>> ImporterMesh::convex_decompose(const Mesh::ConvexDecomposit return ret; } -Ref<Shape3D> ImporterMesh::create_trimesh_shape() const { +Ref<ConcavePolygonShape3D> ImporterMesh::create_trimesh_shape() const { Vector<Face3> faces = get_faces(); if (faces.size() == 0) { - return Ref<Shape3D>(); + return Ref<ConcavePolygonShape3D>(); } Vector<Vector3> face_points; diff --git a/scene/resources/importer_mesh.h b/scene/resources/importer_mesh.h index 088a77edd1..bbd6498fcf 100644 --- a/scene/resources/importer_mesh.h +++ b/scene/resources/importer_mesh.h @@ -119,7 +119,7 @@ public: Vector<Face3> get_faces() const; Vector<Ref<Shape3D>> convex_decompose(const Mesh::ConvexDecompositionSettings &p_settings) const; - Ref<Shape3D> create_trimesh_shape() const; + Ref<ConcavePolygonShape3D> create_trimesh_shape() const; Ref<NavigationMesh> create_navigation_mesh(); Error lightmap_unwrap_cached(const Transform3D &p_base_transform, float p_texel_size, const Vector<uint8_t> &p_src_cache, Vector<uint8_t> &r_dst_cache); diff --git a/scene/resources/label_settings.cpp b/scene/resources/label_settings.cpp index ef380a68f9..c49620ce27 100644 --- a/scene/resources/label_settings.cpp +++ b/scene/resources/label_settings.cpp @@ -66,16 +66,16 @@ void LabelSettings::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "line_spacing", PROPERTY_HINT_NONE, "suffix:px"), "set_line_spacing", "get_line_spacing"); - ADD_GROUP("Font", "font"); + ADD_GROUP("Font", "font_"); 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,1024,1,or_greater,suffix:px"), "set_font_size", "get_font_size"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "font_color"), "set_font_color", "get_font_color"); - ADD_GROUP("Outline", "outline"); + ADD_GROUP("Outline", "outline_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "outline_size", PROPERTY_HINT_RANGE, "0,127,1,or_greater,suffix:px"), "set_outline_size", "get_outline_size"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "outline_color"), "set_outline_color", "get_outline_color"); - ADD_GROUP("Shadow", "shadow"); + ADD_GROUP("Shadow", "shadow_"); ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_size", PROPERTY_HINT_RANGE, "0,127,1,or_greater,suffix:px"), "set_shadow_size", "get_shadow_size"); ADD_PROPERTY(PropertyInfo(Variant::COLOR, "shadow_color"), "set_shadow_color", "get_shadow_color"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "shadow_offset", PROPERTY_HINT_NONE, "suffix:px"), "set_shadow_offset", "get_shadow_offset"); diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index 10d193f950..e457b2d377 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -92,18 +92,13 @@ void Material::inspect_native_shader_code() { RID Material::get_shader_rid() const { RID ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_shader_rid, ret)) { - return ret; - } - return RID(); + GDVIRTUAL_REQUIRED_CALL(_get_shader_rid, ret); + return ret; } Shader::Mode Material::get_shader_mode() const { - Shader::Mode ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_shader_mode, ret)) { - return ret; - } - - return Shader::MODE_MAX; + Shader::Mode ret = Shader::MODE_MAX; + GDVIRTUAL_REQUIRED_CALL(_get_shader_mode, ret); + return ret; } bool Material::_can_do_next_pass() const { diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index d1e300e057..a5e7602c8b 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -40,119 +40,83 @@ Mesh::ConvexDecompositionFunc Mesh::convex_decomposition_function = nullptr; int Mesh::get_surface_count() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_surface_count, ret); + return ret; } int Mesh::surface_get_array_len(int p_idx) const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_surface_get_array_len, p_idx, ret); + return ret; } int Mesh::surface_get_array_index_len(int p_idx) const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_surface_get_array_index_len, p_idx, ret); + return ret; } Array Mesh::surface_get_arrays(int p_surface) const { Array ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret)) { - return ret; - } - return Array(); + GDVIRTUAL_REQUIRED_CALL(_surface_get_arrays, p_surface, ret); + return ret; } TypedArray<Array> Mesh::surface_get_blend_shape_arrays(int p_surface) const { TypedArray<Array> ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret)) { - return ret; - } - - return TypedArray<Array>(); + GDVIRTUAL_REQUIRED_CALL(_surface_get_blend_shape_arrays, p_surface, ret); + return ret; } Dictionary Mesh::surface_get_lods(int p_surface) const { Dictionary ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret)) { - return ret; - } - - return Dictionary(); + GDVIRTUAL_REQUIRED_CALL(_surface_get_lods, p_surface, ret); + return ret; } uint32_t Mesh::surface_get_format(int p_idx) const { - uint32_t ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret)) { - return ret; - } - - return 0; + uint32_t ret = 0; + GDVIRTUAL_REQUIRED_CALL(_surface_get_format, p_idx, ret); + return ret; } Mesh::PrimitiveType Mesh::surface_get_primitive_type(int p_idx) const { - uint32_t ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret)) { - return (Mesh::PrimitiveType)ret; - } - - return PRIMITIVE_MAX; + uint32_t ret = PRIMITIVE_MAX; + GDVIRTUAL_REQUIRED_CALL(_surface_get_primitive_type, p_idx, ret); + return (Mesh::PrimitiveType)ret; } void Mesh::surface_set_material(int p_idx, const Ref<Material> &p_material) { - if (GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material)) { - return; - } + GDVIRTUAL_REQUIRED_CALL(_surface_set_material, p_idx, p_material); } Ref<Material> Mesh::surface_get_material(int p_idx) const { Ref<Material> ret; - if (GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret)) { - return ret; - } - - return Ref<Material>(); + GDVIRTUAL_REQUIRED_CALL(_surface_get_material, p_idx, ret); + return ret; } int Mesh::get_blend_shape_count() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret)) { - return ret; - } - - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_count, ret); + return ret; } StringName Mesh::get_blend_shape_name(int p_index) const { StringName ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret)) { - return ret; - } - - return StringName(); + GDVIRTUAL_REQUIRED_CALL(_get_blend_shape_name, p_index, ret); + return ret; } void Mesh::set_blend_shape_name(int p_index, const StringName &p_name) { - if (GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name)) { - return; - } + GDVIRTUAL_REQUIRED_CALL(_set_blend_shape_name, p_index, p_name); } AABB Mesh::get_aabb() const { AABB ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret)) { - return ret; - } - - return AABB(); + GDVIRTUAL_REQUIRED_CALL(_get_aabb, ret); + return ret; } Ref<TriangleMesh> Mesh::generate_triangle_mesh() const { @@ -388,7 +352,7 @@ Vector<Face3> Mesh::get_surface_faces(int p_surface) const { return Vector<Face3>(); } -Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { +Ref<ConvexPolygonShape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { if (p_simplify) { ConvexDecompositionSettings settings; settings.max_convex_hulls = 1; @@ -425,10 +389,10 @@ Ref<Shape3D> Mesh::create_convex_shape(bool p_clean, bool p_simplify) const { return shape; } -Ref<Shape3D> Mesh::create_trimesh_shape() const { +Ref<ConcavePolygonShape3D> Mesh::create_trimesh_shape() const { Vector<Face3> faces = get_faces(); if (faces.size() == 0) { - return Ref<Shape3D>(); + return Ref<ConcavePolygonShape3D>(); } Vector<Vector3> face_points; diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index 5ed4164117..6f995280e8 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -35,9 +35,12 @@ #include "core/math/face3.h" #include "core/math/triangle_mesh.h" #include "scene/resources/material.h" -#include "scene/resources/shape_3d.h" #include "servers/rendering_server.h" +class ConcavePolygonShape3D; +class ConvexPolygonShape3D; +class Shape3D; + class Mesh : public Resource { GDCLASS(Mesh, Resource); @@ -211,8 +214,8 @@ public: static ConvexDecompositionFunc convex_decomposition_function; Vector<Ref<Shape3D>> convex_decompose(const ConvexDecompositionSettings &p_settings) const; - Ref<Shape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const; - Ref<Shape3D> create_trimesh_shape() const; + Ref<ConvexPolygonShape3D> create_convex_shape(bool p_clean = true, bool p_simplify = false) const; + Ref<ConcavePolygonShape3D> create_trimesh_shape() const; virtual int get_builtin_bind_pose_count() const; virtual Transform3D get_builtin_bind_pose(int p_index) const; diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index f46faa1013..f4b7f3d0b2 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -1005,6 +1005,37 @@ void SceneState::clear() { base_scene_idx = -1; } +Error SceneState::copy_from(const Ref<SceneState> &p_scene_state) { + ERR_FAIL_COND_V(p_scene_state.is_null(), ERR_INVALID_PARAMETER); + + clear(); + + for (const StringName &E : p_scene_state->names) { + names.append(E); + } + for (const Variant &E : p_scene_state->variants) { + variants.append(E); + } + for (const SceneState::NodeData &E : p_scene_state->nodes) { + nodes.append(E); + } + for (const SceneState::ConnectionData &E : p_scene_state->connections) { + connections.append(E); + } + for (KeyValue<NodePath, int> &E : p_scene_state->node_path_cache) { + node_path_cache.insert(E.key, E.value); + } + for (const NodePath &E : p_scene_state->node_paths) { + node_paths.append(E); + } + for (const NodePath &E : p_scene_state->editable_instances) { + editable_instances.append(E); + } + base_scene_idx = p_scene_state->base_scene_idx; + + return OK; +} + Ref<SceneState> SceneState::get_base_scene_state() const { if (base_scene_idx >= 0) { Ref<PackedScene> ps = variants[base_scene_idx]; @@ -1737,6 +1768,28 @@ void PackedScene::clear() { state->clear(); } +void PackedScene::reload_from_file() { + String path = get_path(); + if (!path.is_resource_file()) { + return; + } + + Ref<PackedScene> s = ResourceLoader::load(ResourceLoader::path_remap(path), get_class(), ResourceFormatLoader::CACHE_MODE_IGNORE); + if (!s.is_valid()) { + return; + } + + // Backup the loaded_state + Ref<SceneState> loaded_state = s->get_state(); + // This assigns a new state to s->state + // We do this because of the next step + s->recreate_state(); + // This has a side-effect to clear s->state + copy_from(s); + // Then, we copy the backed-up loaded_state to state + state->copy_from(loaded_state); +} + bool PackedScene::can_instantiate() const { return state->can_instantiate(); } diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index a30ec54d85..ad1f50cd39 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -143,6 +143,7 @@ public: String get_path() const; void clear(); + Error copy_from(const Ref<SceneState> &p_scene_state); bool can_instantiate() const; Node *instantiate(GenEditState p_edit_state) const; @@ -235,6 +236,8 @@ public: void recreate_state(); void replace_state(Ref<SceneState> p_by); + virtual void reload_from_file() override; + virtual void set_path(const String &p_path, bool p_take_over = false) override; #ifdef TOOLS_ENABLED virtual void set_last_modified_time(uint64_t p_time) override { diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 4c6d533c72..2e8fcb3717 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -2779,13 +2779,7 @@ void TextMesh::_generate_glyph_mesh_data(const GlyphMeshKey &p_key, const Glyph real_t step = CLAMP(curve_step / (p0 - p3).length(), 0.01, 0.5); real_t t = step; while (t < 1.0) { - real_t omt = (1.0 - t); - real_t omt2 = omt * omt; - real_t omt3 = omt2 * omt; - real_t t2 = t * t; - real_t t3 = t2 * t; - - Vector2 point = p0 * omt3 + p1 * omt2 * t * 3.0 + p2 * omt * t2 * 3.0 + p3 * t3; + Vector2 point = p0.bezier_interpolate(p1, p2, p3, t); Vector2 p = point * pixel_size + origin; polygon.push_back(ContourPoint(p, false)); t += step; diff --git a/scene/resources/resource_format_text.cpp b/scene/resources/resource_format_text.cpp index 8b2b7e118c..354373ef3c 100644 --- a/scene/resources/resource_format_text.cpp +++ b/scene/resources/resource_format_text.cpp @@ -144,6 +144,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R } String id = token.value; + Error err = OK; if (!ignore_resource_parsing) { if (!ext_resources.has(id)) { @@ -163,7 +164,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R error = ERR_FILE_MISSING_DEPENDENCIES; error_text = "[ext_resource] referenced nonexistent resource at: " + path; _printerr(); - return error; + err = error; } else { ResourceLoader::notify_dependency_error(local_path, path, type); } @@ -175,7 +176,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R error = ERR_FILE_MISSING_DEPENDENCIES; error_text = "[ext_resource] referenced non-loaded resource at: " + path; _printerr(); - return error; + err = error; } } else { r_res = Ref<Resource>(); @@ -187,7 +188,7 @@ Error ResourceLoaderText::_parse_ext_resource(VariantParser::Stream *p_stream, R return ERR_PARSE_ERROR; } - return OK; + return err; } Ref<PackedScene> ResourceLoaderText::_parse_node_tag(VariantParser::ResourceParser &parser) { diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index f379f88bed..ea341152e6 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -35,11 +35,9 @@ #include <limits.h> float StyleBox::get_style_margin(Side p_side) const { - float ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_style_margin, p_side, ret)) { - return ret; - } - return 0; + float ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_style_margin, p_side, ret); + return ret; } bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const { @@ -49,9 +47,7 @@ bool StyleBox::test_mask(const Point2 &p_point, const Rect2 &p_rect) const { } void StyleBox::draw(RID p_canvas_item, const Rect2 &p_rect) const { - if (GDVIRTUAL_REQUIRED_CALL(_draw, p_canvas_item, p_rect)) { - return; - } + GDVIRTUAL_REQUIRED_CALL(_draw, p_canvas_item, p_rect); } void StyleBox::set_default_margin(Side p_side, float p_value) { diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index b5754caa6a..2106619a6b 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -40,19 +40,15 @@ #include "servers/camera/camera_feed.h" int Texture2D::get_width() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_width, ret); + return ret; } int Texture2D::get_height() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_height, ret); + return ret; } Size2 Texture2D::get_size() const { @@ -1092,57 +1088,44 @@ TypedArray<Image> Texture3D::_get_datai() const { } Image::Format Texture3D::get_format() const { - Image::Format ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) { - return ret; - } - return Image::FORMAT_MAX; + Image::Format ret = Image::FORMAT_MAX; + GDVIRTUAL_REQUIRED_CALL(_get_format, ret); + return ret; } int Texture3D::get_width() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_width, ret); + return ret; } int Texture3D::get_height() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_height, ret); + return ret; } int Texture3D::get_depth() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_depth, ret)) { - return ret; - } - - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_depth, ret); + return ret; } bool Texture3D::has_mipmaps() const { - bool ret; - if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) { - return ret; - } - return false; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret); + return ret; } Vector<Ref<Image>> Texture3D::get_data() const { TypedArray<Image> ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_data, ret)) { - Vector<Ref<Image>> data; - data.resize(ret.size()); - for (int i = 0; i < data.size(); i++) { - data.write[i] = ret[i]; - } - return data; + GDVIRTUAL_REQUIRED_CALL(_get_data, ret); + Vector<Ref<Image>> data; + data.resize(ret.size()); + for (int i = 0; i < data.size(); i++) { + data.write[i] = ret[i]; } - return Vector<Ref<Image>>(); + return data; } void Texture3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_format"), &Texture3D::get_format); @@ -2859,60 +2842,45 @@ AnimatedTexture::~AnimatedTexture() { /////////////////////////////// Image::Format TextureLayered::get_format() const { - Image::Format ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_format, ret)) { - return ret; - } - return Image::FORMAT_MAX; + Image::Format ret = Image::FORMAT_MAX; + GDVIRTUAL_REQUIRED_CALL(_get_format, ret); + return ret; } TextureLayered::LayeredType TextureLayered::get_layered_type() const { - uint32_t ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_layered_type, ret)) { - return (LayeredType)ret; - } - return LAYERED_TYPE_2D_ARRAY; + uint32_t ret = LAYERED_TYPE_2D_ARRAY; + GDVIRTUAL_REQUIRED_CALL(_get_layered_type, ret); + return (LayeredType)ret; } int TextureLayered::get_width() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_width, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_width, ret); + return ret; } int TextureLayered::get_height() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_height, ret)) { - return ret; - } - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_height, ret); + return ret; } int TextureLayered::get_layers() const { - int ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_layers, ret)) { - return ret; - } - - return 0; + int ret = 0; + GDVIRTUAL_REQUIRED_CALL(_get_layers, ret); + return ret; } bool TextureLayered::has_mipmaps() const { - bool ret; - if (GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret)) { - return ret; - } - return false; + bool ret = false; + GDVIRTUAL_REQUIRED_CALL(_has_mipmaps, ret); + return ret; } Ref<Image> TextureLayered::get_layer_data(int p_layer) const { Ref<Image> ret; - if (GDVIRTUAL_REQUIRED_CALL(_get_layer_data, p_layer, ret)) { - return ret; - } - return Ref<Image>(); + GDVIRTUAL_REQUIRED_CALL(_get_layer_data, p_layer, ret); + return ret; } void TextureLayered::_bind_methods() { diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index d4ad81614d..9d2537bb4d 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -4363,6 +4363,7 @@ int TileSetAtlasSource::create_alternative_tile(const Vector2i p_atlas_coords, i tiles[p_atlas_coords].alternatives[new_alternative_id] = memnew(TileData); tiles[p_atlas_coords].alternatives[new_alternative_id]->set_tile_set(tile_set); tiles[p_atlas_coords].alternatives[new_alternative_id]->set_allow_transform(true); + tiles[p_atlas_coords].alternatives[new_alternative_id]->connect("changed", callable_mp((Resource *)this, &TileSetAtlasSource::emit_changed)); tiles[p_atlas_coords].alternatives[new_alternative_id]->notify_property_list_changed(); tiles[p_atlas_coords].alternatives_ids.append(new_alternative_id); tiles[p_atlas_coords].alternatives_ids.sort(); |