Olympe Engine 2.0
2D Game Engine with ECS Architecture
Loading...
Searching...
No Matches
AnimationTypes.h
Go to the documentation of this file.
1/*
2Olympe Engine V2 2025
3Animation System - Common Types
4
5Purpose:
6- Define common types, enums, and structures used throughout the animation system
7- Provides shared data structures for AnimationBank, AnimationGraph, and AnimationManager
8*/
9/**
10 * @file AnimationTypes.h
11 * @brief Core animation data structures for 2D sprite animation system
12 * @author Nicolas Chereau
13 * @date 2025
14 *
15 * Defines data structures for frame-based sprite animation including:
16 * - AnimationFrame: Individual frame data
17 * - AnimationSequence: Complete animation with frames and playback settings
18 * - AnimationBank: Collection of animations for an entity
19 * - AnimationGraph: State machine for animation transitions
20 */
21
22#pragma once
23
24#include <string>
25#include <vector>
26#include <SDL3/SDL.h>
27
28// Forward declarations
30
31namespace OlympeAnimation
32{
33 // ========================================================================
34 // Hotspot - 2D position for sprite anchor points
35 // Note: We don't reuse the engine's Vector class here to keep the
36 // animation system decoupled and use a simple POD structure
37 // ========================================================================
38 struct Hotspot
39 {
40 float x = 0.0f;
41 float y = 0.0f;
42
43 Hotspot() = default;
44 Hotspot(float _x, float _y) : x(_x), y(_y) {}
45 };
46
47 // ========================================================================
48 // Blend Mode - How animations blend together
49 // ========================================================================
50 enum class BlendMode
51 {
52 Override, // Replace current animation completely
53 Additive, // Add to current animation
54 Blend // Smooth blend between animations
55 };
56
57 // ========================================================================
58 // Transition Type - How transitions are evaluated
59 // ========================================================================
60 enum class TransitionType
61 {
62 Immediate, // Instant transition
63 Smooth, // Smooth blend over time
64 AfterComplete // Wait for current animation to complete
65 };
66
67 // ========================================================================
68 // Parameter Type - Types of parameters in animation graph
69 // ========================================================================
70 enum class ParameterType
71 {
72 Bool,
73 Float,
74 Int,
75 String
76 };
77
78 // ========================================================================
79 // Comparison Operator - For condition evaluation
80 // ========================================================================
82 {
83 Equal, // ==
84 NotEqual, // !=
85 Greater, // >
86 GreaterOrEqual, // >=
87 Less, // <
88 LessOrEqual // <=
89 };
90
91 // ========================================================================
92 // Parameter Value - Union for storing different parameter types
93 // ========================================================================
111
112 // ========================================================================
113 // Animation Event Data - Events triggered during animation playback
114 // ========================================================================
116 {
117 std::string type; // Event type: "sound", "hitbox", "vfx", "gamelogic"
118 int frame = 0; // Frame number to trigger on
119 std::string dataJson; // JSON string with event-specific data
120 };
121
122} // namespace OlympeAnimation
123#include <unordered_map>
124#include <SDL3/SDL.h>
125
126namespace Olympe
127{
128
129/**
130 * @struct SpritesheetInfo
131 * @brief Metadata for a single spritesheet within an animation bank
132 */
134{
135 std::string id; ///< Unique identifier (e.g., "thesee_idle")
136 std::string path; ///< Relative path to image
137 std::string description;
138
139 int frameWidth = 0; ///< Width of each frame in pixels
140 int frameHeight = 0; ///< Height of each frame in pixels
141 int columns = 0; ///< Number of columns in spritesheet
142 int rows = 0; ///< Number of rows in spritesheet
143 int totalFrames = 0; ///< Total number of frames available
144 int spacing = 0; ///< Spacing between frames in pixels
145 int margin = 0; ///< Margin around spritesheet edges
146
147 SDL_FPoint hotspot = {0.0f, 0.0f}; ///< Default hotspot/pivot point
148
149 SpritesheetInfo() = default;
150};
151
152/**
153 * @brief Represents a single frame in an animation (DEPRECATED - use SpritesheetInfo + frame ranges)
154 */
156{
157 SDL_FRect srcRect; ///< Source rectangle in spritesheet (x, y, w, h)
158 float duration; ///< Duration of this frame in seconds
159 SDL_FPoint hotSpot; ///< Render offset (pivot point)
160 std::string eventName; ///< Optional event triggered when this frame starts (empty if none)
161
163 : srcRect{0, 0, 0, 0}
164 , duration(0.1f)
165 , hotSpot{0, 0}
166 , eventName("")
167 {}
168};
169
170/**
171 * @brief Defines a complete animation sequence
172 */
174{
175 std::string name; ///< Animation name (e.g., "idle", "walk")
176 std::string spritesheetId; ///< References SpritesheetInfo.id
177
178 int startFrame = 0; ///< Starting frame index (0-based)
179 int frameCount = 1; ///< Number of frames in sequence
180
181 float frameDuration = 0.1f; ///< Duration of each frame in seconds
182 bool loop = true; ///< Whether animation loops
183 float speed = 1.0f; ///< Speed multiplier
184 std::string nextAnimation; ///< Animation to play after this one
185
186 // DEPRECATED: Old frame-by-frame approach (kept for backward compatibility)
187 std::string spritesheetPath; ///< Path to spritesheet texture
188 std::vector<AnimationFrame> frames; ///< Frame data
189
191 : name("")
192 , spritesheetId("")
193 , startFrame(0)
194 , frameCount(1)
195 , frameDuration(0.1f)
196 , loop(true)
197 , speed(1.0f)
198 , nextAnimation("")
199 , spritesheetPath("")
200 {}
201
202 float GetTotalDuration() const {
203 return frameCount * frameDuration / speed;
204 }
205
206 float GetEffectiveFPS() const {
207 return (frameDuration > 0.0f) ? (1.0f / frameDuration) * speed : 0.0f;
208 }
209
210 int GetFrameCount() const {
211 // Support both old and new formats
212 return frames.empty() ? frameCount : static_cast<int>(frames.size());
213 }
214};
215
216/**
217 * @brief Collection of animations for an entity with multi-spritesheet support
218 */
220{
221 std::string bankId; ///< Unique identifier for this animation bank
222 std::string description;
223 std::string author;
224 std::string createdDate;
225 std::string lastModifiedDate;
226 std::vector<std::string> tags;
227
228 // Multi-spritesheet support (NEW)
229 std::vector<SpritesheetInfo> spritesheets;
230
231 // DEPRECATED: Old single-spritesheet metadata (kept for backward compatibility)
232 int frameWidth; ///< Width of each frame in pixels
233 int frameHeight; ///< Height of each frame in pixels
234 int columns; ///< Number of columns in spritesheet
235 int spacing; ///< Spacing between frames in pixels
236 int margin; ///< Margin around spritesheet edges in pixels
237
238 // Animation sequences
239 std::unordered_map<std::string, AnimationSequence> animations;
240
242 : bankId("")
243 , description("")
244 , author("")
245 , createdDate("")
246 , lastModifiedDate("")
247 , frameWidth(32)
248 , frameHeight(32)
249 , columns(1)
250 , spacing(0)
251 , margin(0)
252 {}
253
254 /**
255 * @brief Get spritesheet by ID
256 * @param id Spritesheet identifier
257 * @return Pointer to SpritesheetInfo if found, nullptr otherwise
258 */
259 const SpritesheetInfo* GetSpritesheet(const std::string& id) const
260 {
261 for (const auto& sheet : spritesheets)
262 {
263 if (sheet.id == id)
264 return &sheet;
265 }
266 return nullptr;
267 }
268
269 SpritesheetInfo* GetSpritesheet(const std::string& id)
270 {
271 for (auto& sheet : spritesheets)
272 {
273 if (sheet.id == id)
274 return &sheet;
275 }
276 return nullptr;
277 }
278
279 /**
280 * @brief Get animation sequence by name
281 * @param name Animation name
282 * @return Pointer to AnimationSequence if found, nullptr otherwise
283 */
284 const AnimationSequence* GetSequence(const std::string& name) const
285 {
286 auto it = animations.find(name);
287 return (it != animations.end()) ? &it->second : nullptr;
288 }
289
290 AnimationSequence* GetSequence(const std::string& name)
291 {
292 auto it = animations.find(name);
293 return (it != animations.end()) ? &it->second : nullptr;
294 }
295
296 /**
297 * @brief DEPRECATED: Calculate source rectangle for a frame based on spritesheet layout
298 * @param frameIndex Frame index (0-based)
299 * @return Source rectangle in spritesheet coordinates
300 */
302 {
303 int row = frameIndex / columns;
304 int col = frameIndex % columns;
305
307 rect.x = static_cast<float>(margin + col * (frameWidth + spacing));
308 rect.y = static_cast<float>(margin + row * (frameHeight + spacing));
309 rect.w = static_cast<float>(frameWidth);
310 rect.h = static_cast<float>(frameHeight);
311
312 return rect;
313 }
314
315 /**
316 * @brief DEPRECATED: Get animation sequence by name (use GetSequence() instead)
317 * @param name Animation name
318 * @return Pointer to AnimationSequence if found, nullptr otherwise
319 * @deprecated Use GetSequence() for consistency with new API
320 */
321 const AnimationSequence* GetAnimation(const std::string& name) const
322 {
323 return GetSequence(name);
324 }
325};
326
327/**
328 * @struct AnimationState
329 * @brief Single state in FSM
330 */
332{
333 std::string name;
334 std::string animation;
335 std::vector<std::string> transitions;
336
338};
339
340/**
341 * @brief Animation state machine (FSM) for managing transitions
342 */
344{
345 std::string graphId; ///< Unique identifier for this graph
346 std::string defaultState; ///< Initial animation state
347
348 // State machine data
349 std::unordered_map<std::string, AnimationState> states;
350
352 : graphId("")
353 , defaultState("")
354 {}
355
356 /**
357 * @brief Get state by name
358 * @param name State name to search for
359 * @return Pointer to state, or nullptr if not found
360 */
361 const AnimationState* GetState(const std::string& name) const
362 {
363 auto it = states.find(name);
364 return (it != states.end()) ? &it->second : nullptr;
365 }
366
367 /**
368 * @brief Check if transition from one state to another is valid
369 * @param from Source animation state
370 * @param to Target animation state
371 * @return true if transition is allowed
372 */
373 bool CanTransition(const std::string& from, const std::string& to) const
374 {
375 // Always allow transitioning to the same state (restart)
376 if (from == to)
377 return true;
378
379 // Check if explicit transition exists
380 auto it = states.find(from);
381 if (it == states.end())
382 return false;
383
384 for (const auto& target : it->second.transitions)
385 {
386 if (target == to)
387 return true;
388 }
389
390 return false;
391 }
392};
393
394} // namespace Olympe
SDL_Texture * TextureHandle
ComponentTypeID GetComponentTypeID_Static()
Definition ECS_Entity.h:56
Hotspot(float _x, float _y)
ParameterValue(const std::string &val)
Collection of animations for an entity with multi-spritesheet support.
int margin
Margin around spritesheet edges in pixels.
std::string bankId
Unique identifier for this animation bank.
const AnimationSequence * GetSequence(const std::string &name) const
Get animation sequence by name.
std::vector< SpritesheetInfo > spritesheets
int frameWidth
Width of each frame in pixels.
SpritesheetInfo * GetSpritesheet(const std::string &id)
int frameHeight
Height of each frame in pixels.
AnimationSequence * GetSequence(const std::string &name)
const SpritesheetInfo * GetSpritesheet(const std::string &id) const
Get spritesheet by ID.
SDL_FRect CalculateFrameRect(int frameIndex) const
DEPRECATED: Calculate source rectangle for a frame based on spritesheet layout.
std::vector< std::string > tags
int columns
Number of columns in spritesheet.
std::unordered_map< std::string, AnimationSequence > animations
const AnimationSequence * GetAnimation(const std::string &name) const
DEPRECATED: Get animation sequence by name (use GetSequence() instead)
int spacing
Spacing between frames in pixels.
Represents a single frame in an animation (DEPRECATED - use SpritesheetInfo + frame ranges)
SDL_FRect srcRect
Source rectangle in spritesheet (x, y, w, h)
SDL_FPoint hotSpot
Render offset (pivot point)
std::string eventName
Optional event triggered when this frame starts (empty if none)
float duration
Duration of this frame in seconds.
Animation state machine (FSM) for managing transitions.
bool CanTransition(const std::string &from, const std::string &to) const
Check if transition from one state to another is valid.
const AnimationState * GetState(const std::string &name) const
Get state by name.
std::unordered_map< std::string, AnimationState > states
std::string graphId
Unique identifier for this graph.
std::string defaultState
Initial animation state.
Defines a complete animation sequence.
bool loop
Whether animation loops.
int frameCount
Number of frames in sequence.
std::string spritesheetPath
Path to spritesheet texture.
int startFrame
Starting frame index (0-based)
std::vector< AnimationFrame > frames
Frame data.
std::string name
Animation name (e.g., "idle", "walk")
float frameDuration
Duration of each frame in seconds.
std::string nextAnimation
Animation to play after this one.
float speed
Speed multiplier.
std::string spritesheetId
References SpritesheetInfo.id.
Single state in FSM.
std::vector< std::string > transitions
Metadata for a single spritesheet within an animation bank.
int totalFrames
Total number of frames available.
int rows
Number of rows in spritesheet.
int frameHeight
Height of each frame in pixels.
int columns
Number of columns in spritesheet.
int frameWidth
Width of each frame in pixels.
std::string path
Relative path to image.
SDL_FPoint hotspot
Default hotspot/pivot point.
int margin
Margin around spritesheet edges.
std::string id
Unique identifier (e.g., "thesee_idle")
int spacing
Spacing between frames in pixels.