diff --git a/src/libsuperderpy.h b/src/libsuperderpy.h index fc1f091..efba9f9 100644 --- a/src/libsuperderpy.h +++ b/src/libsuperderpy.h @@ -23,6 +23,11 @@ #define LIBSUPERDERPY_MAIN_H struct Game; +struct GamestateResources; + +#ifndef LIBSUPERDERPY_DATA_TYPE +#define LIBSUPERDERPY_DATA_TYPE void +#endif #include #include @@ -49,10 +54,6 @@ struct Game; #include "utils.h" #include -#ifndef LIBSUPERDERPY_DATA_TYPE -#define LIBSUPERDERPY_DATA_TYPE void -#endif - struct Gamestate; struct Viewport { @@ -176,7 +177,6 @@ struct Game* libsuperderpy_init(int argc, char** argv, const char* name, struct int libsuperderpy_run(struct Game* game); void libsuperderpy_destroy(struct Game* game); -struct GamestateResources; extern int Gamestate_ProgressCount; void Gamestate_ProcessEvent(struct Game* game, struct GamestateResources* data, ALLEGRO_EVENT* ev); void Gamestate_Logic(struct Game* game, struct GamestateResources* data, double delta); diff --git a/src/timeline.c b/src/timeline.c index 0bfb55d..b17c903 100644 --- a/src/timeline.c +++ b/src/timeline.c @@ -31,7 +31,7 @@ static void DestroyArgs(struct TM_Arguments* args) { } } -SYMBOL_EXPORT struct Timeline* TM_Init(struct Game* game, char* name) { +SYMBOL_EXPORT struct Timeline* TM_Init(struct Game* game, struct GamestateResources* data, char* name) { PrintConsole(game, "Timeline Manager[%s]: init", name); struct Timeline* timeline = malloc(sizeof(struct Timeline)); timeline->game = game; @@ -39,6 +39,7 @@ SYMBOL_EXPORT struct Timeline* TM_Init(struct Game* game, char* name) { timeline->queue = NULL; timeline->background = NULL; timeline->name = strdup(name); + timeline->data = data; AddTimeline(game, timeline); return timeline; } @@ -64,7 +65,8 @@ SYMBOL_EXPORT void TM_Process(struct Timeline* timeline, double delta) { timeline->queue->started = true; if (timeline->queue->function) { PrintConsole(timeline->game, "Timeline Manager[%s]: queue: run action (%d - %s)", timeline->name, timeline->queue->id, timeline->queue->name); - (*timeline->queue->function)(timeline->game, timeline->queue, TM_ACTIONSTATE_START); + timeline->queue->state = TM_ACTIONSTATE_START; + (*timeline->queue->function)(timeline->game, timeline->data, timeline->queue); } else { PrintConsole(timeline->game, "Timeline Manager[%s]: queue: delay reached (%d - %s)", timeline->name, timeline->queue->id, timeline->queue->name); } @@ -75,14 +77,17 @@ SYMBOL_EXPORT void TM_Process(struct Timeline* timeline, double delta) { if (timeline->queue->function) { if (!timeline->queue->started) { PrintConsole(timeline->game, "Timeline Manager[%s]: queue: run action (%d - %s)", timeline->name, timeline->queue->id, timeline->queue->name); - (*timeline->queue->function)(timeline->game, timeline->queue, TM_ACTIONSTATE_START); + timeline->queue->state = TM_ACTIONSTATE_START; + (*timeline->queue->function)(timeline->game, timeline->data, timeline->queue); timeline->queue->started = true; } - if ((*timeline->queue->function)(timeline->game, timeline->queue, TM_ACTIONSTATE_RUNNING)) { + timeline->queue->state = TM_ACTIONSTATE_RUNNING; + if ((*timeline->queue->function)(timeline->game, timeline->data, timeline->queue)) { PrintConsole(timeline->game, "Timeline Manager[%s]: queue: destroy action (%d - %s)", timeline->name, timeline->queue->id, timeline->queue->name); struct TM_Action* tmp = timeline->queue; timeline->queue = timeline->queue->next; - (*tmp->function)(timeline->game, tmp, TM_ACTIONSTATE_DESTROY); + tmp->state = TM_ACTIONSTATE_DESTROY; + (*tmp->function)(timeline->game, timeline->data, tmp); DestroyArgs(tmp->arguments); free(tmp->name); free(tmp); @@ -117,9 +122,11 @@ SYMBOL_EXPORT void TM_Process(struct Timeline* timeline, double delta) { pom->delta = delta / 1000.0; if (pom->started) { if (pom->function) { - if ((pom->function)(timeline->game, pom, TM_ACTIONSTATE_RUNNING)) { + pom->state = TM_ACTIONSTATE_RUNNING; + if ((pom->function)(timeline->game, timeline->data, pom)) { PrintConsole(timeline->game, "Timeline Manager[%s]: background: destroy action (%d - %s)", timeline->name, pom->id, pom->name); - (pom->function)(timeline->game, pom, TM_ACTIONSTATE_DESTROY); + pom->state = TM_ACTIONSTATE_DESTROY; + (pom->function)(timeline->game, timeline->data, pom); if (tmp) { tmp->next = pom->next; } else { @@ -142,7 +149,8 @@ SYMBOL_EXPORT void TM_Process(struct Timeline* timeline, double delta) { PrintConsole(timeline->game, "Timeline Manager[%s]: background: delay reached, run action (%d - %s)", timeline->name, pom->id, pom->name); pom->delay = 0.0; if (pom->function) { - pom->function(timeline->game, pom, TM_ACTIONSTATE_START); + pom->state = TM_ACTIONSTATE_START; + pom->function(timeline->game, timeline->data, pom); } pom->started = true; } @@ -189,9 +197,11 @@ SYMBOL_EXPORT struct TM_Action* TM_AddAction(struct Timeline* timeline, TM_Actio action->started = false; action->delay = 0.0; action->id = ++timeline->lastid; + action->timeline = timeline; if (action->function) { PrintConsole(timeline->game, "Timeline Manager[%s]: queue: init action (%d - %s)", timeline->name, action->id, action->name); - action->function(timeline->game, action, TM_ACTIONSTATE_INIT); + action->state = TM_ACTIONSTATE_INIT; + action->function(timeline->game, timeline->data, action); } return action; } @@ -215,23 +225,24 @@ SYMBOL_EXPORT struct TM_Action* TM_AddBackgroundAction(struct Timeline* timeline action->id = ++timeline->lastid; action->active = true; action->started = false; + action->timeline = timeline; PrintConsole(timeline->game, "Timeline Manager[%s]: background: init action with delay %d ms (%d - %s)", timeline->name, delay, action->id, action->name); - (*action->function)(timeline->game, action, TM_ACTIONSTATE_INIT); + action->state = TM_ACTIONSTATE_INIT; + (*action->function)(timeline->game, timeline->data, action); return action; } /*! \brief Predefined action used by TM_AddQueuedBackgroundAction */ static TM_Action(RunInBackground) { - int* delay = (int*)TM_GetArg(action->arguments, 1); - char* name = (char*)TM_GetArg(action->arguments, 2); - struct Timeline* timeline = (struct Timeline*)TM_GetArg(action->arguments, 3); - struct TM_Arguments* arguments = (struct TM_Arguments*)TM_GetArg(action->arguments, 4); - bool* used = (bool*)TM_GetArg(action->arguments, 5); - if (state == TM_ACTIONSTATE_START) { - TM_AddBackgroundAction(timeline, TM_GetArg(action->arguments, 0), arguments, *delay, name); + int* delay = TM_Arg(1); + char* name = TM_Arg(2); + struct TM_Arguments* arguments = TM_Arg(3); + bool* used = TM_Arg(4); + if (action->state == TM_ACTIONSTATE_START) { + TM_AddBackgroundAction(action->timeline, TM_Arg(0), arguments, *delay, name); *used = true; } - if (state == TM_ACTIONSTATE_DESTROY) { + if (action->state == TM_ACTIONSTATE_DESTROY) { free(name); free(delay); if (!(*used)) { @@ -245,7 +256,7 @@ static TM_Action(RunInBackground) { SYMBOL_EXPORT struct TM_Action* TM_AddQueuedBackgroundAction(struct Timeline* timeline, TM_ActionCallback* func, struct TM_Arguments* args, int delay, char* name) { TM_WrapArg(int, del, delay); TM_WrapArg(bool, used, false); - struct TM_Arguments* arguments = TM_AddToArgs(NULL, 6, (void*)func, del, strdup(name), (void*)timeline, args, used); + struct TM_Arguments* arguments = TM_Args(func, del, strdup(name), args, used); return TM_AddAction(timeline, RunInBackground, arguments, "TM_BackgroundAction"); } @@ -260,7 +271,8 @@ SYMBOL_EXPORT void TM_CleanQueue(struct Timeline* timeline) { struct TM_Action *tmp, *pom = timeline->queue; while (pom != NULL) { if (*pom->function) { - (*pom->function)(timeline->game, pom, TM_ACTIONSTATE_DESTROY); + pom->state = TM_ACTIONSTATE_DESTROY; + (*pom->function)(timeline->game, timeline->data, pom); } DestroyArgs(pom->arguments); tmp = pom->next; @@ -276,7 +288,8 @@ SYMBOL_EXPORT void TM_CleanBackgroundQueue(struct Timeline* timeline) { struct TM_Action *tmp, *pom = timeline->background; while (pom != NULL) { if (*pom->function) { - (*pom->function)(timeline->game, pom, TM_ACTIONSTATE_DESTROY); + pom->state = TM_ACTIONSTATE_DESTROY; + (*pom->function)(timeline->game, timeline->data, pom); } DestroyArgs(pom->arguments); tmp = pom->next; diff --git a/src/timeline.h b/src/timeline.h index 152773b..2495d5d 100644 --- a/src/timeline.h +++ b/src/timeline.h @@ -23,12 +23,9 @@ #include "libsuperderpy.h" -#define TM_WrapArg(type, result, val) \ - type* result = malloc(sizeof(type)); \ - *result = val; - -#define TM_RunningOnly \ - if (state != TM_ACTIONSTATE_RUNNING) return false; +struct TM_Action; +typedef bool TM_ActionCallback(struct Game*, struct GamestateResources*, struct TM_Action*); +#define TM_NUMARGS(...) (sizeof((void* []){__VA_ARGS__}) / sizeof(void*)) /*! \brief State of the TM_Action. */ enum TM_ActionState { @@ -38,10 +35,6 @@ enum TM_ActionState { TM_ACTIONSTATE_DESTROY }; -struct TM_Action; -typedef bool TM_ActionCallback(struct Game*, struct TM_Action*, enum TM_ActionState); -#define TM_Action(x) bool x(struct Game* game, struct TM_Action* action, enum TM_ActionState state) - /*! \brief Timeline structure. */ struct Timeline { struct TM_Action* queue; /*!< Main timeline queue. */ @@ -49,6 +42,7 @@ struct Timeline { char* name; /*!< Name of the timeline. */ unsigned int lastid; /*!< Last ID given to timeline action. */ struct Game* game; /*!< Reference to the game object. */ + struct GamestateResources* data; /*!< User data pointer for use in actions. */ }; /*! \brief Arguments for TM_Action. */ @@ -67,11 +61,13 @@ struct TM_Action { double delta; /*!< Number of miliseconds since the last TM_Process invocation. */ unsigned int id; /*!< ID of the action. */ char* name; /*!< "User friendly" name of the action. */ + struct Timeline* timeline; /*!< A pointer to the timeline where this action is used. */ + enum TM_ActionState state; /*!< Current state of the action. */ struct TM_Action* next; /*!< Pointer to next action in queue. */ }; /*! \brief Init timeline. */ -struct Timeline* TM_Init(struct Game* game, char* name); +struct Timeline* TM_Init(struct Game* game, struct GamestateResources* data, char* name); /*! \brief Process current timeline actions. */ void TM_Process(struct Timeline*, double delta); /*! \brief Add new action to main queue. */ @@ -98,5 +94,18 @@ void TM_SkipDelay(struct Timeline*); bool TM_IsEmpty(struct Timeline* timeline); /*! \brief Checks if the background queue is empty */ bool TM_IsBackgroundEmpty(struct Timeline* timeline); +/*! \brief Allocates memory and sets given value. */ +#define TM_WrapArg(type, result, val) \ + type* result = malloc(sizeof(type)); \ + *result = val; +/*! \brief Indicates that the action handles only TM_ACTIONSTATE_RUNNING state. */ +#define TM_RunningOnly \ + if (action->state != TM_ACTIONSTATE_RUNNING) return false; +/*! \brief Shorthand for creating list of arguments for action. */ +#define TM_Args(...) TM_AddToArgs(NULL, TM_NUMARGS(__VA_ARGS__), __VA_ARGS__) +/*! \brief Shorthand for accessing the nth argument of current action. */ +#define TM_Arg(n) TM_GetArg(action->arguments, n) +/*! \brief Macro for easy timeline action definition. */ +#define TM_Action(name) bool name(struct Game* game, struct GamestateResources* data, struct TM_Action* action) #endif