Skip to content

Commit 7fea2c7

Browse files
committed
create immediate mode animation for tsoding
1 parent 85e0d37 commit 7fea2c7

File tree

5 files changed

+395
-0
lines changed

5 files changed

+395
-0
lines changed

nob.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ int main(int argc, char **argv)
122122
if (!build_plug_c(force, PLUGS_DIR"template/plug.c", BUILD_DIR"libtemplate.so")) return 1;
123123
if (!build_plug_c(force, PLUGS_DIR"squares/plug.c", BUILD_DIR"libsquare.so")) return 1;
124124
if (!build_plug_c(force, PLUGS_DIR"tsoding/plug.c", BUILD_DIR"libtsoding.so")) return 1;
125+
if (!build_plug_c(force, PLUGS_DIR"imtsoding/plug.c", BUILD_DIR"libimtsoding.so")) return 1;
125126
if (!build_plug_c(force, PLUGS_DIR"bezier/plug.c", BUILD_DIR"libbezier.so")) return 1;
126127
if (!build_plug_cxx(force, PLUGS_DIR"cpp/plug.cpp", BUILD_DIR"libcpp.so")) return 1;
127128

plugs/imtsoding/imanim.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
2+
3+
float clipTime(AnimState *a, float duration) {
4+
float timeSinceStart = a->currentTime - a->clipStartTime;
5+
float animT = timeSinceStart / duration;
6+
if(animT < 0) //before the clip requested
7+
animT = 0.f;
8+
if(animT > 1) //after the clip requested
9+
animT = 1.f;
10+
11+
if(a->globEnd < (a->clipStartTime + duration))
12+
a->globEnd = a->clipStartTime + duration;
13+
14+
return animT;
15+
}
16+
float prevClipTime(AnimState *a, float duration) {
17+
float timeSinceStart = a->currentTime - a->deltaTime - a->clipStartTime;
18+
float animT = timeSinceStart / duration;
19+
if(animT < 0) //before the clip requested
20+
animT = 0.f;
21+
if(animT > 1) //after the clip requested
22+
animT = 1.f;
23+
24+
if(a->globEnd < (a->clipStartTime + duration))
25+
a->globEnd = a->clipStartTime + duration;
26+
27+
return animT;
28+
}
29+
30+
void anim_wait(AnimState *a, float duration) {
31+
if(a->globEnd < (a->clipStartTime + duration))
32+
a->globEnd = a->clipStartTime + duration;
33+
a->clipStartTime = a->globEnd;
34+
}
35+
36+
void wait_for_end(AnimState *a){
37+
a->clipStartTime = a->globEnd;
38+
}
39+
40+
void anim_move_scalar(AnimState *anim, float *src, float dst, float duration, Interp_Func func)
41+
{
42+
float t = interp_func(func, clipTime(anim, duration));
43+
if(t<=0.0f) return;
44+
if(t>=1.0f) {
45+
*src = dst; return;
46+
}
47+
*src = Lerp(*src, dst, t);
48+
}
49+
50+
void anim_move_vec2(AnimState *anim, Vector2 *src, Vector2 dst, float duration, Interp_Func func)
51+
{
52+
float t = interp_func(func, clipTime(anim, duration));
53+
if(t<=0.0f) return;
54+
if(t>=1.0f) {
55+
*src = dst; return;
56+
}
57+
*src = Vector2Lerp(*src, dst, t);
58+
}
59+
60+
void anim_move_vec4(AnimState *anim, Vector4 *src, Vector4 dst, float duration, Interp_Func func)
61+
{
62+
float t = interp_func(func, clipTime(anim, duration));
63+
if(t<=0.0f) return;
64+
if(t>=1.0f) {
65+
*src = dst; return;
66+
}
67+
*src = Vector4Lerp(*src, dst, t);
68+
}

plugs/imtsoding/imanim.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include "interpolators.h"
2+
#include <raymath.h>
3+
4+
typedef struct {
5+
float currentTime; // time since start of the animation, increment with deltaTime every frame
6+
float clipStartTime; // where the code is in the animation, only updated by a "wait" operation, reset every frame.
7+
float globEnd; // when the animation ends, updated by clipTime, reset every frame.
8+
float deltaTime;
9+
10+
} AnimState;
11+
12+
/*
13+
* returns a value between [0.0, 1.0] representing at which point
14+
* the current time the animation is in.
15+
* a 0.0 return value represents that the current clip hasn't started yet
16+
* a 1.0 return value represents that the current clip is fully finished
17+
*
18+
* updates the globEnd value used in wait_for_end
19+
*/
20+
float clipTime(AnimState *a, float duration);
21+
22+
/*
23+
* returns a value between [0.0, 1.0] representing at which point
24+
* the time the animation was in last frame.
25+
*
26+
* updates the globEnd value used in wait_for_end
27+
*
28+
* this is useful for sound triggers
29+
*
30+
* if(clipTime(anim, 0.1f) > 0 && prevClipTime(anim, 0.1f) == 0.0)
31+
* p->env.play_sound(p->kick_sound, p->kick_wave);
32+
*/
33+
float prevClipTime(AnimState *a, float duration);
34+
35+
/*
36+
* advances the clipStartTime
37+
*/
38+
void anim_wait(AnimState *a, float duration) ;
39+
void wait_for_end(AnimState *a);
40+
41+
/*
42+
* utilities for interpolating floats using clipTime(anim, duration)
43+
*
44+
* if clipTime would return 0.0f it is a noop
45+
* if clipTime(anim, duration) would return 1.0f does `*src = dst;`
46+
*/
47+
void anim_move_scalar(AnimState *anim, float *src, float dst, float duration, Interp_Func func);
48+
void anim_move_vec2(AnimState *anim, Vector2 *src, Vector2 dst, float duration, Interp_Func func);
49+
void anim_move_vec4(AnimState *anim, Vector4 *src, Vector4 dst, float duration, Interp_Func func);

plugs/imtsoding/interpolators.h

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#ifndef INTERPOLATORS_H_
2+
#define INTERPOLATORS_H_
3+
4+
#include <assert.h>
5+
#include <math.h>
6+
#include <raymath.h>
7+
8+
typedef enum {
9+
FUNC_ID,
10+
FUNC_SINSTEP,
11+
FUNC_SMOOTHSTEP,
12+
FUNC_SQR,
13+
FUNC_SQRT,
14+
FUNC_SINPULSE,
15+
} Interp_Func;
16+
17+
static inline float smoothstep(float x)
18+
{
19+
if (x < 0.0) return 0.0;
20+
if (x >= 1.0) return 1.0;
21+
return 3*x*x - 2*x*x*x;
22+
}
23+
24+
static inline float sinstep(float t)
25+
{
26+
if (t < 0.0) return 0.0;
27+
if (t >= 1.0) return 1.0;
28+
return (sinf(PI*t - PI*0.5) + 1)*0.5;
29+
}
30+
31+
static inline float sinpulse(float t)
32+
{
33+
if (t < 0.0) return 0.0;
34+
if (t >= 1.0) return 0.0;
35+
return sinf(PI*t);
36+
}
37+
38+
static inline Vector2 cubic_bezier(float t, Vector2 nodes[4])
39+
{
40+
float it = 1 - t;
41+
Vector2 b = Vector2Scale(nodes[0], it*it*it);
42+
b = Vector2Add(b, Vector2Scale(nodes[1], 3*it*it*t));
43+
b = Vector2Add(b, Vector2Scale(nodes[2], 3*it*t*t));
44+
b = Vector2Add(b, Vector2Scale(nodes[3], t*t*t));
45+
return b;
46+
}
47+
48+
static inline Vector2 cubic_bezier_der(float t, Vector2 nodes[4])
49+
{
50+
float it = 1 - t;
51+
Vector2 b = Vector2Scale(nodes[0], -3*it*it);
52+
b = Vector2Add(b, Vector2Scale(nodes[1], 3*it*it));
53+
b = Vector2Add(b, Vector2Scale(nodes[1], -6*it*t));
54+
b = Vector2Add(b, Vector2Scale(nodes[2], 6*it*t));
55+
b = Vector2Add(b, Vector2Scale(nodes[2], -3*t*t));
56+
b = Vector2Add(b, Vector2Scale(nodes[3], 3*t*t));
57+
return b;
58+
}
59+
60+
static inline float cuber_bezier_newton(float x, Vector2 nodes[4], size_t n)
61+
{
62+
float t = 0;
63+
for (size_t i = 0; i < n; ++i) {
64+
t = t - (cubic_bezier(t, nodes).x - x)/cubic_bezier_der(t, nodes).x;
65+
}
66+
return t;
67+
}
68+
69+
static inline float interp_func(Interp_Func func, float t)
70+
{
71+
switch (func) {
72+
case FUNC_ID: return t;
73+
case FUNC_SQR: return t*t;
74+
case FUNC_SQRT: return sqrtf(t);
75+
case FUNC_SINSTEP: return sinstep(t);
76+
case FUNC_SMOOTHSTEP: return smoothstep(t);
77+
case FUNC_SINPULSE: return sinpulse(t);
78+
}
79+
assert(0 && "UNREACHABLE");
80+
return 0.0f;
81+
}
82+
83+
#endif // INTERPOLATORS_H_

0 commit comments

Comments
 (0)