{-# LANGUAGE AllowAmbiguousTypes #-} module Mischief.Animation.Animator where import Data.Data import Data.Kind (Type) import Data.Maybe import GHC.Stack (HasCallStack) import Mischief.Animation.Spritesheet import Mischief.Assets import Mischief.ECS data AnimationStatus = Finished | Running class (Typeable (Input a), Typeable a, Typeable (State a), Typeable (Shift a)) => AnimatorTag a where data State a :: Type data Input a :: Type data Shift a :: Type transition :: State a -> Input a -> Maybe (Shift a) -> AnimationStatus -> Maybe (State a) transition State a _ Input a _ Maybe (Shift a) _ AnimationStatus _ = Maybe (State a) forall a. Maybe a Nothing defInput :: Input a default defInput :: (Default (Input a)) => Input a defInput = Input a forall a. Default a => a def animation :: (HasCallStack) => State a -> AssetRef Animation start :: State a data TransitionType = SoftTransition | HardTransition deriving (TransitionType -> TransitionType -> Bool (TransitionType -> TransitionType -> Bool) -> (TransitionType -> TransitionType -> Bool) -> Eq TransitionType forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a $c== :: TransitionType -> TransitionType -> Bool == :: TransitionType -> TransitionType -> Bool $c/= :: TransitionType -> TransitionType -> Bool /= :: TransitionType -> TransitionType -> Bool Eq) data Transition state input shift = Transition { forall state input shift. Transition state input shift -> TransitionType transType :: TransitionType, forall state input shift. Transition state input shift -> state transTo :: state, forall state input shift. Transition state input shift -> Condition input shift transCond :: Condition input shift } to :: state -> Condition input shift -> Transition state input shift to :: forall state input shift. state -> Condition input shift -> Transition state input shift to state b Condition input shift c = Transition {transType :: TransitionType transType = TransitionType SoftTransition, transTo :: state transTo = state b, transCond :: Condition input shift transCond = Condition input shift c} to' :: state -> Condition input shift -> Transition state input shift to' :: forall state input shift. state -> Condition input shift -> Transition state input shift to' state b Condition input shift c = Transition {transType :: TransitionType transType = TransitionType HardTransition, transTo :: state transTo = state b, transCond :: Condition input shift transCond = Condition input shift c} data Condition input shift = WhenCondition (input -> Bool) | ShiftCondition shift when :: (input -> Bool) -> Condition input shift when :: forall input shift. (input -> Bool) -> Condition input shift when = (input -> Bool) -> Condition input shift forall input shift. (input -> Bool) -> Condition input shift WhenCondition on :: shift -> Condition input shift on :: forall shift input. shift -> Condition input shift on = shift -> Condition input shift forall input shift. shift -> Condition input shift ShiftCondition type IsFinished = Bool checkTransitions :: forall a. (AnimatorTag a) => State a -> Input a -> Maybe (Shift a) -> AnimationStatus -> Maybe (State a) checkTransitions :: forall {k} (a :: k). AnimatorTag a => State a -> Input a -> Maybe (Shift a) -> AnimationStatus -> Maybe (State a) checkTransitions = State a -> Input a -> Maybe (Shift a) -> AnimationStatus -> Maybe (State a) forall {k} (a :: k). AnimatorTag a => State a -> Input a -> Maybe (Shift a) -> AnimationStatus -> Maybe (State a) transition