Skip to content

Instantly share code, notes, and snippets.

@Faultz
Last active June 3, 2022 01:35
Show Gist options
  • Save Faultz/e175bb69c1f95344f1222efd81152d81 to your computer and use it in GitHub Desktop.
Save Faultz/e175bb69c1f95344f1222efd81152d81 to your computer and use it in GitHub Desktop.
Animation class for C++
#include "stdafx.h"
#define clamp(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
animations g_anim;
void animation_data::process_animation()
{
float elapsed_time = static_cast<float>(move - start_data);
float delta_time = static_cast<float>(get_time_now() - start_time);
float scale = clamp(delta_time / duration, 0.0f, 1.0f);
float progression = static_cast<float>(elapsed_time * interpolate(scale));
*data = start_data + progression;
if (get_time_now() >= end_time)
{
for (int i = 0; i < g_anim.animation_stack.size(); i++)
{
if (this->id == g_anim.animation_stack[i].id)
{
auto callback = g_anim.animation_stack[i].callback;
if (callback)
callback();
g_anim.animation_stack.erase(g_anim.animation_stack.begin() + i);
}
}
}
}
void animation_data::add_animation(const char* name, void(*callback)(), float(*interpolate)(float), float* data, int* move, int duration)
{
if (animations::already_added(name))
return;
animation_data newAnim = animation_data();
newAnim.id = hash(name);
newAnim.interpolate = interpolate;
newAnim.start_time = get_time_now();
newAnim.duration = duration;
newAnim.end_time = newAnim.start_time + newAnim.duration;
newAnim.data = data;
newAnim.move = *(float*)move;
newAnim.start_data = *(float*)newAnim.data;
newAnim.callback = callback;
g_anim.animation_stack.push_back(newAnim);
}
void animations::add_animation(const char* name, void(*callback)(), float(*interpolate)(float), float* data, float move, clock_t duration)
{
if (*data == move || interpolate == nullptr) return;
animation_data::add_animation(name, callback, interpolate, (float*)data, (int*)&move, duration);
}
void animations::add_animation(const char* name, void(*callback)(), float(*interpolate)(float), int* data, int move, clock_t duration)
{
if (*data == move || interpolate == nullptr) return;
animation_data::add_animation(name, callback, interpolate, (float*)data, &move, duration);
}
void animations::add_animation(const char* name, void(*callback)(), float(*interpolate)(float), vec2_t* data, vec2_t move, clock_t duration)
{
if (*data == move || interpolate == nullptr) return;
animation_data::add_animation(name, callback, interpolate, (float*)&data->x, (int*)&move.x, duration);
animation_data::add_animation(va("%s_2", name), callback, interpolate, (float*)&data->y, (int*)&move.y, duration);
}
void animations::add_animation(const char* name, void(*callback)(), float(*interpolate)(float), vec3_t* data, vec3_t move, clock_t duration)
{
if (*data == move || interpolate == nullptr) return;
animation_data::add_animation(name, callback, interpolate, (float*)&data->x, (int*)&move.x, duration);
animation_data::add_animation(va("%s_1", name), callback, interpolate, (float*)&data->y, (int*)&move.y, duration);
animation_data::add_animation(va("%s_2", name), callback, interpolate, (float*)&data->z, (int*)&move.z, duration);
}
void animations::run_frame()
{
for (animation_data anim : animation_stack)
anim.process_animation();
}
animation_data* animations::find_anim(anim_id id)
{
for (auto anim : g_anim.animation_stack)
if (anim.id == id)
return &anim;
return nullptr;
}
animation_data* animations::find_anim(const char* id_name)
{
const auto& hashed_id = hash(id_name);
for (auto anim : g_anim.animation_stack)
if (anim.id == hashed_id)
return &anim;
return nullptr;
}
bool animations::already_added(anim_id id)
{
for (int i = 0; i < g_anim.animation_stack.size(); i++)
{
if (g_anim.animation_stack[i].id == id)
return true;
}
return false;
}
bool animations::already_added(const char* id_name)
{
for (int i = 0; i < g_anim.animation_stack.size(); i++)
{
if (g_anim.animation_stack[i].id == hash(id_name))
return true;
}
return false;
}
#pragma once
typedef uint32_t anim_id;
class animation_data
{
public:
anim_id id;
int start_time;
int move_time;
int end_time;
void(*callback)();
float(*interpolate)(float val);
float* data;
float start_data;
float move;
int duration;
void process_animation();
static void add_animation(const char* name, void(*callback)(), float(*interpolate)(float), float* data, int* move, int duration);
};
class animations
{
public:
~animations()
{
animation_stack.clear();
}
void add_animation(const char* name, void(*callback)(), float(*interpolate)(float), float* data, float move, clock_t duration);
void add_animation(const char* name, void(*callback)(), float(*interpolate)(float), int* data, int move, clock_t duration);
void add_animation(const char* name, void(*callback)(), float(*interpolate)(float), vec2_t* data, vec2_t move, clock_t duration);
void add_animation(const char* name, void(*callback)(), float(*interpolate)(float), vec3_t* data, vec3_t move, clock_t duration);
void run_frame();
animation_data* find_anim(anim_id id);
animation_data* find_anim(const char* id_name);
static bool already_added(anim_id id);
static bool already_added(const char* id_name);
std::vector<animation_data> animation_stack;
};
extern animations g_anim;
#pragma once
inline uint32_t hash(const char* str)
{
uint64_t hash = 0xCBF29CE484222325;
while(*str)
{
hash =
(hash ^ uint32_t((*str >= 'A' && *str <= 'Z') ? *str - ('A' - 'a') : *str)) * 0x100000001B3;
str++;
}
return hash;
}
namespace easing
{
#pragma once
constexpr float m_pi = 3.14159265358979323846;
inline float linear(const float t)
{
return t;
}
inline float in_sine(const float t)
{
return sinf(1.5707963 * t);
}
inline float out_sine(float t)
{
return 1 + sinf(1.5707963 * (--t));
}
inline float in_out_sine(const float t)
{
return 0.5 * (1 + sinf(3.1415926 * (t - 0.5)));
}
inline float inquad(const float t)
{
return t * t;
}
inline float out_quad(const float t)
{
return t * (2 - t);
}
inline float in_out_quad(const float t)
{
return t < 0.5 ? 2 * t * t : t * (4 - 2 * t) - 1;
}
inline float in_cubic(const float t)
{
return t * t * t;
}
inline float out_cubic(float t)
{
return 1 + (--t) * t * t;
}
inline float in_out_cubic(float t)
{
return t < 0.5 ? 4 * t * t * t : 1 + (--t) * (2 * (--t)) * (2 * t);
}
inline float in_quart(float t)
{
t *= t;
return t * t;
}
inline float out_quart(float t)
{
t = (--t) * t;
return 1 - t * t;
}
inline float in_out_quart(float t)
{
if (t < 0.5)
{
t *= t;
return 8 * t * t;
}
else
{
t = (--t) * t;
return 1 - 8 * t * t;
}
}
inline float in_quint(const float t)
{
const float t2 = t * t;
return t * t2 * t2;
}
inline float out_quint(float t)
{
const float t2 = (--t) * t;
return 1 + t * t2 * t2;
}
inline float in_out_quint(float t)
{
float t2;
if (t < 0.5)
{
t2 = t * t;
return 16 * t * t2 * t2;
}
else
{
t2 = (--t) * t;
return 1 + 16 * t * t2 * t2;
}
}
inline float in_expo(const float t)
{
return (powf(2, 8 * t) - 1) / 255;
}
inline float out_expo(const float t)
{
return 1 - powf(2, -8 * t);
}
inline float in_out_expo(const float t)
{
if (t < 0.5)
{
return (powf(2, 16 * t) - 1) / 510;
}
else
{
return 1 - 0.5 * powf(2, -16 * (t - 0.5));
}
}
inline float in_circ(const float t)
{
return 1 - sqrtf(1 - t);
}
inline float out_circ(const float t)
{
return sqrtf(t);
}
inline float in_out_circ(const float t)
{
if (t < 0.5)
{
return (1 - sqrtf(1 - 2 * t)) * 0.5;
}
else
{
return (1 + sqrtf(2 * t - 1)) * 0.5;
}
}
inline float in_back(const float t)
{
return t * t * (2.70158 * t - 1.70158);
}
inline float out_back(float t)
{
return 1 + (--t) * t * (2.70158 * t + 1.70158);
}
inline float in_out_back(float t)
{
if (t < 0.5)
{
return t * t * (7 * t - 2.5) * 2;
}
else
{
return 1 + (--t) * t * 2 * (7 * t + 2.5);
}
}
inline float in_elastic(const float t)
{
const float t2 = t * t;
return t2 * t2 * sinf(t * m_pi * 4.5);
}
inline float out_elastic(const float t)
{
const float t2 = (t - 1) * (t - 1);
return 1 - t2 * t2 * cosf(t * m_pi * 4.5);
}
inline float in_out_elastic(const float t)
{
float t2;
if (t < 0.45)
{
t2 = t * t;
return 8 * t2 * t2 * sinf(t * m_pi * 9);
}
else if (t < 0.55)
{
return 0.5 + 0.75 * sinf(t * m_pi * 4);
}
else
{
t2 = (t - 1) * (t - 1);
return 1 - 8 * t2 * t2 * sinf(t * m_pi * 9);
}
}
inline float in_bounce(const float t)
{
return powf(2, 6 * (t - 1)) * fabsf(sinf(t * m_pi * 3.5));
}
inline float out_bounce(const float t)
{
return 1 - powf(2, -6 * t) * fabsf(cosf(t * m_pi * 3.5));
}
inline float in_out_bounce(const float t)
{
if (t < 0.5)
{
return 8 * powf(2, 8 * (t - 1)) * fabsf(sinf(t * m_pi * 7));
}
else
{
return 1 - 8 * powf(2, -8 * t) * fabsf(sinf(t * m_pi * 7));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment