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