diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d6ff2b2cb..3c3cba67b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,7 @@ set(CYTHON_MIN_VERSION 0.25) foreach(pol CMP0067 # honor language standard in try_compile() CMP0071 # enable automoc for generated files + CMP0072 # prefers GLVND by default FindOpenGL ) if (POLICY ${pol}) cmake_policy(SET ${pol} NEW) diff --git a/buildsystem/HandleCXXOptions.cmake b/buildsystem/HandleCXXOptions.cmake index 35c105d07e..4721a65fc7 100644 --- a/buildsystem/HandleCXXOptions.cmake +++ b/buildsystem/HandleCXXOptions.cmake @@ -90,36 +90,36 @@ set(CMAKE_CXX_FLAGS_DEBUG "-g") set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG") # If CXX_OPTIMIZATION_LEVEL was not provided, default to auto -if(${CXX_OPTIMIZATION_LEVEL} STREQUAL "") +if("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "") set(CXX_OPTIMIZATION_LEVEL "auto") endif() -if(${CXX_OPTIMIZATION_LEVEL} STREQUAL "auto") +if("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "auto") if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") - set(${CXX_OPTIMIZATION_LEVEL} "g") + set(CXX_OPTIMIZATION_LEVEL "g") else() - set(${CXX_OPTIMIZATION_LEVEL} "3") + set(CXX_OPTIMIZATION_LEVEL "3") endif() endif() -if(${CXX_OPTIMIZATION_LEVEL} STREQUAL "0") +if("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "0") set_cxx_optimize_flags("-O0") -elseif(${CXX_OPTIMIZATION_LEVEL} STREQUAL "1") +elseif("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "1") set_cxx_optimize_flags("-O1") -elseif(${CXX_OPTIMIZATION_LEVEL} STREQUAL "2") +elseif("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "2") set_cxx_optimize_flags("-O2") -elseif(${CXX_OPTIMIZATION_LEVEL} STREQUAL "3") +elseif("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "3") set_cxx_optimize_flags("-O3") -elseif(${CXX_OPTIMIZATION_LEVEL} STREQUAL "g") - if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") +elseif("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "g") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set_cxx_optimize_flags("-Og") else() set_cxx_optimize_flags("-O0") endif() -elseif(${CXX_OPTIMIZATION_LEVEL} STREQUAL "max") +elseif("${CXX_OPTIMIZATION_LEVEL}" STREQUAL "max") set_cxx_optimize_flags("-O3 -march=native") - if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") include(ProcessorCount) ProcessorCount(N) if(NOT N EQUAL 0) @@ -136,29 +136,29 @@ if(NOT CXX_SANITIZE_MODE) set(CXX_SANITIZE_MODE "none") endif() -if (${CXX_SANITIZE_MODE} STREQUAL "none") +if("${CXX_SANITIZE_MODE}" STREQUAL "none") # Do nothing - if(${CXX_SANITIZE_FATAL}) + if("${CXX_SANITIZE_FATAL}") message(WARNING "CXX_SANITIZE_FATAL is only valid when CXX_SANITIZE_MODE is not none") endif() else() set_compiler_flags("CXX" "-fno-omit-frame-pointer") - if(${CXX_SANITIZE_FATAL} AND ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + if("${CXX_SANITIZE_FATAL}" AND "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") set_compiler_flags("CXX" "-fno-sanitize-recover") endif() - if (${CXX_SANITIZE_MODE} STREQUAL "yes") + if("${CXX_SANITIZE_MODE}" STREQUAL "yes") set_compiler_flags("CXX" "-fsanitize=address") set_compiler_flags("CXX" "-fsanitize=undefined") - elseif(${CXX_SANITIZE_MODE} STREQUAL "mem") + elseif("${CXX_SANITIZE_MODE}" STREQUAL "mem") if(NOT APPLE) set_compiler_flags("CXX" "-fsanitize=memory") endif() - elseif(${CXX_SANITIZE_MODE} STREQUAL "thread") + elseif("${CXX_SANITIZE_MODE}" STREQUAL "thread") if(NOT APPLE) set_compiler_flags("CXX" "-fsanitize=thread") endif() - if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set_compiler_flags("CXX" "-fPIC") set_compiler_flags("CXX" "-pie") endif() diff --git a/copying.md b/copying.md index 517613526c..cf7cff74a6 100644 --- a/copying.md +++ b/copying.md @@ -110,7 +110,7 @@ _the openage authors_ are: | Rafael X. Morales Georgi | chocoladisco | chocoladisco à gmail dawt com | | Marcel Schneider | schnema123 | marcelschneider5 à outlook dawt de | | Samuel Grigolato | samuelgrigolato | samuel dawt grigolato à gmail dawt com | -| Andrew Thompson           | mrwerdo331@me.com | mrwerdo331 à me dawt com | +| Andrew Thompson | mrwerdo | mrwerdo331 à me dawt com | | Benedikt Freisen | roybaer | b dawt freisen à gmx dawt net | | Finn Günther | Kawzeg | kawzeg à gmail dawt com | | Akshit Sharma | akshit-sharma | akshit9sharma à gmail dawt com | diff --git a/dist/README.md b/dist/README.md index 988035fec7..8f99be9aaf 100644 --- a/dist/README.md +++ b/dist/README.md @@ -6,10 +6,3 @@ Contains files useful for package distribution. The [openage.desktop](openage.desktop) file can be found in this directory and will be installed at `/usr/share/applications/openage.desktop`. - -## Desktop icon - -In lieu of a logo/icon for openage a cropped version of [assets/gaben.png](/assets/gaben.png) is -created instead. See [assets/CMakeLists.txt](/assets/CMakeLists.txt) for details on how the icon -is generated. The final icon will be installed at `/usr/share/pixmaps/openage.png` via -`make install`. diff --git a/doc/build_instructions/arch_linux.md b/doc/build_instructions/arch_linux.md index 5046c6116b..dc4972ce38 100644 --- a/doc/build_instructions/arch_linux.md +++ b/doc/build_instructions/arch_linux.md @@ -1,13 +1,15 @@ # Prerequisite steps for Arch Linux users -> NOTE: [aur](https://aur.archlinux.org/packages/openage-git/) exists, to install via **yaourt** run `yaourt -S openage-git`. +> NOTE: `openage` is packaged in the [AUR](https://aur.archlinux.org/packages/openage-git/)! This command should provide required packages for Arch Linux installation: -`sudo pacman -S --needed python python-jinja python-pillow python-numpy python-pygments cython libepoxy libogg libpng ttf-dejavu freetype2 fontconfig harfbuzz cmake sdl2 sdl2_image opusfile opus python-pylint qt5-declarative qt5-quickcontrols` +`sudo pacman -S --needed eigen python python-jinja python-pillow python-numpy python-pygments cython libepoxy libogg libpng ttf-dejavu freetype2 fontconfig harfbuzz cmake sdl2 sdl2_image opusfile opus python-pylint qt5-declarative qt5-quickcontrols` If you don't have a compiler installed, you can select between these commands to install it: - `sudo pacman -S --needed gcc` - `sudo pacman -S --needed clang` You can install both compilers and select the one to be used by `./configure`. + +You will also need [nyan](https://github.com/SFTtech/nyan/blob/master/doc/building.md) and its dependencies. diff --git a/doc/build_instructions/debian.md b/doc/build_instructions/debian.md index a6b3edfaa8..e693dcf7d5 100644 --- a/doc/build_instructions/debian.md +++ b/doc/build_instructions/debian.md @@ -1,6 +1,6 @@ # Prerequisite steps for Debian Sid users - `sudo apt-get update` - - `sudo apt-get install cmake libfreetype6-dev python3-dev python3-pip libepoxy-dev libsdl2-dev libsdl2-image-dev libopusfile-dev libfontconfig1-dev libharfbuzz-dev libpng-dev opus-tools python3-pil python3-numpy python3-pygments qtdeclarative5-dev qml-module-qtquick-controls cython3 python3-jinja2` + - `sudo apt-get install cmake cython3 libeigen3-dev libepoxy-dev libfontconfig1-dev libfreetype6-dev libharfbuzz-dev libogg-dev libopus-dev libopusfile-dev libpng-dev libsdl2-dev libsdl2-image-dev python3-dev python3-jinja2 python3-numpy python3-pil python3-pip python3-pygments qml-module-qtquick-controls qtdeclarative5-dev` You will also need [nyan](https://github.com/SFTtech/nyan/blob/master/doc/building.md) and its dependencies. diff --git a/doc/build_instructions/fedora.md b/doc/build_instructions/fedora.md index 8254eee322..a8b9b1af9e 100644 --- a/doc/build_instructions/fedora.md +++ b/doc/build_instructions/fedora.md @@ -2,6 +2,6 @@ Run the following command: -`sudo dnf install cmake gcc-c++ clang SDL2-devel SDL2_image-devel python3-Cython python3-devel python3-numpy python3-pillow python3-pygments libepoxy-devel libogg-devel libopusenc-devel python3-jinja2 libpng-devel opusfile-devel fontconfig-devel harfbuzz-devel qt5-qtdeclarative-devel qt5-qtquickcontrols` +`sudo dnf install clang cmake eigen3-devel fontconfig-devel gcc-c harfbuzz-devel libepoxy-devel libogg-devel libopusenc-devel libpng-devel opusfile-devel python3-Cython python3-devel python3-jinja2 python3-numpy python3-pillow python3-pygments SDL2-devel SDL2_image-devel++ qt5-qtdeclarative-devel qt5-qtquickcontrols` You will also need [nyan](https://github.com/SFTtech/nyan/blob/master/doc/building.md) and its dependencies. diff --git a/doc/build_instructions/freebsd.md b/doc/build_instructions/freebsd.md index 5328aa13e0..c59970af06 100644 --- a/doc/build_instructions/freebsd.md +++ b/doc/build_instructions/freebsd.md @@ -2,11 +2,11 @@ This command should provide required packages for FreeBSD installation: -`sudo pkg install python py-pillow py-numpy py-pygments cython harfbuzz cmake sdl2 sdl2_image opusfile opus-tools png pylint qt5` +`sudo pkg install cmake cython eigen3 harfbuzz opus-tools opusfile png py-numpy py-pillow py-pygments pylint python qt5 sdl2 sdl2_image` You will also need [nyan](https://github.com/SFTtech/nyan/blob/master/doc/building.md) and its dependencies. -clang is the base compiler however, it is possible to use either any version of gcc>=7 or any other version of clang present in pkg: +`clang` is the base compiler however, it is possible to use either any version of `gcc>=7` or any other version of `clang` present in `pkg`: - `sudo pkg install gcc` -Select the one to be used by `./configure`. +Select the one to be used by `./configure --help`. diff --git a/doc/build_instructions/gentoo.md b/doc/build_instructions/gentoo.md index e25a77a663..cbbf75db73 100644 --- a/doc/build_instructions/gentoo.md +++ b/doc/build_instructions/gentoo.md @@ -31,5 +31,5 @@ If you want to install the latest git version: =games-strategy/openage-9999::sft ** ``` -Beware, the git version does not do automatic updates. +Beware, the git version does **not** do automatic updates. You have to explicitly "reinstall" openage or use `app-portage/smart-live-rebuild`. diff --git a/doc/build_instructions/opensuse_13.2.md b/doc/build_instructions/opensuse_13.2.md index 48b6ead569..d044b93a40 100644 --- a/doc/build_instructions/opensuse_13.2.md +++ b/doc/build_instructions/opensuse_13.2.md @@ -6,6 +6,6 @@ if all packages can be installed. - `zypper addrepo http://download.opensuse.org/repositories/devel:languages:python3/openSUSE_13.2/devel:languages:python3.repo` - `zypper refresh` -- `zypper install --no-recommends cmake doxygen fontconfig-devel harfbuzz-devel gcc49-c++ graphviz libpng-devel libSDL2-devel libSDL2_image-devel libfreetype6 libepoxy-devel libogg-devel libopus-devel opusfile-devel pkgconfig python3-Cython python3-Jinja2 python3-Pillow python3-Pygments python3-devel libqt5-qtdeclarative-devel libqt5-qtquickcontrols` +- `zypper install --no-recommends cmake doxygen eigen3-devel fontconfig-devel gcc49-c graphviz++ harfbuzz-devel libSDL2-devel libSDL2_image-devel libepoxy-devel libfreetype6 libogg-devel libopus-devel libpng-devel libqt5-qtdeclarative-devel libqt5-qtquickcontrols opusfile-devel pkgconfig python3-Cython python3-Jinja2 python3-Pillow python3-Pygments python3-devel` You will also need [nyan](https://github.com/SFTtech/nyan/blob/master/doc/building.md) and its dependencies. diff --git a/doc/build_instructions/opensuse_tumbleweed.md b/doc/build_instructions/opensuse_tumbleweed.md index 57bbf83d13..a85de0177f 100644 --- a/doc/build_instructions/opensuse_tumbleweed.md +++ b/doc/build_instructions/opensuse_tumbleweed.md @@ -1,5 +1,5 @@ # Prerequisite steps for openSUSE users (openSUSE Tumbleweed) - - `zypper install --no-recommends cmake doxygen fontconfig-devel harfbuzz-devel gcc-c++ graphviz libpng-devel libSDL2-devel libSDL2_image-devel libfreetype6 libepoxy-devel libogg-devel libopus-devel opusfile-devel pkgconfig python3-Cython python3-Jinja2 python3-Pillow python3-Pygments python3-devel libqt5-qtdeclarative-devel libqt5-qtquickcontrols` + - `zypper install --no-recommends cmake doxygen eigen3-devel fontconfig-devel gcc-c graphviz++ harfbuzz-devel libSDL2-devel libSDL2_image-devel libepoxy-devel libfreetype6 libogg-devel libopus-devel libpng-devel libqt5-qtdeclarative-devel libqt5-qtquickcontrols opusfile-devel pkgconfig python3-Cython python3-Jinja2 python3-Pillow python3-Pygments python3-devel` You will also need [nyan](https://github.com/SFTtech/nyan/blob/master/doc/building.md) and its dependencies. diff --git a/doc/build_instructions/ubuntu.md b/doc/build_instructions/ubuntu.md index de2465b3f4..c1855f505f 100644 --- a/doc/build_instructions/ubuntu.md +++ b/doc/build_instructions/ubuntu.md @@ -1,7 +1,6 @@ # Prerequisite steps for Ubuntu users (Ubuntu 18.04) - `sudo apt-get update` - - `sudo apt-get install cmake libfreetype6-dev python3-dev python3-pip libepoxy-dev libsdl2-dev libsdl2-image-dev libopusfile-dev libfontconfig1-dev libharfbuzz-dev libogg-dev libopus-dev libpng-dev python3-pil python3-numpy python3-pygments python3-jinja2 qtdeclarative5-dev qml-module-qtquick-controls` - - `pip3 install cython` + - `sudo apt-get install cmake cython3 libeigen3-dev libepoxy-dev libfontconfig1-dev libfreetype6-dev libharfbuzz-dev libogg-dev libopus-dev libopusfile-dev libpng-dev libsdl2-dev libsdl2-image-dev python3-dev python3-jinja2 python3-numpy python3-pil python3-pip python3-pygments qml-module-qtquick-controls qtdeclarative5-dev` You will also need [nyan](https://github.com/SFTtech/nyan/blob/master/doc/building.md) and its dependencies. diff --git a/doc/build_instructions/windows_msvc.md b/doc/build_instructions/windows_msvc.md index f6e6aa6693..dd380c7eec 100644 --- a/doc/build_instructions/windows_msvc.md +++ b/doc/build_instructions/windows_msvc.md @@ -25,7 +25,7 @@ ### vcpkg packages Set up [vcpkg](https://github.com/Microsoft/vcpkg#quick-start). Open a command prompt at `` - vcpkg install dirent libepoxy fontconfig freetype harfbuzz libogg opus opusfile qt5-base qt5-declarative qt5-quickcontrols sdl2 sdl2-image libpng + vcpkg install dirent eigen3 fontconfig freetype harfbuzz libepoxy libogg libpng opus opusfile qt5-base qt5-declarative qt5-quickcontrols sdl2 sdl2-image _Note:_ The `qt5` port in vcpkg has been split into multiple packages, build times are acceptable now. If you want, you can still use [the prebuilt version](https://www.qt.io/download-open-source/) instead. diff --git a/doc/building.md b/doc/building.md index f66fb093d6..bb1af0dafb 100644 --- a/doc/building.md +++ b/doc/building.md @@ -33,28 +33,30 @@ Dependency list: C cmake >=3.1.0 A numpy A python imaging library (PIL) -> pillow - CR opengl >=2.1 + CR opengl >=3.3 CR libepoxy CR libpng R dejavu font + CR eigen >=3 CR freetype2 CR fontconfig - CR harfbuzz >= 1.0.0 + CR harfbuzz >=1.0.0 CR nyan (https://github.com/SFTtech/nyan) CR O ncurses C jinja2 CR sdl2 CR sdl2_image CR opusfile - CRA libopus - CRA libogg - S pycodestyle (or pep8 (deprecated)) + CRA opus + CRA ogg + S pycodestyle C pygments S pylint CR qt5 >=5.5 (Core, Quick, QuickControls modules) + CR O vulkan A An installed version of any of the following (wine is your friend). - Other versions _might_ work; setup disk support will be added soon: + Other versions _might_ work: - Age of Empires II: The Conquerors Patch 1.0c - Age of Empires II: Forgotten Empires diff --git a/libopenage/CMakeLists.txt b/libopenage/CMakeLists.txt index 1caf5e874e..674306e406 100644 --- a/libopenage/CMakeLists.txt +++ b/libopenage/CMakeLists.txt @@ -216,16 +216,14 @@ endif() if(WANT_OPENGL AND OPENGL_FOUND) have_config_option(opengl OPENGL true) - include_directories(${OPENGL_INCLUDE_DIR}) - target_link_libraries(libopenage PRIVATE ${OPENGL_LIBRARY}) + target_link_libraries(libopenage PRIVATE OpenGL::GL) else() have_config_option(opengl OPENGL false) endif() if(WANT_VULKAN AND VULKAN_FOUND) have_config_option(vulkan VULKAN true) - include_directories(${Vulkan_INCLUDE_DIRS}) - target_link_libraries(libopenage PRIVATE ${Vulkan_LIBRARIES}) + target_link_libraries(libopenage PRIVATE Vulkan::Vulkan) else() have_config_option(vulkan VULKAN false) endif() @@ -241,6 +239,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) @@ -327,8 +331,10 @@ pxdgen( add_subdirectory("audio") add_subdirectory("console") add_subdirectory("coord") +add_subdirectory("curve") add_subdirectory("cvar") add_subdirectory("datastructure") +add_subdirectory("event") add_subdirectory("gui") add_subdirectory("error") add_subdirectory("gamestate") 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