From 5d530b0d8735345c28934b8b6c910f36197271d9 Mon Sep 17 00:00:00 2001 From: "C. J. Howard" Date: Wed, 8 Jun 2022 22:31:14 +0800 Subject: [PATCH] Separate animation_channel into separate header from animation --- src/animation/animation-channel.hpp | 202 ++++++++++++++++++++++++++++ src/animation/animation.hpp | 179 +----------------------- src/animation/animator.hpp | 20 ++- 3 files changed, 225 insertions(+), 176 deletions(-) create mode 100644 src/animation/animation-channel.hpp diff --git a/src/animation/animation-channel.hpp b/src/animation/animation-channel.hpp new file mode 100644 index 0000000..0c2898d --- /dev/null +++ b/src/animation/animation-channel.hpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2021 Christopher J. Howard + * + * This file is part of Antkeeper source code. + * + * Antkeeper source code is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Antkeeper source code is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Antkeeper source code. If not, see . + */ + +#ifndef ANTKEEPER_ANIMATION_CHANNEL_HPP +#define ANTKEEPER_ANIMATION_CHANNEL_HPP + +#include +#include +#include + +/** + * Single channel in a keyframe animation. + * + * @see animation + */ +template +class animation_channel +{ +public: + /// Keyframe consisting of a time and a value. + typedef std::tuple keyframe; + + /** + * Creates an animation channel. + * + * @param id ID of the channel. + */ + animation_channel(int id); + + /// Creates an animation channel. + animation_channel(); + + /// Creates an animation channel. + animation_channel(const animation_channel& other); + + /// Assigns the contents of another channel to this channel. + animation_channel& operator=(const animation_channel& other); + + /** + * Adds a keyframe to the animation. + * + * @param k Keyframe to add. + */ + void insert_keyframe(const keyframe& k); + + /** + * Removes all keyframes on `[start, end)`. + * + * @param start Starting position in time (inclusive). + * @param end Ending position in time (non-inclusive). + */ + void remove_keyframes(double start, double end); + + /// Removes all keyframes from the animation. + void remove_keyframes(); + + /** + * Finds the keyframes to the left and right of @p position. + * + * @param position Position in time. + * @return Array containing the the keyframes on the left and right of @p position. + */ + std::array find_keyframes(double position) const; + + /** + * Finds all the keyframes on `[start, end)`. + * + * @param start Starting position in time (inclusive). + * @param end Ending position in time (non-inclusive). + * @return All keyframes on `[start, end)`. + */ + std::list find_keyframes(double start, double end) const; + + /// Returns the ID of the animation channel. + int get_id() const; + + /// Returns the duration of the animation channel. + double get_duration() const; + +private: + struct keyframe_compare + { + inline bool operator()(const keyframe& lhs, const keyframe& rhs) const + { + return std::get<0>(lhs) < std::get<0>(rhs); + } + }; + + int id; + std::set keyframes; +}; + +template +animation_channel::animation_channel(int id): + id(id), + keyframes(keyframe_compare()) +{} + +template +animation_channel::animation_channel(): + animation_channel(-1) +{} + +template +animation_channel::animation_channel(const animation_channel& other): + id(other.id), + keyframes(other.keyframes) +{} + +template +animation_channel& animation_channel::operator=(const animation_channel& other) +{ + id = other.id; + keyframes = other.keyframes; +} + +template +void animation_channel::insert_keyframe(const keyframe& k) +{ + keyframes.emplace(k); +} + +template +void animation_channel::remove_keyframes(double start, double end) +{ + auto lower_bound = keyframes.lower_bound({start, T()}); + auto upper_bound = keyframes.upper_bound({end, T()}); + keyframes.erase(lower_bound, upper_bound); +} + +template +void animation_channel::remove_keyframes() +{ + keyframes.clear(); +} + +template +std::array::keyframe*, 2> animation_channel::find_keyframes(double position) const +{ + // Find the following keyframe + auto upper_bound = keyframes.upper_bound({position, T()}); + + // Find the preceding keyframe + auto lower_bound = upper_bound; + --lower_bound; + + std::array frames; + frames[0] = (lower_bound != keyframes.end()) ? &(*lower_bound) : nullptr; + frames[1] = (upper_bound != keyframes.end()) ? &(*upper_bound) : nullptr; + + return frames; +} + +template +std::list::keyframe> animation_channel::find_keyframes(double start, double end) const +{ + std::list keyframe_list; + + auto lower_bound = keyframes.lower_bound({start, T()}); + auto upper_bound = keyframes.upper_bound({end, T()}); + for (auto iterator = lower_bound; iterator != upper_bound; ++iterator) + { + keyframe_list.push_back(*iterator); + } + + return keyframe_list; +} + +template +inline int animation_channel::get_id() const +{ + return id; +} + +template +double animation_channel::get_duration() const +{ + if (keyframes.empty()) + { + return 0.0; + } + + return std::get<0>(*keyframes.rbegin()); +} + +#endif // ANTKEEPER_ANIMATION_CHANNEL_HPP diff --git a/src/animation/animation.hpp b/src/animation/animation.hpp index 343c7d4..6028075 100644 --- a/src/animation/animation.hpp +++ b/src/animation/animation.hpp @@ -20,15 +20,14 @@ #ifndef ANTKEEPER_ANIMATION_HPP #define ANTKEEPER_ANIMATION_HPP +#include "animation-channel.hpp" #include #include -#include -#include #include #include /** - * Abstract base class for animations. + * Abstract base class for keyframe animations. */ class animation_base { @@ -140,178 +139,10 @@ inline int animation_base::get_loop_count() const return loop_count; } -template -class animation_channel -{ -public: - /// Keyframe consisting of a time and a value. - typedef std::tuple keyframe; - - /** - * Creates an animation channel. - * - * @param id ID of the channel. - */ - animation_channel(int id); - - /// Creates an animation channel. - animation_channel(); - - /// Creates an animation channel. - animation_channel(const animation_channel& other); - - /// Assigns the contents of another channel to this channel. - animation_channel& operator=(const animation_channel& other); - - /** - * Adds a keyframe to the animation. - * - * @param k Keyframe to add. - */ - void insert_keyframe(const keyframe& k); - - /** - * Removes all keyframes on `[start, end)`. - * - * @param start Starting position in time (inclusive). - * @param end Ending position in time (non-inclusive). - */ - void remove_keyframes(double start, double end); - - /// Removes all keyframes from the animation. - void remove_keyframes(); - - /** - * Finds the keyframes to the left and right of @p position. - * - * @param position Position in time. - * @return Array containing the the keyframes on the left and right of @p position. - */ - std::array find_keyframes(double position) const; - - /** - * Finds all the keyframes on `[start, end)`. - * - * @param start Starting position in time (inclusive). - * @param end Ending position in time (non-inclusive). - * @return All keyframes on `[start, end)`. - */ - std::list find_keyframes(double start, double end) const; - - /// Returns the ID of the animation channel. - int get_id() const; - - /// Returns the duration of the animation channel. - double get_duration() const; - -private: - struct keyframe_compare - { - inline bool operator()(const keyframe& lhs, const keyframe& rhs) const - { - return std::get<0>(lhs) < std::get<0>(rhs); - } - }; - - int id; - std::set keyframes; -}; - -template -animation_channel::animation_channel(int id): - id(id), - keyframes(keyframe_compare()) -{} - -template -animation_channel::animation_channel(): - animation_channel(-1) -{} - -template -animation_channel::animation_channel(const animation_channel& other): - id(other.id), - keyframes(other.keyframes) -{} - -template -animation_channel& animation_channel::operator=(const animation_channel& other) -{ - id = other.id; - keyframes = other.keyframes; -} - -template -void animation_channel::insert_keyframe(const keyframe& k) -{ - keyframes.emplace(k); -} - -template -void animation_channel::remove_keyframes(double start, double end) -{ - auto lower_bound = keyframes.lower_bound({start, T()}); - auto upper_bound = keyframes.upper_bound({end, T()}); - keyframes.erase(lower_bound, upper_bound); -} - -template -void animation_channel::remove_keyframes() -{ - keyframes.clear(); -} - -template -std::array::keyframe*, 2> animation_channel::find_keyframes(double position) const -{ - // Find the following keyframe - auto upper_bound = keyframes.upper_bound({position, T()}); - - // Find the preceding keyframe - auto lower_bound = upper_bound; - --lower_bound; - - std::array frames; - frames[0] = (lower_bound != keyframes.end()) ? &(*lower_bound) : nullptr; - frames[1] = (upper_bound != keyframes.end()) ? &(*upper_bound) : nullptr; - - return frames; -} - -template -std::list::keyframe> animation_channel::find_keyframes(double start, double end) const -{ - std::list keyframe_list; - - auto lower_bound = keyframes.lower_bound({start, T()}); - auto upper_bound = keyframes.upper_bound({end, T()}); - for (auto iterator = lower_bound; iterator != upper_bound; ++iterator) - { - keyframe_list.push_back(*iterator); - } - - return keyframe_list; -} - -template -inline int animation_channel::get_id() const -{ - return id; -} - -template -double animation_channel::get_duration() const -{ - if (keyframes.empty()) - { - return 0.0; - } - - return std::get<0>(*keyframes.rbegin()); -} - /** - * Templated keyframe animation class. + * Keyframe animation. + * + * @tparam T Animated data type. */ template class animation: public animation_base diff --git a/src/animation/animator.hpp b/src/animation/animator.hpp index eb18587..6bbb90a 100644 --- a/src/animation/animator.hpp +++ b/src/animation/animator.hpp @@ -20,10 +20,13 @@ #ifndef ANTKEEPER_ANIMATOR_HPP #define ANTKEEPER_ANIMATOR_HPP -#include +#include class animation_base; +/** + * Progresses a set of animations. + */ class animator { public: @@ -34,12 +37,25 @@ public: */ void animate(double dt); + /** + * Adds an animation to the animator. + * + * @param animation Animation to add. + */ void add_animation(animation_base* animation); + + /** + * Removes an animation from the animator. + * + * @param animation Animation to remove. + */ void remove_animation(animation_base* animation); + + /// Removes all animations from the animator. void remove_animations(); private: - std::set animations; + std::unordered_set animations; }; #endif // ANTKEEPER_ANIMATOR_HPP