-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add animation_player and animation_context classes. Add animation_com…
…ponent struct. Change function signature of animation_track output functions. Add animation duration functions. Make animation_system advance animation_component players.
- Loading branch information
Showing
16 changed files
with
486 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// SPDX-FileCopyrightText: 2023 C. J. Howard | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#ifndef ANTKEEPER_ANIMATION_ANIMATION_CONTEXT_HPP | ||
#define ANTKEEPER_ANIMATION_ANIMATION_CONTEXT_HPP | ||
|
||
#include <entt/entt.hpp> | ||
|
||
/** | ||
* Context for animation track output functions. | ||
*/ | ||
struct animation_context | ||
{ | ||
/** Handle to the entity being animated. */ | ||
entt::handle handle; | ||
}; | ||
|
||
#endif // ANTKEEPER_ANIMATION_ANIMATION_CONTEXT_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-FileCopyrightText: 2023 C. J. Howard | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#ifndef ANTKEEPER_ANIMATION_ANIMATION_PLAYBACK_STATE_HPP | ||
#define ANTKEEPER_ANIMATION_ANIMATION_PLAYBACK_STATE_HPP | ||
|
||
/** Animation player states. */ | ||
enum class animation_player_state | ||
{ | ||
/** Animation player is stopped. */ | ||
stopped, | ||
|
||
/** Animation player is playing. */ | ||
playing, | ||
|
||
/** Animation player is paused. */ | ||
paused | ||
}; | ||
|
||
#endif // ANTKEEPER_ANIMATION_ANIMATION_PLAYBACK_STATE_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// SPDX-FileCopyrightText: 2023 C. J. Howard | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#include <engine/animation/animation-player.hpp> | ||
|
||
void animation_player::advance(float seconds) | ||
{ | ||
if (!m_sequence) | ||
{ | ||
// No active animation sequence, advance position and return | ||
m_position += seconds; | ||
return; | ||
} | ||
|
||
// Remember previous playback position | ||
const auto previous_position = m_position; | ||
|
||
// Advance playback position | ||
m_position += seconds; | ||
|
||
// Loop | ||
std::size_t loop_count = 0; | ||
if (m_looping && m_position >= m_sequence_duration) | ||
{ | ||
if (m_sequence_duration > 0.0f) | ||
{ | ||
// Calculate looped position | ||
const auto looped_position = std::fmod(m_position, m_sequence_duration); | ||
|
||
// Calculate number of times looped | ||
loop_count = static_cast<std::size_t>(m_position / m_sequence_duration); | ||
|
||
// Set current position to looped position | ||
m_position = looped_position; | ||
} | ||
else | ||
{ | ||
// Zero-duration looping sequence | ||
m_position = 0.0f; | ||
} | ||
} | ||
|
||
for (const auto& [path, track]: m_sequence->tracks()) | ||
{ | ||
if (!track.output()) | ||
{ | ||
// Ignore tracks with no output functions | ||
continue; | ||
} | ||
|
||
if (m_sample_buffer.size() < track.channels().size()) | ||
{ | ||
// Grow sample buffer to accommodate track channels | ||
m_sample_buffer.resize(track.channels().size()); | ||
} | ||
|
||
// Sample track | ||
track.sample(m_position, m_sample_buffer); | ||
|
||
// Pass sample buffer and animation context to track output function | ||
track.output()(m_sample_buffer, m_context); | ||
} | ||
|
||
if (loop_count) | ||
{ | ||
// Trigger cues on [previous position, m_sequence_duration) | ||
m_sequence->trigger_cues(previous_position, m_sequence_duration, m_context); | ||
|
||
// For each additional loop, trigger cues on [0, m_sequence_duration) | ||
for (std::size_t i = 1; i < loop_count; ++i) | ||
{ | ||
m_sequence->trigger_cues(0.0f, m_sequence_duration, m_context); | ||
} | ||
|
||
// Trigger cues on [0, m_position) | ||
m_sequence->trigger_cues(0.0f, m_position, m_context); | ||
} | ||
else | ||
{ | ||
// Trigger cues on [previous_position, m_position) | ||
m_sequence->trigger_cues(previous_position, m_position, m_context); | ||
} | ||
} | ||
|
||
void animation_player::play(std::shared_ptr<animation_sequence> sequence) | ||
{ | ||
m_sequence = std::move(sequence); | ||
|
||
// Determine duration of sequence | ||
if (m_sequence) | ||
{ | ||
m_sequence_duration = m_sequence->duration(); | ||
} | ||
else | ||
{ | ||
m_sequence_duration = 0.0f; | ||
} | ||
|
||
m_state = animation_player_state::playing; | ||
} | ||
|
||
void animation_player::play() | ||
{ | ||
m_state = animation_player_state::playing; | ||
} | ||
|
||
void animation_player::stop() | ||
{ | ||
m_state = animation_player_state::stopped; | ||
m_position = 0.0f; | ||
} | ||
|
||
void animation_player::rewind() | ||
{ | ||
m_position = 0.0f; | ||
} | ||
|
||
void animation_player::pause() | ||
{ | ||
m_state = animation_player_state::paused; | ||
} | ||
|
||
void animation_player::seek(float seconds) | ||
{ | ||
m_position = seconds; | ||
} | ||
|
||
void animation_player::loop(bool enabled) | ||
{ | ||
m_looping = enabled; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// SPDX-FileCopyrightText: 2023 C. J. Howard | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
|
||
#ifndef ANTKEEPER_ANIMATION_ANIMATION_PLAYER_HPP | ||
#define ANTKEEPER_ANIMATION_ANIMATION_PLAYER_HPP | ||
|
||
#include <engine/animation/animation-player-state.hpp> | ||
#include <engine/animation/animation-sequence.hpp> | ||
#include <engine/animation/animation-context.hpp> | ||
#include <memory> | ||
#include <functional> | ||
#include <map> | ||
#include <string> | ||
#include <span> | ||
#include <vector> | ||
|
||
/** | ||
* Plays animation sequences. | ||
*/ | ||
class animation_player | ||
{ | ||
public: | ||
/** | ||
* Advances the animation sequence by a given timestep. | ||
* | ||
* @param seconds Timestep, in seconds. | ||
*/ | ||
void advance(float seconds); | ||
|
||
/** | ||
* Starts playing an animation sequence. | ||
* | ||
* @param sequence Animation sequence to play. | ||
*/ | ||
void play(std::shared_ptr<animation_sequence> sequence); | ||
|
||
/** Starts playing the current animation sequence. */ | ||
void play(); | ||
|
||
/** Stops playing the current animation sequence. */ | ||
void stop(); | ||
|
||
/** Rewinds the current animation sequence. */ | ||
void rewind(); | ||
|
||
/** Pauses the current animation sequence. */ | ||
void pause(); | ||
|
||
/** | ||
* Sets the playback position of the animation player. | ||
* | ||
* @param seconds Offset from the start of an animation sequence, in seconds. | ||
*/ | ||
void seek(float seconds); | ||
|
||
/** | ||
* Enables or disables looping of the animation sequence. | ||
* | ||
* @param enabled `true` to enable looping, `false` to disable looping. | ||
*/ | ||
void loop(bool enabled); | ||
|
||
/** Returns the state of the animation player. */ | ||
[[nodiscard]] inline constexpr const auto& state() const noexcept | ||
{ | ||
return m_state; | ||
} | ||
|
||
/** Returns `true` if the animation player is stopped, `false` otherwise. */ | ||
[[nodiscard]] inline constexpr auto is_stopped() const noexcept | ||
{ | ||
return m_state == animation_player_state::stopped; | ||
} | ||
|
||
/** Returns `true` if the animation player is playing, `false` otherwise. */ | ||
[[nodiscard]] inline constexpr auto is_playing() const noexcept | ||
{ | ||
return m_state == animation_player_state::playing; | ||
} | ||
|
||
/** Returns `true` if the animation player is paused, `false` otherwise. */ | ||
[[nodiscard]] inline constexpr auto is_paused() const noexcept | ||
{ | ||
return m_state == animation_player_state::paused; | ||
} | ||
|
||
/** Returns the playback position of the animation player. */ | ||
[[nodiscard]] inline constexpr auto position() const noexcept | ||
{ | ||
return m_position; | ||
} | ||
|
||
/** Returns `true` if sequence looping is enabled, `false` otherwise. */ | ||
[[nodiscard]] inline constexpr auto is_looping() const noexcept | ||
{ | ||
return m_looping; | ||
} | ||
|
||
/** Returns a reference to the animation context of the player. */ | ||
[[nodiscard]] inline constexpr auto& context() noexcept | ||
{ | ||
return m_context; | ||
} | ||
|
||
/** @copydoc context() */ | ||
[[nodiscard]] inline constexpr const auto& context() const noexcept | ||
{ | ||
return m_context; | ||
} | ||
|
||
private: | ||
std::shared_ptr<animation_sequence> m_sequence; | ||
float m_sequence_duration{}; | ||
animation_player_state m_state{animation_player_state::stopped}; | ||
float m_position{}; | ||
bool m_looping{}; | ||
std::vector<float> m_sample_buffer; | ||
animation_context m_context{}; | ||
}; | ||
|
||
#endif // ANTKEEPER_ANIMATION_PLAYER_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.