2012-04-06 17:28:38 +02:00
/*! \file timeline.c
* \ brief Timeline Manager framework code .
*/
/*
* Copyright ( c ) Sebastian Krzyszkowiak < dos @ dosowisko . net >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*/
# include <allegro5/allegro.h>
2012-12-24 19:41:12 +01:00
# include "utils.h"
2012-04-06 17:28:38 +02:00
# include "timeline.h"
2015-03-18 02:21:57 +01:00
struct Timeline * TM_Init ( struct Game * g , char * name ) {
PrintConsole ( g , " Timeline Manager[%s]: init " , name ) ;
struct Timeline * timeline = malloc ( sizeof ( struct Timeline ) ) ;
timeline - > game = g ;
timeline - > lastid = 0 ;
timeline - > queue = NULL ;
timeline - > background = NULL ;
timeline - > name = strdup ( name ) ;
return timeline ;
2012-04-06 17:28:38 +02:00
}
2015-03-18 02:21:57 +01:00
void TM_Process ( struct Timeline * timeline ) {
2012-09-27 02:48:45 +02:00
/* process first element from queue
if returns true , delete it */
2015-03-18 02:21:57 +01:00
if ( timeline - > queue ) {
if ( * timeline - > queue - > function ) {
if ( ! timeline - > queue - > active ) {
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 ) ;
2012-09-29 02:34:42 +02:00
}
2015-03-18 02:21:57 +01:00
timeline - > queue - > active = true ;
if ( ( * timeline - > queue - > function ) ( timeline - > game , timeline - > queue , TM_ACTIONSTATE_RUNNING ) ) {
PrintConsole ( timeline - > game , " Timeline Manager[%s]: queue: destroy action (%d - %s) " , timeline - > name , timeline - > queue - > id , timeline - > queue - > name ) ;
timeline - > queue - > active = false ;
struct TM_Action * tmp = timeline - > queue ;
timeline - > queue = timeline - > queue - > next ;
( * tmp - > function ) ( timeline - > game , tmp , TM_ACTIONSTATE_DESTROY ) ;
2012-04-09 17:17:16 +02:00
free ( tmp - > name ) ;
2012-04-06 23:32:15 +02:00
free ( tmp ) ;
}
} else {
2012-04-14 22:26:33 +02:00
/* delay handling */
2015-03-18 02:21:57 +01:00
if ( timeline - > queue - > active ) {
struct TM_Action * tmp = timeline - > queue ;
timeline - > queue = timeline - > queue - > next ;
2012-04-09 17:17:16 +02:00
free ( tmp - > name ) ;
2012-04-07 23:03:34 +02:00
free ( tmp ) ;
} else {
2015-03-18 02:21:57 +01:00
if ( ! al_get_timer_started ( timeline - > queue - > timer ) ) {
PrintConsole ( timeline - > game , " Timeline Manager[%s]: queue: delay started %d ms (%d - %s) " , timeline - > name , timeline - > queue - > delay , timeline - > queue - > id , timeline - > queue - > name ) ;
al_start_timer ( timeline - > queue - > timer ) ;
2012-09-29 02:34:42 +02:00
}
2012-04-07 23:03:34 +02:00
}
2012-04-06 23:32:15 +02:00
}
}
2012-04-14 22:26:33 +02:00
/* process all elements from background marked as active */
2015-03-18 02:21:57 +01:00
struct TM_Action * tmp , * tmp2 , * pom = timeline - > background ;
2012-04-06 23:32:15 +02:00
tmp = NULL ;
while ( pom ! = NULL ) {
2015-03-15 05:38:15 +01:00
bool destroy = false ;
2012-04-06 23:32:15 +02:00
if ( pom - > active ) {
if ( * pom - > function ) {
2015-03-18 02:21:57 +01:00
if ( ( * pom - > function ) ( timeline - > game , pom , TM_ACTIONSTATE_RUNNING ) ) {
2012-04-07 18:32:47 +02:00
pom - > active = false ;
2015-03-18 02:21:57 +01:00
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 ) ;
2012-04-06 23:32:15 +02:00
if ( tmp ) {
tmp - > next = pom - > next ;
} else {
2015-03-18 02:21:57 +01:00
timeline - > background = pom - > next ;
2012-04-06 23:32:15 +02:00
}
2015-03-15 05:38:15 +01:00
destroy = true ;
2012-04-06 23:32:15 +02:00
}
} else {
2012-04-14 22:26:33 +02:00
/* delay handling */
2012-04-07 23:03:34 +02:00
if ( tmp ) {
tmp - > next = pom - > next ;
} else {
2015-03-18 02:21:57 +01:00
timeline - > background = pom - > next ;
2012-04-07 23:03:34 +02:00
}
2015-03-15 05:38:15 +01:00
destroy = true ;
2012-04-06 23:32:15 +02:00
}
}
2015-03-15 05:38:15 +01:00
if ( ! destroy ) {
2012-04-06 23:32:15 +02:00
tmp = pom ;
pom = pom - > next ;
} else {
2012-04-09 17:17:16 +02:00
free ( pom - > name ) ;
2012-04-06 23:32:15 +02:00
free ( pom ) ;
tmp2 = tmp ;
2015-03-15 05:38:15 +01:00
if ( ! tmp ) {
2015-03-18 02:21:57 +01:00
if ( timeline - > background ) {
pom = timeline - > background - > next ;
2015-03-15 05:38:15 +01:00
} else {
pom = NULL ;
}
}
2012-04-06 23:32:15 +02:00
else pom = tmp - > next ;
tmp = tmp2 ;
}
}
2012-04-06 17:28:38 +02:00
}
2015-03-18 02:21:57 +01:00
void PauseTimers ( struct Timeline * timeline , bool pause ) {
if ( timeline - > queue ) {
if ( timeline - > queue - > timer ) {
2012-09-26 23:28:16 +02:00
if ( pause ) {
2015-03-18 02:21:57 +01:00
al_stop_timer ( timeline - > queue - > timer ) ;
} else if ( ! timeline - > queue - > active ) al_start_timer ( timeline - > queue - > timer ) ;
2012-09-26 23:28:16 +02:00
}
}
2015-03-18 02:21:57 +01:00
struct TM_Action * tmp = timeline - > background ;
2012-09-26 23:28:16 +02:00
while ( tmp ) {
if ( tmp - > timer ) {
if ( pause ) {
al_stop_timer ( tmp - > timer ) ;
} else if ( ! tmp - > active ) al_start_timer ( tmp - > timer ) ;
}
tmp = tmp - > next ;
}
}
2015-03-18 02:21:57 +01:00
void Propagate ( struct Timeline * timeline , enum TM_ActionState action ) {
if ( timeline - > queue ) {
if ( ( * timeline - > queue - > function ) & & ( timeline - > queue - > active ) ) {
( * timeline - > queue - > function ) ( timeline - > game , timeline - > queue , action ) ;
2012-09-26 18:48:36 +02:00
}
}
/* process all elements from background marked as active */
2015-03-18 02:21:57 +01:00
struct TM_Action * pom = timeline - > background ;
2012-09-26 18:48:36 +02:00
while ( pom ! = NULL ) {
if ( pom - > active ) {
if ( * pom - > function ) {
2015-03-18 02:21:57 +01:00
( * pom - > function ) ( timeline - > game , pom , action ) ;
2012-09-26 18:48:36 +02:00
}
}
pom = pom - > next ;
}
}
2015-03-18 02:21:57 +01:00
void TM_Draw ( struct Timeline * timeline ) {
Propagate ( timeline , TM_ACTIONSTATE_DRAW ) ;
2012-09-26 23:28:16 +02:00
}
2015-03-18 02:21:57 +01:00
void TM_Pause ( struct Timeline * timeline ) {
PrintConsole ( timeline - > game , " Timeline Manager[%s]: Pause. " , timeline - > name ) ;
PauseTimers ( timeline , true ) ;
Propagate ( timeline , TM_ACTIONSTATE_PAUSE ) ;
2012-09-26 23:28:16 +02:00
}
2015-03-18 02:21:57 +01:00
void TM_Resume ( struct Timeline * timeline ) {
PrintConsole ( timeline - > game , " Timeline Manager[%s]: Resume. " , timeline - > name ) ;
Propagate ( timeline , TM_ACTIONSTATE_RESUME ) ;
PauseTimers ( timeline , false ) ;
2012-09-26 23:28:16 +02:00
}
2015-03-18 02:21:57 +01:00
void TM_HandleEvent ( struct Timeline * timeline , ALLEGRO_EVENT * ev ) {
2012-04-07 23:03:34 +02:00
if ( ev - > type ! = ALLEGRO_EVENT_TIMER ) return ;
2015-03-18 02:21:57 +01:00
if ( timeline - > queue ) {
if ( ev - > timer . source = = timeline - > queue - > timer ) {
timeline - > queue - > active = true ;
al_destroy_timer ( timeline - > queue - > timer ) ;
timeline - > queue - > timer = NULL ;
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 ) ;
2012-04-07 23:03:34 +02:00
} else {
2015-03-18 02:21:57 +01:00
PrintConsole ( timeline - > game , " Timeline Manager[%s]: queue: delay reached (%d - %s) " , timeline - > name , timeline - > queue - > id , timeline - > queue - > name ) ;
2012-04-07 23:03:34 +02:00
}
return ;
}
}
2015-03-18 02:21:57 +01:00
struct TM_Action * pom = timeline - > background ;
2012-04-07 23:03:34 +02:00
while ( pom ) {
if ( ev - > timer . source = = pom - > timer ) {
2015-03-18 02:21:57 +01:00
PrintConsole ( timeline - > game , " Timeline Manager[%s]: background: delay reached, run action (%d - %s) " , timeline - > name , pom - > id , pom - > name ) ;
2012-04-07 23:03:34 +02:00
pom - > active = true ;
al_destroy_timer ( pom - > timer ) ;
pom - > timer = NULL ;
2015-03-18 02:21:57 +01:00
( * pom - > function ) ( timeline - > game , pom , TM_ACTIONSTATE_START ) ;
2012-04-07 23:03:34 +02:00
return ;
}
pom = pom - > next ;
}
2012-04-06 17:28:38 +02:00
}
2015-03-18 02:21:57 +01:00
struct TM_Action * TM_AddAction ( struct Timeline * timeline , bool ( * func ) ( struct Game * , struct TM_Action * , enum TM_ActionState ) , struct TM_Arguments * args , char * name ) {
2012-04-06 23:32:15 +02:00
struct TM_Action * action = malloc ( sizeof ( struct TM_Action ) ) ;
2015-03-18 02:21:57 +01:00
if ( timeline - > queue ) {
struct TM_Action * pom = timeline - > queue ;
2012-04-06 23:32:15 +02:00
while ( pom - > next ! = NULL ) {
pom = pom - > next ;
}
pom - > next = action ;
} else {
2015-03-18 02:21:57 +01:00
timeline - > queue = action ;
2012-04-06 23:32:15 +02:00
}
action - > next = NULL ;
action - > function = func ;
action - > arguments = args ;
2013-02-25 01:23:27 +01:00
action - > name = strdup ( name ) ;
2012-04-06 23:32:15 +02:00
action - > timer = NULL ;
action - > active = false ;
action - > delay = 0 ;
2015-03-18 02:21:57 +01:00
action - > id = + + timeline - > lastid ;
2012-09-03 02:25:32 +02:00
if ( action - > function ) {
2015-03-18 02:21:57 +01:00
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 ) ;
2012-04-07 23:03:34 +02:00
}
return action ;
2012-04-06 23:32:15 +02:00
}
2015-03-18 02:21:57 +01:00
struct TM_Action * TM_AddBackgroundAction ( struct Timeline * timeline , bool ( * func ) ( struct Game * , struct TM_Action * , enum TM_ActionState ) , struct TM_Arguments * args , int delay , char * name ) {
2012-04-06 23:32:15 +02:00
struct TM_Action * action = malloc ( sizeof ( struct TM_Action ) ) ;
2015-03-18 02:21:57 +01:00
if ( timeline - > background ) {
struct TM_Action * pom = timeline - > background ;
2012-04-06 23:32:15 +02:00
while ( pom - > next ! = NULL ) {
pom = pom - > next ;
}
pom - > next = action ;
} else {
2015-03-18 02:21:57 +01:00
timeline - > background = action ;
2012-04-06 23:32:15 +02:00
}
action - > next = NULL ;
action - > function = func ;
action - > arguments = args ;
2013-02-25 01:23:27 +01:00
action - > name = strdup ( name ) ;
2012-04-07 18:32:47 +02:00
action - > delay = delay ;
2015-03-18 02:21:57 +01:00
action - > id = + + timeline - > lastid ;
2012-04-07 20:32:47 +02:00
if ( delay ) {
2015-03-18 02:21:57 +01:00
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 ) ;
2012-04-07 20:32:47 +02:00
action - > active = false ;
2012-04-07 23:03:34 +02:00
action - > timer = al_create_timer ( delay / 1000.0 ) ;
2015-03-18 02:21:57 +01:00
al_register_event_source ( timeline - > game - > _priv . event_queue , al_get_timer_event_source ( action - > timer ) ) ;
2012-04-07 23:03:34 +02:00
al_start_timer ( action - > timer ) ;
2012-04-07 20:32:47 +02:00
} else {
2015-03-18 02:21:57 +01:00
PrintConsole ( timeline - > game , " Timeline Manager[%s]: background: init action (%d - %s) " , timeline - > name , action - > id , action - > name ) ;
( * action - > function ) ( timeline - > game , action , TM_ACTIONSTATE_INIT ) ;
2012-04-07 23:03:34 +02:00
action - > timer = NULL ;
2012-04-07 20:32:47 +02:00
action - > active = true ;
2015-03-18 02:21:57 +01:00
PrintConsole ( timeline - > game , " Timeline Manager[%s]: background: run action (%d - %s) " , timeline - > name , action - > id , action - > name ) ;
( * action - > function ) ( timeline - > game , action , TM_ACTIONSTATE_START ) ;
2012-04-07 20:32:47 +02:00
}
2012-04-08 23:25:14 +02:00
return action ;
2012-04-06 23:32:15 +02:00
}
2012-05-21 10:25:22 +02:00
/*! \brief Predefined action used by TM_AddQueuedBackgroundAction */
2012-04-09 12:55:04 +02:00
bool runinbackground ( struct Game * game , struct TM_Action * action , enum TM_ActionState state ) {
if ( state ! = TM_ACTIONSTATE_RUNNING ) return false ;
2012-09-29 02:34:42 +02:00
int * delay = ( int * ) action - > arguments - > next - > value ;
2012-04-09 17:17:16 +02:00
char * name = ( char * ) action - > arguments - > next - > next - > value ;
2015-03-18 02:21:57 +01:00
struct Timeline * timeline = ( struct Timeline * ) action - > arguments - > next - > next - > next - > value ;
TM_AddBackgroundAction ( timeline , action - > arguments - > value , action - > arguments - > next - > next - > next - > next , * delay , name ) ;
2012-04-09 17:17:16 +02:00
free ( name ) ;
2012-04-09 12:55:04 +02:00
return true ;
}
2015-03-18 02:21:57 +01:00
struct TM_Action * TM_AddQueuedBackgroundAction ( struct Timeline * timeline , bool ( * func ) ( struct Game * , struct TM_Action * , enum TM_ActionState ) , struct TM_Arguments * args , int delay , char * name ) {
2013-06-05 23:59:02 +02:00
TM_WrapArg ( int , del , delay ) ;
2015-03-18 02:21:57 +01:00
struct TM_Arguments * arguments = TM_AddToArgs ( NULL , 4 , ( void * ) func , del , strdup ( name ) , ( void * ) timeline ) ;
arguments - > next - > next - > next - > next = args ;
return TM_AddAction ( timeline , * runinbackground , arguments , " TM_BackgroundAction " ) ;
2012-04-09 12:55:04 +02:00
}
2015-03-18 02:21:57 +01:00
void TM_AddDelay ( struct Timeline * timeline , int delay ) {
2012-04-07 23:03:34 +02:00
/*int *tmp;
tmp = malloc ( sizeof ( int ) ) ;
* tmp = delay ;
TM_AddAction ( NULL , TM_AddToArgs ( NULL , tmp ) ) ; */
2015-03-18 02:21:57 +01:00
struct TM_Action * tmp = TM_AddAction ( timeline , NULL , NULL , " TM_Delay " ) ;
PrintConsole ( timeline - > game , " Timeline Manager[%s]: queue: adding delay %d ms (%d) " , timeline - > name , delay , tmp - > id ) ;
2012-04-07 23:03:34 +02:00
tmp - > delay = delay ;
tmp - > timer = al_create_timer ( delay / 1000.0 ) ;
2015-03-18 02:21:57 +01:00
al_register_event_source ( timeline - > game - > _priv . event_queue , al_get_timer_event_source ( tmp - > timer ) ) ;
2012-04-06 17:28:38 +02:00
}
2015-03-18 02:21:57 +01:00
void TM_Destroy ( struct Timeline * timeline ) {
PrintConsole ( timeline - > game , " Timeline Manager[%s]: destroy " , timeline - > name ) ;
struct TM_Action * tmp , * tmp2 , * pom = timeline - > queue ;
2012-04-07 18:32:47 +02:00
tmp = NULL ;
while ( pom ! = NULL ) {
if ( pom - > active ) {
2015-03-18 02:21:57 +01:00
if ( * pom - > function ) ( * pom - > function ) ( timeline - > game , pom , TM_ACTIONSTATE_DESTROY ) ;
2012-04-07 18:41:39 +02:00
else {
2012-04-07 23:03:34 +02:00
if ( pom - > timer ) al_destroy_timer ( pom - > timer ) ;
2012-04-07 18:32:47 +02:00
}
2012-04-07 18:41:39 +02:00
} else {
TM_DestroyArgs ( pom - > arguments ) ;
pom - > arguments = NULL ;
2012-04-07 18:32:47 +02:00
}
if ( ( ! tmp ) | | ( tmp - > next = = pom ) ) {
tmp = pom ;
pom = pom - > next ;
} else {
2012-04-09 17:17:16 +02:00
free ( pom - > name ) ;
2012-04-07 18:32:47 +02:00
free ( pom ) ;
tmp2 = tmp ;
2015-03-18 02:21:57 +01:00
if ( ! tmp ) pom = timeline - > background - > next ;
2012-04-07 18:32:47 +02:00
else pom = tmp - > next ;
tmp = tmp2 ;
}
}
tmp = NULL ;
2015-03-18 02:21:57 +01:00
pom = timeline - > background ;
2012-04-07 18:32:47 +02:00
while ( pom ! = NULL ) {
if ( pom - > active ) {
2015-03-18 02:21:57 +01:00
if ( * pom - > function ) ( * pom - > function ) ( timeline - > game , pom , TM_ACTIONSTATE_DESTROY ) ;
2012-04-07 18:41:39 +02:00
else {
2012-04-07 23:03:34 +02:00
if ( pom - > timer ) al_destroy_timer ( pom - > timer ) ;
2012-04-07 18:32:47 +02:00
}
2012-04-07 18:41:39 +02:00
} else {
TM_DestroyArgs ( pom - > arguments ) ;
pom - > arguments = NULL ;
2012-04-07 18:32:47 +02:00
}
if ( ( ! tmp ) | | ( tmp - > next = = pom ) ) {
tmp = pom ;
pom = pom - > next ;
} else {
2012-04-09 17:17:16 +02:00
free ( pom - > name ) ;
2012-04-07 18:32:47 +02:00
free ( pom ) ;
tmp2 = tmp ;
2015-03-18 02:21:57 +01:00
if ( ! tmp ) pom = timeline - > background - > next ;
2012-04-07 18:32:47 +02:00
else pom = tmp - > next ;
tmp = tmp2 ;
}
}
2015-03-18 02:21:57 +01:00
free ( timeline - > name ) ;
free ( timeline ) ;
2012-04-06 17:28:38 +02:00
}
2013-06-05 23:59:02 +02:00
struct TM_Arguments * TM_AddToArgs ( struct TM_Arguments * args , int num , . . . ) {
va_list ap ;
int i ;
va_start ( ap , num ) ;
2012-04-08 23:25:14 +02:00
struct TM_Arguments * tmp = args ;
2013-06-05 23:59:02 +02:00
for ( i = 0 ; i < num ; i + + ) {
if ( ! tmp ) {
tmp = malloc ( sizeof ( struct TM_Arguments ) ) ;
tmp - > value = va_arg ( ap , void * ) ;
tmp - > next = NULL ;
args = tmp ;
} else {
while ( tmp - > next ) {
tmp = tmp - > next ;
}
tmp - > next = malloc ( sizeof ( struct TM_Arguments ) ) ;
tmp - > next - > value = va_arg ( ap , void * ) ;
tmp - > next - > next = NULL ;
}
2012-04-07 20:32:47 +02:00
}
2013-06-05 23:59:02 +02:00
va_end ( ap ) ;
2012-04-07 20:32:47 +02:00
return args ;
2012-04-06 17:28:38 +02:00
}
void TM_DestroyArgs ( struct TM_Arguments * args ) {
2012-04-07 18:32:47 +02:00
struct TM_Arguments * pom ;
while ( args ) {
pom = args - > next ;
free ( args ) ;
args = pom ;
}
}