mischief-assets-0.1.0.0: src/Mischief/Assets/Tutorial/Kdl.hs
{-# OPTIONS_GHC -Wno-unused-imports #-}
-- |
-- [Previous Chapter: Asset Control Flow]("Mischief.Assets.Tutorial.Control")
--
-- [Next Chapter: Asset Control Flow]("Mischief.Assets.Tutorial.Control")
--
-- [Main Page]("Mischief.Assets")
module Mischief.Assets.Tutorial.Kdl
( -- * Chapter 4: Kdl Assets
-- $intro
-- * The KdlAsset Class
-- $kdlasset
-- * Manual Decoding
-- $decoding
-- * Collections
-- $collection
)
where
import KDL qualified
import Linear
import Mischief.Assets
import Mischief.ECS
-- $intro
-- [Kdl](https://kdl.dev/spec/) is the official file format used by Mischief.
-- $kdlasset
-- The KdlAsset typeclass is a helper for defining assets that are loaded from .kdl files without needing to parse their fields manually.
--
-- Generally, only types with named fields (records) can automatically derive it:
--
-- @
-- data Foo = Foo
-- {
-- a :: 'Int'
-- b :: 'Float'
-- c :: 'V2' 'Int'
-- }
-- deriving ('Generic', 'KdlAsset')
-- @
--
-- You can now use the @loadKdl@ function provided by the typeclass to quickly make a loadable asset:
--
-- @
-- instance 'Asset' Foo where
-- type 'Saveable' Foo = 'False'
--
-- 'loadAsset' = 'loadKdl' \"foo\"
-- @
--
-- The asset itself should look something like this:
--
-- @
-- foo {
-- a 6
-- b 3.2
-- c 2 4
-- }
-- @
-- $decoding
-- You can write custom kdl decoders using the [kdl-hs]("KDL") library.
--
-- For instance, this is how you could decode the asset from the previous section:
--
-- @
-- instance 'KdlAsset' Foo where
-- 'decodeKdl' path = KDL.'KDL.children' $ do
-- a <- KDL.'KDL.argAt' \"a\"
-- b <- KDL.'KDL.argAt' \"b\"
-- c <- KDL.'KDL.nodeWith' \"c\" KDL.'KDL.nodeDecoder'
-- pure $ Foo {a, b, c}
-- @
--
-- Note that here we can use @"KDL.nodeDecoder"@ because @V2 a@ has a @KDL.'KDL.DecodeNode'@ instance. Otherwise you'd need
-- to parse it manually, like the others.
--
-- The @path@ argument is used to decode references to other assets. For instance, if @Foo@ also had this field:
--
-- @
-- bar :: 'AssetRef' Bar
-- @
--
-- You'd decode it like this:
--
-- @
-- bar <- 'KDL.argAtWith' $ \"bar\" $ 'decodeRef' path
-- @
--
-- For KdlRefs you use 'decodeKdlRef' instead.
-- $collection
-- A Kdl Collection is a map of nodes of the same type.
--
-- For instance, this field:
--
-- @
-- a :: 'KdlCollection' 'Int'
-- @
--
-- Expects something that looks like this:
--
-- @
-- a {
-- name1 4
-- name2 6
-- name3 5
-- ...
-- }
-- @
--
-- You can use @'colGet'@ to try and get the value of a node from a collection by name. Or @'colGetMany'@ to get the
-- value of all nodes with the given name.