module Mischief.Animation.Animations where

import Data.Functor ((<&>))
import Data.Text (Text)
import KDL qualified
import Mischief.Animation.Spritesheet
import Mischief.Assets
import Mischief.ECS (Component)

data Animations = Animations {Animations -> KdlRef Spritesheet
spritesheet :: KdlRef Spritesheet, Animations -> KdlCollection Animation
collection :: KdlCollection Animation} deriving (Int -> Animations -> ShowS
[Animations] -> ShowS
Animations -> String
(Int -> Animations -> ShowS)
-> (Animations -> String)
-> ([Animations] -> ShowS)
-> Show Animations
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Animations -> ShowS
showsPrec :: Int -> Animations -> ShowS
$cshow :: Animations -> String
show :: Animations -> String
$cshowList :: [Animations] -> ShowS
showList :: [Animations] -> ShowS
Show, Typeable Animations
[HookRel Animations]
[Hook Animations]
Set DefaultComponentType
IsExclusive (IsExclusiveRel Animations)
(Typeable Animations, IsExclusive (IsExclusiveRel Animations)) =>
Set DefaultComponentType
-> [Hook Animations]
-> [Hook Animations]
-> [Hook Animations]
-> [HookRel Animations]
-> [HookRel Animations]
-> [HookRel Animations]
-> Component Animations
forall c.
(Typeable c, IsExclusive (IsExclusiveRel c)) =>
Set DefaultComponentType
-> [Hook c]
-> [Hook c]
-> [Hook c]
-> [HookRel c]
-> [HookRel c]
-> [HookRel c]
-> Component c
$crequired :: Set DefaultComponentType
required :: Set DefaultComponentType
$conAdd :: [Hook Animations]
onAdd :: [Hook Animations]
$conSet :: [Hook Animations]
onSet :: [Hook Animations]
$conRemove :: [Hook Animations]
onRemove :: [Hook Animations]
$conAddRel :: [HookRel Animations]
onAddRel :: [HookRel Animations]
$conSetRel :: [HookRel Animations]
onSetRel :: [HookRel Animations]
$conRemoveRel :: [HookRel Animations]
onRemoveRel :: [HookRel Animations]
Component)

instance KdlAsset Animations where
  decodeKdl :: RelativePath -> NodeDecoder Animations
decodeKdl RelativePath
path = NodeListDecodeArrow () Animations -> NodeDecoder Animations
forall a b. NodeListDecodeArrow a b -> NodeDecodeArrow a b
KDL.children (NodeListDecodeArrow () Animations -> NodeDecoder Animations)
-> NodeListDecodeArrow () Animations -> NodeDecoder Animations
forall a b. (a -> b) -> a -> b
$ do
    spritesheet <- RelativePath
-> NodeDecodeArrow () (KdlRef Spritesheet)
-> NodeListDecodeArrow () (KdlRef Spritesheet)
forall a b.
Typeable b =>
RelativePath -> NodeDecodeArrow a b -> NodeListDecodeArrow a b
KDL.nodeWith RelativePath
"spritesheet" (NodeDecodeArrow () (KdlRef Spritesheet)
 -> NodeListDecodeArrow () (KdlRef Spritesheet))
-> NodeDecodeArrow () (KdlRef Spritesheet)
-> NodeListDecodeArrow () (KdlRef Spritesheet)
forall a b. (a -> b) -> a -> b
$ RelativePath -> NodeDecodeArrow () (KdlRef Spritesheet)
forall a. KdlAsset a => RelativePath -> NodeDecoder a
decodeKdl RelativePath
path
    collection <- KDL.nodeWith "collection" $ KDL.children $ colDecodeWith $ decodeAnimationWithSpritesheet spritesheet

    pure $ Animations {spritesheet, collection}

instance Asset Animations where
  type Saveable Animations = False
  loadAsset :: String -> RelativePath -> IO (Either RelativePath Animations)
loadAsset = RelativePath
-> String -> RelativePath -> IO (Either RelativePath Animations)
forall a.
KdlAsset a =>
RelativePath
-> String -> RelativePath -> IO (Either RelativePath a)
loadKdl RelativePath
"animations"

decodeAnimationWithSpritesheet :: KdlRef Spritesheet -> KDL.NodeDecoder Animation
decodeAnimationWithSpritesheet :: KdlRef Spritesheet -> NodeDecoder Animation
decodeAnimationWithSpritesheet KdlRef Spritesheet
spritesheet = NodeListDecodeArrow () Animation -> NodeDecoder Animation
forall a b. NodeListDecodeArrow a b -> NodeDecodeArrow a b
KDL.children (NodeListDecodeArrow () Animation -> NodeDecoder Animation)
-> NodeListDecodeArrow () Animation -> NodeDecoder Animation
forall a b. (a -> b) -> a -> b
$ do
  frames <- NodeListDecoder AnimationFrames
animationFramesDecoder
  time <- animationTimeDecoder
  loop <- animationLoopDecoder
  pure $ Animation {dummy = False, time, frames, loop, spritesheet}

selAnim :: Text -> Text -> AssetRef Animation
selAnim :: RelativePath -> RelativePath -> AssetRef Animation
selAnim RelativePath
file RelativePath
anim = forall a. (Asset a, Bundle a) => RelativePath -> AssetRef a
Ref @Animations RelativePath
file AssetRef Animations
-> (Animations -> Animation) -> AssetRef Animation
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (RelativePath -> KdlCollection Animation -> Animation
forall a. RelativePath -> KdlCollection a -> a
colGetU RelativePath
anim (KdlCollection Animation -> Animation)
-> (Animations -> KdlCollection Animation)
-> Animations
-> Animation
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.collection))