mischief-assets-0.1.0.0: src/Mischief/Assets/Tutorial/Control.hs
{-# OPTIONS_GHC -Wno-unused-imports #-}
-- |
-- [Previous Chapter: Asset Refs]("Mischief.Assets.Tutorial.Refs")
--
-- [Next Chapter: Kdl Assets]("Mischief.Assets.Tutorial.Kdl")
--
-- [Main Page]("Mischief.Assets")
module Mischief.Assets.Tutorial.Control
( -- * Chapter 3: Asset Control Flow
-- $intro
-- * Active vs. Passive Querying
-- $passiveactive
-- * Recursive Loading
-- $rec
-- * Events
-- $events
-- * One-Shot Observers
-- $oneshot
-- * [Next Chapter: Kdl Assets]("Mischief.Assets.Tutorial.Kdl")
)
where
import Mischief.Assets
import Mischief.ECS
-- $intro
-- Some pointers on controlling the logic control flow when working with assets.
-- $passiveactive
-- Attempting to query for an asset will, by default, prompt the asset to load. This is called
-- /active/ querying.
--
-- For instance, running this every frame:
--
-- @
-- foo <- 'asset' \@Foo \"foo.kdl\"
-- @
--
-- Will prompt Foo to start loading if it hasn't yet.
--
-- Assuming that it takes it less than a frame to load, this should be returning a @Just Foo@ starting with the second frame.
--
-- This mechanism is extremely powerful when used in conjunction with queries, via @qasset@, since
-- queries are designed to stop executing when something you're trying to grab isn't available:
--
-- @
-- 'query_' $ do
-- foo <- 'qasset' \@Foo getB
-- 'qlift' $ 'info' ['i'|Reading asset: #{foo}|]
-- @
--
-- You can choose to use /passive/ querying, through the equivalent functions ending in @'@. Such as
-- @'asset''@ and @'qasset''@. These functions will attempt to grab the asset, but they will not prompt it to load.
-- $events
-- You can spawn observers that listen to the @OnLoad@ events, which is triggered each time an asset is loaded.
--
-- @
-- onFoo :: 'OnLoad' Foo -> 'System'
-- onFoo event = ...
-- @
--
-- Since assets are components, you can also listen to @'OnAdd'@, @'OnSet'@, and so on.
-- $rec
-- By default, each asset is loaded lazily. Meaning the least possible amount of I/O operations will be performed in order to get the data you need.
--
-- If asset @A@ contains a reference to asset @B@, neither @'load'@ nor @'asset'@ of @A@ will attempt to load @B@.
-- You can alternatively use the dedicated @'loadRec'@ and @'assetRec'@ which will trigger a recursive loading sequence.
--
-- For all assets you define, you are responsible for specifying the references that will be loaded in such a case. For instance:
--
-- @
-- data Foo = Foo
-- {
-- i :: 'Int',
-- ref1 :: 'AssetRef' Bar
-- ref2 :: 'KdlRef' Baz
-- }
--
-- instance 'Asset' Foo where
-- 'rec' foo = do
-- 'addRec' foo.ref1
-- 'addRec' $ 'toRef' foo.ref2
-- @
-- $oneshot
-- You can use @'runWhen'@ and similar functions to run a system when a specific asset (or group of assets) has been loaded, like so:
--
-- @
-- 'runWhenOne'
-- (
-- foo <- 'qasset' \@Foo \"foo.kdl\"
-- bar <- 'qasset' \@Bar \"bar.kdl\"
-- 'pure' (foo, bar)
-- )
-- (\\(foo, bar) -> do
-- ...
-- )
-- @
--
-- Note however, that each time this function is ran, an instance of your query will be scheduled to run at every sync point until
-- it returns a result. In order to not waste a large amount of resources, this should only be used in one-time logic such as
-- on Startup or in an Observer, rather than in logic that runs at a fixed interval.