changeset 320:fc79b57d4646

Add in unfinished timeline code.
author Matti Hamalainen <ccr@tnsp.org>
date Sun, 14 Oct 2012 14:24:11 +0300
parents 37382bee0619
children 148e981739f4
files dmtimeline.c dmtimeline.h dmtimelinew.c
diffstat 3 files changed, 554 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmtimeline.c	Sun Oct 14 14:24:11 2012 +0300
@@ -0,0 +1,361 @@
+#include "dmtimeline.h"
+
+
+DMEffect *dmEffects = NULL;
+int ndmEffects = 0, ndmEffectsAlloc = 0;
+void **dmEffectData = NULL;
+
+
+int dmRegisterEffect(const DMEffect *ef)
+{
+    if (ef == NULL)
+        return DMERR_NULLPTR;
+
+    // Allocate more space for effects
+    if (ndmEffects + 1 >= ndmEffectsAlloc)
+    {
+        ndmEffectsAlloc += 16;
+        dmEffects = dmRealloc(dmEffects, sizeof(DMEffect) * ndmEffectsAlloc);
+        if (dmEffects == NULL)
+        {
+            dmError("Could not expand effects structure.\n"); 
+            return DMERR_INIT_FAIL;
+        }
+        
+        dmEffectData = dmRealloc(dmEffectData, sizeof(void *) * ndmEffectsAlloc);
+        if (dmEffectData == NULL)
+        {
+            dmError("Could not expand effects data structure.\n"); 
+            return DMERR_INIT_FAIL;
+        }
+    }
+
+    // Copy effects structure
+    memcpy(dmEffects + ndmEffects, ef, sizeof(DMEffect));
+    dmEffectData[ndmEffects] = NULL;
+
+    ndmEffects++;
+    
+    return DMERR_OK;
+}
+
+
+int dmInitializeEffects()
+{
+    int i, res;
+    for (i = 0; i < ndmEffects; i++)
+    {
+        if (dmEffects[i].init != NULL &&
+            (res = dmEffects[i].init(&dmEffectData[i])) != DMERR_OK)
+            return res;
+    }
+
+    return DMERR_OK;
+}
+
+
+void dmShutdownEffects()
+{
+    int i;
+    for (i = 0; i < ndmEffects; i++)
+    {
+        if (dmEffects[i].shutdown != NULL)
+            dmEffects[i].shutdown(dmEffectData[i]);
+    }
+}
+
+
+DMEffect *dmFindEffect(const char *name, const int nparams)
+{
+    int i;
+    for (i = 0; i < ndmEffects; i++)
+    {
+        if (strcmp(dmEffects[i].name, name) == 0 &&
+            dmEffects[i].nparams == nparams)
+            return &dmEffects[i];
+    }
+    return NULL;
+}
+
+
+int dmLoadFloatValue(DMResource *res, DMFloat *val)
+{
+    char tmp[DT_FLOAT_STORE_SIZE + 1];
+    if (dmf_read_str(res, (Uint8 *) tmp, DT_FLOAT_STORE_SIZE) != DT_FLOAT_STORE_SIZE)
+        return DMERR_FREAD;
+
+    tmp[DT_FLOAT_STORE_SIZE] = 0;
+    *val = atof(tmp);
+    return DMERR_OK;
+}
+
+
+int dmLoadTimelinePoints(DMResource *res, DMTimelinePoints *points)
+{
+    
+    return DMERR_OK;
+}
+
+
+int dmLoadTimelineEventParam(DMResource *res, DMTimelineEventParam *param)
+{
+    DMFTimelineEventParam hdr;
+    int err;
+    Uint16 len;
+    Uint32 tmp32;
+
+    if (dmf_read_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)) != sizeof(hdr.name))
+        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:
+            break;
+        
+        case EFPT_INT:
+            if (!dmf_read_le32(res, &tmp32))
+                return DMERR_FREAD;
+            param->vint = tmp32;
+            break;
+        
+        case EFPT_FLOAT:
+            if ((err = dmLoadFloatValue(res, &param->vfloat)) != DMERR_OK)
+                return err;
+            break;
+        
+        case EFPT_STRING:
+            if (!dmf_read_le16(res, &len))
+                return DMERR_FREAD;
+
+            param->vstr = dmMalloc((unsigned int)len + 1);
+            if (dmf_read_str(res, (Uint8 *) param->vstr, len) != len)
+                return DMERR_FREAD;
+
+            param->vstr[len] = 0;
+            break;
+    }
+
+    return DMERR_OK;
+}
+
+
+int dmLoadTimelineEvent(DMResource *res, DMTimelineEvent **pevent)
+{
+    int param;
+    DMFTimelineEvent hdr;
+    DMTimelineEvent *event;
+    if ((*pevent = event = dmMalloc0(sizeof(DMTimelineEvent))) == NULL)
+        return DMERR_MALLOC;
+
+    // Get basic event data
+    if (!dmf_read_le32(res, &hdr.startTime))
+        return DMERR_FREAD;
+    if (!dmf_read_le32(res, &hdr.duration))
+        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);
+        return DMERR_INVALID_DATA;
+    }
+
+    event->startTime = hdr.startTime;
+    event->duration  = hdr.duration;
+    event->nparams   = hdr.nparams;
+    event->effect    = dmFindEffect(hdr.effectName, hdr.nparams);
+    if (event->effect == NULL)
+    {
+        dmError("No matching registered effect found for '%s'.\n", hdr.effectName);
+        return DMERR_INVALID_DATA;
+    }
+
+    event->params    = dmCalloc(event->nparams, sizeof(DMTimelineEventParam));
+    if (event->params == NULL)
+    {
+        dmError("Could not allocate memory for timeline event parameters.\n");
+        return DMERR_MALLOC;
+    }
+
+    for (param = 0; param < event->nparams; param++)
+    {
+        int err;
+        if ((err = dmLoadTimelineEventParam(res, &(event->params[param]))) != DMERR_OK)
+            return err;
+    }
+
+    return DMERR_OK;
+}
+
+
+int dmLoadTimelineCurve(DMResource *res, DMTimelineCurve *curve)
+{
+    int err;
+
+    curve->enabled = dmfgetc(res);
+    if ((err = dmLoadTimelinePoints(res, &(curve->points))) != DMERR_OK)
+        return err;
+    
+    return DMERR_OK;
+}
+
+
+int dmLoadTimelineTrack(DMResource *res, DMTimelineTrack **ptrack)
+{
+    int event, err;
+    DMFTimelineTrack hdr;
+    DMTimelineTrack *track;
+    if ((*ptrack = track = dmMalloc0(sizeof(DMTimelineTrack))) == NULL)
+        return DMERR_MALLOC;
+
+    if (dmf_read_str(res, (Uint8 *) &hdr.name, sizeof(hdr.name)) != sizeof(hdr.name))
+        return DMERR_FREAD;
+
+    hdr.enabled = dmfgetc(res);
+    if (!dmf_read_le32(res, &hdr.nevents))
+        return DMERR_FREAD;
+
+    if (hdr.nevents >= 4096)
+        return DMERR_INVALID_DATA;
+
+    if ((track->events = dmCalloc(hdr.nevents, sizeof(DMTimelineEvent *))) == NULL)
+        return DMERR_MALLOC;
+
+    hdr.name[sizeof(hdr.name) - 1] = 0;
+    track->name = dm_strdup(hdr.name);
+    track->enabled = hdr.enabled;
+    track->nevents = hdr.nevents;
+
+    for (event = 0; event < track->nevents; event++)
+    {
+        if ((err = dmLoadTimelineEvent(res, &(track->events[event]))) != DMERR_OK)
+            return err;
+    }
+
+    if ((err = dmLoadTimelineCurve(res, &(track->composite))) != DMERR_OK)
+        return err;
+
+    return DMERR_OK;
+}
+
+
+int dmLoadTimeline(DMResource *res, DMTimeline **ptl)
+{
+    int track, err;
+    DMFTimeline hdr;
+    DMTimeline *tl;
+    if ((*ptl = tl = dmMalloc0(sizeof(DMTimeline))) == NULL)
+        return DMERR_MALLOC;
+
+    // Read and check header
+    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)
+        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))
+        return DMERR_FREAD;
+
+    if (hdr.ntracks >= 64)
+        return DMERR_INVALID_DATA;
+
+    // Allocate track pointers
+    tl->tracks = (DMTimelineTrack **) dmCalloc(hdr.ntracks, sizeof(DMTimelineTrack *));
+    if (tl->tracks == NULL)
+        return DMERR_MALLOC;
+
+    // Copy rest
+    hdr.name[sizeof(hdr.name) - 1] = 0;
+    tl->name     = dm_strdup(hdr.name);
+    tl->duration = hdr.duration;
+    tl->ntracks  = hdr.ntracks;
+
+    // Read tracks
+    for (track = 0; track < tl->ntracks; track++)
+    {
+        if ((err = dmLoadTimelineTrack(res, &(tl->tracks[track]))) != DMERR_OK)
+            return err;
+    }
+    
+    return DMERR_OK;
+}
+
+
+void dmFreeTimelinePoints(DMTimelinePoints *points)
+{
+    dmFree(points->points);
+    points->points = NULL;
+    points->npoints = points->nallocated = 0;
+}
+
+
+void dmFreeTimelineTrack(DMTimelineTrack *track)
+{
+    if (track != NULL)
+    {
+        dmFree(track->name);
+        track->name = NULL;
+        dmFreeTimelinePoints(&(track->composite.points));
+    }
+}
+
+
+void dmFreeTimeline(DMTimeline *tl)
+{
+    if (tl != NULL)
+    {
+        int i;
+        for (i = 0; i < tl->ntracks; i++)
+            dmFreeTimelineTrack(tl->tracks[i]);
+
+        dmFree(tl->tracks);
+        dmFree(tl->name);
+        dmFree(tl->pevents);
+    }
+}
+
+
+/* Prepare a loaded timeline for execution. Creates the "stacked" structure
+ * of timeline data for efficient rendering.
+ */
+int dmPrepareTimeline(DMTimeline *tl)
+{
+    return DMERR_OK;
+}
+
+
+/* Seeks to specified position in the timeline. The execution function
+ * only handles monotonously increasing time, going backwards will not work
+ * there correctly, thus to seek freely this function must be used.
+ */
+int dmSeekTimeline(DMTimeline *tl, int time)
+{
+    return DMERR_OK;
+}
+
+
+/* "Executes", or rather renders a frame on the specified timeline position.
+ */
+int dmExecuteTimeline(DMTimeline *tl, SDL_Surface *screen, int time)
+{
+    return DMERR_OK;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmtimeline.h	Sun Oct 14 14:24:11 2012 +0300
@@ -0,0 +1,185 @@
+#ifndef DMTIMELINE_H
+#define DMTIMELINE_H
+
+#include "dmlib.h"
+#include "dmres.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define DT_MAX_EFFECT_PARAMS  16
+#define DT_MAX_NAME_LENGTH    32
+#define DT_FLOAT_STORE_SIZE   16
+
+enum
+{
+    EFIT_SET,    // No interpolation, just "set" the value
+    EFIT_LINEAR, // Linear interpolation
+    EFIT_SMOOTH, // Smoothstep interpolation
+};
+
+enum
+{
+    EFPT_POINTS,
+    EFPT_INT,
+    EFPT_FLOAT,
+    EFPT_STRING,
+};
+
+
+typedef struct
+{
+    int type;                // Interpolation type (EFIT_*) between this and next point
+    int time;                // Offsets to event start, -1 == attach to event start, -2 = event end (if event)
+    DMFloat value;
+} DMTimelinePoint;
+
+
+typedef struct
+{
+    int npoints, nallocated;
+    DMTimelinePoint *points;
+} DMTimelinePoints;
+
+
+typedef struct
+{
+    char *name;              // Name / description of the parameter
+    int type;                // Type (EFPT_*)
+
+    char *vstr;
+    int vint;
+    DMFloat vfloat;
+    DMTimelinePoints vpoints;
+
+    // Execution related
+    DMLerpContext lerp;
+} DMTimelineEventParam;
+
+
+typedef struct
+{
+    char name[DT_MAX_NAME_LENGTH];
+    Uint32 type;
+} DMFTimelineEventParam;
+
+
+typedef struct
+{
+    char *  name;
+    int     type;
+    
+    int     (*init)(void **data);
+    void    (*shutdown)(void *data);
+    int     (*render)(SDL_Surface *screen, void *data, const DMTimelineEventParam *params);
+
+    int     nparams;
+    DMTimelineEventParam params[DT_MAX_EFFECT_PARAMS];
+} DMEffect;
+
+
+typedef struct
+{
+    Uint32 startTime, duration;
+    char effectName[DT_MAX_NAME_LENGTH];
+    Uint32 nparams;
+} DMFTimelineEvent;
+
+
+typedef struct
+{
+    int startTime, duration;
+    DMEffect *effect;
+    int nparams;
+    DMTimelineEventParam *params;
+} DMTimelineEvent;
+
+
+typedef struct
+{
+    BOOL enabled;
+    DMTimelinePoints points;
+} DMTimelineCurve;
+
+
+typedef struct
+{
+    char name[DT_MAX_NAME_LENGTH];
+    Uint8 enabled;
+    Uint32 nevents;
+} DMFTimelineTrack;
+
+
+typedef struct
+{
+    char *name;        // Name of the timeline track
+    BOOL enabled;      // Enabled?
+
+    int nevents;       // Number of events
+    DMTimelineEvent **events;   // Events
+
+    DMTimelineCurve composite; // Composite curve (transparency of the "layer")
+} DMTimelineTrack;
+
+
+typedef struct
+{
+    DMTimelineTrack *track;
+    DMTimelineEvent *event;
+} DMPreparedEvent;
+
+
+typedef struct
+{
+    int start, end, nevents;
+    DMPreparedEvent *events;
+} DMPreparedEventGroup;
+
+
+typedef struct
+{
+    char   magic[8];
+    char   name[DT_MAX_NAME_LENGTH];
+    Uint32 ntracks;
+    Uint32 duration;
+} DMFTimeline;
+
+
+typedef struct
+{
+    char *name;
+    int ntracks, duration;
+    DMTimelineTrack **tracks;
+
+    // Prepared data
+    int nevents;
+    DMPreparedEventGroup *pevents;
+} DMTimeline;
+
+
+extern DMEffect *dmEffects;
+extern int ndmEffects, ndmEffectsAlloc;
+extern void **dmEffectData;
+
+
+int  dmRegisterEffect(const DMEffect *ef);
+int  dmInitializeEffects();
+void dmShutdownEffects();
+
+int  dmLoadTimeline(DMResource *res, DMTimeline **tl);
+int  dmSaveTimeline(DMResource *res, DMTimeline *tl);
+void dmFreeTimeline(DMTimeline *tl);
+
+
+int  dmPrepareTimeline(DMTimeline *tl);
+int  dmSeekTimeline(DMTimeline *tl, int time);
+int  dmExecuteTimeline(DMTimeline *tl, SDL_Surface *screen, int time);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // DMTIMELINE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmtimelinew.c	Sun Oct 14 14:24:11 2012 +0300
@@ -0,0 +1,8 @@
+#include "dmtimeline.h"
+
+int dmSaveTimeline(DMResource *res, DMTimeline *tl)
+{
+    return DMERR_OK;
+}
+
+