+
+int dsys_add_track(const char *name)
+{
+ struct anm_track trk;
+ int idx;
+
+ if(rb_find(dsys.trackmap, (char*)name)) {
+ fprintf(stderr, "ignoring duplicate track: %s\n", name);
+ return -1;
+ }
+
+ idx = darr_size(dsys.track);
+ darr_push(dsys.track, &trk);
+ darr_pushf(dsys.value, 0);
+
+ anm_init_track(dsys.track + idx);
+
+ if(rb_insert(dsys.trackmap, (char*)strdup_nf(name), (void*)(intptr_t)idx) == -1) {
+ fprintf(stderr, "failed to insert to track map: %s\n", name);
+ abort();
+ }
+ dsys.num_tracks = idx + 1;
+ return idx;
+}
+
+int dsys_find_track(const char *name)
+{
+ struct rbnode *n = rb_find(dsys.trackmap, (char*)name);
+ if(!n) return -1;
+
+ return (intptr_t)n->data;
+}
+
+float dsys_value(const char *name)
+{
+ int idx = dsys_find_track(name);
+ return idx == -1 ? 0.0f : dsys.value[idx];
+}
+
+static void del_rbnode(struct rbnode *node, void *cls)
+{
+ free(node->key);
+}