Appkit: /loading_screen.lua — code sample - Stingray Lua API Reference

Appkit: /loading_screen.lua — code sample

Code

--[[
Simple visual functionality for a Loading Screen. Fades in and out, calls a lua
callback when finished fading out.
]]--

Appkit.LoadingScreen = Appkit.LoadingScreen or {}
local LoadingScreen = Appkit.LoadingScreen

-- Global class behavior config
LoadingScreen.config = LoadingScreen.config or {}
local config = LoadingScreen.config
config.fade_in_time = config.fade_in_time or 0.1
config.display_time = config.display_time or 0.625 -- Starting from when fade in is finished
config.fade_out_time = config.fade_out_time or 0.275

local Application = stingray.Application
local Gui = stingray.Gui
local Keyboard = stingray.Keyboard
local Vector2 = stingray.Vector2
local Vector3 = stingray.Vector3
local World = stingray.World

-- Must be called to start the LoadingScreen.
function LoadingScreen.init(world, material_name, finished_callback)
    if LoadingScreen.gui then
        print "Error in Appkit.LoadingScreen.init. Already initialized. Call destroy before using again."
        return
    end

    LoadingScreen.finished_callback = finished_callback

    local w, h = Application.back_buffer_size()
    LoadingScreen.world = world
    local gui = World.create_screen_gui(world)
    LoadingScreen.gui = gui
    local size = Vector2(w,h)

    -- Loading Screen Image
    LoadingScreen.bitmap = Gui.bitmap(gui, material_name, Vector3(0,0,1), size)

    -- Quad to fade in/out
    LoadingScreen.fade_rect = Gui.rect(gui, Vector3(0,0,2), size, stingray.Color(0,0,0,0))

    LoadingScreen.start_time = Application.time_since_launch()

    LoadingScreen.can_start_fade_out = false
end

-- This must be called to allow the fade out to begin once the fade in and
-- presentation sequence are finished. The loading screen will never fade out
-- or call the finished_callback if this is not called.
function LoadingScreen.allow_fade_out()
    LoadingScreen.can_start_fade_out = true
end

-- Updates the LoadingScreen and returns true if active, if not then returns
-- false. The LoadingScreen is considered active if `Init` has been called and
-- `destroy` has not.
function LoadingScreen.update(dt)
    local gui = LoadingScreen.gui
    if not gui then return false end

    if Keyboard.pressed(Keyboard.button_id('esc')) then
        Application.quit()
    end

    -- function: ax^(a-1) - (a-1)x^a, where a = power
    local ease_fast_in_slow_out_quadratic = function(x, pow)
        local pow_minus_one = pow - 1
        return (pow * math.pow(x, pow_minus_one) - pow_minus_one * math.pow(x, pow))
    end

    local time = Application.time_since_launch() - LoadingScreen.start_time
    local fade_in_time = config.fade_in_time
    local fade = 0
    -- Calc fade in
    if time < fade_in_time then
        fade = ease_fast_in_slow_out_quadratic((fade_in_time - time) / fade_in_time, 4) * 255
    -- or fade out
    elseif LoadingScreen.can_start_fade_out and time > fade_in_time + config.display_time then
        local fade_out_time = config.fade_out_time
        end_time = fade_in_time + config.display_time + fade_out_time
        if time >= end_time then
            if LoadingScreen.finished_callback then
                LoadingScreen.finished_callback()
                -- Exit if the finished_callback called `LoadingScreen.destroy`.
                if LoadingScreen.gui == nil then return false end
            end
            time = end_time
        end
        fade = ease_fast_in_slow_out_quadratic((1 - (end_time - time) / fade_out_time), 6) * 255
    end

    -- Apply fade
    local w, h = Application.back_buffer_size()
    local size = Vector2(w,h)
    Gui.update_rect(gui, LoadingScreen.fade_rect, Vector3(0,0,2), size, stingray.Color(fade,0,0,0))
    return true
end

-- This must be called to stop drawing the loading screen final image and clean
-- up resources.
function LoadingScreen.destroy()
    local gui = LoadingScreen.gui
    if not gui then return end
    Gui.destroy_rect(gui, LoadingScreen.fade_rect)
    LoadingScreen.fade_rect = nil
    Gui.destroy_bitmap(LoadingScreen.gui, LoadingScreen.bitmap)
    LoadingScreen.bitmap = nil
    World.destroy_gui(LoadingScreen.world, gui)
    LoadingScreen.gui = nil
    LoadingScreen.world = nil
end

return LoadingScreen