module Mischief.ECS.Timer where import Data.Function import Mischief.ECS.Components import Mischief.ECS.Components.Bundle import Mischief.ECS.Time qualified as Time import Mischief.ECS.World import Mischief.ECS.World.Insert import Mischief.ECS.World.Query import Mischief.ECS.World.Query.Markers import Mischief.ECS.World.Query.Pipe data Timer = Timer {Timer -> Float duration :: Float, Timer -> Float elapsed :: Float, Timer -> Mode mode :: Mode} data Mode = Once | Repeat new :: Float -> Mode -> Timer new :: Float -> Mode -> Timer new Float duration Mode mode = Timer {Float duration :: Float duration :: Float duration, Mode mode :: Mode mode :: Mode mode, elapsed :: Float elapsed = Float 0} tick :: Float -> Timer -> (Timer, Bool) tick :: Float -> Timer -> (Timer, Bool) tick Float _ Timer timer | Timer timer.elapsed Float -> Float -> Bool forall a. Ord a => a -> a -> Bool >= Timer timer.duration = (Timer timer, Bool False) tick Float x Timer timer | Timer timer.elapsed Float -> Float -> Float forall a. Num a => a -> a -> a + Float x Float -> Float -> Bool forall a. Ord a => a -> a -> Bool < Timer timer.duration = (Timer timer {elapsed = timer.elapsed + x}, Bool False) tick Float _ Timer {Float duration :: Timer -> Float duration :: Float duration, elapsed :: Timer -> Float elapsed = Float _, mode :: Timer -> Mode mode = Mode Once} = (Timer {Float duration :: Float duration :: Float duration, elapsed :: Float elapsed = Float duration, mode :: Mode mode = Mode Once}, Bool True) tick Float x Timer {Float duration :: Timer -> Float duration :: Float duration, Float elapsed :: Timer -> Float elapsed :: Float elapsed, mode :: Timer -> Mode mode = Mode Repeat} = (Timer {Float duration :: Float duration :: Float duration, elapsed :: Float elapsed = Float elapsed Float -> Float -> Float forall a. Num a => a -> a -> a + Float x Float -> Float -> Float forall a. Num a => a -> a -> a - Float duration, mode :: Mode mode = Mode Repeat}, Bool True) qtimer :: forall b a. (Bundle b, Component b) => (b -> Timer) -> (Timer -> b) -> Query System a -> Query System a qtimer :: forall b a. (Bundle b, Component b) => (b -> Timer) -> (Timer -> b) -> Query System a -> Query System a qtimer b -> Timer f Timer -> b f' Query System a x = Query System a x Query System a -> (Query System a -> Query System (a, b)) -> Query System (a, b) forall a b. a -> (a -> b) -> b & C b -> (a -> b -> (a, b)) -> Query System a -> Query System (a, b) forall w (m :: * -> *) qd out a c. (MonadSystem w m, Queryable qd out) => qd -> (a -> out -> c) -> Query m a -> Query m c qextend (forall a. C a forall {k} (a :: k). C a C @b) (,) Query System (a, b) -> (Query System (a, b) -> Query System (a, b)) -> Query System (a, b) forall a b. a -> (a -> b) -> b & (Entity -> (a, b) -> System Bool) -> Query System (a, b) -> Query System (a, b) forall a (m :: * -> *). (Entity -> a -> m Bool) -> Query m a -> Query m a qfilterM ( \Entity entity (a _, b a) -> do let timer :: Timer timer = b -> Timer f b a delta <- System Float Time.delta let (timer', justFinished) = tick delta timer insert (f' timer') entity pure justFinished ) Query System (a, b) -> (Query System (a, b) -> Query System a) -> Query System a forall a b. a -> (a -> b) -> b & ((a, b) -> a) -> Query System (a, b) -> Query System a forall w (m :: * -> *) a b. MonadSystem w m => (a -> b) -> Query m a -> Query m b qmap (a, b) -> a forall a b. (a, b) -> a fst qtimer' :: forall b a. (Bundle b, Component b) => (b -> Timer) -> (Timer -> b) -> Float -> Query System a -> Query System a qtimer' :: forall b a. (Bundle b, Component b) => (b -> Timer) -> (Timer -> b) -> Float -> Query System a -> Query System a qtimer' b -> Timer f Timer -> b f' Float delta Query System a x = Query System a x Query System a -> (Query System a -> Query System (a, b)) -> Query System (a, b) forall a b. a -> (a -> b) -> b & C b -> (a -> b -> (a, b)) -> Query System a -> Query System (a, b) forall w (m :: * -> *) qd out a c. (MonadSystem w m, Queryable qd out) => qd -> (a -> out -> c) -> Query m a -> Query m c qextend (forall a. C a forall {k} (a :: k). C a C @b) (,) Query System (a, b) -> (Query System (a, b) -> Query System (a, b)) -> Query System (a, b) forall a b. a -> (a -> b) -> b & (Entity -> (a, b) -> System Bool) -> Query System (a, b) -> Query System (a, b) forall a (m :: * -> *). (Entity -> a -> m Bool) -> Query m a -> Query m a qfilterM ( \Entity entity (a _, b a) -> do let timer :: Timer timer = b -> Timer f b a let (Timer timer', Bool justFinished) = Float -> Timer -> (Timer, Bool) tick Float delta Timer timer b -> Entity -> System () forall b. (HasCallStack, Bundle b) => b -> Entity -> System () forall b. Bundle b => b -> Entity -> System () insert (Timer -> b f' Timer timer') Entity entity Bool -> System Bool forall a. a -> System a forall (f :: * -> *) a. Applicative f => a -> f a pure Bool justFinished ) Query System (a, b) -> (Query System (a, b) -> Query System a) -> Query System a forall a b. a -> (a -> b) -> b & ((a, b) -> a) -> Query System (a, b) -> Query System a forall w (m :: * -> *) a b. MonadSystem w m => (a -> b) -> Query m a -> Query m b qmap (a, b) -> a forall a b. (a, b) -> a fst