1 /*
2  * This software is licensed under the terms of the MIT License.
3  * See COPYING for further information.
4  * ---
5  * Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
6  * Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
7  */
8 
9 #include "taisei.h"
10 
11 #include "aniplayer.h"
12 #include "list.h"
13 #include "global.h"
14 #include "stageobjects.h"
15 
aniplayer_create(AniPlayer * plr,Animation * ani,const char * startsequence)16 void aniplayer_create(AniPlayer *plr, Animation *ani, const char *startsequence) {
17 	memset(plr,0,sizeof(AniPlayer));
18 	plr->ani = ani;
19 
20 	aniplayer_queue(plr,startsequence,0);
21 }
22 
aniplayer_get_frame(AniPlayer * plr)23 Sprite *aniplayer_get_frame(AniPlayer *plr) {
24 	assert(plr->queue.first != NULL);
25 	return animation_get_frame(plr->ani, plr->queue.first->sequence, plr->queue.first->clock);
26 }
27 
aniplayer_free(AniPlayer * plr)28 void aniplayer_free(AniPlayer *plr) {
29 	plr->queuesize = 0;
30 	alist_free_all(&plr->queue);
31 }
32 
33 // Deletes the queue. If hard is set, even the last element is removed leaving the player in an invalid state.
aniplayer_reset(AniPlayer * plr,bool hard)34 static void aniplayer_reset(AniPlayer *plr, bool hard) {
35 	if(plr->queuesize == 0)
36 		return;
37 	if(hard) {
38 		alist_free_all(&plr->queue);
39 		plr->queuesize = 0;
40 		return;
41 	}
42 
43 	list_free_all(&plr->queue.first->next);
44 	plr->queue.last = plr->queue.first;
45 	plr->queuesize = 1;
46 }
47 
aniplayer_queue(AniPlayer * plr,const char * seqname,int loops)48 AniQueueEntry *aniplayer_queue(AniPlayer *plr, const char *seqname, int loops) {
49 	AniQueueEntry *s = calloc(1, sizeof(AniQueueEntry));
50 	alist_append(&plr->queue, s);
51 	plr->queuesize++;
52 
53 	if(loops < 0)
54 		log_fatal("Negative number of loops passed: %d",loops);
55 	s->sequence = get_ani_sequence(plr->ani,seqname);
56 
57 	s->duration = loops*s->sequence->length;
58 
59 	return s;
60 }
61 
aniplayer_queue_frames(AniPlayer * plr,const char * seqname,int frames)62 AniQueueEntry *aniplayer_queue_frames(AniPlayer *plr, const char *seqname, int frames) {
63 	AniQueueEntry *s = aniplayer_queue(plr, seqname, 0);
64 	s->duration = frames;
65 	return s;
66 }
67 
aniplayer_soft_switch(AniPlayer * plr,const char * seqname,int loops)68 AniQueueEntry *aniplayer_soft_switch(AniPlayer *plr, const char *seqname, int loops) {
69 	aniplayer_reset(plr,false);
70 	return aniplayer_queue(plr,seqname,loops);
71 }
72 
aniplayer_hard_switch(AniPlayer * plr,const char * seqname,int loops)73 AniQueueEntry *aniplayer_hard_switch(AniPlayer *plr, const char *seqname, int loops) {
74 	aniplayer_reset(plr,true);
75 	return aniplayer_queue(plr,seqname,loops);
76 }
77 
aniplayer_update(AniPlayer * plr)78 void aniplayer_update(AniPlayer *plr) {
79 	assert(plr->queue.first != NULL); // The queue should never be empty.
80 	AniQueueEntry *s = plr->queue.first;
81 
82 	s->clock++;
83 	// The last condition assures that animations only switch at their end points
84 	if(s->clock >= s->duration && plr->queuesize > 1 && s->clock%s->sequence->length == 0) {
85 		free(alist_pop(&plr->queue));
86 		plr->queuesize--;
87 	}
88 }
89 
90