+#include <stdio.h>
+#include <map>
+#include <string>
+
+#include <gmath/gmath.h>
+
+#include "state_manager.h"
+
+StateManager state_manager;
+
+State *StateManager::get_state(const char *name)
+{
+ std::map<std::string, int>::iterator it;
+ it = statemap.find(name);
+ return it == statemap.end() ? 0 : &states[it->second];
+}
+
+int StateManager::add_state_element(const char *name, int num_floats)
+{
+ State *st = get_state(name);
+ if(st) {
+ if(st->num != num_floats) {
+ fprintf(stderr, "Uniform %s, type mismatch!\n", name);
+ return -1;
+ }
+
+ return st - &states[0];
+ }
+
+ State state;
+ state.num = num_floats;
+
+ state.name = new char[strlen(name) + 1];
+ strcpy(state.name, name);
+
+ int sz = sizeof *state.data * num_floats;
+ state.data = new float[sz];
+ memset(state.data, 0, sz);
+
+ int idx = (int)states.size();
+ states.push_back(state);
+
+ statemap[name] = idx;
+
+ printf("State manager: added state %s with %d float data.\n", name, num_floats);
+ return idx;
+}
+
+void StateManager::set_state(const char *name, float value)
+{
+ set_state(name, Vec4(value, 0, 0, 1));
+}
+
+void StateManager::set_state(const char *name, const Vec3 &vec)
+{
+ set_state(name, Vec4(vec.x, vec.y, vec.z, 1));
+}
+
+void StateManager::set_state(const char *name, const Vec4 &vec)
+{
+ State *state = get_state(name);
+ if(!state)
+ return;
+
+ switch(state->num) {
+ case 4:
+ state->data[3] = vec.w;
+ case 3:
+ state->data[2] = vec.z;
+ case 2:
+ state->data[1] = vec.y;
+ case 1:
+ state->data[0] = vec.x;
+ default:
+ break;
+ }
+}
+
+void StateManager::set_state(const char *name, const Mat4 &mat)
+{
+ State *state = get_state(name);
+
+ if(!state)
+ return;
+
+ if(state->num != 16) {
+ fprintf(stderr, "State manager: state %s can only be a 4x4 matrix.\n", name);
+ return;
+ }
+
+ for(int j=0; j<4; j++) {
+ for(int i=0; i<4; i++) {
+ state->data[4 * i + j] = mat.m[i][j];
+ }
+ }
+}
+
+const State *StateManager::get_state(const char *name) const
+{
+ return ((StateManager *)this)->get_state(name);
+}
+
+const State *StateManager::get_state(int idx) const
+{
+ return &states[idx];
+}
\ No newline at end of file