/** * Copyright (c) 2021 Dominic Masters * * This software is released under the MIT License. * https://opensource.org/licenses/MIT */ #include "queue.h" void queueInit(queue_t *queue) { queue->timeline = 0; queue->count = 0; queue->current = ANIMATION_QUEUE_START; } queueaction_t * queueNext(queue_t *queue) { queueaction_t *action; // Is there a currently running action? If so, end it. if(queue->current != ANIMATION_QUEUE_START) { action = queue->items + queue->current; if(action->onEnd != NULL) action->onEnd(queue, action, queue->current); } // Prepare to go to next action if there is a next action. queue->current++; queue->actionStarted = queue->timeline; if(queue->current >= queue->count) return NULL; // Go to next action, start it. action = queue->items + queue->current; if(action->onStart != NULL) action->onStart(queue, action, queue->current); return action; } queueaction_t * queueAdd(queue_t *queue) { queueaction_t *action; action = queue->items + queue->count; action->index = queue->count; action->data = NULL; action->onStart = NULL; action->onUpdate = NULL; action->onEnd = NULL; queue->count++; return action; } void queueUpdate(queue_t *queue, engine_t *engine) { queueaction_t *action; queue->timeline += engine->time.delta; if(queue->current >= queue->count) return; action = queue->items + queue->current; if(action->onUpdate != NULL) { action->onUpdate(queue, action, queue->current); } } void queueDispose(queue_t *queue) { queueaction_t *action; if(queue->current >= queue->count) return; action = queue->items + queue->current; if(action->onEnd != NULL) action->onEnd(queue, action, queue->current); } void queueRestack(queue_t *queue) { queueaction_t *action; uint8_t i; queueaction_t items[ANIMATION_QUEUE_ITEM_MAX]; // Take the current queue and copy it. arrayCopy(sizeof(queueaction_t), queue->items+queue->current, queue->count - queue->current, items ); // Now rewind the stack queue->count -= queue->current; queue->current = 0; // Now copy back arrayCopy(sizeof(queueaction_t), items, queue->count, queue->items); // Now fix indexes for(i = 0; i < queue->count; i++) { queue->items[i].index = i; } } void _queueDelayUpdate(queue_t *queue, queueaction_t *action, uint8_t i) { float n = queue->timeline - queue->actionStarted; if(n < queue->delays[i]) return; queueNext(queue); } queueaction_t * queueDelay(queue_t *queue, float delay) { queueaction_t *action = queueAdd(queue); queue->delays[action->index] = delay; action->onUpdate = &_queueDelayUpdate; return action; }