diff --git a/libopenage/curve/CMakeLists.txt b/libopenage/curve/CMakeLists.txt index 63a7a12c00..0b800ced83 100644 --- a/libopenage/curve/CMakeLists.txt +++ b/libopenage/curve/CMakeLists.txt @@ -1,4 +1,5 @@ add_sources(libopenage + array.cpp base_curve.cpp continuous.cpp discrete.cpp @@ -12,7 +13,6 @@ add_sources(libopenage queue.cpp queue_filter_iterator.cpp segmented.cpp - array.cpp ) add_subdirectory("tests") diff --git a/libopenage/curve/array.cpp b/libopenage/curve/array.cpp index 23c60bf154..97e07033ce 100644 --- a/libopenage/curve/array.cpp +++ b/libopenage/curve/array.cpp @@ -1,10 +1,10 @@ -// Copyright 2017-2024 the openage authors. See copying.md for legal info. - - -#include "array.h" - -namespace openage::curve { - -// This file is intended to be empty - -} // openage::curve +// Copyright 2024-2024 the openage authors. See copying.md for legal info. + + +#include "array.h" + +namespace openage::curve { + +// This file is intended to be empty + +} // openage::curve diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index 417317a9d2..ec87a9c2be 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -1,152 +1,151 @@ -// Copyright 2017-2024 the openage authors. See copying.md for legal info. - -#pragma once - -#include - -#include "curve/base_curve.h" -#include "curve/keyframe_container.h" - - -// remember to update docs -namespace openage { -namespace curve { - -template -class Array { -public: - using container_t = std::array, Size>; - - - Array() = default; - - // prevent accidental copy of queue - Array(const Array &) = delete; - - - T get(const time::time_t &t, const size_t index) const; - - - std::array get_all(const time::time_t &t) const; - - - size_t size() const; - - const Keyframe &frame(const time::time_t &t, const size_t index) const; - - - const Keyframe &next_frame(const time::time_t &t, const size_t index) const; - - void set_insert(const time::time_t &t, const size_t index, T value); - - void set_last(const time::time_t &t, const size_t index, T value); - - void set_replace(const time::time_t &t, const size_t index, T value); - - void sync(const Array &other, const time::time_t &t); - - - class Iterator { - public: - Iterator(Array *curve, const time::time_t &time = time::TIME_MAX, size_t offset = 0) : - curve(curve), time(time), offset(offset) {}; - - const T &operator*() { - return curve->frame(this->time, this->offset).value; - } - - void operator++() { - this->offset++; - } - - bool operator!=(const Array::Iterator &rhs) const { - return this->offset != rhs.offset; - } - - - private: - size_t offset; - Array *curve; - time::time_t time; - }; - - - Iterator begin(const time::time_t &time = time::TIME_MAX); - - Iterator end(const time::time_t &time = time::TIME_MAX); - - -private: - container_t container; - mutable size_t last_hit_index = 0; -}; - - -template -const Keyframe &Array::frame(const time::time_t &t, const size_t index) const { - this->last_hit_index = container[index].last(t, this->last_hit_index); - return container[index].get(this->last_hit_index); -} - -template -const Keyframe &Array::next_frame(const time::time_t &t, const size_t index) const { - this->last_hit_index = container[index].last(t, this->last_hit_index); - return container[index].get(this->last_hit_index + 1); -} - -template -T Array::get(const time::time_t &t, const size_t index) const { - return this->frame(t, index).value; -} - -template -std::array Array::get_all(const time::time_t &t) const { - return [&](std::index_sequence) { - return std::array{this->get(t, I)...}; - }(std::make_index_sequence{}); -} - -template -size_t Array::size() const { - return Size; -} - - -template -void Array::set_insert(const time::time_t &t, const size_t index, T value) { - this->last_hit_index = this->container[index].insert_after(Keyframe(t, value), this->last_hit_index); -} - - -template -void Array::set_last(const time::time_t &t, const size_t index, T value) { - this->last_hit_index = this->container[index].insert_after(Keyframe(t, value), this->last_hit_index); - this->container[index].erase_after(this->last_hit_index); -} - - -template -void Array::set_replace(const time::time_t &t, const size_t index, T value) { - this->container[index].insert_overwrite(Keyframe(t, value), this->last_hit_index); -} - -template -void Array::sync(const Array &other, const time::time_t &start) { - for (int i = 0; i < Size; i++) { - this->container[i].sync(other, start); - } -} - -template -typename Array::Iterator Array::begin(const time::time_t &time) { - return Array::Iterator(this, time); -} - - -template -typename Array::Iterator Array::end(const time::time_t &time) { - return Array::Iterator(this, time, this->container.size()); -} - -} // namespace curve -} // namespace openage +// Copyright 2024-2024 the openage authors. See copying.md for legal info. + +#pragma once + +#include + +#include "curve/base_curve.h" +#include "curve/keyframe_container.h" + + +// remember to update docs +namespace openage { +namespace curve { + +template +class Array { +public: + Array() = default; + + // prevent accidental copy of queue + Array(const Array &) = delete; + + + T get(const time::time_t &t, const size_t index) const; + + + std::array get_all(const time::time_t &t) const; + + + consteval size_t size() const; + + std::pair frame(const time::time_t &t, const size_t index) const; + + + std::pair next_frame(const time::time_t &t, const size_t index) const; + + void set_insert(const time::time_t &t, const size_t index, T value); + + void set_last(const time::time_t &t, const size_t index, T value); + + void set_replace(const time::time_t &t, const size_t index, T value); + + void sync(const Array &other, const time::time_t &t); + + + class Iterator { + public: + Iterator(Array *curve, const time::time_t &time = time::TIME_MAX, size_t offset = 0) : + curve(curve), time(time), offset(offset) {}; + + const T &operator*() { + return curve->frame(this->time, this->offset).second; + } + + void operator++() { + this->offset++; + } + + bool operator!=(const Array::Iterator &rhs) const { + return this->offset != rhs.offset; + } + + + private: + size_t offset; + Array *curve; + time::time_t time; + }; + + + Iterator begin(const time::time_t &time = time::TIME_MAX); + + Iterator end(const time::time_t &time = time::TIME_MAX); + + +private: + std::array, Size> container; + + //hint for KeyframeContainer operations + mutable size_t last_element = 0; +}; + + +template +std::pair Array::frame(const time::time_t &t, const size_t index) const { + this->last_element = container[index].last(t, this->last_element); + return container[index].get(this->last_element).make_pair(); +} + +template +std::pair Array::next_frame(const time::time_t &t, const size_t index) const { + this->last_element = container[index].last(t, this->last_element); + return container[index].get(this->last_element + 1); +} + +template +T Array::get(const time::time_t &t, const size_t index) const { + return this->frame(t, index).second; +} + +template +std::array Array::get_all(const time::time_t &t) const { + return [&](std::index_sequence) { + return std::array{this->get(t, I)...}; + }(std::make_index_sequence{}); +} + +template +consteval size_t Array::size() const { + return Size; +} + + +template +void Array::set_insert(const time::time_t &t, const size_t index, T value) { + this->last_element = this->container[index].insert_after(Keyframe(t, value), this->last_element); +} + + +template +void Array::set_last(const time::time_t &t, const size_t index, T value) { + this->last_element = this->container[index].insert_after(Keyframe(t, value), this->last_element); + this->container[index].erase_after(this->last_element); +} + + +template +void Array::set_replace(const time::time_t &t, const size_t index, T value) { + this->container[index].insert_overwrite(Keyframe(t, value), this->last_element); +} + +template +void Array::sync(const Array &other, const time::time_t &start) { + for (int i = 0; i < Size; i++) { + this->container[i].sync(other[i], start); + } +} + +template +typename Array::Iterator Array::begin(const time::time_t &time) { + return Array::Iterator(this, time); +} + + +template +typename Array::Iterator Array::end(const time::time_t &time) { + return Array::Iterator(this, time, this->container.size()); +} + +} // namespace curve +} // namespace openage diff --git a/libopenage/curve/keyframe.h b/libopenage/curve/keyframe.h index e868783cbb..a34b0c6262 100644 --- a/libopenage/curve/keyframe.h +++ b/libopenage/curve/keyframe.h @@ -54,6 +54,15 @@ class Keyframe { return this->value; } + /** + * Get the value and timestamp of the keyframe in form of std::pair + * @return keyframe pair + */ + std::pair make_pair() const + { + return {time(), val()}; + } + public: /** * Value of the keyframe. diff --git a/libopenage/curve/keyframe_container.h b/libopenage/curve/keyframe_container.h index d9bb9a0bbd..8434942058 100644 --- a/libopenage/curve/keyframe_container.h +++ b/libopenage/curve/keyframe_container.h @@ -279,8 +279,6 @@ class KeyframeContainer { * Replaces all keyframes beginning at t >= start with keyframes from \p other. * * @param other Curve that keyframes are copied from. - * @param converter Function that converts the value type of \p other to the - * value type of \p this. * @param start Start time at which keyframes are replaced (default = -INF). * Using the default value replaces ALL keyframes of \p this with * the keyframes of \p other.