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