From d647fb2d33ab079ccda8c247fed486c810b1b0d7 Mon Sep 17 00:00:00 2001 From: Johannes Walcher Date: Wed, 2 May 2018 00:32:51 +0200 Subject: [PATCH 01/18] event: initial implementation of core simulation components Co-authored-by: Jonas Jelten --- libopenage/CMakeLists.txt | 6 + libopenage/curve/CMakeLists.txt | 14 + libopenage/curve/continuous.cpp | 9 + libopenage/curve/continuous.h | 63 +++ libopenage/curve/curve.cpp | 9 + libopenage/curve/curve.h | 18 + libopenage/curve/discrete.cpp | 9 + libopenage/curve/discrete.h | 75 +++ libopenage/curve/iterator.cpp | 9 + libopenage/curve/iterator.h | 135 +++++ libopenage/curve/keyframe_container.cpp | 9 + libopenage/curve/keyframe_container.h | 271 ++++++++++ libopenage/curve/map.cpp | 9 + libopenage/curve/map.h | 210 ++++++++ libopenage/curve/map_filter_iterator.cpp | 9 + libopenage/curve/map_filter_iterator.h | 64 +++ libopenage/curve/queue.cpp | 7 + libopenage/curve/queue.h | 172 +++++++ libopenage/curve/queue_filter_iterator.cpp | 9 + libopenage/curve/queue_filter_iterator.h | 52 ++ libopenage/curve/tests/CMakeLists.txt | 4 + libopenage/curve/tests/container.cpp | 212 ++++++++ libopenage/curve/tests/curve_types.cpp | 148 ++++++ libopenage/curve/value_container.cpp | 7 + libopenage/curve/value_container.h | 104 ++++ libopenage/event/CMakeLists.txt | 12 + libopenage/event/demo/CMakeLists.txt | 12 + libopenage/event/demo/aicontroller.cpp | 29 ++ libopenage/event/demo/aicontroller.h | 23 + libopenage/event/demo/gamestate.cpp | 9 + libopenage/event/demo/gamestate.h | 129 +++++ libopenage/event/demo/gui.cpp | 242 +++++++++ libopenage/event/demo/gui.h | 32 ++ libopenage/event/demo/main.cpp | 208 ++++++++ libopenage/event/demo/main.h | 14 + libopenage/event/demo/physics.cpp | 485 ++++++++++++++++++ libopenage/event/demo/physics.h | 34 ++ libopenage/event/event.cpp | 37 ++ libopenage/event/event.h | 85 ++++ libopenage/event/eventclass.cpp | 48 ++ libopenage/event/eventclass.h | 218 ++++++++ libopenage/event/eventfilter.cpp | 17 + libopenage/event/eventfilter.h | 27 + libopenage/event/eventqueue.cpp | 284 +++++++++++ libopenage/event/eventqueue.h | 158 ++++++ libopenage/event/eventtarget.cpp | 107 ++++ libopenage/event/eventtarget.h | 76 +++ libopenage/event/loop.cpp | 198 ++++++++ libopenage/event/loop.h | 147 ++++++ libopenage/event/state.cpp | 7 + libopenage/event/state.h | 19 + libopenage/event/tests.cpp | 557 +++++++++++++++++++++ libopenage/util/fixed_point.h | 91 +++- libopenage/util/matrix.h | 109 ++-- libopenage/util/matrix_test.cpp | 42 +- libopenage/util/quaternion.h | 25 +- libopenage/util/quaternion_test.cpp | 132 ++--- libopenage/util/vector.h | 101 ++-- libopenage/util/vector_test.cpp | 18 +- openage/CMakeLists.txt | 6 +- openage/event/CMakeLists.txt | 7 + openage/event/__init__.py | 6 + openage/event/demo.pyx | 48 ++ openage/testing/testlist.py | 5 + 64 files changed, 5244 insertions(+), 194 deletions(-) create mode 100644 libopenage/curve/CMakeLists.txt create mode 100644 libopenage/curve/continuous.cpp create mode 100644 libopenage/curve/continuous.h create mode 100644 libopenage/curve/curve.cpp create mode 100644 libopenage/curve/curve.h create mode 100644 libopenage/curve/discrete.cpp create mode 100644 libopenage/curve/discrete.h create mode 100644 libopenage/curve/iterator.cpp create mode 100644 libopenage/curve/iterator.h create mode 100644 libopenage/curve/keyframe_container.cpp create mode 100644 libopenage/curve/keyframe_container.h create mode 100644 libopenage/curve/map.cpp create mode 100644 libopenage/curve/map.h create mode 100644 libopenage/curve/map_filter_iterator.cpp create mode 100644 libopenage/curve/map_filter_iterator.h create mode 100644 libopenage/curve/queue.cpp create mode 100644 libopenage/curve/queue.h create mode 100644 libopenage/curve/queue_filter_iterator.cpp create mode 100644 libopenage/curve/queue_filter_iterator.h create mode 100644 libopenage/curve/tests/CMakeLists.txt create mode 100644 libopenage/curve/tests/container.cpp create mode 100644 libopenage/curve/tests/curve_types.cpp create mode 100644 libopenage/curve/value_container.cpp create mode 100644 libopenage/curve/value_container.h create mode 100644 libopenage/event/CMakeLists.txt create mode 100644 libopenage/event/demo/CMakeLists.txt create mode 100644 libopenage/event/demo/aicontroller.cpp create mode 100644 libopenage/event/demo/aicontroller.h create mode 100644 libopenage/event/demo/gamestate.cpp create mode 100644 libopenage/event/demo/gamestate.h create mode 100644 libopenage/event/demo/gui.cpp create mode 100644 libopenage/event/demo/gui.h create mode 100644 libopenage/event/demo/main.cpp create mode 100644 libopenage/event/demo/main.h create mode 100644 libopenage/event/demo/physics.cpp create mode 100644 libopenage/event/demo/physics.h create mode 100644 libopenage/event/event.cpp create mode 100644 libopenage/event/event.h create mode 100644 libopenage/event/eventclass.cpp create mode 100644 libopenage/event/eventclass.h create mode 100644 libopenage/event/eventfilter.cpp create mode 100644 libopenage/event/eventfilter.h create mode 100644 libopenage/event/eventqueue.cpp create mode 100644 libopenage/event/eventqueue.h create mode 100644 libopenage/event/eventtarget.cpp create mode 100644 libopenage/event/eventtarget.h create mode 100644 libopenage/event/loop.cpp create mode 100644 libopenage/event/loop.h create mode 100644 libopenage/event/state.cpp create mode 100644 libopenage/event/state.h create mode 100644 libopenage/event/tests.cpp create mode 100644 openage/event/CMakeLists.txt create mode 100644 openage/event/__init__.py create mode 100644 openage/event/demo.pyx diff --git a/libopenage/CMakeLists.txt b/libopenage/CMakeLists.txt index 1caf5e874e..b8b323fa83 100644 --- a/libopenage/CMakeLists.txt +++ b/libopenage/CMakeLists.txt @@ -241,6 +241,12 @@ get_config_option_string() configure_file(config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h) configure_file(config.cpp.in ${CMAKE_CURRENT_SOURCE_DIR}/config.cpp) +configure_file( + "${CMAKE_SOURCE_DIR}/openage/config.py.in" + "${CMAKE_SOURCE_DIR}/openage/config.py" +) + + ################################################## # platform specifics if(APPLE) diff --git a/libopenage/curve/CMakeLists.txt b/libopenage/curve/CMakeLists.txt new file mode 100644 index 0000000000..fd797510ab --- /dev/null +++ b/libopenage/curve/CMakeLists.txt @@ -0,0 +1,14 @@ +add_sources(libopenage + continuous.cpp + curve.cpp + discrete.cpp + iterator.cpp + keyframe_container.cpp + map.cpp + map_filter_iterator.cpp + queue.cpp + queue_filter_iterator.cpp + value_container.cpp +) + +add_subdirectory("tests") diff --git a/libopenage/curve/continuous.cpp b/libopenage/curve/continuous.cpp new file mode 100644 index 0000000000..73b3920c64 --- /dev/null +++ b/libopenage/curve/continuous.cpp @@ -0,0 +1,9 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#include "continuous.h" + +namespace openage::curve { + +// This file is intended to be empty + +} // openage::curve diff --git a/libopenage/curve/continuous.h b/libopenage/curve/continuous.h new file mode 100644 index 0000000000..77aa5dac59 --- /dev/null +++ b/libopenage/curve/continuous.h @@ -0,0 +1,63 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#pragma once + +#include + +#include "value_container.h" +#include "../log/log.h" + +namespace openage::curve { + + +/** + * Continuous Datatype. + * Stores a value container with continuous access. + * The bound template type T has to implement `operator+(T)` and + * `operator*(time_t)`. + */ +template +class Continuous : public ValueContainer { +public: + using ValueContainer::ValueContainer; + /** + * will interpolate between the keyframes linearly based on the time. + */ + T get(const time_t &) const override; +}; + + + +template +T Continuous::get(const time_t &time) const { + const auto &e = this->container.last(time, this->last_element); + this->last_element = e; + + auto nxt = e; + ++nxt; + + time_t diff_time = 0; + + auto offset = time - e->time; + + // If we do not have a next (buffer underrun!!) we assign values + if (nxt == this->container.end()) { + // log::log(WARN << "Continuous buffer underrun. This might be bad! Assuming constant."); + } else { + diff_time = nxt->time - e->time; + } + + if (nxt == this->container.end() // use the last curve value + || offset == 0 // values equal -> don't need to interpolate + || diff_time == 0) { // values at the same time -> division-by-zero-error + + return e->value; + } else { + // Interpolation between time(now) and time(next) that has elapsed + double elapsed_frac = offset.to_double() / diff_time.to_double(); + + return e->value + (nxt->value - e->value) * elapsed_frac; + } +} + +} // openage::curve diff --git a/libopenage/curve/curve.cpp b/libopenage/curve/curve.cpp new file mode 100644 index 0000000000..4ec84fe407 --- /dev/null +++ b/libopenage/curve/curve.cpp @@ -0,0 +1,9 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#include "curve.h" + +namespace openage::curve { + +// This file is intended to be empty + +} // openage::curve diff --git a/libopenage/curve/curve.h b/libopenage/curve/curve.h new file mode 100644 index 0000000000..381ce727b3 --- /dev/null +++ b/libopenage/curve/curve.h @@ -0,0 +1,18 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#pragma once + +#include + +#include "../util/fixed_point.h" + + +namespace openage::curve { + +/** + * Defines the type that is used as time index. + * it has to implement all basic mathematically operations. + */ +using time_t = util::FixedPoint; + +} // openage::curve diff --git a/libopenage/curve/discrete.cpp b/libopenage/curve/discrete.cpp new file mode 100644 index 0000000000..4bfab12bdd --- /dev/null +++ b/libopenage/curve/discrete.cpp @@ -0,0 +1,9 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#include "discrete.h" + +namespace openage::curve { + +// This file is intended to be empty + +} // openage::curve diff --git a/libopenage/curve/discrete.h b/libopenage/curve/discrete.h new file mode 100644 index 0000000000..63abf65638 --- /dev/null +++ b/libopenage/curve/discrete.h @@ -0,0 +1,75 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#pragma once + +#include +#include + +#include "value_container.h" + + +namespace openage::curve { + +/** + * Does not interpolate between values. The template type does only need to + * implement `operator=` and copy ctor. + */ +template +class Discrete : public ValueContainer { + static_assert(std::is_copy_assignable::value, + "Template type is not copy assignable"); + static_assert(std::is_copy_constructible::value, + "Template type is not copy constructible"); +public: + using ValueContainer::ValueContainer; + + /** + * Does not interpolate anything, + * just returns gives the raw value of the last keyframe with time <= t. + */ + T get(const time_t &t) const override; + + /** + * Return the last time and keyframe with time <= t. + */ + std::pair get_time(const time_t &t) const; + + /** + * Return, if existing, the time and value of keyframe with time < t + */ + std::optional> get_previous(const time_t &t) const; +}; + + +template +T Discrete::get(const time_t &time) const { + auto e = this->container.last(time, this->last_element); + this->last_element = e; // TODO if Caching? + return e->value; +} + + +template +std::pair Discrete::get_time(const 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); +} + + +template +std::optional> Discrete::get_previous(const time_t &time) const { + auto e = this->container.last(time, this->last_element); + this->last_element = e; + + // if we're not at the container head + // go back one entry. + if (e == std::begin(this->container)) { + return {}; + } + + e--; + return std::make_pair(e->time, e->value); +} + +} // openage::curve diff --git a/libopenage/curve/iterator.cpp b/libopenage/curve/iterator.cpp new file mode 100644 index 0000000000..b449d93812 --- /dev/null +++ b/libopenage/curve/iterator.cpp @@ -0,0 +1,9 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#include "iterator.h" + +namespace openage::curve { + +// This file is intended to be empty + +} // namespace openage::curve diff --git a/libopenage/curve/iterator.h b/libopenage/curve/iterator.h new file mode 100644 index 0000000000..b965b65640 --- /dev/null +++ b/libopenage/curve/iterator.h @@ -0,0 +1,135 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#pragma once + +#include "curve.h" + +namespace openage::curve { + +/** + * Default interface for curve containers + */ +template +class CurveIterator { +public: + /** + * access the value of the iterator + */ + virtual const val_t &value() const = 0; + + /** + * Check if the iterator is still valid + * (this breaks from the stl - in the best way) + */ + virtual bool valid() const = 0; + + /** + * The iterator needs a reference to the container + */ + explicit CurveIterator(const container_t *c) + : + base{}, + container{c}, + from{-std::numeric_limits::max()}, + to{+std::numeric_limits::max()} {} + +protected: + /** + * Can only be constructed from the referenced container + */ + CurveIterator(const iterator_t &base, + const container_t *container, + const time_t &from, + const time_t &to) + : + base{base}, + container{container}, + from{from}, + to{to} {} + +public: + /** Default copy c'tor */ + CurveIterator (const CurveIterator &) = default; + + virtual ~CurveIterator() = default; + + /** Default assignment operator */ + CurveIterator &operator= ( + const CurveIterator &) = default; + + /** Dereference will call the virtual function */ + virtual const val_t &operator *() const { + return this->value(); + } + + /** Dereference will call the virutal function */ + virtual const val_t *operator ->() const { + return &this->value(); + } + + /** + * For equalness only the base iterator will be testet - not the timespans + * this is defined in. + */ + virtual bool operator ==(const CurveIterator &rhs) const { + return this->base == rhs.base; + } + + /** + * For unequalness only the base iterator will be testet - not the timespans + * this is defined in. + */ + virtual bool operator !=(const CurveIterator &rhs) const { + return this->base != rhs.base; + } + + /** + * Advance to the next valid element. + */ + virtual CurveIterator &operator ++() { + do { + ++this->base; + } while (this->container->end().base != this->base and not this->valid()); + + return *this; + } + + /** + * Access the underlying + */ + const iterator_t &get_base() const { + return base; + } + + /** + * Access the lower end value of the defined time frame + */ + const time_t &get_from() const { + return from; + } + + /** + * Access the higher end value of the defined time frame + */ + const time_t &get_to() const { + return to; + } + +protected: + /// The iterator this is currently referring to. + iterator_t base; + + /// The base container. + const container_t *container; + + /// The time, from where this iterator started to iterate. + time_t from; + + /// The time, to where this iterator will iterate. + time_t to; +}; + + +} // openage::curve diff --git a/libopenage/curve/keyframe_container.cpp b/libopenage/curve/keyframe_container.cpp new file mode 100644 index 0000000000..4fabb77893 --- /dev/null +++ b/libopenage/curve/keyframe_container.cpp @@ -0,0 +1,9 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#include "keyframe_container.h" + +namespace openage::curve { + +// nothing to see here, keep walking (to the header) + +} // openage::curve diff --git a/libopenage/curve/keyframe_container.h b/libopenage/curve/keyframe_container.h new file mode 100644 index 0000000000..9aed77717b --- /dev/null +++ b/libopenage/curve/keyframe_container.h @@ -0,0 +1,271 @@ +// Copyright 2017-2018 the openage authors. See copying.md for legal info. + +#pragma once + +#include +#include +#include + +#include "curve.h" +#include "../event/loop.h" +#include "../error/error.h" + +namespace openage::curve { + +/** + * A timely ordered list with several management functions + * + * This class manages different time-based management functions for list + * approach that lies underneath. It contains list to be accessed via a + * non-accurate timing functionality, this means, that for getting a value, not + * the exact timestamp has to be known, it will always return the one closest, + * less or equal to the requested one. + **/ +template +class KeyframeContainer { +public: + /** + * A element of the curvecontainer. This is especially used to keep track of + * the value-timing. + */ + class Keyframe { + public: + /** + * New default object at numericlimits