diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index ea1cb71724..4b90f38a61 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -48,7 +48,7 @@ class Array : event::EventEntity { _id{id}, _idstr{idstr}, loop{loop}, - last_element{} {} + last_elements{} {} // prevent copying because it invalidates the usage of unique ids and event // registration. If you need to copy a curve, use the sync() method. @@ -260,35 +260,50 @@ class Array : event::EventEntity { * * mutable as hints are updated by const read-only functions. */ - mutable std::array::elem_ptr, Size> last_element = {}; + mutable std::array::elem_ptr, Size> last_elements = {}; }; template std::pair Array::frame(const time::time_t &t, const index_t index) const { - size_t &hint = this->last_element[index]; + // find elem_ptr in container to get the last keyframe + auto hint = this->last_elements[index]; size_t frame_index = this->containers.at(index).last(t, hint); - hint = frame_index; - return this->containers.at(index).get(frame_index).make_pair(); + + // update the hint + this->last_elements[index] = frame_index; + + return this->containers.at(index).get(frame_index).as_pair(); } template std::pair Array::next_frame(const time::time_t &t, const index_t index) const { - size_t &hint = this->last_element[index]; + // find elem_ptr in container to get the last keyframe with time <= t + auto hint = this->last_elements[index]; size_t frame_index = this->containers.at(index).last(t, hint); - hint = frame_index; - return this->containers.at(index).get(frame_index + 1).make_pair(); + + // increment the index to get the next keyframe + frame_index++; + + // update the hint + this->last_elements[index] = frame_index; + + return this->containers.at(index).get(frame_index).as_pair(); } template T Array::at(const time::time_t &t, const index_t index) const { - size_t &hint = this->last_element[index]; - size_t frame_index = this->containers.at(index).last(t, hint); - hint = frame_index; - return this->containers.at(index).get(frame_index).val(); + // find elem_ptr in container to get the last keyframe with time <= t + auto hint = this->last_elements[index]; + size_t e = this->containers.at(index).last(t, hint); + + // update the hint + this->last_elements[index] = e; + + return this->containers.at(index).get(e).val(); } template @@ -307,7 +322,12 @@ template void Array::set_insert(const time::time_t &t, const index_t index, T value) { - this->last_element[index] = this->containers.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); + // find elem_ptr in container to get the last keyframe with time <= t + auto hint = this->last_elements[index]; + auto e = this->containers.at(index).insert_after(Keyframe{t, value}, hint); + + // update the hint + this->last_elements[index] = e; this->changes(t); } @@ -316,9 +336,23 @@ template void Array::set_last(const time::time_t &t, const index_t index, T value) { - size_t frame_index = this->containers.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); - this->last_element[index] = frame_index; - this->containers.at(index).erase_after(frame_index); + // find elem_ptr in container to get the last keyframe with time <= t + auto hint = this->last_elements[index]; + auto e = this->containers.at(index).last(t, hint); + + // erase max one same-time value + if (this->containers.at(index).get(e).time() == t) { + e--; + } + + // erase all keyframes with time > t + this->containers.at(index).erase_after(e); + + // insert the new keyframe at the end + this->containers.at(index).insert_before(Keyframe{t, value}, e); + + // update the hint + this->last_elements[index] = hint; this->changes(t); } @@ -327,7 +361,12 @@ template void Array::set_replace(const time::time_t &t, const index_t index, T value) { - this->containers.at(index).insert_overwrite(Keyframe{t, value}, this->last_element[index]); + // find elem_ptr in container to get the last keyframe with time <= t + auto hint = this->last_elements[index]; + auto e = this->containers.at(index).insert_overwrite(Keyframe{t, value}, hint); + + // update the hint + this->last_elements[index] = e; this->changes(t); } diff --git a/libopenage/curve/base_curve.h b/libopenage/curve/base_curve.h index e5e265b5a0..de5c14201d 100644 --- a/libopenage/curve/base_curve.h +++ b/libopenage/curve/base_curve.h @@ -1,4 +1,4 @@ -// Copyright 2017-2024 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #pragma once @@ -246,7 +246,7 @@ template std::pair BaseCurve::frame(const time::time_t &time) const { auto e = this->container.last(time, this->container.size()); auto elem = this->container.get(e); - return elem.make_pair(); + return elem.as_pair(); } @@ -255,7 +255,7 @@ std::pair BaseCurve::next_frame(const time::time_t &ti auto e = this->container.last(time, this->container.size()); e++; auto elem = this->container.get(e); - return elem.make_pair(); + return elem.as_pair(); } template diff --git a/libopenage/curve/discrete.h b/libopenage/curve/discrete.h index 44fe132de6..b9f9b6b00c 100644 --- a/libopenage/curve/discrete.h +++ b/libopenage/curve/discrete.h @@ -1,4 +1,4 @@ -// Copyright 2017-2024 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #pragma once @@ -80,7 +80,7 @@ std::pair Discrete::get_time(const time::time_t &time) const this->last_element = e; auto elem = this->container.get(e); - return std::make_pair(elem.time, elem.value); + return elem.as_pair(); } @@ -97,7 +97,7 @@ std::optional> Discrete::get_previous(const time:: e--; auto elem = this->container.get(e); - return std::make_pair(elem.time(), elem.val()); + return elem.as_pair(); } } // namespace openage::curve diff --git a/libopenage/curve/keyframe.h b/libopenage/curve/keyframe.h index a34b0c6262..cd2ebf6ced 100644 --- a/libopenage/curve/keyframe.h +++ b/libopenage/curve/keyframe.h @@ -1,4 +1,4 @@ -// Copyright 2019-2024 the openage authors. See copying.md for legal info. +// Copyright 2019-2025 the openage authors. See copying.md for legal info. #pragma once @@ -55,12 +55,12 @@ class Keyframe { } /** - * Get the value and timestamp of the keyframe in form of std::pair - * @return keyframe pair + * Get a time-value pair of this keyframe. + * + * @return Keyframe time-value pair. */ - std::pair make_pair() const - { - return {time(), val()}; + std::pair as_pair() const { + return {this->timestamp, this->value}; } public: