about summary refs log tree commit diff
path: root/src/game/client/animstate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/game/client/animstate.cpp')
-rw-r--r--src/game/client/animstate.cpp95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/game/client/animstate.cpp b/src/game/client/animstate.cpp
new file mode 100644
index 00000000..d8c20dec
--- /dev/null
+++ b/src/game/client/animstate.cpp
@@ -0,0 +1,95 @@
+
+#include <base/math.hpp>
+#include <engine/e_client_interface.h>
+#include <game/generated/g_protocol.hpp>
+#include <game/generated/gc_data.hpp>
+
+#include "animstate.hpp"
+
+static void anim_seq_eval(ANIM_SEQUENCE *seq, float time, ANIM_KEYFRAME *frame)
+{
+	if(seq->num_frames == 0)
+	{
+		frame->time = 0;
+		frame->x = 0;
+		frame->y = 0;
+		frame->angle = 0;
+	}
+	else if(seq->num_frames == 1)
+	{
+		*frame = seq->frames[0];
+	}
+	else
+	{
+		//time = max(0.0f, min(1.0f, time / duration)); // TODO: use clamp
+		ANIM_KEYFRAME *frame1 = 0;
+		ANIM_KEYFRAME *frame2 = 0;
+		float blend = 0.0f;
+
+		// TODO: make this smarter.. binary search
+		for (int i = 1; i < seq->num_frames; i++)
+		{
+			if (seq->frames[i-1].time <= time && seq->frames[i].time >= time)
+			{
+				frame1 = &seq->frames[i-1];
+				frame2 = &seq->frames[i];
+				blend = (time - frame1->time) / (frame2->time - frame1->time);
+				break;
+			}
+		}
+
+		if (frame1 && frame2)
+		{
+			frame->time = time;
+			frame->x = mix(frame1->x, frame2->x, blend);
+			frame->y = mix(frame1->y, frame2->y, blend);
+			frame->angle = mix(frame1->angle, frame2->angle, blend);
+		}
+	}
+}
+
+static void anim_add_keyframe(ANIM_KEYFRAME *seq, ANIM_KEYFRAME *added, float amount)
+{
+	seq->x += added->x*amount;
+	seq->y += added->y*amount;
+	seq->angle += added->angle*amount;
+}
+
+static void anim_add(ANIMSTATE *state, ANIMSTATE *added, float amount)
+{
+	anim_add_keyframe(&state->body, &added->body, amount);
+	anim_add_keyframe(&state->back_foot, &added->back_foot, amount);
+	anim_add_keyframe(&state->front_foot, &added->front_foot, amount);
+	anim_add_keyframe(&state->attach, &added->attach, amount);
+}
+
+
+void ANIMSTATE::set(ANIMATION *anim, float time)
+{
+	anim_seq_eval(&anim->body, time, &body);
+	anim_seq_eval(&anim->back_foot, time, &back_foot);
+	anim_seq_eval(&anim->front_foot, time, &front_foot);
+	anim_seq_eval(&anim->attach, time, &attach);
+}
+
+void ANIMSTATE::add(ANIMATION *anim, float time, float amount)
+{
+	ANIMSTATE add;
+	add.set(anim, time);
+	anim_add(this, &add, amount);
+}
+
+ANIMSTATE *ANIMSTATE::get_idle()
+{
+	static ANIMSTATE state;
+	static bool init = true;
+	
+	if(init)
+	{
+		state.set(&data->animations[ANIM_BASE], 0);
+		state.add(&data->animations[ANIM_IDLE], 0, 1.0f);
+		init = false;
+	}
+	
+	return &state;
+}