From 9ba478ede2945c64a3e3cc8436d1695d4463cf34 Mon Sep 17 00:00:00 2001 From: Jeremiah Morgan Date: Fri, 13 Dec 2024 16:17:45 +0000 Subject: [PATCH 01/13] impliment curve::array --- libopenage/curve/CMakeLists.txt | 1 + libopenage/curve/array.cpp | 10 + libopenage/curve/array.h | 244 +++++++++++++++++++++++++ libopenage/curve/keyframe.h | 9 + libopenage/curve/keyframe_container.h | 2 - libopenage/curve/tests/curve_types.cpp | 87 ++++++++- 6 files changed, 348 insertions(+), 5 deletions(-) create mode 100644 libopenage/curve/array.cpp create mode 100644 libopenage/curve/array.h diff --git a/libopenage/curve/CMakeLists.txt b/libopenage/curve/CMakeLists.txt index 623a22a25a..174498e23b 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 diff --git a/libopenage/curve/array.cpp b/libopenage/curve/array.cpp new file mode 100644 index 0000000000..97e07033ce --- /dev/null +++ b/libopenage/curve/array.cpp @@ -0,0 +1,10 @@ +// 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 new file mode 100644 index 0000000000..7076082459 --- /dev/null +++ b/libopenage/curve/array.h @@ -0,0 +1,244 @@ +// Copyright 2024-2024 the openage authors. See copying.md for legal info. + +#pragma once + +#include + +#include "curve/keyframe_container.h" +#include "event/evententity.h" + + +// remember to update docs +namespace openage { +namespace curve { + +template +class Array : event::EventEntity { +public: + Array(const std::shared_ptr &loop, + size_t id, + const std::string &idstr = "", + const EventEntity::single_change_notifier ¬ifier = nullptr) : + EventEntity(loop, notifier), _id{id}, _idstr{idstr}, loop{loop}{} + + Array(const Array &) = delete; + + + /** + * Get the last element with elem->time <= time from + * the keyfram container at a given index + */ + T get(const time::time_t &t, const size_t index) const; + + + /** + * Get an array of the last elements with elem->time <= time from + * all keyfram containers contained within this array curve + */ + std::array get_all(const time::time_t &t) const; + + + consteval size_t size() const; + + /** + * Get the last element and associated time which has elem->time <= time from + * the keyfram container at a given index + */ + std::pair frame(const time::time_t &t, const size_t index) const; + + + /** + * Get the first element and associated time which has elem->time >= time from + * the keyfram container at a given index + */ + std::pair next_frame(const time::time_t &t, const size_t index) const; + + + /** + * Insert a new keyframe value at time t at index + */ + void set_insert(const time::time_t &t, const size_t index, T value); + + + /** + * Insert a new keyframe value at time t; delete all keyframes after time t at index + */ + void set_last(const time::time_t &t, const size_t index, T value); + + + /** + * Insert a new keyframe value at time t at index i; remove all other keyframes with time t at index i + */ + void set_replace(const time::time_t &t, const size_t index, T value); + + + /** + * Copy keyframes from another container to this container. + * + * Replaces all keyframes beginning at t >= start with keyframes from \p other. + * + * @param other Curve that keyframes are copied from. + * @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. + */ + void sync(const Array &other, const time::time_t &start); + + + /** + * Get the identifier of this curve. + * + * @return Identifier. + */ + size_t id() const override { + return this->_id; + } + + /** + * Get the human-readable identifier of this curve. + * + * @return Human-readable identifier. + */ + std::string idstr() const override { + if (this->_idstr.size() == 0) { + return std::to_string(this->id()); + } + return this->_idstr; + } + + + KeyframeContainer& operator[] (size_t index) + { + return this->container[index]; + } + + KeyframeContainer operator[] (size_t index) const + { + return this->container[index]; + } + + 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 std::array last_element = {}; + + /** + * Identifier for the container + */ + const size_t _id; + + /** + * Human-readable identifier for the container + */ + const std::string _idstr; + + /** + * The eventloop this curve was registered to + */ + const std::shared_ptr loop; +}; + + +template +std::pair Array::frame(const time::time_t &t, const size_t index) const { + size_t frmae_index = container[index].last(t, this->last_element[index]); + this->last_element[index] = frmae_index; + return container[index].get(frmae_index).make_pair(); +} + +template +std::pair Array::next_frame(const time::time_t &t, const size_t index) const { + size_t frmae_index = container[index].last(t, this->last_element[index]); + this->last_element[index] = frmae_index; + return container[index].get(frmae_index + 1).make_pair(); +} + +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[index] = this->container[index].insert_after(Keyframe(t, value), this->last_element[index]); +} + + +template +void Array::set_last(const time::time_t &t, const size_t index, T value) { + + size_t frame_index = this->container[index].insert_after(Keyframe(t, value), this->last_element[index]); + this->last_element[index] = frame_index; + this->container[index].erase_after(frame_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_element[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.container[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. diff --git a/libopenage/curve/tests/curve_types.cpp b/libopenage/curve/tests/curve_types.cpp index 421d3fb4d7..6c754e5df9 100644 --- a/libopenage/curve/tests/curve_types.cpp +++ b/libopenage/curve/tests/curve_types.cpp @@ -5,6 +5,7 @@ #include #include +#include "curve/array.h" #include "curve/continuous.h" #include "curve/discrete.h" #include "curve/discrete_mod.h" @@ -232,7 +233,7 @@ void curve_types() { TESTEQUALS(c.get(8), 4); } - //Check the discrete type + // Check the discrete type { auto f = std::make_shared(); Discrete c(f, 0); @@ -257,7 +258,7 @@ void curve_types() { TESTEQUALS(complex.get(10), "Test 10"); } - //Check the discrete mod type + // Check the discrete mod type { auto f = std::make_shared(); DiscreteMod c(f, 0); @@ -290,7 +291,7 @@ void curve_types() { TESTEQUALS(c.get_mod(15, 0), 0); } - //check set_last + // check set_last { auto f = std::make_shared(); Discrete c(f, 0); @@ -386,6 +387,86 @@ void curve_types() { TESTEQUALS(c.get(1), 0); TESTEQUALS(c.get(5), 0); } + + { // array + auto f = std::make_shared(); + + Array a(f,0); + a.set_insert(time::time_t(1), 0, 0); + a.set_insert(time::time_t(1), 1, 1); + a.set_insert(time::time_t(1), 2, 2); + a.set_insert(time::time_t(1), 3, 3); + //a = [[0:0, 1:0],[0:0, 1:1],[0:0, 1:2],[0:0, 1:3]] + + auto res = a.get_all(time::time_t(1)); + TESTEQUALS(res[0], 0); + TESTEQUALS(res[1], 1); + TESTEQUALS(res[2], 2); + TESTEQUALS(res[3], 3); + + Array other(f,0); + other[0].last(999); + other[1].last(999); + other[2].last(999); + other[3].last(999); + other.set_insert(time::time_t(1), 0, 4); + other.set_insert(time::time_t(1), 1, 5); + other.set_insert(time::time_t(1), 2, 6); + other.set_insert(time::time_t(1), 3, 7); + //other = [[0:999, 1:4],[0:999, 1:5],[0:999, 1:6],[0:999, 1:7]] + + + a.sync(other, time::time_t(1)); + //a = [[0:0, 1:4],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] + + res = a.get_all(time::time_t(0)); + TESTEQUALS(res[0], 0); + TESTEQUALS(res[1], 0); + TESTEQUALS(res[2], 0); + TESTEQUALS(res[3], 0); + res = a.get_all(time::time_t(1)); + TESTEQUALS(res[0], 4); + TESTEQUALS(res[1], 5); + TESTEQUALS(res[2], 6); + TESTEQUALS(res[3], 7); + + // Additional tests + a.set_insert(time::time_t(2), 0, 15); + a.set_insert(time::time_t(2), 0, 20); + a.set_replace(time::time_t(2), 0, 25); + TESTEQUALS(a.get(time::time_t(2), 0), 25); + // a = [[0:0, 1:4, 2:25],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] + + a.set_insert(time::time_t(3), 0, 30); + a.set_insert(time::time_t(4), 0, 40); + a.set_last(time::time_t(3), 0, 35); + TESTEQUALS(a.get(time::time_t(3), 0), 35); + // a = [[0:0, 1:4, 2:25, 3:35],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] + + auto frame = a.frame(time::time_t(1), 2); + TESTEQUALS(frame.second, 6); + TESTEQUALS(frame.first, time::time_t(1)); + + a.set_insert(time::time_t(5), 3, 40); + auto next_frame = a.next_frame(time::time_t(1), 3); + TESTEQUALS(next_frame.second, 40); + TESTEQUALS(next_frame.first, time::time_t(5)); + + // Test operator[] + TESTEQUALS(a[0].get(a[0].last(time::time_t(2))).val(), 25); + TESTEQUALS(a[1].get(a[1].last(time::time_t(2))).val(), 5); + + // Test begin and end + auto it = a.begin(time::time_t(1)); + TESTEQUALS(*it, 4); + ++it; + TESTEQUALS(*it, 5); + ++it; + TESTEQUALS(*it, 6); + ++it; + TESTEQUALS(*it, 7); + ++it; + } } } // namespace openage::curve::tests From 8647a7bc98ef652c5b1e96ddfc3ea3c2cef74f1d Mon Sep 17 00:00:00 2001 From: Jeremiah Morgan Date: Thu, 26 Dec 2024 15:44:48 +0000 Subject: [PATCH 02/13] address comments --- libopenage/curve/array.h | 94 +++++++++++++++----------- libopenage/curve/base_curve.h | 4 +- libopenage/curve/tests/container.cpp | 84 ++++++++++++++++++++++- libopenage/curve/tests/curve_types.cpp | 81 ---------------------- 4 files changed, 139 insertions(+), 124 deletions(-) diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index 7076082459..34109365db 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -16,10 +16,10 @@ template class Array : event::EventEntity { public: Array(const std::shared_ptr &loop, - size_t id, - const std::string &idstr = "", - const EventEntity::single_change_notifier ¬ifier = nullptr) : - EventEntity(loop, notifier), _id{id}, _idstr{idstr}, loop{loop}{} + size_t id, + const std::string &idstr = "", + const EventEntity::single_change_notifier ¬ifier = nullptr) : + EventEntity(loop, notifier), _id{id}, _idstr{idstr}, loop{loop} {} Array(const Array &) = delete; @@ -28,16 +28,16 @@ class Array : event::EventEntity { * Get the last element with elem->time <= time from * the keyfram container at a given index */ - T get(const time::time_t &t, const size_t index) const; + T at(const time::time_t &t, const size_t index) const; /** * Get an array of the last elements with elem->time <= time from * all keyfram containers contained within this array curve */ - std::array get_all(const time::time_t &t) const; - + std::array get(const time::time_t &t) const; + // Get the amount of KeyframeContainers in array curve consteval size_t size() const; /** @@ -107,92 +107,107 @@ class Array : event::EventEntity { } - KeyframeContainer& operator[] (size_t index) - { - return this->container[index]; - } - - KeyframeContainer operator[] (size_t index) const - { - return this->container[index]; + // get a copy to the KeyframeContainer at index + KeyframeContainer operator[](size_t index) const { + return this->container.at(index); } + // Array::Iterator is used to iterate over KeyframeContainers contained in a curve at a given time. class Iterator { public: Iterator(Array *curve, const time::time_t &time = time::TIME_MAX, size_t offset = 0) : curve(curve), time(time), offset(offset) {}; + // returns a copy of the keyframe at the current offset and time const T operator*() { - return curve->frame(this->time, this->offset).second; + return this->curve->frame(this->time, this->offset).second; } + // increments the Iterator to point at the next KeyframeContainer void operator++() { this->offset++; } + // Compare two Iterators by their offset bool operator!=(const Array::Iterator &rhs) const { return this->offset != rhs.offset; } private: + // used to index the Curve::Array pointed to by this iterator size_t offset; + + // curve::Array that this iterator is iterating over Array *curve; + + // time at which this iterator is iterating over time::time_t time; }; - Iterator begin(const time::time_t &time = time::TIME_MAX); + // iterator pointing to a keyframe of the first KeyframeContainer in the curve at a given time + Iterator begin(const time::time_t &time = time::TIME_MIN); - Iterator end(const time::time_t &time = time::TIME_MAX); + // iterator pointing after the last KeyframeContainer in the curve at a given time + Iterator end(const time::time_t &time = time::TIME_MIN); private: std::array, Size> container; - //hint for KeyframeContainer operations + /** + * hints for KeyframeContainer operations, mutable as hints + * are updated by const read functions. + * This is used to speed up the search for next keyframe to be accessed + */ mutable std::array last_element = {}; /** - * Identifier for the container - */ + * Identifier for the container + */ const size_t _id; /** - * Human-readable identifier for the container - */ + * Human-readable identifier for the container + */ const std::string _idstr; /** - * The eventloop this curve was registered to - */ + * The eventloop this curve was registered to + */ const std::shared_ptr loop; }; template std::pair Array::frame(const time::time_t &t, const size_t index) const { - size_t frmae_index = container[index].last(t, this->last_element[index]); - this->last_element[index] = frmae_index; - return container[index].get(frmae_index).make_pair(); + size_t &hint = this->last_element[index]; + size_t frame_index = this->container.at(index).last(t, hint); + hint = frame_index; + return this->container.at(index).get(frame_index).make_pair(); } template std::pair Array::next_frame(const time::time_t &t, const size_t index) const { - size_t frmae_index = container[index].last(t, this->last_element[index]); - this->last_element[index] = frmae_index; - return container[index].get(frmae_index + 1).make_pair(); + size_t &hint = this->last_element[index]; + size_t frame_index = this->container.at(index).last(t, hint); + hint = frame_index; + return this->container.at(index).get(frame_index + 1).make_pair(); } template -T Array::get(const time::time_t &t, const size_t index) const { - return this->frame(t, index).second; +T Array::at(const time::time_t &t, const size_t index) const { + size_t &hint = this->last_element[index]; + size_t frame_index = this->container.at(index).last(t, hint); + hint = frame_index; + return this->container.at(index).get(frame_index).val(); } template -std::array Array::get_all(const time::time_t &t) const { +std::array Array::get(const time::time_t &t) const { return [&](std::index_sequence) { - return std::array{this->get(t, I)...}; + return std::array{this->at(t, I)...}; }(std::make_index_sequence{}); } @@ -204,22 +219,21 @@ consteval size_t Array::size() const { template void Array::set_insert(const time::time_t &t, const size_t index, T value) { - this->last_element[index] = this->container[index].insert_after(Keyframe(t, value), this->last_element[index]); + this->last_element[index] = this->container.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); } template void Array::set_last(const time::time_t &t, const size_t index, T value) { - - size_t frame_index = this->container[index].insert_after(Keyframe(t, value), this->last_element[index]); + size_t frame_index = this->container.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); this->last_element[index] = frame_index; - this->container[index].erase_after(frame_index); + this->container.at(index).erase_after(frame_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_element[index]); + this->container.at(index).insert_overwrite(Keyframe{t, value}, this->last_element[index]); } template diff --git a/libopenage/curve/base_curve.h b/libopenage/curve/base_curve.h index dc58885b98..3d2ff20343 100644 --- a/libopenage/curve/base_curve.h +++ b/libopenage/curve/base_curve.h @@ -245,7 +245,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 std::make_pair(elem.time(), elem.val()); + return elem.make_pair(); } @@ -254,7 +254,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 std::make_pair(elem.time(), elem.val()); + return elem.make_pair(); } template diff --git a/libopenage/curve/tests/container.cpp b/libopenage/curve/tests/container.cpp index 020e2aad99..51a5e4bee2 100644 --- a/libopenage/curve/tests/container.cpp +++ b/libopenage/curve/tests/container.cpp @@ -9,6 +9,7 @@ #include #include +#include "curve/array.h" #include "curve/iterator.h" #include "curve/map.h" #include "curve/map_filter_iterator.h" @@ -56,7 +57,7 @@ void test_map() { // Basic tests test lookup in the middle of the range. { - auto t = map.at(2, 0); //At timestamp 2 element 0 + auto t = map.at(2, 0); // At timestamp 2 element 0 TESTEQUALS(t.has_value(), true); TESTEQUALS(t.value().value(), 0); t = map.at(20, 5); @@ -242,11 +243,92 @@ void test_queue() { TESTEQUALS(q.empty(100001), false); } +void test_array() { + auto f = std::make_shared(); + + Array a(f, 0); + a.set_insert(1, 0, 0); + a.set_insert(1, 1, 1); + a.set_insert(1, 2, 2); + a.set_insert(1, 3, 3); + // a = [[0:0, 1:0],[0:0, 1:1],[0:0, 1:2],[0:0, 1:3]] + + auto res = a.get(1); + TESTEQUALS(res.at(0), 0); + TESTEQUALS(res.at(1), 1); + TESTEQUALS(res.at(2), 2); + TESTEQUALS(res.at(3), 3); + + Array other(f, 0); + other.set_last(0, 0, 999); + other.set_last(0, 1, 999); + other.set_last(0, 2, 999); + other.set_last(0, 3, 999); + + other.set_insert(1, 0, 4); + other.set_insert(1, 1, 5); + other.set_insert(1, 2, 6); + other.set_insert(1, 3, 7); + // other = [[0:999, 1:4],[0:999, 1:5],[0:999, 1:6],[0:999, 1:7]] + + + a.sync(other, 1); + // a = [[0:0, 1:4],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] + + res = a.get(0); + TESTEQUALS(res.at(0), 0); + TESTEQUALS(res.at(1), 0); + TESTEQUALS(res.at(2), 0); + TESTEQUALS(res.at(3), 0); + res = a.get(1); + TESTEQUALS(res.at(0), 4); + TESTEQUALS(res.at(1), 5); + TESTEQUALS(res.at(2), 6); + TESTEQUALS(res.at(3), 7); + + // Additional tests + a.set_insert(2, 0, 15); + a.set_insert(2, 0, 20); + a.set_replace(2, 0, 25); + TESTEQUALS(a.at(2, 0), 25); + // a = [[0:0, 1:4, 2:25],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] + + a.set_insert(3, 0, 30); + a.set_insert(4, 0, 40); + a.set_last(3, 0, 35); + TESTEQUALS(a.at(4, 0), 35); + // a = [[0:0, 1:4, 2:25, 3:35],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] + + auto frame = a.frame(1, 2); + TESTEQUALS(frame.second, 6); + TESTEQUALS(frame.first, 1); + + a.set_insert(5, 3, 40); + auto next_frame = a.next_frame(1, 3); + TESTEQUALS(next_frame.second, 40); + TESTEQUALS(next_frame.first, 5); + + // Test operator[] + TESTEQUALS(a[0].get(a[0].last(2)).val(), 25); + TESTEQUALS(a[1].get(a[1].last(2)).val(), 5); + + // Test begin and end + auto it = a.begin(1); + TESTEQUALS(*it, 4); + ++it; + TESTEQUALS(*it, 5); + ++it; + TESTEQUALS(*it, 6); + ++it; + TESTEQUALS(*it, 7); +} + void container() { test_map(); test_list(); test_queue(); + test_array(); } diff --git a/libopenage/curve/tests/curve_types.cpp b/libopenage/curve/tests/curve_types.cpp index 6c754e5df9..935aa7141d 100644 --- a/libopenage/curve/tests/curve_types.cpp +++ b/libopenage/curve/tests/curve_types.cpp @@ -5,7 +5,6 @@ #include #include -#include "curve/array.h" #include "curve/continuous.h" #include "curve/discrete.h" #include "curve/discrete_mod.h" @@ -387,86 +386,6 @@ void curve_types() { TESTEQUALS(c.get(1), 0); TESTEQUALS(c.get(5), 0); } - - { // array - auto f = std::make_shared(); - - Array a(f,0); - a.set_insert(time::time_t(1), 0, 0); - a.set_insert(time::time_t(1), 1, 1); - a.set_insert(time::time_t(1), 2, 2); - a.set_insert(time::time_t(1), 3, 3); - //a = [[0:0, 1:0],[0:0, 1:1],[0:0, 1:2],[0:0, 1:3]] - - auto res = a.get_all(time::time_t(1)); - TESTEQUALS(res[0], 0); - TESTEQUALS(res[1], 1); - TESTEQUALS(res[2], 2); - TESTEQUALS(res[3], 3); - - Array other(f,0); - other[0].last(999); - other[1].last(999); - other[2].last(999); - other[3].last(999); - other.set_insert(time::time_t(1), 0, 4); - other.set_insert(time::time_t(1), 1, 5); - other.set_insert(time::time_t(1), 2, 6); - other.set_insert(time::time_t(1), 3, 7); - //other = [[0:999, 1:4],[0:999, 1:5],[0:999, 1:6],[0:999, 1:7]] - - - a.sync(other, time::time_t(1)); - //a = [[0:0, 1:4],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] - - res = a.get_all(time::time_t(0)); - TESTEQUALS(res[0], 0); - TESTEQUALS(res[1], 0); - TESTEQUALS(res[2], 0); - TESTEQUALS(res[3], 0); - res = a.get_all(time::time_t(1)); - TESTEQUALS(res[0], 4); - TESTEQUALS(res[1], 5); - TESTEQUALS(res[2], 6); - TESTEQUALS(res[3], 7); - - // Additional tests - a.set_insert(time::time_t(2), 0, 15); - a.set_insert(time::time_t(2), 0, 20); - a.set_replace(time::time_t(2), 0, 25); - TESTEQUALS(a.get(time::time_t(2), 0), 25); - // a = [[0:0, 1:4, 2:25],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] - - a.set_insert(time::time_t(3), 0, 30); - a.set_insert(time::time_t(4), 0, 40); - a.set_last(time::time_t(3), 0, 35); - TESTEQUALS(a.get(time::time_t(3), 0), 35); - // a = [[0:0, 1:4, 2:25, 3:35],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] - - auto frame = a.frame(time::time_t(1), 2); - TESTEQUALS(frame.second, 6); - TESTEQUALS(frame.first, time::time_t(1)); - - a.set_insert(time::time_t(5), 3, 40); - auto next_frame = a.next_frame(time::time_t(1), 3); - TESTEQUALS(next_frame.second, 40); - TESTEQUALS(next_frame.first, time::time_t(5)); - - // Test operator[] - TESTEQUALS(a[0].get(a[0].last(time::time_t(2))).val(), 25); - TESTEQUALS(a[1].get(a[1].last(time::time_t(2))).val(), 5); - - // Test begin and end - auto it = a.begin(time::time_t(1)); - TESTEQUALS(*it, 4); - ++it; - TESTEQUALS(*it, 5); - ++it; - TESTEQUALS(*it, 6); - ++it; - TESTEQUALS(*it, 7); - ++it; - } } } // namespace openage::curve::tests From 5f5c0f4b4d9011f9f4d8bc0ff8c937a5aa3d4be1 Mon Sep 17 00:00:00 2001 From: Jeremiah Morgan Date: Fri, 27 Dec 2024 11:12:18 +0000 Subject: [PATCH 03/13] libopenage/curve/base_curve.h --- libopenage/curve/base_curve.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libopenage/curve/base_curve.h b/libopenage/curve/base_curve.h index 3d2ff20343..e5e265b5a0 100644 --- a/libopenage/curve/base_curve.h +++ b/libopenage/curve/base_curve.h @@ -47,6 +47,7 @@ class BaseCurve : public event::EventEntity { // registration. If you need to copy a curve, use the sync() method. // TODO: if copying is enabled again, these members have to be reassigned: _id, _idstr, last_element BaseCurve(const BaseCurve &) = delete; + BaseCurve &operator=(const BaseCurve &) = delete; BaseCurve(BaseCurve &&) = default; From a5600f44d2f5450c636b3352a978c7f4b7b1f11f Mon Sep 17 00:00:00 2001 From: Jeremiah Morgan Date: Wed, 8 Jan 2025 23:55:27 +0000 Subject: [PATCH 04/13] address new comments --- libopenage/curve/array.h | 74 ++++++++++++++++++++-------- libopenage/curve/tests/container.cpp | 5 +- 2 files changed, 54 insertions(+), 25 deletions(-) diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index 34109365db..fb5be284cd 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -1,25 +1,34 @@ -// Copyright 2024-2024 the openage authors. See copying.md for legal info. +// Copyright 2024-2025 the openage authors. See copying.md for legal info. #pragma once #include +#include "curve/iterator.h" #include "curve/keyframe_container.h" #include "event/evententity.h" -// remember to update docs +// ASDF: remember to update docs namespace openage { namespace curve { template class Array : event::EventEntity { public: + /** + * The underlaying container type. + */ + using container_t = std::array, Size>; + Array(const std::shared_ptr &loop, size_t id, + const T &default_val = T(), const std::string &idstr = "", const EventEntity::single_change_notifier ¬ifier = nullptr) : - EventEntity(loop, notifier), _id{id}, _idstr{idstr}, loop{loop} {} + EventEntity(loop, notifier), + _id{id}, _idstr{idstr}, loop{loop}, container{KeyframeContainer(default_val)} { + } Array(const Array &) = delete; @@ -37,7 +46,9 @@ class Array : event::EventEntity { */ std::array get(const time::time_t &t) const; - // Get the amount of KeyframeContainers in array curve + /** + * Get the amount of KeyframeContainers in array curve + */ consteval size_t size() const; /** @@ -107,59 +118,80 @@ class Array : event::EventEntity { } - // get a copy to the KeyframeContainer at index - KeyframeContainer operator[](size_t index) const { - return this->container.at(index); - } - - // Array::Iterator is used to iterate over KeyframeContainers contained in a curve at a given time. + /** + * Array::Iterator is used to iterate over KeyframeContainers contained in a curve at a given time. + */ class Iterator { public: Iterator(Array *curve, const time::time_t &time = time::TIME_MAX, size_t offset = 0) : curve(curve), time(time), offset(offset) {}; - // returns a copy of the keyframe at the current offset and time + /** + * returns a copy of the keyframe at the current offset and time + */ const T operator*() { return this->curve->frame(this->time, this->offset).second; } - // increments the Iterator to point at the next KeyframeContainer + /** + * increments the Iterator to point at the next KeyframeContainer + */ void operator++() { this->offset++; } - // Compare two Iterators by their offset + /** + * Compare two Iterators by their offset + */ bool operator!=(const Array::Iterator &rhs) const { return this->offset != rhs.offset; } private: - // used to index the Curve::Array pointed to by this iterator + /** + * used to index the Curve::Array pointed to by this iterator + */ size_t offset; - // curve::Array that this iterator is iterating over + /** + * the curve object that this iterator, iterates over + */ Array *curve; - // time at which this iterator is iterating over + /** + * time at which this iterator is iterating over + */ time::time_t time; }; - // iterator pointing to a keyframe of the first KeyframeContainer in the curve at a given time + /** + * iterator pointing to a keyframe of the first KeyframeContainer in the curve at a given time + */ Iterator begin(const time::time_t &time = time::TIME_MIN); - // iterator pointing after the last KeyframeContainer in the curve at a given time + /** + * iterator pointing after the last KeyframeContainer in the curve at a given time + */ Iterator end(const time::time_t &time = time::TIME_MIN); private: + /** + * get a copy to the KeyframeContainer at index + */ + KeyframeContainer operator[](size_t index) const { + return this->container.at(index); + } + + std::array, Size> container; /** - * hints for KeyframeContainer operations, mutable as hints - * are updated by const read functions. - * This is used to speed up the search for next keyframe to be accessed + * hints for KeyframeContainer operations + * hints is used to speed up the search for next keyframe to be accessed + * mutable as hints are updated by const read-only functions. */ mutable std::array last_element = {}; diff --git a/libopenage/curve/tests/container.cpp b/libopenage/curve/tests/container.cpp index 51a5e4bee2..8aed3c8d05 100644 --- a/libopenage/curve/tests/container.cpp +++ b/libopenage/curve/tests/container.cpp @@ -247,6 +247,7 @@ void test_array() { auto f = std::make_shared(); Array a(f, 0); + const std::array &default_val = std::array(); a.set_insert(1, 0, 0); a.set_insert(1, 1, 1); a.set_insert(1, 2, 2); @@ -308,10 +309,6 @@ void test_array() { TESTEQUALS(next_frame.second, 40); TESTEQUALS(next_frame.first, 5); - // Test operator[] - TESTEQUALS(a[0].get(a[0].last(2)).val(), 25); - TESTEQUALS(a[1].get(a[1].last(2)).val(), 5); - // Test begin and end auto it = a.begin(1); TESTEQUALS(*it, 4); From 2f3573236af59c0a5ada1226860bb31c6e84d5ae Mon Sep 17 00:00:00 2001 From: Jeremiah Morgan Date: Thu, 9 Jan 2025 16:04:55 +0000 Subject: [PATCH 05/13] update curves.md --- doc/code/curves.md | 35 ++++++++++++++++++++++++++++++++++- libopenage/curve/array.h | 1 - 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/doc/code/curves.md b/doc/code/curves.md index ff4bbb248d..372a4b0153 100644 --- a/doc/code/curves.md +++ b/doc/code/curves.md @@ -198,7 +198,7 @@ e.g. angles between 0 and 360 degrees. ### Container Container curves are intended for storing changes to collections and containers. -The currently supported containers are `Queue` and `UnorderedMap`. +The currently supported containers are `Queue`, `UnorderedMap` and `Array`. The most important distinction between regular C++ containers and curve containers is that curve containers track the *lifespan* of each element, i.e. their insertion time, @@ -253,3 +253,36 @@ Unordered map curve containers store key-value pairs while additionally keeping track of element insertion time. Requests for a key `k` at time `t` will return the value of `k` at that time. The unordered map can also be iterated over for a specific time `t` which allows access to all key-value pairs that were in the map at time `t`. + + +#### Array +Array curve containers are the equivalent to the `std::array` C++ containers. Unlike other curve containers, +each element of the underlying std::array is a `keyframecontainer` and when a value is added to the `Array curve` +at a given index they are added to the respective `keyframecontainer` at that index as a keyframe. + +**Read** + +Read operations retrieve values for a specific point in time. + +| Method | Description | +| ----------------- | --------------------------------------- ---------------------------------| +| `get(t, i)` | Get value of index `i` at time <= `t` | +| `get(t)` | Get array of keyframes at time <= `t` | +| `size()` | Get size of the array | +| `frame(t, i)` | Get the time and value of the keyframe at index `i` with time <= `t` | +| `next_frame(t, i)`| Get the time and value of the first keyframe at index `i` with time > `t`| + +**Modify** + +Modify operations insert values for a specific point in time. + +| Method | Description | +| ------------------------- | ------------------------------------------------------------------------------------------| +| `set_insert(t, i, value)` | Insert a new keyframe(`t`, `value`) at index `i` | +| `set_last(t, i, value)` | Insert a new keyframe(`t`, `value`) at index `i`; delete all keyframes after time `t` | +| `set_replace(t, i, value)`| Insert a new keyframe(`t`, `value`) at index `i`; remove all other keyframes with time `t`| + +**Copy** +| Method | Description | +| ---------------- | ------------------------------------------------------------------------------------------------ | +| `sync(Curve, t)` | Replace all keyframes from self after time `t` with keyframes from source `Curve` after time `t` | diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index fb5be284cd..8b8ca00e77 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -9,7 +9,6 @@ #include "event/evententity.h" -// ASDF: remember to update docs namespace openage { namespace curve { From bb9b9673c74c467b6a5cd8a66bdd53b04c961a0c Mon Sep 17 00:00:00 2001 From: heinezen Date: Thu, 16 Jan 2025 03:48:16 +0100 Subject: [PATCH 06/13] curve: Add more docstrings to array container. --- libopenage/curve/array.h | 176 ++++++++++++++++++++++++++------------- 1 file changed, 117 insertions(+), 59 deletions(-) diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index 8b8ca00e77..4e39ff28ab 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -20,68 +20,111 @@ class Array : event::EventEntity { */ using container_t = std::array, Size>; + /** + * Create a new array curve container. + * + * @param loop Event loop this curve is registered on for notifications. + * @param id Unique identifier for this curve. + * @param idstr Human-readable identifier for this curve. + * @param notifier Function to call when this curve changes. + * @param default_val Default value for all elements in the array. + */ Array(const std::shared_ptr &loop, size_t id, - const T &default_val = T(), const std::string &idstr = "", - const EventEntity::single_change_notifier ¬ifier = nullptr) : + const EventEntity::single_change_notifier ¬ifier = nullptr, + const T &default_val = T()) : EventEntity(loop, notifier), - _id{id}, _idstr{idstr}, loop{loop}, container{KeyframeContainer(default_val)} { - } - + containers{KeyframeContainer(default_val)}, + _id{id}, + _idstr{idstr}, + loop{loop}, + last_element{} {} + + // prevent copying because it invalidates the usage of unique ids and event + // registration. If you need to copy a curve, use the sync() method. Array(const Array &) = delete; + Array &operator=(const Array &) = delete; + Array(Array &&) = default; /** - * Get the last element with elem->time <= time from - * the keyfram container at a given index + * Get the last element with elem->time <= time. + * + * @param t Time of access. + * @param index Index of the array element. + * + * @return Value of the last element with time <= t. */ T at(const time::time_t &t, const size_t index) const; - /** - * Get an array of the last elements with elem->time <= time from - * all keyfram containers contained within this array curve + * Get all elements at time t. + * + * @param t Time of access. + * + * @return Array of values at time t. */ std::array get(const time::time_t &t) const; /** - * Get the amount of KeyframeContainers in array curve + * Get the size of the array. + * + * @return Array size. */ consteval size_t size() const; /** - * Get the last element and associated time which has elem->time <= time from - * the keyfram container at a given index + * Get the last keyframe value and time with elem->time <= time. + * + * @param t Time of access. + * @param index Index of the array element. + * + * @return Time-value pair of the last keyframe with time <= t. */ std::pair frame(const time::time_t &t, const size_t index) const; - /** - * Get the first element and associated time which has elem->time >= time from - * the keyfram container at a given index + * Get the first keyframe value and time with elem->time > time. + * + * If there is no keyframe with time > t, the behavior is undefined. + * + * @param t Time of access. + * @param index Index of the array element. + * + * @return Time-value pair of the first keyframe with time > t. */ std::pair next_frame(const time::time_t &t, const size_t index) const; - /** - * Insert a new keyframe value at time t at index + * Insert a new keyframe value at time t. + * + * If there is already a keyframe at time t, the new keyframe is inserted after the existing one. + * + * @param t Time of insertion. + * @param index Index of the array element. + * @param value Keyframe value. */ void set_insert(const time::time_t &t, const size_t index, T value); - /** - * Insert a new keyframe value at time t; delete all keyframes after time t at index + * Insert a new keyframe value at time t. Erase all other keyframes with elem->time > t. + * + * @param t Time of insertion. + * @param index Index of the array element. + * @param value Keyframe value. */ void set_last(const time::time_t &t, const size_t index, T value); - /** - * Insert a new keyframe value at time t at index i; remove all other keyframes with time t at index i + * Replace all keyframes at elem->time == t with a new keyframe value. + * + * @param t Time of insertion. + * @param index Index of the array element. + * @param value Keyframe value. */ void set_replace(const time::time_t &t, const size_t index, T value); - /** * Copy keyframes from another container to this container. * @@ -94,7 +137,6 @@ class Array : event::EventEntity { */ void sync(const Array &other, const time::time_t &start); - /** * Get the identifier of this curve. * @@ -116,7 +158,6 @@ class Array : event::EventEntity { return this->_idstr; } - /** * Array::Iterator is used to iterate over KeyframeContainers contained in a curve at a given time. */ @@ -146,7 +187,6 @@ class Array : event::EventEntity { return this->offset != rhs.offset; } - private: /** * used to index the Curve::Array pointed to by this iterator @@ -164,7 +204,6 @@ class Array : event::EventEntity { time::time_t time; }; - /** * iterator pointing to a keyframe of the first KeyframeContainer in the curve at a given time */ @@ -175,24 +214,20 @@ class Array : event::EventEntity { */ Iterator end(const time::time_t &time = time::TIME_MIN); - private: /** * get a copy to the KeyframeContainer at index */ KeyframeContainer operator[](size_t index) const { - return this->container.at(index); + return this->containers.at(index); } - - std::array, Size> container; - /** - * hints for KeyframeContainer operations - * hints is used to speed up the search for next keyframe to be accessed - * mutable as hints are updated by const read-only functions. + * Containers for each array element. + * + * Each element is managed by a KeyframeContainer. */ - mutable std::array last_element = {}; + std::array, Size> containers; /** * Identifier for the container @@ -208,31 +243,43 @@ class Array : event::EventEntity { * The eventloop this curve was registered to */ const std::shared_ptr loop; + + /** + * Cache hints for containers. Stores the index of the last keyframe accessed in each container. + * + * hints is used to speed up the search for keyframes. + * + * mutable as hints are updated by const read-only functions. + */ + mutable std::array::elem_ptr, Size> last_element = {}; }; template -std::pair Array::frame(const time::time_t &t, const size_t index) const { +std::pair Array::frame(const time::time_t &t, + const size_t index) const { size_t &hint = this->last_element[index]; - size_t frame_index = this->container.at(index).last(t, hint); + size_t frame_index = this->containers.at(index).last(t, hint); hint = frame_index; - return this->container.at(index).get(frame_index).make_pair(); + return this->containers.at(index).get(frame_index).make_pair(); } template -std::pair Array::next_frame(const time::time_t &t, const size_t index) const { +std::pair Array::next_frame(const time::time_t &t, + const size_t index) const { size_t &hint = this->last_element[index]; - size_t frame_index = this->container.at(index).last(t, hint); + size_t frame_index = this->containers.at(index).last(t, hint); hint = frame_index; - return this->container.at(index).get(frame_index + 1).make_pair(); + return this->containers.at(index).get(frame_index + 1).make_pair(); } template -T Array::at(const time::time_t &t, const size_t index) const { +T Array::at(const time::time_t &t, + const size_t index) const { size_t &hint = this->last_element[index]; - size_t frame_index = this->container.at(index).last(t, hint); + size_t frame_index = this->containers.at(index).last(t, hint); hint = frame_index; - return this->container.at(index).get(frame_index).val(); + return this->containers.at(index).get(frame_index).val(); } template @@ -247,31 +294,43 @@ 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[index] = this->container.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); -} +void Array::set_insert(const time::time_t &t, + const size_t index, + T value) { + this->last_element[index] = this->containers.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); + // ASDF: Change notification +} template -void Array::set_last(const time::time_t &t, const size_t index, T value) { - size_t frame_index = this->container.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); +void Array::set_last(const time::time_t &t, + const size_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->container.at(index).erase_after(frame_index); -} + this->containers.at(index).erase_after(frame_index); + // ASDF: Change notification +} template -void Array::set_replace(const time::time_t &t, const size_t index, T value) { - this->container.at(index).insert_overwrite(Keyframe{t, value}, this->last_element[index]); +void Array::set_replace(const time::time_t &t, + const size_t index, + T value) { + this->containers.at(index).insert_overwrite(Keyframe{t, value}, this->last_element[index]); + + // ASDF: Change notification } template -void Array::sync(const Array &other, const time::time_t &start) { +void Array::sync(const Array &other, + const time::time_t &start) { for (int i = 0; i < Size; i++) { - this->container[i].sync(other.container[i], start); + this->containers[i].sync(other.containers[i], start); } + + // ASDF: Change notification } template @@ -279,10 +338,9 @@ 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()); + return Array::Iterator(this, time, this->containers.size()); } } // namespace curve From e36e94fc47242be79cf821042c91c529df6531e1 Mon Sep 17 00:00:00 2001 From: heinezen Date: Thu, 16 Jan 2025 03:49:13 +0100 Subject: [PATCH 07/13] curve: Add event notification function call to modify operations. --- libopenage/curve/array.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index 4e39ff28ab..2bcf52522d 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -300,7 +300,7 @@ void Array::set_insert(const time::time_t &t, T value) { this->last_element[index] = this->containers.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); - // ASDF: Change notification + this->changes(t); } template @@ -311,7 +311,7 @@ void Array::set_last(const time::time_t &t, this->last_element[index] = frame_index; this->containers.at(index).erase_after(frame_index); - // ASDF: Change notification + this->changes(t); } template @@ -320,7 +320,7 @@ void Array::set_replace(const time::time_t &t, T value) { this->containers.at(index).insert_overwrite(Keyframe{t, value}, this->last_element[index]); - // ASDF: Change notification + this->changes(t); } template @@ -330,7 +330,7 @@ void Array::sync(const Array &other, this->containers[i].sync(other.containers[i], start); } - // ASDF: Change notification + this->changes(start); } template From 4b12a991fdbc1db7d39d18922e5408ce266b71bc Mon Sep 17 00:00:00 2001 From: heinezen Date: Thu, 16 Jan 2025 04:28:09 +0100 Subject: [PATCH 08/13] curve: Allow array default values to be different for each element. --- libopenage/curve/array.h | 49 ++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index 2bcf52522d..857638f5e0 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -12,13 +12,22 @@ namespace openage { namespace curve { +template +constexpr std::array, Size> init_default_vals(const std::array &default_vals) { + std::array, Size> containers; + for (size_t i = 0; i < Size; i++) { + containers[i] = KeyframeContainer(default_vals[i]); + } + return containers; +} + template class Array : event::EventEntity { public: - /** - * The underlaying container type. - */ + /// Underlying container type. using container_t = std::array, Size>; + /// Index type to access elements in the container. + using index_t = typename container_t::size_type; /** * Create a new array curve container. @@ -27,15 +36,15 @@ class Array : event::EventEntity { * @param id Unique identifier for this curve. * @param idstr Human-readable identifier for this curve. * @param notifier Function to call when this curve changes. - * @param default_val Default value for all elements in the array. + * @param default_vals Default values for the array elements. */ Array(const std::shared_ptr &loop, size_t id, const std::string &idstr = "", const EventEntity::single_change_notifier ¬ifier = nullptr, - const T &default_val = T()) : + const std::array &default_vals = {}) : EventEntity(loop, notifier), - containers{KeyframeContainer(default_val)}, + containers{init_default_vals(default_vals)}, _id{id}, _idstr{idstr}, loop{loop}, @@ -56,7 +65,7 @@ class Array : event::EventEntity { * * @return Value of the last element with time <= t. */ - T at(const time::time_t &t, const size_t index) const; + T at(const time::time_t &t, const index_t index) const; /** * Get all elements at time t. @@ -82,7 +91,7 @@ class Array : event::EventEntity { * * @return Time-value pair of the last keyframe with time <= t. */ - std::pair frame(const time::time_t &t, const size_t index) const; + std::pair frame(const time::time_t &t, const index_t index) const; /** * Get the first keyframe value and time with elem->time > time. @@ -94,7 +103,7 @@ class Array : event::EventEntity { * * @return Time-value pair of the first keyframe with time > t. */ - std::pair next_frame(const time::time_t &t, const size_t index) const; + std::pair next_frame(const time::time_t &t, const index_t index) const; /** * Insert a new keyframe value at time t. @@ -105,7 +114,7 @@ class Array : event::EventEntity { * @param index Index of the array element. * @param value Keyframe value. */ - void set_insert(const time::time_t &t, const size_t index, T value); + void set_insert(const time::time_t &t, const index_t index, T value); /** * Insert a new keyframe value at time t. Erase all other keyframes with elem->time > t. @@ -114,7 +123,7 @@ class Array : event::EventEntity { * @param index Index of the array element. * @param value Keyframe value. */ - void set_last(const time::time_t &t, const size_t index, T value); + void set_last(const time::time_t &t, const index_t index, T value); /** * Replace all keyframes at elem->time == t with a new keyframe value. @@ -123,7 +132,7 @@ class Array : event::EventEntity { * @param index Index of the array element. * @param value Keyframe value. */ - void set_replace(const time::time_t &t, const size_t index, T value); + void set_replace(const time::time_t &t, const index_t index, T value); /** * Copy keyframes from another container to this container. @@ -218,7 +227,7 @@ class Array : event::EventEntity { /** * get a copy to the KeyframeContainer at index */ - KeyframeContainer operator[](size_t index) const { + KeyframeContainer operator[](index_t index) const { return this->containers.at(index); } @@ -227,7 +236,7 @@ class Array : event::EventEntity { * * Each element is managed by a KeyframeContainer. */ - std::array, Size> containers; + container_t containers; /** * Identifier for the container @@ -257,7 +266,7 @@ class Array : event::EventEntity { template std::pair Array::frame(const time::time_t &t, - const size_t index) const { + 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; @@ -266,7 +275,7 @@ std::pair Array::frame(const time::time_t &t, template std::pair Array::next_frame(const time::time_t &t, - const size_t index) const { + 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; @@ -275,7 +284,7 @@ std::pair Array::next_frame(const time::time_t &t, template T Array::at(const time::time_t &t, - const size_t index) const { + 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; @@ -296,7 +305,7 @@ consteval size_t Array::size() const { template void Array::set_insert(const time::time_t &t, - const size_t index, + const index_t index, T value) { this->last_element[index] = this->containers.at(index).insert_after(Keyframe{t, value}, this->last_element[index]); @@ -305,7 +314,7 @@ void Array::set_insert(const time::time_t &t, template void Array::set_last(const time::time_t &t, - const size_t index, + 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; @@ -316,7 +325,7 @@ void Array::set_last(const time::time_t &t, template void Array::set_replace(const time::time_t &t, - const size_t index, + const index_t index, T value) { this->containers.at(index).insert_overwrite(Keyframe{t, value}, this->last_element[index]); From e8c124294386b836c36e81727996bb871fc50f59 Mon Sep 17 00:00:00 2001 From: heinezen Date: Thu, 16 Jan 2025 04:31:39 +0100 Subject: [PATCH 09/13] curve: Fix gcc compiler warnings. --- libopenage/curve/array.h | 12 ++++++------ libopenage/curve/tests/container.cpp | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index 857638f5e0..ea1cb71724 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/array.h @@ -197,11 +197,6 @@ class Array : event::EventEntity { } private: - /** - * used to index the Curve::Array pointed to by this iterator - */ - size_t offset; - /** * the curve object that this iterator, iterates over */ @@ -211,6 +206,11 @@ class Array : event::EventEntity { * time at which this iterator is iterating over */ time::time_t time; + + /** + * used to index the Curve::Array pointed to by this iterator + */ + size_t offset; }; /** @@ -335,7 +335,7 @@ void Array::set_replace(const time::time_t &t, template void Array::sync(const Array &other, const time::time_t &start) { - for (int i = 0; i < Size; i++) { + for (index_t i = 0; i < Size; i++) { this->containers[i].sync(other.containers[i], start); } diff --git a/libopenage/curve/tests/container.cpp b/libopenage/curve/tests/container.cpp index 8aed3c8d05..48a3b19202 100644 --- a/libopenage/curve/tests/container.cpp +++ b/libopenage/curve/tests/container.cpp @@ -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. #include #include @@ -247,7 +247,7 @@ void test_array() { auto f = std::make_shared(); Array a(f, 0); - const std::array &default_val = std::array(); + // const std::array &default_val = std::array(); a.set_insert(1, 0, 0); a.set_insert(1, 1, 1); a.set_insert(1, 2, 2); From 599f7bd8645b3ec1db64b7f06e467c7c3543b467 Mon Sep 17 00:00:00 2001 From: heinezen Date: Thu, 16 Jan 2025 04:52:33 +0100 Subject: [PATCH 10/13] curve: Fix elem_ptr caching for array. --- libopenage/curve/array.h | 77 ++++++++++++++++++++++++++--------- libopenage/curve/base_curve.h | 6 +-- libopenage/curve/discrete.h | 6 +-- libopenage/curve/keyframe.h | 12 +++--- 4 files changed, 70 insertions(+), 31 deletions(-) diff --git a/libopenage/curve/array.h b/libopenage/curve/array.h index ea1cb71724..9f9bacd09c 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]; - size_t frame_index = this->containers.at(index).last(t, hint); - hint = frame_index; - return this->containers.at(index).get(frame_index).make_pair(); + // find elem_ptr in container to get the last keyframe + auto hint = this->last_elements[index]; + auto frame_index = this->containers.at(index).last(t, hint); + + // 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]; - 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(); + // find elem_ptr in container to get the last keyframe with time <= t + auto hint = this->last_elements[index]; + auto frame_index = this->containers.at(index).last(t, hint); + + // 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]; + auto 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: From 156d009daa69df970e8aeaa36d5560a7b411a6aa Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 19 Jan 2025 15:49:28 +0100 Subject: [PATCH 11/13] curve: Add more comments to tests and check additional methods. --- libopenage/curve/tests/container.cpp | 56 ++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 15 deletions(-) diff --git a/libopenage/curve/tests/container.cpp b/libopenage/curve/tests/container.cpp index 48a3b19202..92b885320d 100644 --- a/libopenage/curve/tests/container.cpp +++ b/libopenage/curve/tests/container.cpp @@ -244,35 +244,58 @@ void test_queue() { } void test_array() { - auto f = std::make_shared(); + auto loop = std::make_shared(); - Array a(f, 0); - // const std::array &default_val = std::array(); + Array a(loop, 0); a.set_insert(1, 0, 0); a.set_insert(1, 1, 1); a.set_insert(1, 2, 2); a.set_insert(1, 3, 3); // a = [[0:0, 1:0],[0:0, 1:1],[0:0, 1:2],[0:0, 1:3]] + // test size + TESTEQUALS(a.size(), 4); + + // extracting array at time t == 1 auto res = a.get(1); + auto expected = std::array{0, 1, 2, 3}; + TESTEQUALS(res.at(0), expected.at(0)); + TESTEQUALS(res.at(1), expected.at(1)); + TESTEQUALS(res.at(2), expected.at(2)); + TESTEQUALS(res.at(3), expected.at(3)); + TESTEQUALS(res.size(), expected.size()); + + // extracting array at time t == 0 + // array should have default values (== 0) for all keyframes + res = a.get(0); TESTEQUALS(res.at(0), 0); - TESTEQUALS(res.at(1), 1); - TESTEQUALS(res.at(2), 2); - TESTEQUALS(res.at(3), 3); + TESTEQUALS(res.at(1), 0); + TESTEQUALS(res.at(2), 0); + TESTEQUALS(res.at(3), 0); - Array other(f, 0); + Array other(loop, 0); other.set_last(0, 0, 999); other.set_last(0, 1, 999); other.set_last(0, 2, 999); other.set_last(0, 3, 999); + // inserting keyframes at time t == 1 other.set_insert(1, 0, 4); other.set_insert(1, 1, 5); other.set_insert(1, 2, 6); other.set_insert(1, 3, 7); // other = [[0:999, 1:4],[0:999, 1:5],[0:999, 1:6],[0:999, 1:7]] + TESTEQUALS(other.at(0, 0), 999); + TESTEQUALS(other.at(0, 1), 999); + TESTEQUALS(other.at(0, 2), 999); + TESTEQUALS(other.at(0, 3), 999); + TESTEQUALS(other.at(1, 0), 4); + TESTEQUALS(other.at(1, 1), 5); + TESTEQUALS(other.at(1, 2), 6); + TESTEQUALS(other.at(1, 3), 7); + // sync keyframes from other to a a.sync(other, 1); // a = [[0:0, 1:4],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] @@ -287,27 +310,30 @@ void test_array() { TESTEQUALS(res.at(2), 6); TESTEQUALS(res.at(3), 7); - // Additional tests + // replace keyframes at time t == 2 a.set_insert(2, 0, 15); a.set_insert(2, 0, 20); a.set_replace(2, 0, 25); TESTEQUALS(a.at(2, 0), 25); // a = [[0:0, 1:4, 2:25],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] - a.set_insert(3, 0, 30); - a.set_insert(4, 0, 40); - a.set_last(3, 0, 35); + // set last keyframe at time t == 3 + a.set_insert(3, 0, 30); // a = [[0:0, 1:4, 2:25, 3:30], ... + a.set_insert(4, 0, 40); // a = [[0:0, 1:4, 2:25, 3:30, 4:40], ... + a.set_last(3, 0, 35); // a = [[0:0, 1:4, 2:25, 3:35],... TESTEQUALS(a.at(4, 0), 35); // a = [[0:0, 1:4, 2:25, 3:35],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7]] + // test frame and next_frame auto frame = a.frame(1, 2); - TESTEQUALS(frame.second, 6); - TESTEQUALS(frame.first, 1); + TESTEQUALS(frame.first, 1); // time + TESTEQUALS(frame.second, 6); // value a.set_insert(5, 3, 40); + // a = [[0:0, 1:4, 2:25, 3:35],[0:0, 1:5],[0:0, 1:6],[0:0, 1:7, 5:40]] auto next_frame = a.next_frame(1, 3); - TESTEQUALS(next_frame.second, 40); - TESTEQUALS(next_frame.first, 5); + TESTEQUALS(next_frame.first, 5); // time + TESTEQUALS(next_frame.second, 40); // value // Test begin and end auto it = a.begin(1); From ad747a6bc0fb71689cc540a4e0fef978e2a053cb Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 19 Jan 2025 16:03:41 +0100 Subject: [PATCH 12/13] doc: Fix formatting of curve docs and reformulate array docs a bit. --- doc/code/curves.md | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/doc/code/curves.md b/doc/code/curves.md index 372a4b0153..e914f8bcfe 100644 --- a/doc/code/curves.md +++ b/doc/code/curves.md @@ -17,6 +17,7 @@ Curves are an integral part of openage's event-based game simulation. 2. [Container](#container) 1. [Queue](#queue) 2. [Unordered Map](#unordered-map) + 3. [Array](#array) ## Motivation @@ -256,33 +257,38 @@ allows access to all key-value pairs that were in the map at time `t`. #### Array -Array curve containers are the equivalent to the `std::array` C++ containers. Unlike other curve containers, -each element of the underlying std::array is a `keyframecontainer` and when a value is added to the `Array curve` -at a given index they are added to the respective `keyframecontainer` at that index as a keyframe. + +Array curve containers store a fixed number of `n` elements where `n` is determined at compile-time. +They are the curve equivalent to the `std::array` C++ containers. In comparison to `std::array` each +element in the array curve container is tracked individually over time. Hence, each index is associated +with its own `KeyframeContainer` whose keyframes can be updated independent from other indices. +When a value is added to the `Array` curve at a given index, a new keyframe is added to the respective +`KeyframeContainer` stored at that index. **Read** Read operations retrieve values for a specific point in time. -| Method | Description | -| ----------------- | --------------------------------------- ---------------------------------| -| `get(t, i)` | Get value of index `i` at time <= `t` | -| `get(t)` | Get array of keyframes at time <= `t` | -| `size()` | Get size of the array | -| `frame(t, i)` | Get the time and value of the keyframe at index `i` with time <= `t` | -| `next_frame(t, i)`| Get the time and value of the first keyframe at index `i` with time > `t`| +| Method | Description | +| ------------------ | ------------------------------------------------------------------------ | +| `get(t, i)` | Get value of element at index `i` at time <= `t` | +| `get(t)` | Get array of values at time <= `t` | +| `size()` | Get the number of elements in the array | +| `frame(t, i)` | Get the previous keyframe (time and value) at index `i` before or at `t` | +| `next_frame(t, i)` | Get the next keyframe (time and value) at index `i` after `t` | **Modify** Modify operations insert values for a specific point in time. -| Method | Description | -| ------------------------- | ------------------------------------------------------------------------------------------| -| `set_insert(t, i, value)` | Insert a new keyframe(`t`, `value`) at index `i` | -| `set_last(t, i, value)` | Insert a new keyframe(`t`, `value`) at index `i`; delete all keyframes after time `t` | -| `set_replace(t, i, value)`| Insert a new keyframe(`t`, `value`) at index `i`; remove all other keyframes with time `t`| +| Method | Description | +| -------------------------- | ------------------------------------------------------------------------------------------ | +| `set_insert(t, i, value)` | Insert a new keyframe(`t`, `value`) at index `i` | +| `set_last(t, i, value)` | Insert a new keyframe(`t`, `value`) at index `i`; delete all keyframes after time `t` | +| `set_replace(t, i, value)` | Insert a new keyframe(`t`, `value`) at index `i`; remove all other keyframes with time `t` | **Copy** + | Method | Description | -| ---------------- | ------------------------------------------------------------------------------------------------ | +| ---------------- | ------------------------------------------------------------------------------------------------ | | `sync(Curve, t)` | Replace all keyframes from self after time `t` with keyframes from source `Curve` after time `t` | From d571822ef9f341be22b7b3c93e5c599a7dbbb8ae Mon Sep 17 00:00:00 2001 From: heinezen Date: Sun, 19 Jan 2025 16:10:58 +0100 Subject: [PATCH 13/13] curve: Refactor and move curve containers to subfolder. --- libopenage/curve/CMakeLists.txt | 8 +------- libopenage/curve/container/CMakeLists.txt | 9 +++++++++ libopenage/curve/{ => container}/array.cpp | 2 +- libopenage/curve/{ => container}/array.h | 2 +- libopenage/curve/{ => container}/element_wrapper.cpp | 2 +- libopenage/curve/{ => container}/element_wrapper.h | 2 +- libopenage/curve/{ => container}/iterator.cpp | 2 +- libopenage/curve/{ => container}/iterator.h | 2 +- libopenage/curve/{ => container}/map.cpp | 2 +- libopenage/curve/{ => container}/map.h | 7 +++---- .../curve/{ => container}/map_filter_iterator.cpp | 2 +- .../curve/{ => container}/map_filter_iterator.h | 4 ++-- libopenage/curve/{ => container}/queue.cpp | 2 +- libopenage/curve/{ => container}/queue.h | 8 ++++---- .../curve/{ => container}/queue_filter_iterator.cpp | 2 +- .../curve/{ => container}/queue_filter_iterator.h | 4 ++-- libopenage/curve/tests/container.cpp | 12 ++++++------ libopenage/gamestate/component/api/live.cpp | 6 +++--- libopenage/gamestate/component/api/live.h | 4 ++-- .../gamestate/component/internal/command_queue.h | 4 ++-- libopenage/gamestate/entity_factory.cpp | 4 ++-- 21 files changed, 46 insertions(+), 44 deletions(-) create mode 100644 libopenage/curve/container/CMakeLists.txt rename libopenage/curve/{ => container}/array.cpp (65%) rename libopenage/curve/{ => container}/array.h (99%) rename libopenage/curve/{ => container}/element_wrapper.cpp (68%) rename libopenage/curve/{ => container}/element_wrapper.h (96%) rename libopenage/curve/{ => container}/iterator.cpp (67%) rename libopenage/curve/{ => container}/iterator.h (97%) rename libopenage/curve/{ => container}/map.cpp (66%) rename libopenage/curve/{ => container}/map.h (97%) rename libopenage/curve/{ => container}/map_filter_iterator.cpp (68%) rename libopenage/curve/{ => container}/map_filter_iterator.h (93%) rename libopenage/curve/{ => container}/queue.cpp (58%) rename libopenage/curve/{ => container}/queue.h (98%) rename libopenage/curve/{ => container}/queue_filter_iterator.cpp (69%) rename libopenage/curve/{ => container}/queue_filter_iterator.h (93%) diff --git a/libopenage/curve/CMakeLists.txt b/libopenage/curve/CMakeLists.txt index 174498e23b..eb52858f43 100644 --- a/libopenage/curve/CMakeLists.txt +++ b/libopenage/curve/CMakeLists.txt @@ -1,19 +1,13 @@ add_sources(libopenage - array.cpp base_curve.cpp continuous.cpp discrete.cpp discrete_mod.cpp - element_wrapper.cpp interpolated.cpp - iterator.cpp keyframe.cpp keyframe_container.cpp - map.cpp - map_filter_iterator.cpp - queue.cpp - queue_filter_iterator.cpp segmented.cpp ) +add_subdirectory("container") add_subdirectory("tests") diff --git a/libopenage/curve/container/CMakeLists.txt b/libopenage/curve/container/CMakeLists.txt new file mode 100644 index 0000000000..a187e01429 --- /dev/null +++ b/libopenage/curve/container/CMakeLists.txt @@ -0,0 +1,9 @@ +add_sources(libopenage + array.cpp + element_wrapper.cpp + iterator.cpp + map.cpp + map_filter_iterator.cpp + queue.cpp + queue_filter_iterator.cpp +) diff --git a/libopenage/curve/array.cpp b/libopenage/curve/container/array.cpp similarity index 65% rename from libopenage/curve/array.cpp rename to libopenage/curve/container/array.cpp index 97e07033ce..609ee117a3 100644 --- a/libopenage/curve/array.cpp +++ b/libopenage/curve/container/array.cpp @@ -1,4 +1,4 @@ -// Copyright 2024-2024 the openage authors. See copying.md for legal info. +// Copyright 2024-2025 the openage authors. See copying.md for legal info. #include "array.h" diff --git a/libopenage/curve/array.h b/libopenage/curve/container/array.h similarity index 99% rename from libopenage/curve/array.h rename to libopenage/curve/container/array.h index 9f9bacd09c..e980d77915 100644 --- a/libopenage/curve/array.h +++ b/libopenage/curve/container/array.h @@ -4,7 +4,7 @@ #include -#include "curve/iterator.h" +#include "curve/container/iterator.h" #include "curve/keyframe_container.h" #include "event/evententity.h" diff --git a/libopenage/curve/element_wrapper.cpp b/libopenage/curve/container/element_wrapper.cpp similarity index 68% rename from libopenage/curve/element_wrapper.cpp rename to libopenage/curve/container/element_wrapper.cpp index 5d2eaa08af..bdbca7346f 100644 --- a/libopenage/curve/element_wrapper.cpp +++ b/libopenage/curve/container/element_wrapper.cpp @@ -1,4 +1,4 @@ -// Copyright 2024-2024 the openage authors. See copying.md for legal info. +// Copyright 2024-2025 the openage authors. See copying.md for legal info. #include "element_wrapper.h" diff --git a/libopenage/curve/element_wrapper.h b/libopenage/curve/container/element_wrapper.h similarity index 96% rename from libopenage/curve/element_wrapper.h rename to libopenage/curve/container/element_wrapper.h index 764b61d5cd..0032e4c6fe 100644 --- a/libopenage/curve/element_wrapper.h +++ b/libopenage/curve/container/element_wrapper.h @@ -1,4 +1,4 @@ -// Copyright 2024-2024 the openage authors. See copying.md for legal info. +// Copyright 2024-2025 the openage authors. See copying.md for legal info. #pragma once diff --git a/libopenage/curve/iterator.cpp b/libopenage/curve/container/iterator.cpp similarity index 67% rename from libopenage/curve/iterator.cpp rename to libopenage/curve/container/iterator.cpp index b449d93812..594df3a5b8 100644 --- a/libopenage/curve/iterator.cpp +++ b/libopenage/curve/container/iterator.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #include "iterator.h" diff --git a/libopenage/curve/iterator.h b/libopenage/curve/container/iterator.h similarity index 97% rename from libopenage/curve/iterator.h rename to libopenage/curve/container/iterator.h index d0346e1b5d..7a4fb82d6b 100644 --- a/libopenage/curve/iterator.h +++ b/libopenage/curve/container/iterator.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 diff --git a/libopenage/curve/map.cpp b/libopenage/curve/container/map.cpp similarity index 66% rename from libopenage/curve/map.cpp rename to libopenage/curve/container/map.cpp index 82b26f9ecc..a2469bfa5f 100644 --- a/libopenage/curve/map.cpp +++ b/libopenage/curve/container/map.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #include "map.h" diff --git a/libopenage/curve/map.h b/libopenage/curve/container/map.h similarity index 97% rename from libopenage/curve/map.h rename to libopenage/curve/container/map.h index 5a5e0a4d9b..4997824a6d 100644 --- a/libopenage/curve/map.h +++ b/libopenage/curve/container/map.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 @@ -7,8 +7,8 @@ #include #include -#include "curve/map_filter_iterator.h" -#include "curve/element_wrapper.h" +#include "curve/container/element_wrapper.h" +#include "curve/container/map_filter_iterator.h" #include "time/time.h" #include "util/fixed_point.h" @@ -21,7 +21,6 @@ namespace openage::curve { */ template class UnorderedMap { - /** * Data holder. Maps keys to map elements. * Map elements themselves store when they are valid. diff --git a/libopenage/curve/map_filter_iterator.cpp b/libopenage/curve/container/map_filter_iterator.cpp similarity index 68% rename from libopenage/curve/map_filter_iterator.cpp rename to libopenage/curve/container/map_filter_iterator.cpp index da10b01774..bba3ffa478 100644 --- a/libopenage/curve/map_filter_iterator.cpp +++ b/libopenage/curve/container/map_filter_iterator.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #include "map_filter_iterator.h" diff --git a/libopenage/curve/map_filter_iterator.h b/libopenage/curve/container/map_filter_iterator.h similarity index 93% rename from libopenage/curve/map_filter_iterator.h rename to libopenage/curve/container/map_filter_iterator.h index 3aec2a899e..c9afceee88 100644 --- a/libopenage/curve/map_filter_iterator.h +++ b/libopenage/curve/container/map_filter_iterator.h @@ -1,8 +1,8 @@ -// 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 -#include "curve/iterator.h" +#include "curve/container/iterator.h" #include "time/time.h" diff --git a/libopenage/curve/queue.cpp b/libopenage/curve/container/queue.cpp similarity index 58% rename from libopenage/curve/queue.cpp rename to libopenage/curve/container/queue.cpp index d994b6c82e..842a140045 100644 --- a/libopenage/curve/queue.cpp +++ b/libopenage/curve/container/queue.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #include "queue.h" diff --git a/libopenage/curve/queue.h b/libopenage/curve/container/queue.h similarity index 98% rename from libopenage/curve/queue.h rename to libopenage/curve/container/queue.h index 9314dd3a0e..fb32a53cbb 100644 --- a/libopenage/curve/queue.h +++ b/libopenage/curve/container/queue.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 @@ -11,9 +11,9 @@ #include "error/error.h" -#include "curve/iterator.h" -#include "curve/queue_filter_iterator.h" -#include "curve/element_wrapper.h" +#include "curve/container/element_wrapper.h" +#include "curve/container/iterator.h" +#include "curve/container/queue_filter_iterator.h" #include "event/evententity.h" #include "time/time.h" #include "util/fixed_point.h" diff --git a/libopenage/curve/queue_filter_iterator.cpp b/libopenage/curve/container/queue_filter_iterator.cpp similarity index 69% rename from libopenage/curve/queue_filter_iterator.cpp rename to libopenage/curve/container/queue_filter_iterator.cpp index fa0b3ad15a..b4ceb2b7e6 100644 --- a/libopenage/curve/queue_filter_iterator.cpp +++ b/libopenage/curve/container/queue_filter_iterator.cpp @@ -1,4 +1,4 @@ -// Copyright 2017-2018 the openage authors. See copying.md for legal info. +// Copyright 2017-2025 the openage authors. See copying.md for legal info. #include "queue_filter_iterator.h" diff --git a/libopenage/curve/queue_filter_iterator.h b/libopenage/curve/container/queue_filter_iterator.h similarity index 93% rename from libopenage/curve/queue_filter_iterator.h rename to libopenage/curve/container/queue_filter_iterator.h index cf6bc5aa2c..6b2fa471f2 100644 --- a/libopenage/curve/queue_filter_iterator.h +++ b/libopenage/curve/container/queue_filter_iterator.h @@ -1,8 +1,8 @@ -// 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 -#include "curve/iterator.h" +#include "curve/container/iterator.h" #include "time/time.h" diff --git a/libopenage/curve/tests/container.cpp b/libopenage/curve/tests/container.cpp index 92b885320d..16da2476e9 100644 --- a/libopenage/curve/tests/container.cpp +++ b/libopenage/curve/tests/container.cpp @@ -9,12 +9,12 @@ #include #include -#include "curve/array.h" -#include "curve/iterator.h" -#include "curve/map.h" -#include "curve/map_filter_iterator.h" -#include "curve/queue.h" -#include "curve/queue_filter_iterator.h" +#include "curve/container/array.h" +#include "curve/container/iterator.h" +#include "curve/container/map.h" +#include "curve/container/map_filter_iterator.h" +#include "curve/container/queue.h" +#include "curve/container/queue_filter_iterator.h" #include "event/event_loop.h" #include "testing/testing.h" diff --git a/libopenage/gamestate/component/api/live.cpp b/libopenage/gamestate/component/api/live.cpp index 01fafde5ea..f7a1f17d98 100644 --- a/libopenage/gamestate/component/api/live.cpp +++ b/libopenage/gamestate/component/api/live.cpp @@ -1,12 +1,12 @@ -// Copyright 2021-2023 the openage authors. See copying.md for legal info. +// Copyright 2021-2025 the openage authors. See copying.md for legal info. #include "live.h" #include +#include "curve/container/iterator.h" +#include "curve/container/map_filter_iterator.h" #include "curve/discrete.h" -#include "curve/iterator.h" -#include "curve/map_filter_iterator.h" #include "gamestate/component/types.h" diff --git a/libopenage/gamestate/component/api/live.h b/libopenage/gamestate/component/api/live.h index 2e1f5e41d5..4916713cdc 100644 --- a/libopenage/gamestate/component/api/live.h +++ b/libopenage/gamestate/component/api/live.h @@ -1,4 +1,4 @@ -// Copyright 2021-2024 the openage authors. See copying.md for legal info. +// Copyright 2021-2025 the openage authors. See copying.md for legal info. #pragma once @@ -7,7 +7,7 @@ #include -#include "curve/map.h" +#include "curve/container/map.h" #include "gamestate/component/api_component.h" #include "gamestate/component/types.h" #include "time/time.h" diff --git a/libopenage/gamestate/component/internal/command_queue.h b/libopenage/gamestate/component/internal/command_queue.h index a7905c4d24..fb3179b470 100644 --- a/libopenage/gamestate/component/internal/command_queue.h +++ b/libopenage/gamestate/component/internal/command_queue.h @@ -1,10 +1,10 @@ -// Copyright 2021-2024 the openage authors. See copying.md for legal info. +// Copyright 2021-2025 the openage authors. See copying.md for legal info. #pragma once #include -#include "curve/queue.h" +#include "curve/container/queue.h" #include "gamestate/component/internal/commands/base_command.h" #include "gamestate/component/internal_component.h" #include "gamestate/component/types.h" diff --git a/libopenage/gamestate/entity_factory.cpp b/libopenage/gamestate/entity_factory.cpp index f2f489206c..6e1a4c825f 100644 --- a/libopenage/gamestate/entity_factory.cpp +++ b/libopenage/gamestate/entity_factory.cpp @@ -1,4 +1,4 @@ -// Copyright 2023-2023 the openage authors. See copying.md for legal info. +// Copyright 2023-2025 the openage authors. See copying.md for legal info. #include "entity_factory.h" @@ -10,8 +10,8 @@ #include "error/error.h" +#include "curve/container/queue.h" #include "curve/discrete.h" -#include "curve/queue.h" #include "event/event_loop.h" #include "gamestate/activity/activity.h" #include "gamestate/activity/condition/command_in_queue.h"