changeset 327:2964947674d1

More work on the timeline code.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 14 Oct 2012 23:36:06 +0300
parents 9cc4c6c52938
children dd7b1356d726
files dmtimeline.c dmtimeline.h dmtimelinew.c
diffstat 3 files changed, 335 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/dmtimeline.c	Sun Oct 14 23:35:57 2012 +0300
+++ b/dmtimeline.c	Sun Oct 14 23:36:06 2012 +0300
@@ -78,6 +78,18 @@
 }
 
 
+DMEffect *dmFindEffectByName(const char *name)
+{
+    int i;
+    for (i = 0; i < ndmEffects; i++)
+    {
+        if (strcmp(dmEffects[i].name, name) == 0)
+            return &dmEffects[i];
+    }
+    return NULL;
+}
+
+
 BOOL dmLoadFloatValue(DMResource *res, DMFloat *val)
 {
     char tmp[DT_FLOAT_STORE_SIZE + 1];
@@ -126,23 +138,25 @@
 
 int dmLoadTimelineEventParam(DMResource *res, DMTimelineEventParam *param)
 {
+    int err;
     DMFTimelineEventParam hdr;
     Uint16 len;
     Uint32 tmp32;
 
-    if (dmf_read_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)) != sizeof(hdr.name))
+    if (dmf_read_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)) != sizeof(hdr.name) ||
+        !dmf_read_le32(res, &hdr.type))
         return DMERR_FREAD;
+
     hdr.name[sizeof(hdr.name) - 1] = 0;
 
-    if (!dmf_read_le32(res, &hdr.type))
-        return DMERR_FREAD;
-
     param->name = dm_strdup(hdr.name);
     param->type = hdr.type;
 
     switch (hdr.type)
     {
         case EFPT_POINTS:
+            if ((err = dmLoadTimelinePoints(res, &param->vpts)) != DMERR_OK)
+                return err;
             break;
         
         case EFPT_INT:
@@ -181,24 +195,22 @@
         return DMERR_MALLOC;
 
     // Get basic event data
-    if (!dmf_read_le32(res, &hdr.startTime))
-        return DMERR_FREAD;
-    if (!dmf_read_le32(res, &hdr.duration))
+    if (!dmf_read_le32(res, &hdr.start) ||
+        !dmf_read_le32(res, &hdr.duration) ||
+        dmf_read_str(res, (Uint8 *) &hdr.effectName, sizeof(hdr.effectName)) != sizeof(hdr.effectName) ||
+        !dmf_read_le32(res, &hdr.nparams))
         return DMERR_FREAD;
-    if (dmf_read_str(res, (Uint8 *) &hdr.effectName, sizeof(hdr.effectName)) != sizeof(hdr.effectName))
-        return DMERR_FREAD;
+
     hdr.effectName[sizeof(hdr.effectName) - 1] = 0;
-    if (!dmf_read_le32(res, &hdr.nparams))
-        return DMERR_FREAD;
     
     if (hdr.nparams > DT_MAX_EFFECT_PARAMS)
     {
         dmError("Invalid number of parameters, %d > %d ('%s' @ %d:%d)\n",
-            hdr.nparams, DT_MAX_EFFECT_PARAMS, hdr.effectName, hdr.startTime, hdr.duration);
+            hdr.nparams, DT_MAX_EFFECT_PARAMS, hdr.effectName, hdr.start, hdr.duration);
         return DMERR_INVALID_DATA;
     }
 
-    event->startTime = hdr.startTime;
+    event->start     = hdr.start;
     event->duration  = hdr.duration;
     event->nparams   = hdr.nparams;
     event->effect    = dmFindEffect(hdr.effectName, hdr.nparams);
@@ -289,16 +301,12 @@
     if (dmf_read_str(res, (Uint8 *) &hdr.magic, sizeof(hdr.magic)) != sizeof(hdr.magic))
         return DMERR_FREAD;
 
-    if (memcmp(hdr.magic, "SDMETLNE", sizeof(hdr.magic)) != 0)
+    if (memcmp(hdr.magic, DT_MAGIC_ID, sizeof(hdr.magic)) != 0)
         return DMERR_INVALID_DATA;
 
-    if (dmf_read_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)) != sizeof(hdr.name))
-        return DMERR_FREAD;
-
-    if (!dmf_read_le32(res, &hdr.ntracks))
-        return DMERR_FREAD;
-
-    if (!dmf_read_le32(res, &hdr.duration))
+    if (dmf_read_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)) != sizeof(hdr.name) ||
+        !dmf_read_le32(res, &hdr.ntracks) ||
+        !dmf_read_le32(res, &hdr.duration))
         return DMERR_FREAD;
 
     if (hdr.ntracks >= 64)
--- a/dmtimeline.h	Sun Oct 14 23:35:57 2012 +0300
+++ b/dmtimeline.h	Sun Oct 14 23:36:06 2012 +0300
@@ -8,7 +8,7 @@
 extern "C" {
 #endif
 
-
+#define DT_MAGIC_ID           "SDMETLNE"
 #define DT_MAX_EFFECT_PARAMS  16
 #define DT_MAX_NAME_LENGTH    32
 #define DT_FLOAT_STORE_SIZE   16
@@ -53,10 +53,7 @@
     char *vstr;
     int vint;
     DMFloat vfloat;
-    DMTimelinePoints vpoints;
-
-    // Execution related
-    DMLerpContext lerp;
+    DMTimelinePoints vpts;
 } DMTimelineEventParam;
 
 
@@ -83,7 +80,7 @@
 
 typedef struct
 {
-    Uint32 startTime, duration;
+    Uint32 start, duration;
     char effectName[DT_MAX_NAME_LENGTH];
     Uint32 nparams;
 } DMFTimelineEvent;
@@ -91,7 +88,7 @@
 
 typedef struct
 {
-    int startTime, duration;
+    int start, duration;
     DMEffect *effect;
     int nparams;
     DMTimelineEventParam *params;
@@ -118,10 +115,10 @@
     char *name;        // Name of the timeline track
     BOOL enabled;      // Enabled?
 
-    int nevents;       // Number of events
+    int nevents, nallocated;    // Number of events
     DMTimelineEvent **events;   // Events
 
-    DMTimelineCurve composite; // Composite curve (transparency of the "layer")
+    DMTimelineCurve composite;  // Composite curve (transparency of the "layer")
 } DMTimelineTrack;
 
 
@@ -151,7 +148,7 @@
 typedef struct
 {
     char *name;
-    int ntracks, duration;
+    int ntracks, nallocated, duration;
     DMTimelineTrack **tracks;
 
     // Prepared data
@@ -168,17 +165,33 @@
 int  dmRegisterEffect(const DMEffect *ef);
 int  dmInitializeEffects();
 void dmShutdownEffects();
+DMEffect *dmFindEffect(const char *name, const int nparams);
+DMEffect *dmFindEffectByName(const char *name);
+
 
 int  dmLoadTimeline(DMResource *res, DMTimeline **tl);
-int  dmSaveTimeline(DMResource *res, DMTimeline *tl);
 void dmFreeTimeline(DMTimeline *tl);
 
 
+// Execution related
 int  dmPrepareTimeline(DMTimeline *tl);
 int  dmSeekTimeline(DMTimeline *tl, int time);
 int  dmExecuteTimeline(DMTimeline *tl, SDL_Surface *screen, int time);
 
 
+// Editing/saving related functions
+int  dmSaveTimeline(DMResource *res, DMTimeline *tl);
+
+int  dmTimelineNew(DMTimeline **tl, const char *name);
+int  dmTimelineAddTrack(DMTimeline *tl, DMTimelineTrack **track, const char *name);
+int  dmTimelineTrackAddEvent(DMTimelineTrack *track, int start, int duration, DMTimelineEvent **pev);
+int  dmTimelineEventSetEffect(DMTimelineEvent *event, const char *name);
+
+DMTimelineEvent *dmTimelineGetEventAt(DMTimelineTrack *track, int time);
+
+
+
+
 #ifdef __cplusplus
 }
 #endif
--- a/dmtimelinew.c	Sun Oct 14 23:35:57 2012 +0300
+++ b/dmtimelinew.c	Sun Oct 14 23:36:06 2012 +0300
@@ -1,4 +1,286 @@
 #include "dmtimeline.h"
+#include "dmresw.h"
+
+
+BOOL dmSaveFloatValue(DMResource *res, DMFloat val)
+{
+    char tmp[DT_FLOAT_STORE_SIZE];
+    snprintf(tmp, DT_FLOAT_STORE_SIZE, "%f", val);
+    return (dmf_write_str(res, (Uint8 *) tmp, DT_FLOAT_STORE_SIZE) == DT_FLOAT_STORE_SIZE);
+}
+
+
+int dmSaveTimelinePoints(DMResource *res, DMTimelinePoints *points)
+{
+    int point;
+    Uint32 npoints;
+
+    // Save number of points
+    npoints = points->npoints;
+    if (!dmf_write_le32(res, npoints))
+        return DMERR_FWRITE;
+    
+    // Save points
+    for (point = 0; point < points->npoints; point++)
+    {
+        DMTimelinePoint *pt = &(points->points[point]);
+        Uint32 ptype, ptime;
+        ptype = pt->type;
+        ptime = pt->time;
+        if (!dmf_write_le32(res, ptype) ||
+            !dmf_write_le32(res, ptime) ||
+            !dmSaveFloatValue(res, pt->value))
+            return DMERR_FWRITE;
+    }
+    return DMERR_OK;
+}
+
+
+int dmSaveTimelineCurve(DMResource *res, DMTimelineCurve *curve)
+{
+    int err;
+
+    dmfputc(curve->enabled, res);
+    if ((err = dmSaveTimelinePoints(res, &(curve->points))) != DMERR_OK)
+        return err;
+    
+    return DMERR_OK;
+}
+
+
+int dmSaveTimelineEventParam(DMResource *res, DMTimelineEventParam *param)
+{
+    int err;
+    DMFTimelineEventParam hdr;
+    Uint16 len;
+    Uint32 tmp32;
+
+    strncpy(hdr.name, param->name, sizeof(hdr.name));
+    hdr.type = param->type;
+
+    if (dmf_write_str(res, (Uint8 *) hdr.name, sizeof(hdr.name)) != sizeof(hdr.name) ||
+        !dmf_write_le32(res, hdr.type))
+        return DMERR_FWRITE;
+
+    switch (param->type)
+    {
+        case EFPT_POINTS:
+            if ((err = dmSaveTimelinePoints(res, &param->vpts)) != DMERR_OK)
+                return err;
+            break;
+        
+        case EFPT_INT:
+            tmp32 = param->vint;
+            if (!dmf_write_le32(res, tmp32))
+                return DMERR_FWRITE;
+            break;
+        
+        case EFPT_FLOAT:
+            if (!dmSaveFloatValue(res, param->vfloat))
+                return DMERR_FWRITE;
+            break;
+        
+        case EFPT_STRING:
+            len = strlen(param->vstr);
+            if (!dmf_write_le16(res, len))
+                return DMERR_FWRITE;
+
+            if (dmf_write_str(res, (Uint8 *) param->vstr, len) != len)
+                return DMERR_FWRITE;
+            break;
+    }
+
+    return DMERR_OK;
+}
+
+
+int dmSaveTimelineEvent(DMResource *res, DMTimelineEvent *event)
+{
+    int param, err;
+    DMFTimelineEvent hdr;
+
+    strncpy(hdr.effectName, event->effect->name, sizeof(hdr.effectName));
+    hdr.start    = event->start;
+    hdr.duration = event->duration;
+    hdr.nparams  = event->nparams;
+
+    if (!dmf_write_le32(res, hdr.start) ||
+        !dmf_write_le32(res, hdr.duration) ||
+        dmf_write_str(res, (Uint8 *) hdr.effectName, sizeof(hdr.effectName)) != sizeof(hdr.effectName) ||
+        !dmf_write_le32(res, hdr.nparams))
+        return DMERR_FREAD;
+
+    for (param = 0; param < event->nparams; param++)
+    {
+        if ((err = dmSaveTimelineEventParam(res, &(event->params[param]))) != DMERR_OK)
+            return err;
+    }
+
+    return DMERR_OK;
+}
+
+
+int dmSaveTimelineTrack(DMResource *res, DMTimelineTrack *track)
+{
+    int event, err;
+    DMFTimelineTrack hdr;
+    
+    strncpy(hdr.name, track->name, sizeof(hdr.name));
+    hdr.enabled = track->enabled;
+    hdr.nevents = track->nevents;
+
+    if (dmf_write_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)) != sizeof(hdr.name))
+        return DMERR_FWRITE;
+
+    dmfputc(hdr.enabled, res);
+    if (!dmf_write_le32(res, hdr.nevents))
+        return DMERR_FWRITE;
+
+    for (event = 0; event < track->nevents; event++)
+    {
+        if ((err = dmSaveTimelineEvent(res, track->events[event])) != DMERR_OK)
+            return err;
+    }
+
+    if ((err = dmSaveTimelineCurve(res, &(track->composite))) != DMERR_OK)
+        return err;
+
+    int track, err;
+    DMFTimeline hdr;
+
+    memcpy(&hdr.magic, DT_MAGIC_ID, sizeof(hdr.magic));
+    strncpy(hdr.name, tl->name, sizeof(hdr.name));
+    hdr.ntracks = tl->ntracks;
+    hdr.duration = tl->duration;
+    
+    if (dmf_write_str(res, (Uint8 *) hdr.magic, sizeof(hdr.magic)) != sizeof(hdr.magic) ||
+        dmf_write_str(res, (Uint8 *) hdr.name, sizeof(hdr.name)) != sizeof(hdr.name) ||
+        !dmf_write_le32(res, hdr.ntracks) ||
+        !dmf_write_le32(res, hdr.duration))
+        return DMERR_FWRITE;
+
+    for (track = 0; track < tl->ntracks; track++)
+    {
+        if ((err = dmSaveTimelineTrack(res, tl->tracks[track])) != DMERR_OK)
+            return err;
+    }
+
+    return DMERR_OK;
+int dmTimelineNew(DMTimeline **ptl, const char *name)
+{
+    DMTimeline *tl;
+    if ((*ptl = tl = dmMalloc0(sizeof(DMTimeline))) == NULL)
+        return DMERR_MALLOC;
+
+    tl->name = dm_strdup(name);
+    
+    return DMERR_OK;
+}
+
+
+int dmTimelineAddTrack(DMTimeline *tl, DMTimelineTrack **ptrack, const char *name)
+{
+    DMTimelineTrack *track;
+    
+    if ((*ptrack = track = dmMalloc0(sizeof(DMTimelineTrack))) == NULL)
+        return DMERR_MALLOC;
+    
+    track->name = dm_strdup(name);
+
+    if (tl->ntracks + 1 >= tl->nallocated)
+    {
+        tl->nallocated += 16;
+        tl->tracks = dmRealloc(tl->tracks, sizeof(DMTimelineTrack *) * tl->nallocated);
+        if (tl->tracks == NULL)
+            return DMERR_MALLOC;
+    }
+    
+    tl->tracks[tl->ntracks] = track;
+    tl->ntracks++;
+    
+    return DMERR_OK;
+}
+
+
+int dmTimelineTrackAddEvent(DMTimelineTrack *track, int start, int duration, DMTimelineEvent **pev)
+{
+    DMTimelineEvent *ev;
+    
+    if ((*pev = ev = dmMalloc0(sizeof(DMTimelineEvent))) == NULL)
+        return DMERR_MALLOC;
+    
+    ev->start    = start;
+    ev->duration = duration;
+    
+    if (track->nevents + 1 >= track->nallocated)
+    {
+        track->nallocated += 16;
+        track->events = dmRealloc(track->events, sizeof(DMTimelineEvent *) * track->nallocated);
+        if (track->events == NULL)
+            return DMERR_MALLOC;
+    }
+    
+    track->events[track->nevents] = ev;
+    track->nevents++;
+    
+    return DMERR_OK;
+}
+
+
+int dmTimelineEventSetEffect(DMTimelineEvent *event, const char *name)
+{
+    int param;
+    DMEffect *ef;
+
+    if ((ef = dmFindEffectByName(name)) == NULL)
+        return DMERR_INVALID_DATA;
+
+    event->effect = ef;
+    event->nparams = ef->nparams;
+    event->params = dmCalloc(ef->nparams, sizeof(DMTimelineEventParam));
+    if (event->params == NULL)
+        return DMERR_MALLOC;
+    
+    for (param = 0; param < ef->nparams; param++)
+    {
+        DMTimelineEventParam *psrc = &ef->params[param],
+                             *pdst = &event->params[param];
+
+        pdst->name   = dm_strdup(psrc->name);
+        pdst->type   = psrc->type;
+        pdst->vstr   = dm_strdup(psrc->vstr);
+        pdst->vint   = psrc->vint;
+        pdst->vfloat = psrc->vfloat;
+
+        if (psrc->vpts.points != NULL && psrc->vpts.npoints > 0)
+        {
+            pdst->vpts.npoints    = psrc->vpts.npoints;
+            pdst->vpts.nallocated = psrc->vpts.nallocated;
+            pdst->vpts.points     = dmMalloc(psrc->vpts.nallocated * sizeof(DMTimelinePoint));
+            if (pdst->vpts.points == NULL)
+                return DMERR_MALLOC;
+
+            memcpy(pdst->vpts.points, psrc->vpts.points, pdst->vpts.npoints * sizeof(DMTimelinePoint));
+        }
+    }
+    
+    return DMERR_OK;
+}
+
+
+DMTimelineEvent *dmTimelineGetEventAt(DMTimelineTrack *track, const int time)
+{
+    int event;
+    for (event = 0; event < track->nevents; event++)
+    {
+        DMTimelineEvent *ev = track->events[event];
+        if (time >= ev->start && time <= ev->start + ev->duration)
+            return ev;
+    }
+    return NULL;
+}
+}
+
 
 int dmSaveTimeline(DMResource *res, DMTimeline *tl)
 {