Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions libopenage/curve/base_curve.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include <cstddef>
#include <functional>
#include <iterator>
#include <memory>
#include <sstream>
#include <string>
Expand Down Expand Up @@ -40,7 +39,7 @@ class BaseCurve : public event::EventEntity {
_id{id},
_idstr{idstr},
loop{loop},
last_element{this->container.begin()} {}
last_element{this->container.size()} {}

virtual ~BaseCurve() = default;

Expand Down Expand Up @@ -193,9 +192,9 @@ class BaseCurve : public event::EventEntity {
const std::shared_ptr<event::EventLoop> loop;

/**
* Cache the iterator for quickly finding the last accessed element (usually the end)
* Cache the index of the last accessed element (usually the end).
*/
mutable typename KeyframeContainer<T>::iterator last_element;
mutable typename KeyframeContainer<T>::elem_ptr last_element;
};


Expand All @@ -204,7 +203,7 @@ void BaseCurve<T>::set_last(const time::time_t &at, const T &value) {
auto hint = this->container.last(at, this->last_element);

// erase max one same-time value
if (hint->time == at) {
if (this->container.get(hint).time() == at) {
hint--;
}

Expand All @@ -221,7 +220,7 @@ template <typename T>
void BaseCurve<T>::set_insert(const time::time_t &at, const T &value) {
auto hint = this->container.insert_after(at, value, this->last_element);
// check if this is now the final keyframe
if (hint->time > this->last_element->time) {
if (this->container.get(hint).time() > this->container.get(this->last_element).time()) {
this->last_element = hint;
}
this->changes(at);
Expand All @@ -244,24 +243,26 @@ void BaseCurve<T>::erase(const time::time_t &at) {

template <typename T>
std::pair<time::time_t, const T> BaseCurve<T>::frame(const time::time_t &time) const {
auto e = this->container.last(time, this->container.end());
return std::make_pair(e->time, e->value);
auto e = this->container.last(time, this->container.size());
auto elem = this->container.get(e);
return std::make_pair(elem.time(), elem.val());
}


template <typename T>
std::pair<time::time_t, const T> BaseCurve<T>::next_frame(const time::time_t &time) const {
auto e = this->container.last(time, this->container.end());
auto e = this->container.last(time, this->container.size());
e++;
return std::make_pair(e->time, e->value);
auto elem = this->container.get(e);
return std::make_pair(elem.time(), elem.val());
}

template <typename T>
std::string BaseCurve<T>::str() const {
std::stringstream ss;
ss << "Curve[" << this->idstr() << "]{" << std::endl;
for (const auto &keyframe : this->container) {
ss << " " << keyframe.time << ": " << keyframe.value << "," << std::endl;
ss << " " << keyframe.time() << ": " << keyframe.val() << "," << std::endl;
}
ss << "}";

Expand All @@ -272,10 +273,10 @@ template <typename T>
void BaseCurve<T>::check_integrity() const {
time::time_t last_time = time::TIME_MIN;
for (const auto &keyframe : this->container) {
if (keyframe.time < last_time) {
if (keyframe.time() < last_time) {
throw Error{MSG(err) << "curve is broken after t=" << last_time << ": " << this->str()};
}
last_time = keyframe.time;
last_time = keyframe.time();
}
}

Expand Down
4 changes: 2 additions & 2 deletions libopenage/curve/continuous.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2023 the openage authors. See copying.md for legal info.
// Copyright 2017-2024 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -48,7 +48,7 @@ void Continuous<T>::set_last(const time::time_t &at, const T &value) {
auto hint = this->container.last(at, this->last_element);

// erase all same-time entries
while (hint->time == at) {
while (this->container.get(hint).time() == at) {
hint--;
}

Expand Down
13 changes: 8 additions & 5 deletions libopenage/curve/discrete.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2023 the openage authors. See copying.md for legal info.
// Copyright 2017-2024 the openage authors. See copying.md for legal info.

#pragma once

Expand Down Expand Up @@ -55,7 +55,7 @@ template <typename T>
T Discrete<T>::get(const time::time_t &time) const {
auto e = this->container.last(time, this->last_element);
this->last_element = e; // TODO if Caching?
return e->value;
return this->container.get(e).val();
}


Expand All @@ -78,7 +78,9 @@ template <typename T>
std::pair<time::time_t, T> Discrete<T>::get_time(const time::time_t &time) const {
auto e = this->container.last(time, this->last_element);
this->last_element = e;
return std::make_pair(e->time, e->value);

auto elem = this->container.get(e);
return std::make_pair(elem.time, elem.value);
}


Expand All @@ -89,12 +91,13 @@ std::optional<std::pair<time::time_t, T>> Discrete<T>::get_previous(const time::

// if we're not at the container head
// go back one entry.
if (e == std::begin(this->container)) {
if (e == 0) {
return {};
}

e--;
return std::make_pair(e->time, e->value);
auto elem = this->container.get(e);
return std::make_pair(elem.time(), elem.val());
}

} // namespace openage::curve
2 changes: 1 addition & 1 deletion libopenage/curve/discrete_mod.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void DiscreteMod<T>::erase(const time::time_t &at) {
BaseCurve<T>::erase(at);

if (this->time_length == at) {
this->time_length = this->last_element->time;
this->time_length = this->container.get(this->container.size() - 1).time();
}
}

Expand Down
19 changes: 10 additions & 9 deletions libopenage/curve/interpolated.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,29 @@ class Interpolated : public BaseCurve<T> {

template <typename T>
T Interpolated<T>::get(const time::time_t &time) const {
const auto &e = this->container.last(time, this->last_element);
const auto e = this->container.last(time, this->last_element);
this->last_element = e;

auto nxt = e;
++nxt;

time::time_t interval = 0;

auto offset = time - e->time;
auto offset = time - this->container.get(e).time();

if (nxt != this->container.end()) {
interval = nxt->time - e->time;
if (nxt != this->container.size()) {
interval = this->container.get(nxt).time() - this->container.get(e).time();
}

// here, offset > interval will never hold.
// otherwise the underlying storage is broken.

// If the next element is at the same time, just return the value of this one.
if (nxt == this->container.end() // use the last curve value
|| offset == 0 // values equal -> don't need to interpolate
|| interval == 0) { // values at the same time -> division-by-zero-error
if (nxt == this->container.size() // use the last curve value
|| offset == 0 // values equal -> don't need to interpolate
|| interval == 0) { // values at the same time -> division-by-zero-error

return e->value;
return this->container.get(e).val();
}
else {
// Interpolation between time(now) and time(next) that has elapsed
Expand All @@ -72,7 +72,8 @@ T Interpolated<T>::get(const time::time_t &time) const {
// TODO: nxt->value - e->value will produce wrong results if
// the nxt->value < e->value and curve element type is unsigned
// Example: nxt = 2, e = 4; type = uint8_t ==> 2 - 4 = 254
return e->value + (nxt->value - e->value) * elapsed_frac;
auto diff_value = (this->container.get(nxt).val() - this->container.get(e).val()) * elapsed_frac;
return this->container.get(e).val() + diff_value;
}
}

Expand Down
37 changes: 33 additions & 4 deletions libopenage/curve/keyframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,46 @@ class Keyframe {
* New, default-constructed element at the given time
*/
Keyframe(const time::time_t &time) :
time{time} {}
timestamp{time} {}

/**
* New element fron time and value
*/
Keyframe(const time::time_t &time, const T &value) :
time{time},
value{value} {}
value{value},
timestamp{time} {}

const time::time_t time = time::TIME_MIN;
/**
* Get the time of this keyframe.
*
* @return Keyframe time.
*/
const time::time_t &time() const {
return this->timestamp;
}

/**
* Get the value of this keyframe.
*
* @return Keyframe value.
*/
const T &val() const {
return this->value;
}

public:
/**
* Value of the keyframe.
*
* Can be modified by the curve if necessary.
*/
T value = T{};

private:
/**
* Time of the keyframe.
*/
time::time_t timestamp = time::TIME_MIN;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not leave the time as a const member? then no function to access it is required.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is const then it is not copy assignable/constructible which becomes a problem for working with vector (or deque). I know I can write a new copy/assignment contructor but making them private looks more clean to me.

};

} // namespace openage::curve
Loading