Skip to content

Commit

Permalink
impliment curve::array
Browse files Browse the repository at this point in the history
  • Loading branch information
jere8184 committed Dec 13, 2024
1 parent 2b902a9 commit 1d653cd
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 5 deletions.
1 change: 1 addition & 0 deletions libopenage/curve/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
add_sources(libopenage
array.cpp
base_curve.cpp
continuous.cpp
discrete.cpp
Expand Down
10 changes: 10 additions & 0 deletions libopenage/curve/array.cpp
Original file line number Diff line number Diff line change
@@ -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
197 changes: 197 additions & 0 deletions libopenage/curve/array.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// Copyright 2024-2024 the openage authors. See copying.md for legal info.

#pragma once

#include <array>

#include "curve/keyframe_container.h"
#include "event/evententity.h"


// remember to update docs
namespace openage {
namespace curve {

template <typename T, size_t Size>
class Array : event::EventEntity {
public:
Array(const std::shared_ptr<event::EventLoop> &loop,
size_t id,
const std::string &idstr = "",
const EventEntity::single_change_notifier &notifier = nullptr) :
EventEntity(loop, notifier), _id{id}, _idstr{idstr}, loop{loop}{}

// prevent accidental copy of queue
Array(const Array &) = delete;


T get(const time::time_t &t, const size_t index) const;


std::array<T, Size> get_all(const time::time_t &t) const;


consteval size_t size() const;

std::pair<time::time_t, T> frame(const time::time_t &t, const size_t index) const;


std::pair<time::time_t, T> 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<T, Size> &other, const time::time_t &t);


/**
* 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;
}



class Iterator {
public:
Iterator(Array<T, Size> *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<T, Size>::Iterator &rhs) const {
return this->offset != rhs.offset;
}


private:
size_t offset;
Array<T, Size> *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<KeyframeContainer<T>, Size> container;

//hint for KeyframeContainer operations
mutable std::array<size_t, Size> 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<event::EventLoop> loop;
};


template <typename T, size_t Size>
std::pair<time::time_t, T> Array<T, Size>::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 <typename T, size_t Size>
std::pair<time::time_t, T> Array<T, Size>::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);
}

template <typename T, size_t Size>
T Array<T, Size>::get(const time::time_t &t, const size_t index) const {
return this->frame(t, index).second;
}

template <typename T, size_t Size>
std::array<T, Size> Array<T, Size>::get_all(const time::time_t &t) const {
return [&]<auto... I>(std::index_sequence<I...>) {
return std::array<T, Size>{this->get(t, I)...};
}(std::make_index_sequence<Size>{});
}

template <typename T, size_t Size>
consteval size_t Array<T, Size>::size() const {
return Size;
}


template <typename T, size_t Size>
void Array<T, Size>::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 <typename T, size_t Size>
void Array<T, Size>::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 <typename T, size_t Size>
void Array<T, Size>::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 <typename T, size_t Size>
void Array<T, Size>::sync(const Array<T, Size> &other, const time::time_t &start) {
for (int i = 0; i < Size; i++) {
this->container[i].sync(other[i], start);
}
}

template <typename T, size_t Size>
typename Array<T, Size>::Iterator Array<T, Size>::begin(const time::time_t &time) {
return Array<T, Size>::Iterator(this, time);
}


template <typename T, size_t Size>
typename Array<T, Size>::Iterator Array<T, Size>::end(const time::time_t &time) {
return Array<T, Size>::Iterator(this, time, this->container.size());
}

} // namespace curve
} // namespace openage
9 changes: 9 additions & 0 deletions libopenage/curve/keyframe.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@ class Keyframe {
return this->value;
}

/**
* Get the value and timestamp of the keyframe in form of std::pair<time, value>
* @return keyframe pair
*/
std::pair<time::time_t, T> make_pair() const
{
return {time(), val()};
}

public:
/**
* Value of the keyframe.
Expand Down
2 changes: 0 additions & 2 deletions libopenage/curve/keyframe_container.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
19 changes: 16 additions & 3 deletions libopenage/curve/tests/curve_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <memory>
#include <string>

#include "curve/array.h"
#include "curve/continuous.h"
#include "curve/discrete.h"
#include "curve/discrete_mod.h"
Expand Down Expand Up @@ -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<event::EventLoop>();
Discrete<int> c(f, 0);
Expand All @@ -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<event::EventLoop>();
DiscreteMod<int> c(f, 0);
Expand Down Expand Up @@ -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<event::EventLoop>();
Discrete<int> c(f, 0);
Expand Down Expand Up @@ -386,6 +387,18 @@ void curve_types() {
TESTEQUALS(c.get(1), 0);
TESTEQUALS(c.get(5), 0);
}

{ // array
auto f = std::make_shared<event::EventLoop>();

Array<int, 2> a(f,0);
a.set_insert(time::time_t(1), 0, 0);
a.set_insert(time::time_t(1), 1, 1);
const auto res = a.get_all(1);
TESTEQUALS(res[0], 0);
TESTEQUALS(res[1], 1);
//TODO
}
}

} // namespace openage::curve::tests

0 comments on commit 1d653cd

Please sign in to comment.