{-# 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.