/* * This software is licensed under the terms of the MIT License. * See COPYING for further information. * --- * Copyright (c) 2011-2024, Lukas Weber . * Copyright (c) 2012-2024, Andrei Alexeyev . */ #include "transition.h" #include "renderer/api.h" #include "util/graphics.h" Transition transition; static CallChain swap_cc(CallChain *pcc, CallChain newcc) { CallChain cc = *pcc; *pcc = newcc; return cc; } static CallChain pop_cc(CallChain *pcc) { return swap_cc(pcc, NO_CALLCHAIN); } static void run_cc(CallChain *pcc, bool canceled) { CallChain cc = pop_cc(pcc); run_call_chain(&cc, (void*)(uintptr_t)canceled); } static void swap_cc_withcancel(CallChain *pcc, CallChain newcc) { CallChain oldcc = swap_cc(pcc, newcc); run_cc(&oldcc, true); } void TransFadeBlack(double fade) { fade_out(fade); } void TransFadeWhite(double fade) { colorfill(fade, fade, fade, fade); } void TransLoader(double fade) { r_color4(fade, fade, fade, fade); fill_screen("loading"); r_color4(1, 1, 1, 1); } void TransEmpty(double fade) { } static bool popq(void) { if(transition.queued.rule) { transition.rule2 = transition.rule; transition.rule = transition.queued.rule; if(transition.state == TRANS_IDLE || transition.rule2 == transition.rule) { transition.rule2 = NULL; } transition.dur1 = transition.queued.dur1; transition.dur2 = transition.queued.dur2; swap_cc_withcancel(&transition.cc, transition.queued.cc); transition.queued.cc = NO_CALLCHAIN; transition.queued.rule = NULL; if(transition.dur1 <= 0) { transition.fade = 1.0; transition.state = TRANS_FADE_OUT; } else { transition.state = TRANS_FADE_IN; } return true; } return false; } static void setq(TransitionRule rule, int dur1, int dur2, CallChain cc) { transition.queued.rule = rule; transition.queued.dur1 = dur1; transition.queued.dur2 = dur2; swap_cc_withcancel(&transition.queued.cc, cc); } void set_transition(TransitionRule rule, int dur1, int dur2, CallChain cc) { static bool initialized = false; if(!rule) { return; } setq(rule, dur1, dur2, cc); if(!initialized) { popq(); initialized = true; transition.rule2 = NULL; } // FIXME can we just do this unconditionally? if( transition.state == TRANS_IDLE || transition.state == TRANS_FADE_OUT || rule == transition.rule ) { popq(); } } static bool check_transition(void) { if(transition.state == TRANS_IDLE) { return false; } if(!transition.rule) { transition.state = TRANS_IDLE; return false; } return true; } void draw_transition(void) { if(!check_transition()) { return; } transition.rule(transition.fade); if(transition.rule2 && transition.rule2 != transition.rule) { transition.rule2(transition.fade); } } void update_transition(void) { if(!check_transition()) { return; } if(transition.state == TRANS_FADE_IN) { transition.fade = approach(transition.fade, 1.0, 1.0/transition.dur1); if(transition.fade == 1.0) { transition.state = TRANS_FADE_OUT; popq(); run_cc(&transition.cc, false); } } else if(transition.state == TRANS_FADE_OUT) { transition.fade = transition.dur2 ? approach(transition.fade, 0.0, 1.0/transition.dur2) : 0.0; if(transition.fade == 0.0) { transition.state = TRANS_IDLE; popq(); } } }