+
+typedef void (*mod_framegroupify_parsegroups_t) (unsigned int i, int start, int len, float fps, qboolean loop, void *pass);
+
+int Mod_FrameGroupify_ParseGroups(const char *buf, mod_framegroupify_parsegroups_t cb, void *pass)
+{
+ const char *bufptr;
+ int start, len;
+ float fps;
+ unsigned int i;
+ qboolean loop;
+
+ bufptr = buf;
+ i = 0;
+ for(;;)
+ {
+ // an anim scene!
+ if (!COM_ParseToken_Simple(&bufptr, true, false))
+ break;
+ if (!strcmp(com_token, "\n"))
+ continue; // empty line
+ start = atoi(com_token);
+ if (!COM_ParseToken_Simple(&bufptr, true, false))
+ break;
+ if (!strcmp(com_token, "\n"))
+ {
+ Con_Printf("framegroups file: missing number of frames\n");
+ continue;
+ }
+ len = atoi(com_token);
+ if (!COM_ParseToken_Simple(&bufptr, true, false))
+ break;
+ // we default to looping as it's usually wanted, so to NOT loop you append a 0
+ if (strcmp(com_token, "\n"))
+ {
+ fps = atof(com_token);
+ if (!COM_ParseToken_Simple(&bufptr, true, false))
+ break;
+ if (strcmp(com_token, "\n"))
+ loop = atoi(com_token);
+ else
+ loop = true;
+ }
+ else
+ {
+ fps = 20;
+ loop = true;
+ }
+
+ if(cb)
+ cb(i, start, len, fps, loop, pass);
+ ++i;
+ }
+
+ return i;
+}
+
+void Mod_FrameGroupify_ParseGroups_Count (unsigned int i, int start, int len, float fps, qboolean loop, void *pass)
+{
+ unsigned int *cnt = (unsigned int *) pass;
+ ++*cnt;
+}
+
+void Mod_FrameGroupify_ParseGroups_Store (unsigned int i, int start, int len, float fps, qboolean loop, void *pass)
+{
+ dp_model_t *mod = (dp_model_t *) pass;
+ animscene_t *anim = &mod->animscenes[i];
+ dpsnprintf(anim->name, sizeof(anim[i].name), "groupified_%d", i);
+ anim->firstframe = bound(0, start, mod->num_poses - 1);
+ anim->framecount = bound(1, len, mod->num_poses - anim->firstframe);
+ anim->framerate = max(1, fps);
+ anim->loop = !!loop;
+ //Con_Printf("frame group %d is %d %d %f %d\n", i, start, len, fps, loop);
+}
+
+void Mod_FrameGroupify(dp_model_t *mod, const char *buf)
+{
+ unsigned int cnt;
+
+ // 0. count
+ cnt = Mod_FrameGroupify_ParseGroups(buf, NULL, NULL);
+ if(!cnt)
+ {
+ Con_Printf("no scene found in framegroups file, aborting\n");
+ return;
+ }
+ mod->numframes = cnt;
+
+ // 1. reallocate
+ // (we do not free the previous animscenes, but model unloading will free the pool owning them, so it's okay)
+ mod->animscenes = (animscene_t *) Mem_Alloc(mod->mempool, sizeof(animscene_t) * mod->numframes);
+
+ // 2. parse
+ Mod_FrameGroupify_ParseGroups(buf, Mod_FrameGroupify_ParseGroups_Store, mod);
+}
+