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