Mercurial > hg > dmlib
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, ¶m->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