packages feed

aztecs 0.6.0 → 0.7.0

raw patch · 50 files changed

+1557/−953 lines, 50 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Aztecs: [transformPosition] :: Transform -> !V2 Int
- Aztecs: transform :: Transform
- Aztecs.Asset: AssetLoaderT :: StateT (AssetServer a) m o -> AssetLoaderT a m o
- Aztecs.Asset: [unAssetLoader] :: AssetLoaderT a m o -> StateT (AssetServer a) m o
- Aztecs.Asset: empty :: AssetServer a
- Aztecs.Asset: instance (GHC.Base.Monad m, Aztecs.Asset.Asset a) => Aztecs.Asset.MonadAssetLoader a (Aztecs.Asset.AssetLoaderT a m)
- Aztecs.Asset: instance Control.DeepSeq.NFData (Aztecs.Asset.AssetServer a)
- Aztecs.Asset: instance Control.DeepSeq.NFData (Aztecs.Asset.Handle a)
- Aztecs.Asset: instance Data.Typeable.Internal.Typeable a => Aztecs.ECS.Component.Component (Aztecs.Asset.AssetServer a)
- Aztecs.Asset: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.Asset.AssetLoaderT a m)
- Aztecs.Asset: instance GHC.Base.Monad m => GHC.Base.Applicative (Aztecs.Asset.AssetLoaderT a m)
- Aztecs.Asset: instance GHC.Base.Monad m => GHC.Base.Monad (Aztecs.Asset.AssetLoaderT a m)
- Aztecs.Asset: instance GHC.Classes.Eq (Aztecs.Asset.Handle a)
- Aztecs.Asset: instance GHC.Classes.Eq Aztecs.Asset.AssetId
- Aztecs.Asset: instance GHC.Classes.Ord (Aztecs.Asset.Handle a)
- Aztecs.Asset: instance GHC.Classes.Ord Aztecs.Asset.AssetId
- Aztecs.Asset: instance GHC.Generics.Generic (Aztecs.Asset.AssetServer a)
- Aztecs.Asset: instance GHC.Show.Show (Aztecs.Asset.Handle a)
- Aztecs.Asset: instance GHC.Show.Show Aztecs.Asset.AssetId
- Aztecs.Asset: loadQuery :: (Asset a, ArrowQuery arr) => AssetLoader a o -> arr () o
- Aztecs.Asset: newtype AssetLoaderT a m o
- Aztecs.Asset: type AssetLoader a o = AssetLoaderT a Identity o
- Aztecs.ECS: data Schedule m i o
- Aztecs.ECS: task :: Monad m => (i -> m o) -> Schedule m i o
- Aztecs.ECS.Access: instance GHC.Base.Monad m => Aztecs.ECS.Access.Class.MonadAccess (Aztecs.ECS.Access.AccessT m)
- Aztecs.ECS.Query: entityDyn :: ArrowDynamicQueryReader arr => arr () EntityID
- Aztecs.ECS.Query.Dynamic: entityDyn :: ArrowDynamicQueryReader arr => arr () EntityID
- Aztecs.ECS.Query.Dynamic.Reader: entityDyn :: ArrowDynamicQueryReader arr => arr () EntityID
- Aztecs.ECS.Query.Dynamic.Reader.Class: entityDyn :: ArrowDynamicQueryReader arr => arr () EntityID
- Aztecs.ECS.Query.Reader: Query :: (Components -> (Set ComponentID, Components, DynamicQueryReader i o)) -> QueryReader i o
- Aztecs.ECS.Query.Reader: entityDyn :: ArrowDynamicQueryReader arr => arr () EntityID
- Aztecs.ECS.Query.Reader.Class: entity :: ArrowQueryReader arr => arr () EntityID
- Aztecs.ECS.Schedule: instance Control.Arrow.Arrow (Aztecs.ECS.Schedule.Schedule GHC.Types.IO)
- Aztecs.ECS.Schedule: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.ECS.Schedule.Schedule m i)
- Aztecs.ECS.Schedule: instance GHC.Base.Monad m => Control.Category.Category (Aztecs.ECS.Schedule.Schedule m)
- Aztecs.ECS.Schedule: newtype Schedule m i o
- Aztecs.ECS.Schedule: task :: Monad m => (i -> m o) -> Schedule m i o
- Aztecs.ECS.System.Class: queue :: ArrowSystem q arr => (i -> Access ()) -> arr i ()
- Aztecs.ECS.System.Dynamic: instance Aztecs.ECS.System.Dynamic.Class.ArrowDynamicSystem Aztecs.ECS.System.Dynamic.DynamicSystem
- Aztecs.ECS.System.Dynamic: instance Aztecs.ECS.System.Dynamic.Reader.Class.ArrowDynamicReaderSystem Aztecs.ECS.System.Dynamic.DynamicSystem
- Aztecs.ECS.System.Dynamic.Class: filterMapDyn' :: Set ComponentID -> DynamicQuery i o -> (Node -> Bool) -> DynamicSystem i [o]
- Aztecs.ECS.System.Dynamic.Class: mapDyn' :: Set ComponentID -> DynamicQuery i o -> DynamicSystem i [o]
- Aztecs.ECS.System.Dynamic.Class: mapSingleDyn' :: Set ComponentID -> DynamicQuery i o -> DynamicSystem i o
- Aztecs.ECS.System.Dynamic.Class: mapSingleMaybeDyn' :: Set ComponentID -> DynamicQuery i o -> DynamicSystem i (Maybe o)
- Aztecs.ECS.System.Dynamic.Class: queueDyn :: ArrowDynamicSystem arr => (i -> Access ()) -> arr i ()
- Aztecs.ECS.System.Dynamic.Class: queueDyn' :: (i -> Access ()) -> DynamicSystem i ()
- Aztecs.ECS.System.Dynamic.Class: runArrowSystemDyn :: ArrowDynamicSystem arr => DynamicSystem i o -> arr i o
- Aztecs.ECS.System.Dynamic.Class: type DynamicSystem i o = World -> i -> (o, View, Access ())
- Aztecs.ECS.System.Dynamic.Reader: instance Aztecs.ECS.System.Dynamic.Reader.Class.ArrowDynamicReaderSystem Aztecs.ECS.System.Dynamic.Reader.DynamicReaderSystem
- Aztecs.ECS.System.Reader: filterMap :: ArrowSystem q arr => q i a -> QueryFilter -> arr i [a]
- Aztecs.ECS.System.Reader: map :: ArrowSystem q arr => q i a -> arr i [a]
- Aztecs.ECS.System.Reader: mapSingle :: ArrowSystem q arr => q i a -> arr i a
- Aztecs.ECS.System.Reader: map_ :: ArrowSystem q arr => q i o -> arr i ()
- Aztecs.ECS.World: [archetypes] :: World -> !Archetypes
- Aztecs.ECS.World: [components] :: World -> !Components
- Aztecs.ECS.World: spawnComponent :: forall a. (Component a, Typeable (StorageT a)) => a -> World -> (EntityID, World)
- Aztecs.ECS.World: spawnWithId :: forall a. (Component a, Typeable (StorageT a)) => ComponentID -> a -> World -> (EntityID, World)
- Aztecs.ECS.World.Archetype: AnyStorage :: !Dynamic -> !Int -> Dynamic -> Dynamic -> Dynamic -> !Int -> Dynamic -> (Maybe Dynamic, Dynamic) -> !Int -> Dynamic -> (Maybe AnyStorage, Dynamic) -> !Dynamic -> [Int] -> !Dynamic -> () -> AnyStorage
- Aztecs.ECS.World.Archetype: Bundle :: (Components -> (Set ComponentID, Components, DynamicBundle)) -> Bundle
- Aztecs.ECS.World.Archetype: DynamicBundle :: (EntityID -> Archetype -> Archetype) -> DynamicBundle
- Aztecs.ECS.World.Archetype: [entitiesDyn] :: AnyStorage -> !Dynamic -> [Int]
- Aztecs.ECS.World.Archetype: [insertDyn] :: AnyStorage -> !Int -> Dynamic -> Dynamic -> Dynamic
- Aztecs.ECS.World.Archetype: [removeAny] :: AnyStorage -> !Int -> Dynamic -> (Maybe AnyStorage, Dynamic)
- Aztecs.ECS.World.Archetype: [removeDyn] :: AnyStorage -> !Int -> Dynamic -> (Maybe Dynamic, Dynamic)
- Aztecs.ECS.World.Archetype: [runDynamicBundle] :: DynamicBundle -> EntityID -> Archetype -> Archetype
- Aztecs.ECS.World.Archetype: [storageDyn] :: AnyStorage -> !Dynamic
- Aztecs.ECS.World.Archetype: [storageRnf] :: AnyStorage -> !Dynamic -> ()
- Aztecs.ECS.World.Archetype: [unBundle] :: Bundle -> Components -> (Set ComponentID, Components, DynamicBundle)
- Aztecs.ECS.World.Archetype: all :: Component a => ComponentID -> Archetype -> [(EntityID, a)]
- Aztecs.ECS.World.Archetype: allMaybe :: Component a => ComponentID -> Archetype -> [(EntityID, Maybe a)]
- Aztecs.ECS.World.Archetype: anyStorage :: forall s a. Storage s a => s a -> AnyStorage
- Aztecs.ECS.World.Archetype: bundle :: forall a. (Component a, Typeable (StorageT a)) => a -> Bundle
- Aztecs.ECS.World.Archetype: data AnyStorage
- Aztecs.ECS.World.Archetype: dynBundle :: (Component a, Typeable (StorageT a)) => ComponentID -> a -> DynamicBundle
- Aztecs.ECS.World.Archetype: instance Control.DeepSeq.NFData Aztecs.ECS.World.Archetype.AnyStorage
- Aztecs.ECS.World.Archetype: instance GHC.Base.Monoid Aztecs.ECS.World.Archetype.Bundle
- Aztecs.ECS.World.Archetype: instance GHC.Base.Monoid Aztecs.ECS.World.Archetype.DynamicBundle
- Aztecs.ECS.World.Archetype: instance GHC.Base.Semigroup Aztecs.ECS.World.Archetype.Bundle
- Aztecs.ECS.World.Archetype: instance GHC.Base.Semigroup Aztecs.ECS.World.Archetype.DynamicBundle
- Aztecs.ECS.World.Archetype: instance GHC.Show.Show Aztecs.ECS.World.Archetype.AnyStorage
- Aztecs.ECS.World.Archetype: newtype Bundle
- Aztecs.ECS.World.Archetype: newtype DynamicBundle
- Aztecs.ECS.World.Archetype: runBundle :: Bundle -> Components -> EntityID -> Archetype -> (Components, Archetype)
- Aztecs.ECS.World.Archetype: withAscList :: forall a. Component a => ComponentID -> [a] -> Archetype -> Archetype
- Aztecs.ECS.World.Archetypes: lookupNode :: ArchetypeID -> Archetypes -> Maybe Node
- Aztecs.ECS.World.Storage: all :: Storage s a => s a -> [(Int, a)]
- Aztecs.Transform: [transformPosition] :: Transform -> !V2 Int
- Aztecs.Transform: instance Aztecs.ECS.Component.Component Aztecs.Transform.Size
- Aztecs.Transform: instance Aztecs.ECS.Component.Component Aztecs.Transform.Transform
- Aztecs.Transform: instance Control.DeepSeq.NFData Aztecs.Transform.Size
- Aztecs.Transform: instance Control.DeepSeq.NFData Aztecs.Transform.Transform
- Aztecs.Transform: instance GHC.Classes.Eq Aztecs.Transform.Transform
- Aztecs.Transform: instance GHC.Generics.Generic Aztecs.Transform.Size
- Aztecs.Transform: instance GHC.Generics.Generic Aztecs.Transform.Transform
- Aztecs.Transform: instance GHC.Show.Show Aztecs.Transform.Transform
- Aztecs.Transform: transform :: Transform
+ Aztecs: Size :: v -> Size v
+ Aztecs: [transformTranslation] :: Transform v r -> !v
+ Aztecs: [unSize] :: Size v -> v
+ Aztecs: newtype Size v
+ Aztecs: size2D :: Size (V2 Integer)
+ Aztecs: transform2d :: Transform2D
+ Aztecs: type Size2D = Size (V2 Int)
+ Aztecs: type Transform2D = Transform (V2 Int) Int
+ Aztecs.Asset.AssetLoader: AssetLoaderT :: StateT (AssetServer a) m o -> AssetLoaderT a m o
+ Aztecs.Asset.AssetLoader: [unAssetLoader] :: AssetLoaderT a m o -> StateT (AssetServer a) m o
+ Aztecs.Asset.AssetLoader: asset :: MonadAssetLoader a m => FilePath -> AssetConfig a -> m (Handle a)
+ Aztecs.Asset.AssetLoader: class MonadAssetLoader a m | m -> a
+ Aztecs.Asset.AssetLoader: instance (GHC.Base.Monad m, Aztecs.Asset.Class.Asset a) => Aztecs.Asset.AssetLoader.Class.MonadAssetLoader a (Aztecs.Asset.AssetLoader.AssetLoaderT a m)
+ Aztecs.Asset.AssetLoader: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.Asset.AssetLoader.AssetLoaderT a m)
+ Aztecs.Asset.AssetLoader: instance GHC.Base.Monad m => GHC.Base.Applicative (Aztecs.Asset.AssetLoader.AssetLoaderT a m)
+ Aztecs.Asset.AssetLoader: instance GHC.Base.Monad m => GHC.Base.Monad (Aztecs.Asset.AssetLoader.AssetLoaderT a m)
+ Aztecs.Asset.AssetLoader: load :: (ArrowQuery q, ArrowSystem q arr, Asset a) => AssetLoader a o -> arr () o
+ Aztecs.Asset.AssetLoader: loadQuery :: (Asset a, ArrowQuery arr) => AssetLoader a o -> arr () o
+ Aztecs.Asset.AssetLoader: newtype AssetLoaderT a m o
+ Aztecs.Asset.AssetLoader: type AssetLoader a o = AssetLoaderT a Identity o
+ Aztecs.Asset.AssetLoader.Class: asset :: MonadAssetLoader a m => FilePath -> AssetConfig a -> m (Handle a)
+ Aztecs.Asset.AssetLoader.Class: class MonadAssetLoader a m | m -> a
+ Aztecs.Asset.AssetServer: AssetId :: Int -> AssetId
+ Aztecs.Asset.AssetServer: AssetServer :: !Map AssetId a -> !Map AssetId (Either (IO (IORef (Maybe a))) (IORef (Maybe a))) -> !AssetId -> AssetServer a
+ Aztecs.Asset.AssetServer: Handle :: AssetId -> Handle a
+ Aztecs.Asset.AssetServer: [assetServerAssets] :: AssetServer a -> !Map AssetId a
+ Aztecs.Asset.AssetServer: [handleId] :: Handle a -> AssetId
+ Aztecs.Asset.AssetServer: [loadingAssets] :: AssetServer a -> !Map AssetId (Either (IO (IORef (Maybe a))) (IORef (Maybe a)))
+ Aztecs.Asset.AssetServer: [nextAssetId] :: AssetServer a -> !AssetId
+ Aztecs.Asset.AssetServer: [unAssetId] :: AssetId -> Int
+ Aztecs.Asset.AssetServer: assetServer :: AssetServer a
+ Aztecs.Asset.AssetServer: data AssetServer a
+ Aztecs.Asset.AssetServer: instance Control.DeepSeq.NFData (Aztecs.Asset.AssetServer.AssetServer a)
+ Aztecs.Asset.AssetServer: instance Control.DeepSeq.NFData (Aztecs.Asset.AssetServer.Handle a)
+ Aztecs.Asset.AssetServer: instance Data.Typeable.Internal.Typeable a => Aztecs.ECS.Component.Component (Aztecs.Asset.AssetServer.AssetServer a)
+ Aztecs.Asset.AssetServer: instance GHC.Classes.Eq (Aztecs.Asset.AssetServer.Handle a)
+ Aztecs.Asset.AssetServer: instance GHC.Classes.Eq Aztecs.Asset.AssetServer.AssetId
+ Aztecs.Asset.AssetServer: instance GHC.Classes.Ord (Aztecs.Asset.AssetServer.Handle a)
+ Aztecs.Asset.AssetServer: instance GHC.Classes.Ord Aztecs.Asset.AssetServer.AssetId
+ Aztecs.Asset.AssetServer: instance GHC.Generics.Generic (Aztecs.Asset.AssetServer.AssetServer a)
+ Aztecs.Asset.AssetServer: instance GHC.Show.Show (Aztecs.Asset.AssetServer.Handle a)
+ Aztecs.Asset.AssetServer: instance GHC.Show.Show Aztecs.Asset.AssetServer.AssetId
+ Aztecs.Asset.AssetServer: loadAssets :: forall a qr rs q s b m arr. (Typeable a, ArrowQueryReader qr, ArrowReaderSystem qr rs, ArrowReaderSchedule rs arr, ArrowQuery q, ArrowSystem q s, ArrowSchedule s arr, MonadIO m, ArrowAccessSchedule b m arr) => arr () ()
+ Aztecs.Asset.AssetServer: lookupAsset :: Handle a -> AssetServer a -> Maybe a
+ Aztecs.Asset.AssetServer: newtype AssetId
+ Aztecs.Asset.AssetServer: newtype Handle a
+ Aztecs.Asset.AssetServer: setup :: forall a. Typeable a => System () ()
+ Aztecs.Asset.Class: class (Typeable a) => Asset a where {
+ Aztecs.Asset.Class: loadAsset :: Asset a => FilePath -> AssetConfig a -> IO a
+ Aztecs.Asset.Class: type AssetConfig a;
+ Aztecs.Asset.Class: }
+ Aztecs.ECS: class (MonadAccess b m, Arrow arr) => ArrowAccessSchedule b m arr | arr -> m
+ Aztecs.ECS: class (ArrowDynamicQueryReader arr) => ArrowDynamicQuery arr
+ Aztecs.ECS: class (Arrow arr) => ArrowDynamicQueryReader arr
+ Aztecs.ECS: class (ArrowQueryReader arr) => ArrowQuery arr
+ Aztecs.ECS: class (Arrow arr) => ArrowQueryReader arr
+ Aztecs.ECS: class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m
+ Aztecs.ECS: class (Arrow arr) => ArrowReaderSchedule s arr | arr -> s
+ Aztecs.ECS: class (Arrow arr) => ArrowReaderSystem q arr | arr -> q
+ Aztecs.ECS: class (Arrow arr) => ArrowSchedule s arr | arr -> s
+ Aztecs.ECS: class (Arrow arr) => ArrowSystem q arr | arr -> q
+ Aztecs.ECS: class (Monoid a) => MonoidBundle a
+ Aztecs.ECS: class MonoidDynamicBundle a
+ Aztecs.ECS: data DynamicBundle
+ Aztecs.ECS: delay :: Monad m => a -> Schedule m a a
+ Aztecs.ECS: dynBundle :: (MonoidDynamicBundle a, Component c) => ComponentID -> c -> a
+ Aztecs.ECS: type Schedule m = ScheduleT (AccessT m)
+ Aztecs.ECS.Access: instance Control.Monad.Fix.MonadFix m => Control.Monad.Fix.MonadFix (Aztecs.ECS.Access.AccessT m)
+ Aztecs.ECS.Access: instance GHC.Base.Monad m => Aztecs.ECS.Access.Class.MonadAccess Aztecs.ECS.World.Bundle.Bundle (Aztecs.ECS.Access.AccessT m)
+ Aztecs.ECS.Query: instance Control.Arrow.ArrowChoice Aztecs.ECS.Query.Query
+ Aztecs.ECS.Query.Dynamic: entity :: ArrowDynamicQueryReader arr => arr () EntityID
+ Aztecs.ECS.Query.Dynamic: fromDynReader :: DynamicQueryReader i o -> DynamicQuery i o
+ Aztecs.ECS.Query.Dynamic: instance Control.Arrow.ArrowChoice Aztecs.ECS.Query.Dynamic.DynamicQuery
+ Aztecs.ECS.Query.Dynamic.Reader: entity :: ArrowDynamicQueryReader arr => arr () EntityID
+ Aztecs.ECS.Query.Dynamic.Reader: instance Control.Arrow.ArrowChoice Aztecs.ECS.Query.Dynamic.Reader.DynamicQueryReader
+ Aztecs.ECS.Query.Dynamic.Reader.Class: entity :: ArrowDynamicQueryReader arr => arr () EntityID
+ Aztecs.ECS.Query.Reader: QueryReader :: (Components -> (Set ComponentID, Components, DynamicQueryReader i o)) -> QueryReader i o
+ Aztecs.ECS.Query.Reader: instance Control.Arrow.ArrowChoice Aztecs.ECS.Query.Reader.QueryReader
+ Aztecs.ECS.Schedule: class (MonadAccess b m, Arrow arr) => ArrowAccessSchedule b m arr | arr -> m
+ Aztecs.ECS.Schedule: class (Arrow arr) => ArrowReaderSchedule s arr | arr -> s
+ Aztecs.ECS.Schedule: class (Arrow arr) => ArrowSchedule s arr | arr -> s
+ Aztecs.ECS.Schedule: delay :: Monad m => a -> Schedule m a a
+ Aztecs.ECS.Schedule: instance Control.Monad.Fix.MonadFix m => Control.Arrow.ArrowLoop (Aztecs.ECS.Schedule.ScheduleT m)
+ Aztecs.ECS.Schedule: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.ECS.Schedule.ScheduleT m i)
+ Aztecs.ECS.Schedule: instance GHC.Base.Monad m => Aztecs.ECS.Schedule.Access.Class.ArrowAccessSchedule Aztecs.ECS.World.Bundle.Bundle (Aztecs.ECS.Access.AccessT m) (Aztecs.ECS.Schedule.Schedule m)
+ Aztecs.ECS.Schedule: instance GHC.Base.Monad m => Aztecs.ECS.Schedule.Class.ArrowSchedule Aztecs.ECS.System.System (Aztecs.ECS.Schedule.Schedule m)
+ Aztecs.ECS.Schedule: instance GHC.Base.Monad m => Aztecs.ECS.Schedule.Reader.Class.ArrowReaderSchedule Aztecs.ECS.System.Reader.ReaderSystem (Aztecs.ECS.Schedule.Schedule m)
+ Aztecs.ECS.Schedule: instance GHC.Base.Monad m => Control.Arrow.Arrow (Aztecs.ECS.Schedule.ScheduleT m)
+ Aztecs.ECS.Schedule: instance GHC.Base.Monad m => Control.Category.Category (Aztecs.ECS.Schedule.ScheduleT m)
+ Aztecs.ECS.Schedule: newtype ScheduleT m i o
+ Aztecs.ECS.Schedule: type Schedule m = ScheduleT (AccessT m)
+ Aztecs.ECS.Schedule.Access: AcessSchedule :: (i -> AccessT m o) -> AcessSchedule m i o
+ Aztecs.ECS.Schedule.Access: [runAcessSchedule] :: AcessSchedule m i o -> i -> AccessT m o
+ Aztecs.ECS.Schedule.Access: access :: ArrowAccessSchedule b m arr => (i -> m o) -> arr i o
+ Aztecs.ECS.Schedule.Access: class (MonadAccess b m, Arrow arr) => ArrowAccessSchedule b m arr | arr -> m
+ Aztecs.ECS.Schedule.Access: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.ECS.Schedule.Access.AcessSchedule m i)
+ Aztecs.ECS.Schedule.Access: instance GHC.Base.Monad m => Aztecs.ECS.Schedule.Access.Class.ArrowAccessSchedule Aztecs.ECS.World.Bundle.Bundle (Aztecs.ECS.Access.AccessT m) (Aztecs.ECS.Schedule.Access.AcessSchedule m)
+ Aztecs.ECS.Schedule.Access: instance GHC.Base.Monad m => Control.Arrow.Arrow (Aztecs.ECS.Schedule.Access.AcessSchedule m)
+ Aztecs.ECS.Schedule.Access: instance GHC.Base.Monad m => Control.Category.Category (Aztecs.ECS.Schedule.Access.AcessSchedule m)
+ Aztecs.ECS.Schedule.Access: newtype AcessSchedule m i o
+ Aztecs.ECS.Schedule.Access.Class: access :: ArrowAccessSchedule b m arr => (i -> m o) -> arr i o
+ Aztecs.ECS.Schedule.Access.Class: class (MonadAccess b m, Arrow arr) => ArrowAccessSchedule b m arr | arr -> m
+ Aztecs.ECS.Schedule.Class: class (Arrow arr) => ArrowSchedule s arr | arr -> s
+ Aztecs.ECS.Schedule.Class: system :: ArrowSchedule s arr => s i o -> arr i o
+ Aztecs.ECS.Schedule.Dynamic: DynamicSchedule :: (i -> m (o, DynamicScheduleT m i o)) -> DynamicScheduleT m i o
+ Aztecs.ECS.Schedule.Dynamic: [runScheduleDyn] :: DynamicScheduleT m i o -> i -> m (o, DynamicScheduleT m i o)
+ Aztecs.ECS.Schedule.Dynamic: instance Control.Monad.Fix.MonadFix m => Control.Arrow.ArrowLoop (Aztecs.ECS.Schedule.Dynamic.DynamicScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.ECS.Schedule.Dynamic.DynamicScheduleT m i)
+ Aztecs.ECS.Schedule.Dynamic: instance GHC.Base.Monad m => Control.Arrow.Arrow (Aztecs.ECS.Schedule.Dynamic.DynamicScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic: instance GHC.Base.Monad m => Control.Arrow.ArrowChoice (Aztecs.ECS.Schedule.Dynamic.DynamicScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic: instance GHC.Base.Monad m => Control.Category.Category (Aztecs.ECS.Schedule.Dynamic.DynamicScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic: newtype DynamicScheduleT m i o
+ Aztecs.ECS.Schedule.Dynamic: type DynamicSchedule m = DynamicScheduleT (AccessT m)
+ Aztecs.ECS.Schedule.Dynamic.Reader: DynamicReaderSchedule :: (i -> m (o, DynamicReaderScheduleT m i o)) -> DynamicReaderScheduleT m i o
+ Aztecs.ECS.Schedule.Dynamic.Reader: [runScheduleDyn] :: DynamicReaderScheduleT m i o -> i -> m (o, DynamicReaderScheduleT m i o)
+ Aztecs.ECS.Schedule.Dynamic.Reader: instance Control.Monad.Fix.MonadFix m => Control.Arrow.ArrowLoop (Aztecs.ECS.Schedule.Dynamic.Reader.DynamicReaderScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic.Reader: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.ECS.Schedule.Dynamic.Reader.DynamicReaderScheduleT m i)
+ Aztecs.ECS.Schedule.Dynamic.Reader: instance GHC.Base.Monad m => Control.Arrow.Arrow (Aztecs.ECS.Schedule.Dynamic.Reader.DynamicReaderScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic.Reader: instance GHC.Base.Monad m => Control.Arrow.ArrowChoice (Aztecs.ECS.Schedule.Dynamic.Reader.DynamicReaderScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic.Reader: instance GHC.Base.Monad m => Control.Category.Category (Aztecs.ECS.Schedule.Dynamic.Reader.DynamicReaderScheduleT m)
+ Aztecs.ECS.Schedule.Dynamic.Reader: newtype DynamicReaderScheduleT m i o
+ Aztecs.ECS.Schedule.Dynamic.Reader: type DynamicReaderSchedule m = DynamicReaderScheduleT (AccessT m)
+ Aztecs.ECS.Schedule.Reader: ReaderSchedule :: (Components -> (DynamicReaderScheduleT m i o, Components)) -> ReaderScheduleT m i o
+ Aztecs.ECS.Schedule.Reader: [runReaderSchedule] :: ReaderScheduleT m i o -> Components -> (DynamicReaderScheduleT m i o, Components)
+ Aztecs.ECS.Schedule.Reader: instance Control.Monad.Fix.MonadFix m => Control.Arrow.ArrowLoop (Aztecs.ECS.Schedule.Reader.ReaderScheduleT m)
+ Aztecs.ECS.Schedule.Reader: instance GHC.Base.Functor m => GHC.Base.Functor (Aztecs.ECS.Schedule.Reader.ReaderScheduleT m i)
+ Aztecs.ECS.Schedule.Reader: instance GHC.Base.Monad m => Aztecs.ECS.Schedule.Reader.Class.ArrowReaderSchedule Aztecs.ECS.System.Reader.ReaderSystem (Aztecs.ECS.Schedule.Reader.ReaderSchedule m)
+ Aztecs.ECS.Schedule.Reader: instance GHC.Base.Monad m => Control.Arrow.Arrow (Aztecs.ECS.Schedule.Reader.ReaderScheduleT m)
+ Aztecs.ECS.Schedule.Reader: instance GHC.Base.Monad m => Control.Arrow.ArrowChoice (Aztecs.ECS.Schedule.Reader.ReaderScheduleT m)
+ Aztecs.ECS.Schedule.Reader: instance GHC.Base.Monad m => Control.Category.Category (Aztecs.ECS.Schedule.Reader.ReaderScheduleT m)
+ Aztecs.ECS.Schedule.Reader: newtype ReaderScheduleT m i o
+ Aztecs.ECS.Schedule.Reader.Class: class (Arrow arr) => ArrowReaderSchedule s arr | arr -> s
+ Aztecs.ECS.Schedule.Reader.Class: reader :: ArrowReaderSchedule s arr => s i o -> arr i o
+ Aztecs.ECS.System: class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m
+ Aztecs.ECS.System: fromReader :: ReaderSystem i o -> System i o
+ Aztecs.ECS.System: instance Aztecs.ECS.System.Queue.Class.ArrowQueueSystem Aztecs.ECS.World.Bundle.Bundle Aztecs.ECS.Access.Access Aztecs.ECS.System.System
+ Aztecs.ECS.System: instance Control.Arrow.ArrowChoice Aztecs.ECS.System.System
+ Aztecs.ECS.System: instance Control.Arrow.ArrowLoop Aztecs.ECS.System.System
+ Aztecs.ECS.System.Dynamic: allDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q i o -> arr i [o]
+ Aztecs.ECS.System.Dynamic: class (Arrow arr) => ArrowDynamicReaderSystem q arr | arr -> q
+ Aztecs.ECS.System.Dynamic: class ArrowDynamicSystem q arr | arr -> q
+ Aztecs.ECS.System.Dynamic: class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m
+ Aztecs.ECS.System.Dynamic: filterDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q i o -> (Node -> Bool) -> arr i [o]
+ Aztecs.ECS.System.Dynamic: filterMapDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> (Node -> Bool) -> arr i [o]
+ Aztecs.ECS.System.Dynamic: fromDynReaderSystem :: DynamicReaderSystem i o -> DynamicSystem i o
+ Aztecs.ECS.System.Dynamic: instance Aztecs.ECS.System.Dynamic.Class.ArrowDynamicSystem Aztecs.ECS.Query.Dynamic.DynamicQuery Aztecs.ECS.System.Dynamic.DynamicSystem
+ Aztecs.ECS.System.Dynamic: instance Aztecs.ECS.System.Dynamic.Reader.Class.ArrowDynamicReaderSystem Aztecs.ECS.Query.Dynamic.Reader.DynamicQueryReader Aztecs.ECS.System.Dynamic.DynamicSystem
+ Aztecs.ECS.System.Dynamic: instance Aztecs.ECS.System.Queue.Class.ArrowQueueSystem Aztecs.ECS.World.Bundle.Bundle Aztecs.ECS.Access.Access Aztecs.ECS.System.Dynamic.DynamicSystem
+ Aztecs.ECS.System.Dynamic: instance Control.Arrow.ArrowChoice Aztecs.ECS.System.Dynamic.DynamicSystem
+ Aztecs.ECS.System.Dynamic: instance Control.Arrow.ArrowLoop Aztecs.ECS.System.Dynamic.DynamicSystem
+ Aztecs.ECS.System.Dynamic: mapDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> arr i [o]
+ Aztecs.ECS.System.Dynamic: mapSingleDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> arr i o
+ Aztecs.ECS.System.Dynamic: mapSingleMaybeDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> arr i (Maybe o)
+ Aztecs.ECS.System.Dynamic: queue :: ArrowQueueSystem b m arr => (i -> m ()) -> arr i ()
+ Aztecs.ECS.System.Dynamic: singleDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q () a -> arr () a
+ Aztecs.ECS.System.Dynamic.Reader: class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m
+ Aztecs.ECS.System.Dynamic.Reader: instance Aztecs.ECS.System.Dynamic.Reader.Class.ArrowDynamicReaderSystem Aztecs.ECS.Query.Dynamic.Reader.DynamicQueryReader Aztecs.ECS.System.Dynamic.Reader.DynamicReaderSystem
+ Aztecs.ECS.System.Dynamic.Reader: instance Aztecs.ECS.System.Queue.Class.ArrowQueueSystem Aztecs.ECS.World.Bundle.Bundle Aztecs.ECS.Access.Access Aztecs.ECS.System.Dynamic.Reader.DynamicReaderSystem
+ Aztecs.ECS.System.Dynamic.Reader: instance Control.Arrow.ArrowChoice Aztecs.ECS.System.Dynamic.Reader.DynamicReaderSystem
+ Aztecs.ECS.System.Dynamic.Reader: instance Control.Arrow.ArrowLoop Aztecs.ECS.System.Dynamic.Reader.DynamicReaderSystem
+ Aztecs.ECS.System.Dynamic.Reader: queue :: ArrowQueueSystem b m arr => (i -> m ()) -> arr i ()
+ Aztecs.ECS.System.Queue: QueueSystem :: (i -> (o, Access ())) -> QueueSystem i o
+ Aztecs.ECS.System.Queue: [runQueueSystem] :: QueueSystem i o -> i -> (o, Access ())
+ Aztecs.ECS.System.Queue: class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m
+ Aztecs.ECS.System.Queue: instance Aztecs.ECS.System.Queue.Class.ArrowQueueSystem Aztecs.ECS.World.Bundle.Bundle Aztecs.ECS.Access.Access Aztecs.ECS.System.Queue.QueueSystem
+ Aztecs.ECS.System.Queue: instance Control.Arrow.Arrow Aztecs.ECS.System.Queue.QueueSystem
+ Aztecs.ECS.System.Queue: instance Control.Category.Category Aztecs.ECS.System.Queue.QueueSystem
+ Aztecs.ECS.System.Queue: instance GHC.Base.Functor (Aztecs.ECS.System.Queue.QueueSystem i)
+ Aztecs.ECS.System.Queue: newtype QueueSystem i o
+ Aztecs.ECS.System.Queue: queue :: ArrowQueueSystem b m arr => (i -> m ()) -> arr i ()
+ Aztecs.ECS.System.Queue.Class: class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m
+ Aztecs.ECS.System.Queue.Class: queue :: ArrowQueueSystem b m arr => (i -> m ()) -> arr i ()
+ Aztecs.ECS.System.Reader: class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m
+ Aztecs.ECS.System.Reader: class (Arrow arr) => ArrowReaderSystem q arr | arr -> q
+ Aztecs.ECS.System.Reader: instance Aztecs.ECS.System.Queue.Class.ArrowQueueSystem Aztecs.ECS.World.Bundle.Bundle Aztecs.ECS.Access.Access Aztecs.ECS.System.Reader.ReaderSystem
+ Aztecs.ECS.System.Reader: instance Control.Arrow.ArrowChoice Aztecs.ECS.System.Reader.ReaderSystem
+ Aztecs.ECS.System.Reader: instance Control.Arrow.ArrowLoop Aztecs.ECS.System.Reader.ReaderSystem
+ Aztecs.ECS.World.Archetypes: find :: Set ComponentID -> Archetypes -> Map ArchetypeID Node
+ Aztecs.ECS.World.Bundle: Bundle :: (Components -> (Set ComponentID, Components, DynamicBundle)) -> Bundle
+ Aztecs.ECS.World.Bundle: [unBundle] :: Bundle -> Components -> (Set ComponentID, Components, DynamicBundle)
+ Aztecs.ECS.World.Bundle: bundle :: forall c. (MonoidBundle a, Component c) => c -> a
+ Aztecs.ECS.World.Bundle: class (Monoid a) => MonoidBundle a
+ Aztecs.ECS.World.Bundle: class MonoidDynamicBundle a
+ Aztecs.ECS.World.Bundle: dynBundle :: (MonoidDynamicBundle a, Component c) => ComponentID -> c -> a
+ Aztecs.ECS.World.Bundle: instance Aztecs.ECS.World.Bundle.Class.MonoidBundle Aztecs.ECS.World.Bundle.Bundle
+ Aztecs.ECS.World.Bundle: instance Aztecs.ECS.World.Bundle.Dynamic.Class.MonoidDynamicBundle Aztecs.ECS.World.Bundle.Bundle
+ Aztecs.ECS.World.Bundle: instance GHC.Base.Monoid Aztecs.ECS.World.Bundle.Bundle
+ Aztecs.ECS.World.Bundle: instance GHC.Base.Semigroup Aztecs.ECS.World.Bundle.Bundle
+ Aztecs.ECS.World.Bundle: newtype Bundle
+ Aztecs.ECS.World.Bundle: runBundle :: Bundle -> Components -> EntityID -> Archetype -> (Components, Archetype)
+ Aztecs.ECS.World.Bundle.Class: bundle :: forall c. (MonoidBundle a, Component c) => c -> a
+ Aztecs.ECS.World.Bundle.Class: class (Monoid a) => MonoidBundle a
+ Aztecs.ECS.World.Bundle.Dynamic: DynamicBundle :: (EntityID -> Archetype -> Archetype) -> DynamicBundle
+ Aztecs.ECS.World.Bundle.Dynamic: [runDynamicBundle] :: DynamicBundle -> EntityID -> Archetype -> Archetype
+ Aztecs.ECS.World.Bundle.Dynamic: class MonoidDynamicBundle a
+ Aztecs.ECS.World.Bundle.Dynamic: dynBundle :: (MonoidDynamicBundle a, Component c) => ComponentID -> c -> a
+ Aztecs.ECS.World.Bundle.Dynamic: instance Aztecs.ECS.World.Bundle.Dynamic.Class.MonoidDynamicBundle Aztecs.ECS.World.Bundle.Dynamic.DynamicBundle
+ Aztecs.ECS.World.Bundle.Dynamic: instance GHC.Base.Monoid Aztecs.ECS.World.Bundle.Dynamic.DynamicBundle
+ Aztecs.ECS.World.Bundle.Dynamic: instance GHC.Base.Semigroup Aztecs.ECS.World.Bundle.Dynamic.DynamicBundle
+ Aztecs.ECS.World.Bundle.Dynamic: newtype DynamicBundle
+ Aztecs.ECS.World.Bundle.Dynamic.Class: class MonoidDynamicBundle a
+ Aztecs.ECS.World.Bundle.Dynamic.Class: dynBundle :: (MonoidDynamicBundle a, Component c) => ComponentID -> c -> a
+ Aztecs.ECS.World.Entities: Entities :: !Archetypes -> !Components -> !Map EntityID ArchetypeID -> Entities
+ Aztecs.ECS.World.Entities: [archetypes] :: Entities -> !Archetypes
+ Aztecs.ECS.World.Entities: [components] :: Entities -> !Components
+ Aztecs.ECS.World.Entities: [entities] :: Entities -> !Map EntityID ArchetypeID
+ Aztecs.ECS.World.Entities: data Entities
+ Aztecs.ECS.World.Entities: despawn :: EntityID -> Entities -> (Map ComponentID Dynamic, Entities)
+ Aztecs.ECS.World.Entities: empty :: Entities
+ Aztecs.ECS.World.Entities: insert :: forall a. Component a => EntityID -> a -> Entities -> Entities
+ Aztecs.ECS.World.Entities: insertWithId :: Component a => EntityID -> ComponentID -> a -> Entities -> Entities
+ Aztecs.ECS.World.Entities: instance Control.DeepSeq.NFData Aztecs.ECS.World.Entities.Entities
+ Aztecs.ECS.World.Entities: instance GHC.Generics.Generic Aztecs.ECS.World.Entities.Entities
+ Aztecs.ECS.World.Entities: instance GHC.Show.Show Aztecs.ECS.World.Entities.Entities
+ Aztecs.ECS.World.Entities: lookup :: forall a. Component a => EntityID -> Entities -> Maybe a
+ Aztecs.ECS.World.Entities: remove :: forall a. Component a => EntityID -> Entities -> (Maybe a, Entities)
+ Aztecs.ECS.World.Entities: removeWithId :: forall a. Component a => EntityID -> ComponentID -> Entities -> (Maybe a, Entities)
+ Aztecs.ECS.World.Entities: spawn :: EntityID -> Bundle -> Entities -> Entities
+ Aztecs.ECS.World.Entities: spawnComponent :: forall a. Component a => EntityID -> a -> Entities -> Entities
+ Aztecs.ECS.World.Entities: spawnWithArchetypeId :: forall a. Component a => EntityID -> ArchetypeID -> ComponentID -> a -> Entities -> Entities
+ Aztecs.ECS.World.Entities: spawnWithId :: forall a. Component a => EntityID -> ComponentID -> a -> Entities -> Entities
+ Aztecs.ECS.World.Storage: toList :: Storage s a => s a -> [(Int, a)]
+ Aztecs.ECS.World.Storage.Dynamic: DynamicStorage :: !Dynamic -> !Int -> Dynamic -> Dynamic -> Dynamic -> !Int -> Dynamic -> (Maybe Dynamic, Dynamic) -> !Int -> Dynamic -> (Maybe DynamicStorage, Dynamic) -> !Dynamic -> [Int] -> !Dynamic -> () -> DynamicStorage
+ Aztecs.ECS.World.Storage.Dynamic: [entitiesDyn'] :: DynamicStorage -> !Dynamic -> [Int]
+ Aztecs.ECS.World.Storage.Dynamic: [insertDyn'] :: DynamicStorage -> !Int -> Dynamic -> Dynamic -> Dynamic
+ Aztecs.ECS.World.Storage.Dynamic: [removeAny'] :: DynamicStorage -> !Int -> Dynamic -> (Maybe DynamicStorage, Dynamic)
+ Aztecs.ECS.World.Storage.Dynamic: [removeDyn'] :: DynamicStorage -> !Int -> Dynamic -> (Maybe Dynamic, Dynamic)
+ Aztecs.ECS.World.Storage.Dynamic: [storageDyn] :: DynamicStorage -> !Dynamic
+ Aztecs.ECS.World.Storage.Dynamic: [storageRnf] :: DynamicStorage -> !Dynamic -> ()
+ Aztecs.ECS.World.Storage.Dynamic: data DynamicStorage
+ Aztecs.ECS.World.Storage.Dynamic: dynStorage :: forall s a. Storage s a => s a -> DynamicStorage
+ Aztecs.ECS.World.Storage.Dynamic: entitiesDyn :: DynamicStorage -> [Int]
+ Aztecs.ECS.World.Storage.Dynamic: insertDyn :: Int -> Dynamic -> DynamicStorage -> DynamicStorage
+ Aztecs.ECS.World.Storage.Dynamic: instance Control.DeepSeq.NFData Aztecs.ECS.World.Storage.Dynamic.DynamicStorage
+ Aztecs.ECS.World.Storage.Dynamic: instance GHC.Show.Show Aztecs.ECS.World.Storage.Dynamic.DynamicStorage
+ Aztecs.ECS.World.Storage.Dynamic: removeAny :: Int -> DynamicStorage -> (Maybe DynamicStorage, DynamicStorage)
+ Aztecs.ECS.World.Storage.Dynamic: removeDyn :: Int -> DynamicStorage -> (Maybe Dynamic, DynamicStorage)
+ Aztecs.Hierarchy: foldWithKey :: (EntityID -> a -> b -> b) -> Hierarchy a -> b -> b
+ Aztecs.Hierarchy: instance Data.Foldable.Foldable Aztecs.Hierarchy.Hierarchy
+ Aztecs.Hierarchy: instance Data.Traversable.Traversable Aztecs.Hierarchy.Hierarchy
+ Aztecs.Hierarchy: instance GHC.Base.Functor Aztecs.Hierarchy.Hierarchy
+ Aztecs.Hierarchy: mapWithAccum :: (EntityID -> a -> b -> (c, b)) -> b -> Hierarchy a -> Hierarchy c
+ Aztecs.Hierarchy: mapWithKey :: (EntityID -> a -> b) -> Hierarchy a -> Hierarchy b
+ Aztecs.Hierarchy: toList :: Hierarchy a -> [(EntityID, a)]
+ Aztecs.Transform: [transformTranslation] :: Transform v r -> !v
+ Aztecs.Transform: instance (Control.DeepSeq.NFData v, Control.DeepSeq.NFData r) => Control.DeepSeq.NFData (Aztecs.Transform.Transform v r)
+ Aztecs.Transform: instance (GHC.Classes.Eq r, GHC.Classes.Eq v) => GHC.Classes.Eq (Aztecs.Transform.Transform v r)
+ Aztecs.Transform: instance (GHC.Num.Num v, GHC.Num.Num r) => GHC.Base.Monoid (Aztecs.Transform.Transform v r)
+ Aztecs.Transform: instance (GHC.Num.Num v, GHC.Num.Num r) => GHC.Base.Semigroup (Aztecs.Transform.Transform v r)
+ Aztecs.Transform: instance (GHC.Show.Show r, GHC.Show.Show v) => GHC.Show.Show (Aztecs.Transform.Transform v r)
+ Aztecs.Transform: instance Aztecs.ECS.Component.Component (Aztecs.Transform.Size (Linear.V2.V2 GHC.Types.Int))
+ Aztecs.Transform: instance Aztecs.ECS.Component.Component (Aztecs.Transform.Transform (Linear.V2.V2 GHC.Types.Int) GHC.Types.Int)
+ Aztecs.Transform: instance Control.DeepSeq.NFData v => Control.DeepSeq.NFData (Aztecs.Transform.Size v)
+ Aztecs.Transform: instance GHC.Generics.Generic (Aztecs.Transform.Size v)
+ Aztecs.Transform: instance GHC.Generics.Generic (Aztecs.Transform.Transform v r)
+ Aztecs.Transform: propagate :: (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr, Component a, Monoid a) => arr () [Hierarchy a]
+ Aztecs.Transform: propagate2d :: (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr) => arr () [Hierarchy Transform2D]
+ Aztecs.Transform: size2D :: Size (V2 Integer)
+ Aztecs.Transform: transform2d :: Transform2D
+ Aztecs.Transform: type Size2D = Size (V2 Int)
+ Aztecs.Transform: type Transform2D = Transform (V2 Int) Int
+ Aztecs.Transform: update :: forall q arr b m a. (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr, ArrowQueueSystem b m arr, Component a, Monoid a) => arr () ()
+ Aztecs.Transform: update2d :: (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr, ArrowQueueSystem b m arr) => arr () ()
- Aztecs: Transform :: !V2 Int -> !Float -> !V2 Int -> Transform
+ Aztecs: Transform :: !v -> !r -> !v -> Transform v r
- Aztecs: [transformRotation] :: Transform -> !Float
+ Aztecs: [transformRotation] :: Transform v r -> !r
- Aztecs: [transformScale] :: Transform -> !V2 Int
+ Aztecs: [transformScale] :: Transform v r -> !v
- Aztecs: data Transform
+ Aztecs: data Transform v r
- Aztecs: load :: (ArrowSystem Query arr, Asset a) => AssetLoader a o -> arr () o
+ Aztecs: load :: (ArrowQuery q, ArrowSystem q arr, Asset a) => AssetLoader a o -> arr () o
- Aztecs.Asset: load :: (ArrowSystem Query arr, Asset a) => AssetLoader a o -> arr () o
+ Aztecs.Asset: load :: (ArrowQuery q, ArrowSystem q arr, Asset a) => AssetLoader a o -> arr () o
- Aztecs.Asset: loadAssets :: forall a. Typeable a => Schedule IO () ()
+ Aztecs.Asset: loadAssets :: forall a qr rs q s b m arr. (Typeable a, ArrowQueryReader qr, ArrowReaderSystem qr rs, ArrowReaderSchedule rs arr, ArrowQuery q, ArrowSystem q s, ArrowSchedule s arr, MonadIO m, ArrowAccessSchedule b m arr) => arr () ()
- Aztecs.Camera: addCameraTargets :: (ArrowQueryReader qr, ArrowReaderSystem qr arr, ArrowSystem q arr) => arr () ()
+ Aztecs.Camera: addCameraTargets :: (ArrowQueryReader qr, ArrowDynamicQueryReader qr, ArrowReaderSystem qr arr, ArrowQueueSystem b m arr) => arr () ()
- Aztecs.ECS: access :: Monad m => (i -> AccessT m o) -> Schedule m i o
+ Aztecs.ECS: access :: ArrowAccessSchedule b m arr => (i -> m o) -> arr i o
- Aztecs.ECS: bundle :: forall a. (Component a, Typeable (StorageT a)) => a -> Bundle
+ Aztecs.ECS: bundle :: forall c. (MonoidBundle a, Component c) => c -> a
- Aztecs.ECS: reader :: Monad m => ReaderSystem i o -> Schedule m i o
+ Aztecs.ECS: reader :: ArrowReaderSchedule s arr => s i o -> arr i o
- Aztecs.ECS: runSchedule :: Monad m => Schedule m i o -> World -> i -> m (o, World)
+ Aztecs.ECS: runSchedule :: Monad m => Schedule m i o -> World -> i -> m (o, DynamicSchedule m i o, World)
- Aztecs.ECS: system :: Monad m => System i o -> Schedule m i o
+ Aztecs.ECS: system :: ArrowSchedule s arr => s i o -> arr i o
- Aztecs.ECS.Access: class (Monad m) => MonadAccess m
+ Aztecs.ECS.Access: class (MonoidBundle b, Monad m) => MonadAccess b m | m -> b
- Aztecs.ECS.Access: despawn :: MonadAccess m => EntityID -> m ()
+ Aztecs.ECS.Access: despawn :: MonadAccess b m => EntityID -> m ()
- Aztecs.ECS.Access: insert :: (MonadAccess m, Component a, Typeable (StorageT a)) => EntityID -> a -> m ()
+ Aztecs.ECS.Access: insert :: (MonadAccess b m, Component a) => EntityID -> a -> m ()
- Aztecs.ECS.Access: lookup :: (MonadAccess m, Component a) => EntityID -> m (Maybe a)
+ Aztecs.ECS.Access: lookup :: (MonadAccess b m, Component a) => EntityID -> m (Maybe a)
- Aztecs.ECS.Access: remove :: (MonadAccess m, Component a, Typeable (StorageT a)) => EntityID -> m (Maybe a)
+ Aztecs.ECS.Access: remove :: (MonadAccess b m, Component a) => EntityID -> m (Maybe a)
- Aztecs.ECS.Access: spawn :: MonadAccess m => Bundle -> m EntityID
+ Aztecs.ECS.Access: spawn :: MonadAccess b m => b -> m EntityID
- Aztecs.ECS.Access: spawn_ :: MonadAccess m => Bundle -> m ()
+ Aztecs.ECS.Access: spawn_ :: MonadAccess b m => b -> m ()
- Aztecs.ECS.Access.Class: class (Monad m) => MonadAccess m
+ Aztecs.ECS.Access.Class: class (MonoidBundle b, Monad m) => MonadAccess b m | m -> b
- Aztecs.ECS.Access.Class: despawn :: MonadAccess m => EntityID -> m ()
+ Aztecs.ECS.Access.Class: despawn :: MonadAccess b m => EntityID -> m ()
- Aztecs.ECS.Access.Class: insert :: (MonadAccess m, Component a, Typeable (StorageT a)) => EntityID -> a -> m ()
+ Aztecs.ECS.Access.Class: insert :: (MonadAccess b m, Component a) => EntityID -> a -> m ()
- Aztecs.ECS.Access.Class: lookup :: (MonadAccess m, Component a) => EntityID -> m (Maybe a)
+ Aztecs.ECS.Access.Class: lookup :: (MonadAccess b m, Component a) => EntityID -> m (Maybe a)
- Aztecs.ECS.Access.Class: remove :: (MonadAccess m, Component a, Typeable (StorageT a)) => EntityID -> m (Maybe a)
+ Aztecs.ECS.Access.Class: remove :: (MonadAccess b m, Component a) => EntityID -> m (Maybe a)
- Aztecs.ECS.Access.Class: spawn :: MonadAccess m => Bundle -> m EntityID
+ Aztecs.ECS.Access.Class: spawn :: MonadAccess b m => b -> m EntityID
- Aztecs.ECS.Access.Class: spawn_ :: MonadAccess m => Bundle -> m ()
+ Aztecs.ECS.Access.Class: spawn_ :: MonadAccess b m => b -> m ()
- Aztecs.ECS.Query: all :: Query () a -> World -> ([a], World)
+ Aztecs.ECS.Query: all :: Query () a -> Entities -> ([a], Entities)
- Aztecs.ECS.Query: entity :: ArrowQueryReader arr => arr () EntityID
+ Aztecs.ECS.Query: entity :: ArrowDynamicQueryReader arr => arr () EntityID
- Aztecs.ECS.Query.Reader: entity :: ArrowQueryReader arr => arr () EntityID
+ Aztecs.ECS.Query.Reader: entity :: ArrowDynamicQueryReader arr => arr () EntityID
- Aztecs.ECS.Schedule: Schedule :: (Components -> (i -> AccessT m o, Components)) -> Schedule m i o
+ Aztecs.ECS.Schedule: Schedule :: (Components -> (DynamicScheduleT m i o, Components)) -> ScheduleT m i o
- Aztecs.ECS.Schedule: [runSchedule'] :: Schedule m i o -> Components -> (i -> AccessT m o, Components)
+ Aztecs.ECS.Schedule: [runSchedule'] :: ScheduleT m i o -> Components -> (DynamicScheduleT m i o, Components)
- Aztecs.ECS.Schedule: access :: Monad m => (i -> AccessT m o) -> Schedule m i o
+ Aztecs.ECS.Schedule: access :: ArrowAccessSchedule b m arr => (i -> m o) -> arr i o
- Aztecs.ECS.Schedule: reader :: Monad m => ReaderSystem i o -> Schedule m i o
+ Aztecs.ECS.Schedule: reader :: ArrowReaderSchedule s arr => s i o -> arr i o
- Aztecs.ECS.Schedule: runSchedule :: Monad m => Schedule m i o -> World -> i -> m (o, World)
+ Aztecs.ECS.Schedule: runSchedule :: Monad m => Schedule m i o -> World -> i -> m (o, DynamicSchedule m i o, World)
- Aztecs.ECS.Schedule: system :: Monad m => System i o -> Schedule m i o
+ Aztecs.ECS.Schedule: system :: ArrowSchedule s arr => s i o -> arr i o
- Aztecs.ECS.System: queue :: ArrowSystem q arr => (i -> Access ()) -> arr i ()
+ Aztecs.ECS.System: queue :: ArrowQueueSystem b m arr => (i -> m ()) -> arr i ()
- Aztecs.ECS.System.Dynamic: DynamicSystem :: (World -> i -> (o, View, Access ())) -> DynamicSystem i o
+ Aztecs.ECS.System.Dynamic: DynamicSystem :: (Entities -> i -> (o, View, Access (), DynamicSystem i o)) -> DynamicSystem i o
- Aztecs.ECS.System.Dynamic: [runSystemDyn] :: DynamicSystem i o -> World -> i -> (o, View, Access ())
+ Aztecs.ECS.System.Dynamic: [runSystemDyn] :: DynamicSystem i o -> Entities -> i -> (o, View, Access (), DynamicSystem i o)
- Aztecs.ECS.System.Dynamic.Class: class (ArrowDynamicReaderSystem arr) => ArrowDynamicSystem arr
+ Aztecs.ECS.System.Dynamic.Class: class ArrowDynamicSystem q arr | arr -> q
- Aztecs.ECS.System.Dynamic.Class: filterMapDyn :: ArrowDynamicSystem arr => Set ComponentID -> DynamicQuery i o -> (Node -> Bool) -> arr i [o]
+ Aztecs.ECS.System.Dynamic.Class: filterMapDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> (Node -> Bool) -> arr i [o]
- Aztecs.ECS.System.Dynamic.Class: mapDyn :: ArrowDynamicSystem arr => Set ComponentID -> DynamicQuery i o -> arr i [o]
+ Aztecs.ECS.System.Dynamic.Class: mapDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> arr i [o]
- Aztecs.ECS.System.Dynamic.Class: mapSingleDyn :: ArrowDynamicSystem arr => Set ComponentID -> DynamicQuery i o -> arr i o
+ Aztecs.ECS.System.Dynamic.Class: mapSingleDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> arr i o
- Aztecs.ECS.System.Dynamic.Class: mapSingleMaybeDyn :: ArrowDynamicSystem arr => Set ComponentID -> DynamicQuery i o -> arr i (Maybe o)
+ Aztecs.ECS.System.Dynamic.Class: mapSingleMaybeDyn :: ArrowDynamicSystem q arr => Set ComponentID -> q i o -> arr i (Maybe o)
- Aztecs.ECS.System.Dynamic.Reader: DynamicReaderSystem :: (World -> i -> o) -> DynamicReaderSystem i o
+ Aztecs.ECS.System.Dynamic.Reader: DynamicReaderSystem :: (Entities -> i -> (o, Access (), DynamicReaderSystem i o)) -> DynamicReaderSystem i o
- Aztecs.ECS.System.Dynamic.Reader: [runReaderSystemDyn] :: DynamicReaderSystem i o -> World -> i -> o
+ Aztecs.ECS.System.Dynamic.Reader: [runReaderSystemDyn] :: DynamicReaderSystem i o -> Entities -> i -> (o, Access (), DynamicReaderSystem i o)
- Aztecs.ECS.System.Dynamic.Reader: allDyn :: ArrowDynamicReaderSystem arr => Set ComponentID -> DynamicQueryReader i o -> arr i [o]
+ Aztecs.ECS.System.Dynamic.Reader: allDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q i o -> arr i [o]
- Aztecs.ECS.System.Dynamic.Reader: class (Arrow arr) => ArrowDynamicReaderSystem arr
+ Aztecs.ECS.System.Dynamic.Reader: class (Arrow arr) => ArrowDynamicReaderSystem q arr | arr -> q
- Aztecs.ECS.System.Dynamic.Reader: filterDyn :: ArrowDynamicReaderSystem arr => Set ComponentID -> DynamicQueryReader i o -> (Node -> Bool) -> arr i [o]
+ Aztecs.ECS.System.Dynamic.Reader: filterDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q i o -> (Node -> Bool) -> arr i [o]
- Aztecs.ECS.System.Dynamic.Reader: singleDyn :: ArrowDynamicReaderSystem arr => Set ComponentID -> DynamicQueryReader () a -> arr () a
+ Aztecs.ECS.System.Dynamic.Reader: singleDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q () a -> arr () a
- Aztecs.ECS.System.Dynamic.Reader.Class: allDyn :: ArrowDynamicReaderSystem arr => Set ComponentID -> DynamicQueryReader i o -> arr i [o]
+ Aztecs.ECS.System.Dynamic.Reader.Class: allDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q i o -> arr i [o]
- Aztecs.ECS.System.Dynamic.Reader.Class: class (Arrow arr) => ArrowDynamicReaderSystem arr
+ Aztecs.ECS.System.Dynamic.Reader.Class: class (Arrow arr) => ArrowDynamicReaderSystem q arr | arr -> q
- Aztecs.ECS.System.Dynamic.Reader.Class: filterDyn :: ArrowDynamicReaderSystem arr => Set ComponentID -> DynamicQueryReader i o -> (Node -> Bool) -> arr i [o]
+ Aztecs.ECS.System.Dynamic.Reader.Class: filterDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q i o -> (Node -> Bool) -> arr i [o]
- Aztecs.ECS.System.Dynamic.Reader.Class: singleDyn :: ArrowDynamicReaderSystem arr => Set ComponentID -> DynamicQueryReader () a -> arr () a
+ Aztecs.ECS.System.Dynamic.Reader.Class: singleDyn :: ArrowDynamicReaderSystem q arr => Set ComponentID -> q () a -> arr () a
- Aztecs.ECS.System.Reader: queue :: ArrowSystem q arr => (i -> Access ()) -> arr i ()
+ Aztecs.ECS.System.Reader: queue :: ArrowQueueSystem b m arr => (i -> m ()) -> arr i ()
- Aztecs.ECS.View: unview :: View -> World -> World
+ Aztecs.ECS.View: unview :: View -> Entities -> Entities
- Aztecs.ECS.World: World :: !Archetypes -> !Components -> !Map EntityID ArchetypeID -> !EntityID -> World
+ Aztecs.ECS.World: World :: Entities -> !EntityID -> World
- Aztecs.ECS.World: [entities] :: World -> !Map EntityID ArchetypeID
+ Aztecs.ECS.World: [entities] :: World -> Entities
- Aztecs.ECS.World: insert :: forall a. (Component a, Typeable (StorageT a)) => EntityID -> a -> World -> World
+ Aztecs.ECS.World: insert :: forall a. Component a => EntityID -> a -> World -> World
- Aztecs.ECS.World: insertWithId :: (Component a, Typeable (StorageT a)) => EntityID -> ComponentID -> a -> World -> World
+ Aztecs.ECS.World: insertWithId :: Component a => EntityID -> ComponentID -> a -> World -> World
- Aztecs.ECS.World: remove :: forall a. (Component a, Typeable (StorageT a)) => EntityID -> World -> (Maybe a, World)
+ Aztecs.ECS.World: remove :: forall a. Component a => EntityID -> World -> (Maybe a, World)
- Aztecs.ECS.World: removeWithId :: forall a. (Component a, Typeable (StorageT a)) => EntityID -> ComponentID -> World -> (Maybe a, World)
+ Aztecs.ECS.World: removeWithId :: forall a. Component a => EntityID -> ComponentID -> World -> (Maybe a, World)
- Aztecs.ECS.World: spawnWithArchetypeId :: forall a. (Component a, Typeable (StorageT a)) => a -> ComponentID -> ArchetypeID -> World -> (EntityID, World)
+ Aztecs.ECS.World: spawnWithArchetypeId :: forall a. Component a => ArchetypeID -> ComponentID -> a -> World -> (EntityID, World)
- Aztecs.ECS.World.Archetype: Archetype :: Map ComponentID AnyStorage -> Archetype
+ Aztecs.ECS.World.Archetype: Archetype :: Map ComponentID DynamicStorage -> Archetype
- Aztecs.ECS.World.Archetype: [storages] :: Archetype -> Map ComponentID AnyStorage
+ Aztecs.ECS.World.Archetype: [storages] :: Archetype -> Map ComponentID DynamicStorage
- Aztecs.ECS.World.Archetype: removeStorages :: EntityID -> Archetype -> (Map ComponentID AnyStorage, Archetype)
+ Aztecs.ECS.World.Archetype: removeStorages :: EntityID -> Archetype -> (Map ComponentID DynamicStorage, Archetype)
- Aztecs.ECS.World.Archetypes: insert :: (Component a, Typeable (StorageT a)) => EntityID -> ArchetypeID -> ComponentID -> a -> Archetypes -> (Maybe ArchetypeID, Archetypes)
+ Aztecs.ECS.World.Archetypes: insert :: Component a => EntityID -> ArchetypeID -> ComponentID -> a -> Archetypes -> (Maybe ArchetypeID, Archetypes)
- Aztecs.ECS.World.Archetypes: lookup :: Set ComponentID -> Archetypes -> Map ArchetypeID Node
+ Aztecs.ECS.World.Archetypes: lookup :: ArchetypeID -> Archetypes -> Maybe Node
- Aztecs.ECS.World.Archetypes: remove :: (Component a, Typeable (StorageT a)) => EntityID -> ArchetypeID -> ComponentID -> Archetypes -> (Maybe (a, ArchetypeID), Archetypes)
+ Aztecs.ECS.World.Archetypes: remove :: Component a => EntityID -> ArchetypeID -> ComponentID -> Archetypes -> (Maybe (a, ArchetypeID), Archetypes)
- Aztecs.Hierarchy: hierarchies :: (ArrowQueryReader q, ArrowReaderSystem q arr) => q i a -> arr i [[Hierarchy a]]
+ Aztecs.Hierarchy: hierarchies :: (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr) => q i a -> arr i [Hierarchy a]
- Aztecs.Hierarchy: hierarchy :: (ArrowQueryReader q, ArrowReaderSystem q arr) => EntityID -> q i a -> arr i [Hierarchy a]
+ Aztecs.Hierarchy: hierarchy :: (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr) => EntityID -> q i a -> arr i (Maybe (Hierarchy a))
- Aztecs.Hierarchy: update :: (ArrowQueryReader qr, ArrowQuery q, ArrowReaderSystem qr arr, ArrowSystem q arr) => arr () ()
+ Aztecs.Hierarchy: update :: (ArrowQueryReader qr, ArrowDynamicQueryReader qr, ArrowReaderSystem qr arr, ArrowQueueSystem b m arr) => arr () ()
- Aztecs.Transform: Size :: V2 Int -> Size
+ Aztecs.Transform: Size :: v -> Size v
- Aztecs.Transform: Transform :: !V2 Int -> !Float -> !V2 Int -> Transform
+ Aztecs.Transform: Transform :: !v -> !r -> !v -> Transform v r
- Aztecs.Transform: [transformRotation] :: Transform -> !Float
+ Aztecs.Transform: [transformRotation] :: Transform v r -> !r
- Aztecs.Transform: [transformScale] :: Transform -> !V2 Int
+ Aztecs.Transform: [transformScale] :: Transform v r -> !v
- Aztecs.Transform: [unSize] :: Size -> V2 Int
+ Aztecs.Transform: [unSize] :: Size v -> v
- Aztecs.Transform: data Transform
+ Aztecs.Transform: data Transform v r
- Aztecs.Transform: newtype Size
+ Aztecs.Transform: newtype Size v

Files

aztecs.cabal view
@@ -1,23 +1,27 @@ cabal-version: 2.4 name:          aztecs-version:       0.6.0+version:       0.7.0 license:       BSD-3-Clause license-file:  LICENSE maintainer:    matt@hunzinger.me author:        Matt Hunzinger-synopsis:      A type-safe and friendly Entity-Component-System (ECS) for Haskell-description:   The Entity-Component-System (ECS) pattern is commonly used in video game develop to represent world objects.-               .-               ECS follows the principal of composition over inheritence. Each type of-               object (e.g. sword, monster, etc), in the game has a unique EntityId. Each-               entity has various Components associated with it (material, weight, damage, etc).-               Systems act on entities which have the required Components.-homepage:      https://github.com/matthunz/aztecs+homepage:      https://github.com/aztecs-hs/aztecs+synopsis:+    A modular game engine and Entity-Component-System (ECS) for Haskell.++description:+    A modular game engine and Entity-Component-System (ECS) for Haskell.+    An ECS is a modern approach to organizing your application state as a database,+    providing patterns for data-oriented design and parallel processing.+    Aztecs provides side-effect free components and systems,+    as well as backends for rendering and input (such as `aztecs-sdl`),+    allowing you to structure your game as simple function of `Input -> World -> World`.+ category:      Game Engine  source-repository head     type:     git-    location: https://github.com/matthunz/aztecs.git+    location: https://github.com/aztecs-hs/aztecs.git  library     exposed-modules:@@ -36,27 +40,47 @@         Aztecs.ECS.Query.Reader         Aztecs.ECS.Query.Reader.Class         Aztecs.ECS.Schedule+        Aztecs.ECS.Schedule.Access+        Aztecs.ECS.Schedule.Access.Class+        Aztecs.ECS.Schedule.Class+        Aztecs.ECS.Schedule.Dynamic+        Aztecs.ECS.Schedule.Dynamic.Reader+        Aztecs.ECS.Schedule.Reader+        Aztecs.ECS.Schedule.Reader.Class         Aztecs.ECS.System         Aztecs.ECS.System.Class         Aztecs.ECS.System.Dynamic         Aztecs.ECS.System.Dynamic.Class         Aztecs.ECS.System.Dynamic.Reader         Aztecs.ECS.System.Dynamic.Reader.Class+        Aztecs.ECS.System.Queue+        Aztecs.ECS.System.Queue.Class         Aztecs.ECS.System.Reader         Aztecs.ECS.System.Reader.Class         Aztecs.ECS.View         Aztecs.ECS.World         Aztecs.ECS.World.Archetype         Aztecs.ECS.World.Archetypes+        Aztecs.ECS.World.Bundle+        Aztecs.ECS.World.Bundle.Class+        Aztecs.ECS.World.Bundle.Dynamic+        Aztecs.ECS.World.Bundle.Dynamic.Class         Aztecs.ECS.World.Components+        Aztecs.ECS.World.Entities         Aztecs.ECS.World.Storage+        Aztecs.ECS.World.Storage.Dynamic         Aztecs.Asset+        Aztecs.Asset.AssetLoader+        Aztecs.Asset.AssetLoader.Class+        Aztecs.Asset.AssetServer+        Aztecs.Asset.Class         Aztecs.Camera         Aztecs.Hierarchy         Aztecs.Input         Aztecs.Time         Aztecs.Transform         Aztecs.Window+     hs-source-dirs:   src     default-language: Haskell2010     ghc-options:      -Wall@@ -66,7 +90,7 @@         deepseq >=1,         linear >=1,         mtl >=2,-        parallel >=3,+        parallel >=3  test-suite aztecs-test     type:             exitcode-stdio-1.0
src/Aztecs.hs view
@@ -55,8 +55,6 @@     load,     Camera (..),     CameraTarget (..),-    Transform (..),-    transform,     Key (..),     KeyboardInput (..),     isKeyPressed,@@ -64,6 +62,12 @@     wasKeyReleased,     MouseInput (..),     Time (..),+    Transform (..),+    Transform2D,+    transform2d,+    Size (..),+    Size2D,+    size2D,     Window (..),   ) where@@ -80,5 +84,5 @@     wasKeyReleased,   ) import Aztecs.Time-import Aztecs.Transform (Transform (..), transform)+import Aztecs.Transform import Aztecs.Window
src/Aztecs/Asset.hs view
@@ -1,154 +1,24 @@ {-# LANGUAGE AllowAmbiguousTypes #-}-{-# LANGUAGE Arrows #-}-{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-}  module Aztecs.Asset   ( AssetId (..),     AssetServer (..),-    empty,+    MonadAssetLoader (..),     Asset (..),     Handle (..),-    MonadAssetLoader (..),-    AssetLoader,-    AssetLoaderT (..),-    load,+    lookupAsset,     setup,-    loadQuery,     loadAssets,-    lookupAsset,+    load,   ) where -import Aztecs.ECS-import qualified Aztecs.ECS.Access as A-import Aztecs.ECS.Query (ArrowQuery)-import qualified Aztecs.ECS.Query as Q-import Aztecs.ECS.Query.Reader (QueryReader)-import Aztecs.ECS.System (ArrowSystem)-import qualified Aztecs.ECS.System as S-import Control.Arrow (returnA)-import Control.Concurrent (forkIO)-import Control.DeepSeq-import Control.Monad.Identity (Identity)-import Control.Monad.State.Strict (MonadState (..), StateT, runState)-import Data.Data (Typeable)-import Data.Foldable (foldrM)-import Data.IORef (IORef, newIORef, readIORef, writeIORef)-import Data.Map.Strict (Map)-import qualified Data.Map.Strict as Map-import GHC.Generics (Generic)--newtype AssetId = AssetId {unAssetId :: Int}-  deriving (Eq, Ord, Show)--data AssetServer a = AssetServer-  { assetServerAssets :: !(Map AssetId a),-    loadingAssets :: !(Map AssetId (Either (IO (IORef (Maybe a))) (IORef (Maybe a)))),-    nextAssetId :: !AssetId-  }-  deriving (Generic)--instance (Typeable a) => Component (AssetServer a)--instance NFData (AssetServer a) where-  rnf = rwhnf--empty :: AssetServer a-empty =-  AssetServer-    { assetServerAssets = Map.empty,-      loadingAssets = Map.empty,-      nextAssetId = AssetId 0-    }--class (Typeable a) => Asset a where-  type AssetConfig a--  loadAsset :: FilePath -> AssetConfig a -> IO a--newtype Handle a = Handle {handleId :: AssetId}-  deriving (Eq, Ord, Show)--instance NFData (Handle a) where-  rnf = rwhnf--class MonadAssetLoader a m | m -> a where-  asset :: FilePath -> AssetConfig a -> m (Handle a)--type AssetLoader a o = AssetLoaderT a Identity o--newtype AssetLoaderT a m o = AssetLoaderT {unAssetLoader :: StateT (AssetServer a) m o}-  deriving newtype (Functor, Applicative, Monad)--instance (Monad m, Asset a) => MonadAssetLoader a (AssetLoaderT a m) where-  asset path cfg = AssetLoaderT $ do-    server <- get-    let assetId = nextAssetId server-        go = do-          v <- newIORef Nothing-          _ <- forkIO $ do-            a <- loadAsset path cfg-            writeIORef v (Just a)-          return v-    put $-      server-        { loadingAssets = Map.insert assetId (Left go) (loadingAssets server),-          nextAssetId = AssetId (unAssetId assetId + 1)-        }-    return $ Handle assetId--loadQuery :: (Asset a, ArrowQuery arr) => AssetLoader a o -> arr () o-loadQuery a = proc () -> do-  assetServer <- Q.fetch -< ()-  let (o, assetServer') = runState (unAssetLoader a) assetServer-  Q.set -< assetServer'-  returnA -< o--load :: (ArrowSystem Query arr, Asset a) => AssetLoader a o -> arr () o-load a = S.mapSingle $ loadQuery a--lookupAsset :: Handle a -> AssetServer a -> Maybe a-lookupAsset h server = Map.lookup (handleId h) (assetServerAssets server)--loadAssets :: forall a. (Typeable a) => Schedule IO () ()-loadAssets = proc () -> do-  server <- reader $ S.single (Q.fetch @QueryReader @(AssetServer a)) -< ()-  server' <--    task-      ( \server ->-          foldrM-            ( \(aId, v) acc -> do-                case v of-                  Right r -> do-                    maybeSurface <- readIORef r-                    case maybeSurface of-                      Just surface ->-                        return-                          acc-                            { assetServerAssets = Map.insert aId surface (assetServerAssets acc),-                              loadingAssets = Map.delete aId (loadingAssets acc)-                            }-                      Nothing -> return acc-                  Left f -> do-                    v' <- f-                    return $ acc {loadingAssets = Map.insert aId (Right v') (loadingAssets server)}-            )-            server-            (Map.toList $ loadingAssets server)-      )-      -<-        server-  system $ S.mapSingle Q.set -< server'-  returnA -< ()--setup :: forall a. (Typeable a) => System () ()-setup = S.queue . const . A.spawn_ . bundle $ empty @a+import Aztecs.Asset.AssetLoader+import Aztecs.Asset.AssetServer+import Aztecs.Asset.Class
+ src/Aztecs/Asset/AssetLoader.hs view
@@ -0,0 +1,59 @@+{-# LANGUAGE Arrows #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}++module Aztecs.Asset.AssetLoader+  ( MonadAssetLoader (..),+    AssetLoader,+    AssetLoaderT (..),+    load,+    loadQuery,+  )+where++import Aztecs.Asset.AssetLoader.Class+import Aztecs.Asset.AssetServer (AssetId (..), AssetServer (..), Handle (..))+import Aztecs.Asset.Class+import Aztecs.ECS+import qualified Aztecs.ECS.Query as Q+import qualified Aztecs.ECS.System as S+import Control.Arrow (returnA)+import Control.Concurrent (forkIO)+import Control.Monad.Identity (Identity)+import Control.Monad.State.Strict (MonadState (..), StateT, runState)+import Data.IORef (newIORef, writeIORef)+import qualified Data.Map.Strict as Map++type AssetLoader a o = AssetLoaderT a Identity o++newtype AssetLoaderT a m o = AssetLoaderT {unAssetLoader :: StateT (AssetServer a) m o}+  deriving newtype (Functor, Applicative, Monad)++instance (Monad m, Asset a) => MonadAssetLoader a (AssetLoaderT a m) where+  asset path cfg = AssetLoaderT $ do+    server <- get+    let assetId = nextAssetId server+        go = do+          v <- newIORef Nothing+          _ <- forkIO $ do+            a <- loadAsset path cfg+            writeIORef v (Just a)+          return v+    put $+      server+        { loadingAssets = Map.insert assetId (Left go) (loadingAssets server),+          nextAssetId = AssetId (unAssetId assetId + 1)+        }+    return $ Handle assetId++loadQuery :: (Asset a, ArrowQuery arr) => AssetLoader a o -> arr () o+loadQuery a = proc () -> do+  assetServer <- Q.fetch -< ()+  let (o, assetServer') = runState (unAssetLoader a) assetServer+  Q.set -< assetServer'+  returnA -< o++load :: (ArrowQuery q, ArrowSystem q arr, Asset a) => AssetLoader a o -> arr () o+load a = S.mapSingle $ loadQuery a
+ src/Aztecs/Asset/AssetLoader/Class.hs view
@@ -0,0 +1,19 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}++module Aztecs.Asset.AssetLoader.Class+  ( MonadAssetLoader (..),+  )+where++import Aztecs.Asset.AssetServer (Handle)+import Aztecs.Asset.Class++class MonadAssetLoader a m | m -> a where+  asset :: FilePath -> AssetConfig a -> m (Handle a)
+ src/Aztecs/Asset/AssetServer.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE Arrows #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++module Aztecs.Asset.AssetServer+  ( AssetId (..),+    AssetServer (..),+    assetServer,+    Handle (..),+    setup,+    loadAssets,+    lookupAsset,+  )+where++import Aztecs.ECS+import qualified Aztecs.ECS.Access as A+import qualified Aztecs.ECS.Query as Q+import qualified Aztecs.ECS.System as S+import Control.Arrow (returnA)+import Control.DeepSeq+import Control.Monad.IO.Class (MonadIO (..))+import Data.Data (Typeable)+import Data.Foldable (foldrM)+import Data.IORef (IORef, readIORef)+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import GHC.Generics (Generic)++newtype AssetId = AssetId {unAssetId :: Int}+  deriving (Eq, Ord, Show)++data AssetServer a = AssetServer+  { assetServerAssets :: !(Map AssetId a),+    loadingAssets :: !(Map AssetId (Either (IO (IORef (Maybe a))) (IORef (Maybe a)))),+    nextAssetId :: !AssetId+  }+  deriving (Generic)++instance (Typeable a) => Component (AssetServer a)++instance NFData (AssetServer a) where+  rnf = rwhnf++assetServer :: AssetServer a+assetServer =+  AssetServer+    { assetServerAssets = Map.empty,+      loadingAssets = Map.empty,+      nextAssetId = AssetId 0+    }++newtype Handle a = Handle {handleId :: AssetId}+  deriving (Eq, Ord, Show)++instance NFData (Handle a) where+  rnf = rwhnf++lookupAsset :: Handle a -> AssetServer a -> Maybe a+lookupAsset h server = Map.lookup (handleId h) (assetServerAssets server)++loadAssets ::+  forall a qr rs q s b m arr.+  ( Typeable a,+    ArrowQueryReader qr,+    ArrowReaderSystem qr rs,+    ArrowReaderSchedule rs arr,+    ArrowQuery q,+    ArrowSystem q s,+    ArrowSchedule s arr,+    MonadIO m,+    ArrowAccessSchedule b m arr+  ) =>+  arr () ()+loadAssets = proc () -> do+  server <- reader $ S.single (Q.fetch @_ @(AssetServer a)) -< ()+  server' <-+    access+      ( \server ->+          liftIO $+            foldrM+              ( \(aId, v) acc -> do+                  case v of+                    Right r -> do+                      maybeSurface <- readIORef r+                      case maybeSurface of+                        Just surface ->+                          return+                            acc+                              { assetServerAssets = Map.insert aId surface (assetServerAssets acc),+                                loadingAssets = Map.delete aId (loadingAssets acc)+                              }+                        Nothing -> return acc+                    Left f -> do+                      v' <- f+                      return $ acc {loadingAssets = Map.insert aId (Right v') (loadingAssets server)}+              )+              server+              (Map.toList $ loadingAssets server)+      )+      -<+        server+  system $ S.mapSingle Q.set -< server'+  returnA -< ()++setup :: forall a. (Typeable a) => System () ()+setup = S.queue . const . A.spawn_ . bundle $ assetServer @a
+ src/Aztecs/Asset/Class.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE TypeFamilies #-}++module Aztecs.Asset.Class (Asset (..)) where++import Data.Data (Typeable)++class (Typeable a) => Asset a where+  type AssetConfig a++  loadAsset :: FilePath -> AssetConfig a -> IO a
src/Aztecs/Camera.hs view
@@ -12,9 +12,7 @@  import Aztecs.ECS import qualified Aztecs.ECS.Access as A-import Aztecs.ECS.Query.Reader (ArrowQueryReader) import qualified Aztecs.ECS.Query.Reader as Q-import Aztecs.ECS.System (ArrowReaderSystem, ArrowSystem) import qualified Aztecs.ECS.System as S import Aztecs.Window (Window) import Control.Arrow (Arrow (..))@@ -43,7 +41,13 @@ instance Component CameraTarget  -- | Add `CameraTarget` components to entities with a new `Draw` component.-addCameraTargets :: (ArrowQueryReader qr, ArrowReaderSystem qr arr, ArrowSystem q arr) => arr () ()+addCameraTargets ::+  ( ArrowQueryReader qr,+    ArrowDynamicQueryReader qr,+    ArrowReaderSystem qr arr,+    ArrowQueueSystem b m arr+  ) =>+  arr () () addCameraTargets = proc () -> do   windows <- S.all (Q.entity &&& Q.fetch @_ @Window) -< ()   newCameras <- S.filter (Q.entity &&& Q.fetch @_ @Camera) (without @CameraTarget) -< ()
src/Aztecs/ECS.hs view
@@ -53,21 +53,33 @@   ( Access,     runAccessT,     Bundle,-    bundle,+    MonoidBundle (..),+    DynamicBundle,+    MonoidDynamicBundle (..),     Component (..),     EntityID,     Query,+    ArrowQueryReader,+    ArrowQuery,+    ArrowDynamicQueryReader,+    ArrowDynamicQuery,     QueryFilter,     with,     without,     System,+    ArrowReaderSystem,+    ArrowSystem,+    ArrowQueueSystem,     Schedule,+    ArrowReaderSchedule,+    ArrowSchedule,+    ArrowAccessSchedule,     reader,     system,+    delay,     forever,     forever_,     access,-    task,     runSchedule,     runSchedule_,     World,@@ -77,18 +89,31 @@ import Aztecs.ECS.Access (Access, runAccessT) import Aztecs.ECS.Component (Component (..)) import Aztecs.ECS.Entity (EntityID)-import Aztecs.ECS.Query (Query, QueryFilter, with, without)+import Aztecs.ECS.Query+  ( ArrowDynamicQuery,+    ArrowDynamicQueryReader,+    ArrowQuery,+    ArrowQueryReader,+    Query,+    QueryFilter,+    with,+    without,+  ) import Aztecs.ECS.Schedule-  ( Schedule,+  ( ArrowAccessSchedule,+    ArrowReaderSchedule,+    ArrowSchedule,+    Schedule,     access,+    delay,     forever,     forever_,     reader,     runSchedule,     runSchedule_,     system,-    task,   )-import Aztecs.ECS.System (System)+import Aztecs.ECS.System (ArrowQueueSystem, ArrowReaderSystem, ArrowSystem, System) import Aztecs.ECS.World (World)-import Aztecs.ECS.World.Archetype (Bundle, bundle)+import Aztecs.ECS.World.Bundle (Bundle, MonoidBundle (..))+import Aztecs.ECS.World.Bundle.Dynamic (DynamicBundle, MonoidDynamicBundle (..))
src/Aztecs/ECS/Access.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}  module Aztecs.ECS.Access   ( Access,@@ -12,6 +14,8 @@ import Aztecs.ECS.Access.Class (MonadAccess (..)) import Aztecs.ECS.World (World (..)) import qualified Aztecs.ECS.World as W+import Aztecs.ECS.World.Bundle (Bundle)+import Control.Monad.Fix (MonadFix) import Control.Monad.IO.Class (MonadIO) import Control.Monad.Identity (Identity) import Control.Monad.State.Strict (MonadState (..), StateT (..))@@ -21,13 +25,13 @@  -- | Access into the `World`. newtype AccessT m a = AccessT {unAccessT :: StateT World m a}-  deriving (Functor, Applicative, Monad, MonadIO)+  deriving (Functor, Applicative, Monad, MonadFix, MonadIO)  -- | Run an `Access` on a `World`, returning the output and updated `World`. runAccessT :: (Functor m) => AccessT m a -> World -> m (a, World) runAccessT a = runStateT $ unAccessT a -instance (Monad m) => MonadAccess (AccessT m) where+instance (Monad m) => MonadAccess Bundle (AccessT m) where   spawn b = AccessT $ do     !w <- get     let !(e, w') = W.spawn b w
src/Aztecs/ECS/Access/Class.hs view
@@ -1,32 +1,32 @@ {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FunctionalDependencies #-}  module Aztecs.ECS.Access.Class (MonadAccess (..)) where  import Aztecs.ECS.Component (Component (..)) import Aztecs.ECS.Entity (EntityID (..))-import Aztecs.ECS.World.Archetype (Bundle (..))-import Data.Data (Typeable)+import Aztecs.ECS.World.Bundle (MonoidBundle (..)) import Prelude hiding (all, lookup, map)  -- | Monadic access to a `World`.-class (Monad m) => MonadAccess m where+class (MonoidBundle b, Monad m) => MonadAccess b m | m -> b where   -- | Spawn an entity with a component.-  spawn :: Bundle -> m EntityID+  spawn :: b -> m EntityID    -- | Spawn an entity with a component.-  spawn_ :: Bundle -> m ()+  spawn_ :: b -> m ()   spawn_ c = do     _ <- spawn c     return ()    -- | Insert a component into an entity.-  insert :: (Component a, Typeable (StorageT a)) => EntityID -> a -> m ()+  insert :: (Component a) => EntityID -> a -> m ()    -- | Lookup a component on an entity.   lookup :: (Component a) => EntityID -> m (Maybe a)    -- | Remove a component from an entity.-  remove :: (Component a, Typeable (StorageT a)) => EntityID -> m (Maybe a)+  remove :: (Component a) => EntityID -> m (Maybe a)    -- | Despawn an entity.   despawn :: EntityID -> m ()
src/Aztecs/ECS/Query.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-}@@ -28,18 +29,18 @@  import Aztecs.ECS.Component import Aztecs.ECS.Query.Class (ArrowQuery (..))-import Aztecs.ECS.Query.Dynamic (DynamicQuery (..))+import Aztecs.ECS.Query.Dynamic (DynamicQuery (..), fromDynReader) import Aztecs.ECS.Query.Dynamic.Class (ArrowDynamicQuery (..)) import Aztecs.ECS.Query.Dynamic.Reader.Class (ArrowDynamicQueryReader (..))-import Aztecs.ECS.Query.Reader (QueryFilter (..), with, without)+import Aztecs.ECS.Query.Reader (QueryFilter (..), QueryReader (..), with, without) import Aztecs.ECS.Query.Reader.Class (ArrowQueryReader (..))-import Aztecs.ECS.World (World (..)) import qualified Aztecs.ECS.World.Archetype as A import Aztecs.ECS.World.Archetypes (Node (..)) import qualified Aztecs.ECS.World.Archetypes as AS import Aztecs.ECS.World.Components (Components) import qualified Aztecs.ECS.World.Components as CS-import Control.Arrow (Arrow (..))+import Aztecs.ECS.World.Entities (Entities (..))+import Control.Arrow (Arrow (..), ArrowChoice (..)) import Control.Category (Category (..)) import Data.Set (Set) import qualified Data.Set as Set@@ -48,24 +49,21 @@ -- | Query for matching entities. -- -- === Do notation:--- > move :: (Monad m) => Query m () Position+-- > move :: (ArrowQuery arr) => arr () Position -- > move = proc () -> do -- >   Velocity v <- Q.fetch -< () -- >   Position p <- Q.fetch -< () -- >   Q.set -< Position $ p + v -- -- === Arrow combinators:--- > move :: (Monad m) => Query m () Position+-- > move :: (ArrowQuery arr) => arr () Position -- > move = Q.fetch &&& Q.fetch >>> arr (\(Position p, Velocity v) -> Position $ p + v) >>> Q.set -- -- === Applicative combinators:--- > move :: (Monad m) => Query m () Position+-- > move :: (ArrowQuery arr) => arr () Position -- > move = (,) <$> Q.fetch <*> Q.fetch >>> arr (\(Position p, Velocity v) -> Position $ p + v) >>> Q.set-newtype Query i o-  = Query {runQuery :: Components -> (ReadsWrites, Components, DynamicQuery i o)}--instance Functor (Query i) where-  fmap f (Query q) = Query $ \cs -> let (cIds, cs', qS) = q cs in (cIds, cs', fmap f qS)+newtype Query i o = Query {runQuery :: Components -> (ReadsWrites, Components, DynamicQuery i o)}+  deriving (Functor)  instance Applicative (Query i) where   pure a = Query (mempty,,pure a)@@ -85,21 +83,17 @@   arr f = Query (mempty,,arr f)   first (Query f) = Query $ \comps -> let (cIds, comps', qS) = f comps in (cIds, comps', first qS) +instance ArrowChoice Query where+  left (Query f) = Query $ \comps -> let (cIds, comps', qS) = f comps in (cIds, comps', left qS)+ instance ArrowQueryReader Query where-  entity = Query (mempty,,entityDyn)-  fetch :: forall a. (Component a) => Query () a-  fetch = Query $ \cs ->-    let (cId, cs') = CS.insert @a cs-     in (ReadsWrites (Set.singleton cId) Set.empty, cs', fetchDyn cId)-  fetchMaybe :: forall a. (Component a) => Query () (Maybe a)-  fetchMaybe = Query $ \cs ->-    let (cId, cs') = CS.insert @a cs-     in (ReadsWrites (Set.singleton cId) Set.empty, cs', fetchMaybeDyn cId)+  fetch = fromReader fetch+  fetchMaybe = fromReader fetchMaybe  instance ArrowDynamicQueryReader Query where-  entityDyn = Query (mempty,,entityDyn)-  fetchDyn cId = Query (ReadsWrites (Set.singleton cId) Set.empty,,fetchDyn cId)-  fetchMaybeDyn cId = Query (ReadsWrites (Set.singleton cId) Set.empty,,fetchMaybeDyn cId)+  entity = fromReader entity+  fetchDyn = fromReader . fetchDyn+  fetchMaybeDyn = fromReader . fetchMaybeDyn  instance ArrowDynamicQuery Query where   setDyn cId = Query (ReadsWrites Set.empty (Set.singleton cId),,setDyn cId)@@ -110,6 +104,11 @@     let (cId, cs') = CS.insert @a cs      in (ReadsWrites Set.empty (Set.singleton cId), cs', setDyn cId) +fromReader :: QueryReader i o -> Query i o+fromReader (QueryReader f) = Query $ \cs ->+  let (cIds, cs', dynQ) = f cs in (ReadsWrites cIds Set.empty, cs', fromDynReader dynQ)++-- | Reads and writes of a `Query`. data ReadsWrites = ReadsWrites   { reads :: !(Set ComponentID),     writes :: !(Set ComponentID)@@ -122,17 +121,19 @@ instance Monoid ReadsWrites where   mempty = ReadsWrites mempty mempty +-- | `True` if the reads and writes of two `Query`s overlap. disjoint :: ReadsWrites -> ReadsWrites -> Bool disjoint a b =   Set.disjoint (reads a) (writes b)     || Set.disjoint (reads b) (writes a)     || Set.disjoint (writes b) (writes a) -all :: Query () a -> World -> ([a], World)+-- | Match all entities.+all :: Query () a -> Entities -> ([a], Entities) all q w =   let (rws, cs', dynQ) = runQuery q (components w)       as =         fmap           (\n -> fst $ dynQueryAll dynQ (repeat ()) (A.entities $ nodeArchetype n) (nodeArchetype n))-          (AS.lookup (reads rws <> writes rws) (archetypes w))+          (AS.find (reads rws <> writes rws) (archetypes w))    in (concat as, w {components = cs'})
src/Aztecs/ECS/Query/Class.hs view
@@ -3,6 +3,7 @@ import Aztecs.ECS.Component import Aztecs.ECS.Query.Reader.Class (ArrowQueryReader) +-- | Arrow for queries that can update entities. class (ArrowQueryReader arr) => ArrowQuery arr where   -- | Set a `Component` by its type.   set :: (Component a) => arr a a
src/Aztecs/ECS/Query/Dynamic.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE TypeFamilies #-}  module Aztecs.ECS.Query.Dynamic@@ -6,6 +7,7 @@     DynamicQuery (..),     ArrowDynamicQueryReader (..),     ArrowDynamicQuery (..),+    fromDynReader,      -- * Dynamic query filters     DynamicQueryFilter (..),@@ -14,64 +16,56 @@  import Aztecs.ECS.Entity (EntityID) import Aztecs.ECS.Query.Dynamic.Class (ArrowDynamicQuery (..))-import Aztecs.ECS.Query.Dynamic.Reader (DynamicQueryFilter (..))+import Aztecs.ECS.Query.Dynamic.Reader (DynamicQueryFilter (..), DynamicQueryReader (..)) import Aztecs.ECS.Query.Dynamic.Reader.Class (ArrowDynamicQueryReader (..)) import Aztecs.ECS.World.Archetype (Archetype) import qualified Aztecs.ECS.World.Archetype as A-import Control.Arrow (Arrow (..))+import Control.Arrow (Arrow (..), ArrowChoice (..)) import Control.Category (Category (..))-import Prelude hiding (all, any, id, lookup, map, mapM, reads, (.))+import Data.Either (partitionEithers)+import Prelude hiding ((.))  -- | Dynamic query for components by ID. newtype DynamicQuery i o   = DynamicQuery {dynQueryAll :: [i] -> [EntityID] -> Archetype -> ([o], Archetype)}--instance Functor (DynamicQuery i) where-  fmap f q =-    DynamicQuery $ \i es arch ->-      let (a, arch') = dynQueryAll q i es arch-       in (fmap f a, arch')+  deriving (Functor)  instance Applicative (DynamicQuery i) where   pure a = DynamicQuery $ \_ es arch -> (replicate (length es) a, arch) -  f <*> g =-    DynamicQuery-      { dynQueryAll = \i es arch ->-          let (as, arch') = dynQueryAll g i es arch-              (fs, arch'') = dynQueryAll f i es arch'-           in (zipWith ($) fs as, arch'')-      }+  f <*> g = DynamicQuery $ \i es arch ->+    let (as, arch') = dynQueryAll g i es arch+        (fs, arch'') = dynQueryAll f i es arch'+     in (zipWith ($) fs as, arch'')  instance Category DynamicQuery where   id = DynamicQuery $ \as _ arch -> (as, arch) -  f . g =-    DynamicQuery-      { dynQueryAll = \i es arch ->-          let (as, arch') = dynQueryAll g i es arch-           in dynQueryAll f as es arch'-      }+  f . g = DynamicQuery $ \i es arch ->+    let (as, arch') = dynQueryAll g i es arch in dynQueryAll f as es arch'  instance Arrow DynamicQuery where   arr f = DynamicQuery $ \bs _ arch -> (fmap f bs, arch)-  first f =-    DynamicQuery-      { dynQueryAll = \bds es arch ->-          let (bs, ds) = unzip bds-              (cs, arch') = dynQueryAll f bs es arch-           in (zip cs ds, arch')-      }--instance ArrowDynamicQueryReader DynamicQuery where-  entityDyn = DynamicQuery $ \_ es arch -> (es, arch)+  first f = DynamicQuery $ \bds es arch ->+    let (bs, ds) = unzip bds+        (cs, arch') = dynQueryAll f bs es arch+     in (zip cs ds, arch') -  fetchDyn cId =-    DynamicQuery $ \_ _ arch -> let !as = A.all cId arch in (fmap snd as, arch)+instance ArrowChoice DynamicQuery where+  left f = DynamicQuery $ \eds es arch ->+    let (es', ds) = partitionEithers eds+        (cs, arch') = dynQueryAll f es' es arch+     in (fmap Left cs ++ fmap Right ds, arch') -  fetchMaybeDyn cId =-    DynamicQuery $ \_ _ arch -> let as = A.allMaybe cId arch in (fmap snd as, arch)+instance ArrowDynamicQueryReader DynamicQuery where+  entity = fromDynReader entity+  fetchDyn = fromDynReader . fetchDyn+  fetchMaybeDyn = fromDynReader . fetchMaybeDyn  instance ArrowDynamicQuery DynamicQuery where-  setDyn cId =-    DynamicQuery $ \is _ arch -> let !arch' = A.withAscList cId is arch in (is, arch')+  setDyn cId = DynamicQuery $ \is es arch ->+    let !arch' = A.insertAscList cId (zip es is) arch in (is, arch')++fromDynReader :: DynamicQueryReader i o -> DynamicQuery i o+fromDynReader q = DynamicQuery $ \is es arch ->+  let os = dynQueryReaderAll q is es arch in (os, arch)
src/Aztecs/ECS/Query/Dynamic/Reader.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE TypeFamilies #-}  module Aztecs.ECS.Query.Dynamic.Reader@@ -16,17 +17,16 @@ import Aztecs.ECS.Query.Dynamic.Reader.Class (ArrowDynamicQueryReader (..)) import Aztecs.ECS.World.Archetype (Archetype) import qualified Aztecs.ECS.World.Archetype as A-import Control.Arrow (Arrow (..))-import Control.Category (Category (..))+import qualified Aztecs.ECS.World.Storage as S+import Control.Arrow+import Control.Category+import Data.Either (partitionEithers) import Data.Set (Set)-import Prelude hiding (all, any, id, lookup, map, mapM, reads, (.))  -- | Dynamic query for components by ID. newtype DynamicQueryReader i o   = DynamicQueryReader {dynQueryReaderAll :: [i] -> [EntityID] -> Archetype -> [o]}--instance Functor (DynamicQueryReader i) where-  fmap f q = DynamicQueryReader $ \i es arch -> f <$> dynQueryReaderAll q i es arch+  deriving (Functor)  instance Applicative (DynamicQueryReader i) where   pure a = DynamicQueryReader $ \_ es _ -> replicate (length es) a@@ -49,12 +49,19 @@         cs = dynQueryReaderAll f bs es arch      in zip cs ds +instance ArrowChoice DynamicQueryReader where+  left f = DynamicQueryReader $ \eds es arch ->+    let (es', ds) = partitionEithers eds+        cs = dynQueryReaderAll f es' es arch+     in fmap Left cs ++ fmap Right ds+ instance ArrowDynamicQueryReader DynamicQueryReader where-  entityDyn = DynamicQueryReader $ \_ es _ -> es-  fetchDyn cId =-    DynamicQueryReader $ \_ _ arch -> let !as = A.all cId arch in fmap snd as-  fetchMaybeDyn cId =-    DynamicQueryReader $ \_ _ arch -> let as = A.allMaybe cId arch in fmap snd as+  entity = DynamicQueryReader $ \_ es _ -> es+  fetchDyn cId = DynamicQueryReader $ \_ _ arch ->+    let !as = maybe [] S.toList (A.lookupStorage cId arch) in fmap snd as+  fetchMaybeDyn cId = DynamicQueryReader $ \_ es arch -> case A.lookupStorage cId arch of+    Just s -> let !as = S.toList s in fmap Just $ snd <$> as+    Nothing -> map (const Nothing) es  data DynamicQueryFilter = DynamicQueryFilter   { filterWith :: !(Set ComponentID),
src/Aztecs/ECS/Query/Dynamic/Reader/Class.hs view
@@ -5,8 +5,8 @@ import Control.Arrow (Arrow (..), (>>>))  class (Arrow arr) => ArrowDynamicQueryReader arr where-  -- | Fetch the `EntityID` belonging to this entity.-  entityDyn :: arr () EntityID+  -- | Fetch the currently matched `EntityID`.+  entity :: arr () EntityID    -- | Fetch a `Component` by its `ComponentID`.   fetchDyn :: (Component a) => ComponentID -> arr () a
src/Aztecs/ECS/Query/Reader.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-}@@ -26,67 +27,50 @@ import Aztecs.ECS.Query.Reader.Class (ArrowQueryReader (..)) import Aztecs.ECS.World.Components (Components) import qualified Aztecs.ECS.World.Components as CS-import Control.Arrow (Arrow (..))+import Control.Arrow (Arrow (..), ArrowChoice (..)) import Control.Category (Category (..)) import Data.Set (Set) import qualified Data.Set as Set import Prelude hiding (id, (.)) --- | Query for matching entities.------ === Do notation:--- > move :: (Monad m) => Query m () Position--- > move = proc () -> do--- >   Velocity v <- Q.fetch -< ()--- >   Position p <- Q.fetch -< ()--- >   Q.set -< Position $ p + v------ === Arrow combinators:--- > move :: (Monad m) => Query m () Position--- > move = Q.fetch &&& Q.fetch >>> arr (\(Position p, Velocity v) -> Position $ p + v) >>> Q.set------ === Applicative combinators:--- > move :: (Monad m) => Query m () Position--- > move = (,) <$> Q.fetch <*> Q.fetch >>> arr (\(Position p, Velocity v) -> Position $ p + v) >>> Q.set+-- | Query to read from entities. newtype QueryReader i o-  = Query {runQueryReader :: Components -> (Set ComponentID, Components, DynamicQueryReader i o)}--instance Functor (QueryReader i) where-  fmap f (Query q) = Query $ \cs -> let (cIds, cs', qS) = q cs in (cIds, cs', fmap f qS)+  = QueryReader {runQueryReader :: Components -> (Set ComponentID, Components, DynamicQueryReader i o)}+  deriving (Functor)  instance Applicative (QueryReader i) where-  pure a = Query $ \cs -> (mempty, cs, pure a)-  (Query f) <*> (Query g) = Query $ \cs ->+  pure a = QueryReader $ \cs -> (mempty, cs, pure a)+  (QueryReader f) <*> (QueryReader g) = QueryReader $ \cs ->     let (cIdsG, cs', aQS) = g cs         (cIdsF, cs'', bQS) = f cs'      in (cIdsG <> cIdsF, cs'', bQS <*> aQS)  instance Category QueryReader where-  id = Query $ \cs -> (mempty, cs, id)-  (Query f) . (Query g) = Query $ \cs ->+  id = QueryReader $ \cs -> (mempty, cs, id)+  (QueryReader f) . (QueryReader g) = QueryReader $ \cs ->     let (cIdsG, cs', aQS) = g cs         (cIdsF, cs'', bQS) = f cs'      in (cIdsG <> cIdsF, cs'', bQS . aQS)  instance Arrow QueryReader where-  arr f = Query $ \cs -> (mempty, cs, arr f)-  first (Query f) = Query $ \comps -> let (cIds, comps', qS) = f comps in (cIds, comps', first qS)+  arr f = QueryReader $ \cs -> (mempty, cs, arr f)+  first (QueryReader f) = QueryReader $ \comps -> let (cIds, comps', qS) = f comps in (cIds, comps', first qS) +instance ArrowChoice QueryReader where+  left (QueryReader f) = QueryReader $ \comps -> let (cIds, comps', qS) = f comps in (cIds, comps', left qS)+ instance ArrowQueryReader QueryReader where-  entity = Query $ \cs -> (mempty, cs, entityDyn)   fetch :: forall a. (Component a) => QueryReader () a-  fetch = Query $ \cs ->-    let (cId, cs') = CS.insert @a cs-     in (Set.singleton cId, cs', fetchDyn cId)+  fetch = QueryReader $ \cs ->+    let (cId, cs') = CS.insert @a cs in (Set.singleton cId, cs', fetchDyn cId)   fetchMaybe :: forall a. (Component a) => QueryReader () (Maybe a)-  fetchMaybe = Query $ \cs ->-    let (cId, cs') = CS.insert @a cs-     in (Set.singleton cId, cs', fetchMaybeDyn cId)+  fetchMaybe = QueryReader $ \cs ->+    let (cId, cs') = CS.insert @a cs in (Set.singleton cId, cs', fetchMaybeDyn cId)  instance ArrowDynamicQueryReader QueryReader where-  entityDyn = Query $ \cs -> (mempty, cs, entityDyn)-  fetchDyn cId = Query $ \cs -> (Set.singleton cId, cs, fetchDyn cId)-  fetchMaybeDyn cId = Query $ \cs -> (Set.singleton cId, cs, fetchMaybeDyn cId)+  entity = QueryReader $ \cs -> (mempty, cs, entity)+  fetchDyn cId = QueryReader $ \cs -> (Set.singleton cId, cs, fetchDyn cId)+  fetchMaybeDyn cId = QueryReader $ \cs -> (Set.singleton cId, cs, fetchMaybeDyn cId)  -- | Filter for a `Query`. newtype QueryFilter = QueryFilter {runQueryFilter :: Components -> (DynamicQueryFilter, Components)}
src/Aztecs/ECS/Query/Reader/Class.hs view
@@ -1,13 +1,10 @@ module Aztecs.ECS.Query.Reader.Class (ArrowQueryReader (..)) where  import Aztecs.ECS.Component-import Aztecs.ECS.Entity (EntityID) import Control.Arrow (Arrow (..), (>>>)) +-- | Arrow for queries that can read from entities. class (Arrow arr) => ArrowQueryReader arr where-  -- | Fetch the currently matched `EntityID`.-  entity :: arr () EntityID-   -- | Fetch a `Component` by its type.   fetch :: (Component a) => arr () a 
src/Aztecs/ECS/Schedule.hs view
@@ -1,21 +1,27 @@ {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}  module Aztecs.ECS.Schedule   ( -- * Schedules-    Schedule (..),-    reader,-    system,+    Schedule,+    ScheduleT (..),+    ArrowReaderSchedule (..),+    ArrowSchedule (..),+    ArrowAccessSchedule (..),+    delay,     forever,     forever_,-    access,-    task,     runSchedule,     runSchedule_,   ) where  import Aztecs.ECS.Access (AccessT (..), runAccessT)+import Aztecs.ECS.Schedule.Access.Class (ArrowAccessSchedule (..))+import Aztecs.ECS.Schedule.Class (ArrowSchedule (..))+import Aztecs.ECS.Schedule.Dynamic (DynamicSchedule, DynamicScheduleT (..))+import Aztecs.ECS.Schedule.Reader.Class (ArrowReaderSchedule (..)) import Aztecs.ECS.System (System (..)) import Aztecs.ECS.System.Dynamic (DynamicSystem (..)) import Aztecs.ECS.System.Dynamic.Reader (DynamicReaderSystem (..))@@ -23,78 +29,97 @@ import qualified Aztecs.ECS.View as V import Aztecs.ECS.World (World (..)) import qualified Aztecs.ECS.World as W+import Aztecs.ECS.World.Bundle (Bundle) import Aztecs.ECS.World.Components (Components)-import Control.Arrow (Arrow (..))+import Aztecs.ECS.World.Entities (Entities (..))+import Control.Arrow (Arrow (..), ArrowLoop (..)) import Control.Category (Category (..)) import Control.DeepSeq import Control.Exception (evaluate)-import Control.Monad ((>=>))+import Control.Monad.Fix import Control.Monad.Identity (Identity (runIdentity)) import Control.Monad.State (MonadState (..)) import Control.Monad.Trans (MonadTrans (..)) import Data.Functor (void)+import Prelude hiding (id, (.)) -newtype Schedule m i o = Schedule {runSchedule' :: Components -> (i -> AccessT m o, Components)}+type Schedule m = ScheduleT (AccessT m)++accessDyn :: (Monad m) => (i -> m o) -> DynamicScheduleT m i o+accessDyn f = DynamicSchedule $ \i -> do+  a <- f i+  return (a, accessDyn f)++delayDyn :: (Applicative m) => a -> DynamicScheduleT m a a+delayDyn d = DynamicSchedule $ \this -> pure (d, delayDyn this)++-- | System schedule.+newtype ScheduleT m i o = Schedule {runSchedule' :: Components -> (DynamicScheduleT m i o, Components)}   deriving (Functor) -instance (Monad m) => Category (Schedule m) where-  id = Schedule $ \cs -> (return, cs)+instance (Monad m) => Category (ScheduleT m) where+  id = Schedule $ \cs -> (id, cs)   Schedule f . Schedule g = Schedule $ \cs ->     let (g', cs') = g cs         (f', cs'') = f cs'-     in (g' >=> f', cs'')+     in (f' . g', cs'') -instance Arrow (Schedule IO) where-  arr f = Schedule $ \cs -> (return Prelude.. f, cs)-  first (Schedule f) = Schedule $ \cs ->-    let (g, cs') = f cs in (\(b, d) -> (,) <$> g b <*> return d, cs')+instance (Monad m) => Arrow (ScheduleT m) where+  arr f = Schedule $ \cs -> (arr f, cs)+  first (Schedule f) = Schedule $ \cs -> let (f', cs') = f cs in (first f', cs') -runSchedule :: (Monad m) => Schedule m i o -> World -> i -> m (o, World)-runSchedule s w i = do-  let (f, cs) = runSchedule' s (components w)-  (o, w') <- runAccessT (f i) w {components = cs}-  return (o, w')+instance (MonadFix m) => ArrowLoop (ScheduleT m) where+  loop (Schedule f) = Schedule $ \cs -> let (f', cs') = f cs in (loop f', cs') -runSchedule_ :: (Monad m) => Schedule m () () -> m ()-runSchedule_ s = void (runSchedule s W.empty ())+instance (Monad m) => ArrowAccessSchedule Bundle (AccessT m) (Schedule m) where+  access f = Schedule $ \cs -> (accessDyn f, cs) -reader :: (Monad m) => ReaderSystem i o -> Schedule m i o-reader t = Schedule $ \cs ->-  let (dynT, _, cs') = runReaderSystem t cs-      go i = AccessT $ do-        w <- get-        return $ runReaderSystemDyn dynT w i-   in (go, cs')+instance (Monad m) => ArrowReaderSchedule ReaderSystem (Schedule m) where+  reader s = Schedule $ \cs ->+    let (dynS, _, cs') = runReaderSystem s cs+        go dynSAcc i = AccessT $ do+          w <- get+          let (o, a, dynSAcc') = runReaderSystemDyn dynSAcc (W.entities w) i+              ((), w') = runIdentity $ runAccessT a w+          put w'+          return (o, DynamicSchedule $ go dynSAcc')+     in (DynamicSchedule $ go dynS, cs') -system :: (Monad m) => System i o -> Schedule m i o-system t = Schedule $ \cs ->-  let (dynT, _, cs') = runSystem t cs-      go i = AccessT $ do-        w <- get-        let (o, v, a) = runSystemDyn dynT w i-            ((), w') = runIdentity $ runAccessT a $ V.unview v w-        put w'-        return o-   in (go, cs')+instance (Monad m) => ArrowSchedule System (Schedule m) where+  system s = Schedule $ \cs ->+    let (dynS, _, cs') = runSystem s cs+        go dynSAcc i = AccessT $ do+          w <- get+          let (o, v, a, dynSAcc') = runSystemDyn dynSAcc (W.entities w) i+              ((), w') = runIdentity $ runAccessT a w {W.entities = V.unview v (W.entities w)}+          put w'+          return (o, DynamicSchedule $ go dynSAcc')+     in (DynamicSchedule $ go dynS, cs') -access :: (Monad m) => (i -> AccessT m o) -> Schedule m i o-access f = Schedule $ \cs -> (f, cs)+delay :: (Monad m) => a -> Schedule m a a+delay d = Schedule $ \cs -> (delayDyn d, cs) -task :: (Monad m) => (i -> m o) -> Schedule m i o-task f = Schedule $ \cs -> (AccessT Prelude.. lift Prelude.. f, cs)+runSchedule :: (Monad m) => Schedule m i o -> World -> i -> m (o, DynamicSchedule m i o, World)+runSchedule s w i = do+  let (f, cs) = runSchedule' s (components $ W.entities w)+  ((o, f'), w') <- runAccessT (runScheduleDyn f i) w {W.entities = (W.entities w) {components = cs}}+  return (o, f', w') +runSchedule_ :: (Monad m) => Schedule m () () -> m ()+runSchedule_ s = void (runSchedule s W.empty ())+ forever :: Schedule IO i o -> (o -> IO ()) -> Schedule IO i () forever s f = Schedule $ \cs ->   let (g, cs') = runSchedule' s cs       go i = AccessT $ do         w <- get-        let loop wAcc = do-              (o, wAcc') <- lift $ runAccessT (g i) wAcc+        let go' gAcc wAcc = do+              ((o, g'), wAcc') <- lift $ runAccessT (runScheduleDyn gAcc i) wAcc               lift $ evaluate $ rnf wAcc'               lift $ f o-              loop wAcc'-        loop w-   in (go, cs')+              go' g' wAcc'+        go' g w+   in (DynamicSchedule go, cs')  forever_ :: Schedule IO i o -> Schedule IO i () forever_ s = forever s (const $ pure ())
+ src/Aztecs/ECS/Schedule/Access.hs view
@@ -0,0 +1,27 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE MultiParamTypeClasses #-}++module Aztecs.ECS.Schedule.Access (AcessSchedule (..), ArrowAccessSchedule (..)) where++import Aztecs.ECS.Access (AccessT (..))+import Aztecs.ECS.Schedule (ArrowAccessSchedule (..))+import Aztecs.ECS.World.Bundle (Bundle)+import Control.Arrow (Arrow (..))+import Control.Category (Category (..))+import Control.Monad ((>=>))++newtype AcessSchedule m i o = AcessSchedule {runAcessSchedule :: i -> AccessT m o}+  deriving (Functor)++instance (Monad m) => Category (AcessSchedule m) where+  id = AcessSchedule return+  AcessSchedule f . AcessSchedule g = AcessSchedule (g >=> f)++instance (Monad m) => Arrow (AcessSchedule m) where+  arr f = AcessSchedule $ \i -> return $ f i+  first (AcessSchedule f) = AcessSchedule $ \(b, d) -> do+    c <- f b+    return (c, d)++instance (Monad m) => ArrowAccessSchedule Bundle (AccessT m) (AcessSchedule m) where+  access = AcessSchedule
+ src/Aztecs/ECS/Schedule/Access/Class.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE FunctionalDependencies #-}++module Aztecs.ECS.Schedule.Access.Class (ArrowAccessSchedule (..)) where++import Aztecs.ECS.Access (MonadAccess)+import Control.Arrow (Arrow (..))++-- | Schedule arrow that provides access to a `World`.+class (MonadAccess b m, Arrow arr) => ArrowAccessSchedule b m arr | arr -> m where+  -- | Access the `World`.+  access :: (i -> m o) -> arr i o
+ src/Aztecs/ECS/Schedule/Class.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE FunctionalDependencies #-}++module Aztecs.ECS.Schedule.Class (ArrowSchedule (..)) where++import Control.Arrow (Arrow (..))++-- | Schedule arrow that runs systems.+class (Arrow arr) => ArrowSchedule s arr | arr -> s where+  -- | Schedule a system.+  system :: s i o -> arr i o
+ src/Aztecs/ECS/Schedule/Dynamic.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE RecursiveDo #-}++module Aztecs.ECS.Schedule.Dynamic+  ( DynamicSchedule,+    DynamicScheduleT (..),+  )+where++import Aztecs.ECS.Access+import Control.Arrow+import Control.Category+import Control.Monad.Fix+import Prelude hiding (id, (.))++type DynamicSchedule m = DynamicScheduleT (AccessT m)++newtype DynamicScheduleT m i o = DynamicSchedule {runScheduleDyn :: i -> m (o, DynamicScheduleT m i o)}+  deriving (Functor)++instance (Monad m) => Category (DynamicScheduleT m) where+  id = DynamicSchedule $ \i -> pure (i, id)+  DynamicSchedule f . DynamicSchedule g = DynamicSchedule $ \i -> do+    (b, g') <- g i+    (c, f') <- f b+    return (c, f' . g')++instance (Monad m) => Arrow (DynamicScheduleT m) where+  arr f = DynamicSchedule $ \i -> pure (f i, arr f)+  first (DynamicSchedule f) = DynamicSchedule $ \(b, d) -> do+    (c, f') <- f b+    return ((c, d), first f')++instance (Monad m) => ArrowChoice (DynamicScheduleT m) where+  left (DynamicSchedule f) = DynamicSchedule $ \i -> case i of+    Left b -> do+      (c, f') <- f b+      return (Left c, left f')+    Right d -> return (Right d, left (DynamicSchedule f))++instance (MonadFix m) => ArrowLoop (DynamicScheduleT m) where+  loop (DynamicSchedule f) = DynamicSchedule $ \b -> do+    rec ((c, d), f') <- f (b, d)+    return (c, loop f')
+ src/Aztecs/ECS/Schedule/Dynamic/Reader.hs view
@@ -0,0 +1,45 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE RecursiveDo #-}+{-# LANGUAGE TypeFamilies #-}++module Aztecs.ECS.Schedule.Dynamic.Reader+  ( DynamicReaderSchedule,+    DynamicReaderScheduleT (..),+  )+where++import Aztecs.ECS.Access+import Control.Arrow+import Control.Category+import Control.Monad.Fix+import Prelude hiding (all, any, id, lookup, reads, (.))++type DynamicReaderSchedule m = DynamicReaderScheduleT (AccessT m)++newtype DynamicReaderScheduleT m i o = DynamicReaderSchedule {runScheduleDyn :: i -> m (o, DynamicReaderScheduleT m i o)}+  deriving (Functor)++instance (Monad m) => Category (DynamicReaderScheduleT m) where+  id = DynamicReaderSchedule $ \i -> pure (i, id)+  DynamicReaderSchedule f . DynamicReaderSchedule g = DynamicReaderSchedule $ \i -> do+    (b, g') <- g i+    (c, f') <- f b+    return (c, f' . g')++instance (Monad m) => Arrow (DynamicReaderScheduleT m) where+  arr f = DynamicReaderSchedule $ \i -> pure (f i, arr f)+  first (DynamicReaderSchedule f) = DynamicReaderSchedule $ \(b, d) -> do+    (c, f') <- f b+    return ((c, d), first f')++instance (Monad m) => ArrowChoice (DynamicReaderScheduleT m) where+  left (DynamicReaderSchedule f) = DynamicReaderSchedule $ \i -> case i of+    Left b -> do+      (c, f') <- f b+      return (Left c, left f')+    Right d -> return (Right d, left (DynamicReaderSchedule f))++instance (MonadFix m) => ArrowLoop (DynamicReaderScheduleT m) where+  loop (DynamicReaderSchedule f) = DynamicReaderSchedule $ \b -> do+    rec ((c, d), f') <- f (b, d)+    return (c, loop f')
+ src/Aztecs/ECS/Schedule/Reader.hs view
@@ -0,0 +1,56 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}++module Aztecs.ECS.Schedule.Reader+  ( ReaderScheduleT (..),+  )+where++import Aztecs.ECS.Access (AccessT (..), runAccessT)+import Aztecs.ECS.Schedule.Dynamic.Reader (DynamicReaderScheduleT (..))+import Aztecs.ECS.Schedule.Reader.Class+import Aztecs.ECS.System.Dynamic.Reader (DynamicReaderSystem (..))+import Aztecs.ECS.System.Reader (ReaderSystem (..))+import Aztecs.ECS.World (World (..))+import Aztecs.ECS.World.Components (Components)+import Control.Arrow+import Control.Category+import Control.Monad.Fix+import Control.Monad.Identity (Identity (runIdentity))+import Control.Monad.State (MonadState (..))+import Prelude hiding (id, (.))++type ReaderSchedule m = ReaderScheduleT (AccessT m)++newtype ReaderScheduleT m i o+  = ReaderSchedule {runReaderSchedule :: Components -> (DynamicReaderScheduleT m i o, Components)}+  deriving (Functor)++instance (Monad m) => Category (ReaderScheduleT m) where+  id = ReaderSchedule $ \cs -> (id, cs)+  ReaderSchedule f . ReaderSchedule g = ReaderSchedule $ \cs ->+    let (g', cs') = g cs+        (f', cs'') = f cs'+     in (f' . g', cs'')++instance (Monad m) => Arrow (ReaderScheduleT m) where+  arr f = ReaderSchedule $ \cs -> (arr f, cs)+  first (ReaderSchedule f) = ReaderSchedule $ \cs -> let (f', cs') = f cs in (first f', cs')++instance (Monad m) => ArrowChoice (ReaderScheduleT m) where+  left (ReaderSchedule f) = ReaderSchedule $ \cs -> let (f', cs') = f cs in (left f', cs')++instance (MonadFix m) => ArrowLoop (ReaderScheduleT m) where+  loop (ReaderSchedule f) = ReaderSchedule $ \cs -> let (f', cs') = f cs in (loop f', cs')++instance (Monad m) => ArrowReaderSchedule ReaderSystem (ReaderSchedule m) where+  reader s = ReaderSchedule $ \cs ->+    let (dynS, _, cs') = runReaderSystem s cs+        go dynSAcc i = AccessT $ do+          w <- get+          let (o, a, dynSAcc') = runReaderSystemDyn dynSAcc (entities w) i+              ((), w') = runIdentity $ runAccessT a w+          put w'+          return (o, DynamicReaderSchedule $ go dynSAcc')+     in (DynamicReaderSchedule $ go dynS, cs')
+ src/Aztecs/ECS/Schedule/Reader/Class.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE FunctionalDependencies #-}++module Aztecs.ECS.Schedule.Reader.Class (ArrowReaderSchedule (..)) where++import Control.Arrow (Arrow (..))++-- | Schedule arrow that runs read-only systems.+class (Arrow arr) => ArrowReaderSchedule s arr | arr -> s where+  -- | Schedule a reader system.+  reader :: s i o -> arr i o
src/Aztecs/ECS/System.hs view
@@ -4,29 +4,34 @@ {-# LANGUAGE MultiParamTypeClasses #-}  module Aztecs.ECS.System-  ( -- * Systems-    System (..),+  ( System (..),     ArrowReaderSystem (..),     ArrowSystem (..),+    ArrowQueueSystem (..),+    fromReader,   ) where +import Aztecs.ECS.Access (Access) import Aztecs.ECS.Query (Query (..), QueryFilter (..), ReadsWrites (..)) import qualified Aztecs.ECS.Query as Q import Aztecs.ECS.Query.Reader (QueryReader (..), filterWith, filterWithout)-import Aztecs.ECS.System.Class (ArrowSystem (..), filterMap, map, mapSingle, map_, queue)-import Aztecs.ECS.System.Dynamic (DynamicSystem (..), raceDyn)+import Aztecs.ECS.System.Class (ArrowSystem (..))+import Aztecs.ECS.System.Dynamic (DynamicSystem (..), fromDynReaderSystem, raceDyn) import Aztecs.ECS.System.Dynamic.Class (ArrowDynamicSystem (..)) import Aztecs.ECS.System.Dynamic.Reader.Class (ArrowDynamicReaderSystem (..))+import Aztecs.ECS.System.Queue (ArrowQueueSystem (..))+import Aztecs.ECS.System.Reader (ReaderSystem (..)) import Aztecs.ECS.System.Reader.Class (ArrowReaderSystem (..), all, filter, single) import qualified Aztecs.ECS.World.Archetype as A import Aztecs.ECS.World.Archetypes (Node (..))+import Aztecs.ECS.World.Bundle (Bundle) import Aztecs.ECS.World.Components (Components)-import Control.Arrow (Arrow (..))-import Control.Category (Category (..))+import Control.Arrow+import Control.Category import qualified Data.Foldable as F-import Prelude hiding (all, filter, map, (.))-import qualified Prelude hiding (filter, map)+import Prelude hiding (all, filter, id, map, (.))+import qualified Prelude hiding (filter, id, map)  -- | System to process entities. newtype System i o = System@@ -36,24 +41,28 @@   deriving (Functor)  instance Category System where-  id = System $ \cs -> (DynamicSystem $ \_ i -> (i, mempty, pure ()), mempty, cs)+  id = System $ \cs -> (DynamicSystem $ \_ i -> (i, mempty, pure (), id), mempty, cs)   System f . System g = System $ \cs ->     let (f', rwsF, cs') = f cs         (g', rwsG, cs'') = g cs'      in (f' . g', rwsF <> rwsG, cs'')  instance Arrow System where-  arr f = System $ \cs -> (DynamicSystem $ \_ i -> (f i, mempty, pure ()), mempty, cs)+  arr f = System $ \cs -> (DynamicSystem $ \_ i -> (f i, mempty, pure (), arr f), mempty, cs)   first (System f) = System $ \cs ->     let (f', rwsF, cs') = f cs in (first f', rwsF, cs')   f &&& g = System $ \cs ->     let (dynF, rwsA, cs') = runSystem f cs         (dynG, rwsB, cs'') = runSystem g cs'-     in ( if Q.disjoint rwsA rwsB then dynF &&& dynG else raceDyn dynF dynG,-          rwsA <> rwsB,-          cs''-        )+        dynS = if Q.disjoint rwsA rwsB then dynF &&& dynG else raceDyn dynF dynG+     in (dynS, rwsA <> rwsB, cs'') +instance ArrowChoice System where+  left (System f) = System $ \cs -> let (f', rwsF, cs') = f cs in (left f', rwsF, cs')++instance ArrowLoop System where+  loop (System f) = System $ \cs -> let (f', rwsF, cs') = f cs in (loop f', rwsF, cs')+ instance ArrowReaderSystem QueryReader System where   all q = System $ \cs ->     let !(rs, cs', dynQ) = runQueryReader q cs in (allDyn rs dynQ, ReadsWrites rs mempty, cs')@@ -82,4 +91,10 @@   mapSingleMaybe q = System $ \cs ->     let !(rws, cs', dynQ) = runQuery q cs      in (mapSingleMaybeDyn (Q.reads rws <> Q.writes rws) dynQ, rws, cs')-  queue f = System $ \cs -> (queueDyn f, mempty, cs)++instance ArrowQueueSystem Bundle Access System where+  queue f = System $ \cs -> (queue f, mempty, cs)++fromReader :: ReaderSystem i o -> System i o+fromReader (ReaderSystem f) = System $ \cs ->+  let (f', rs, cs') = f cs in (fromDynReaderSystem f', ReadsWrites rs mempty, cs')
src/Aztecs/ECS/System/Class.hs view
@@ -2,7 +2,6 @@  module Aztecs.ECS.System.Class (ArrowSystem (..)) where -import Aztecs.ECS.Access (Access) import Aztecs.ECS.Query.Reader (QueryFilter (..)) import Control.Arrow (Arrow (..), (>>>)) import Prelude hiding (map)@@ -23,6 +22,3 @@   mapSingle :: q i a -> arr i a    mapSingleMaybe :: q i a -> arr i (Maybe a)--  -- | Queue an `Access` to happen after this system schedule.-  queue :: (i -> Access ()) -> arr i ()
src/Aztecs/ECS/System/Dynamic.hs view
@@ -1,50 +1,100 @@+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} -module Aztecs.ECS.System.Dynamic (DynamicSystem (..), raceDyn) where+module Aztecs.ECS.System.Dynamic+  ( DynamicSystem (..),+    ArrowDynamicReaderSystem (..),+    ArrowDynamicSystem (..),+    ArrowQueueSystem (..),+    raceDyn,+    fromDynReaderSystem,+  )+where  import Aztecs.ECS.Access (Access)+import Aztecs.ECS.Query.Dynamic (DynamicQuery)+import Aztecs.ECS.Query.Dynamic.Reader (DynamicQueryReader) import Aztecs.ECS.System.Dynamic.Class (ArrowDynamicSystem (..))+import Aztecs.ECS.System.Dynamic.Reader (DynamicReaderSystem (..)) import Aztecs.ECS.System.Dynamic.Reader.Class (ArrowDynamicReaderSystem (..))-import Aztecs.ECS.View (View, filterView, readAllDyn, view)-import Aztecs.ECS.World (World (..))-import Control.Arrow (Arrow (..))-import Control.Category (Category (..))+import Aztecs.ECS.System.Queue (ArrowQueueSystem (..))+import Aztecs.ECS.View (View)+import qualified Aztecs.ECS.View as V+import Aztecs.ECS.World.Bundle (Bundle)+import Aztecs.ECS.World.Entities (Entities (..))+import Control.Arrow+import Control.Category import Control.Parallel (par)+import Data.Maybe (fromMaybe)+import Prelude hiding (id, (.))  newtype DynamicSystem i o = DynamicSystem   { -- | Run a dynamic system,     -- producing some output, an updated `View` into the `World`, and any queued `Access`.-    runSystemDyn :: World -> (i -> (o, View, Access ()))+    runSystemDyn :: Entities -> i -> (o, View, Access (), DynamicSystem i o)   }   deriving (Functor)  instance Category DynamicSystem where-  id = DynamicSystem $ \_ i -> (i, mempty, pure ())+  id = DynamicSystem $ \_ i -> (i, mempty, pure (), id)   DynamicSystem f . DynamicSystem g = DynamicSystem $ \w i ->-    let (b, gView, gAccess) = g w i-        (a, fView, fAccess) = f w b-     in (a, gView <> fView, gAccess >> fAccess)+    let (b, gView, gAccess, g') = g w i+        (a, fView, fAccess, f') = f w b+     in (a, gView <> fView, gAccess >> fAccess, f' . g')  instance Arrow DynamicSystem where-  arr f = DynamicSystem $ \_ i -> (f i, mempty, pure ())-  first (DynamicSystem f) = DynamicSystem $ \w (i, x) -> let (a, v, access) = f w i in ((a, x), v, access)+  arr f = DynamicSystem $ \_ i -> (f i, mempty, pure (), arr f)+  first (DynamicSystem f) = DynamicSystem $ \w (i, x) ->+    let (a, v, access, f') = f w i in ((a, x), v, access, first f') -instance ArrowDynamicReaderSystem DynamicSystem where-  allDyn cIds q = DynamicSystem $ \w i ->-    let v = view cIds $ archetypes w in (readAllDyn i q v, v, pure ())-  filterDyn cIds q f = DynamicSystem $ \w i ->-    let v = filterView cIds f $ archetypes w in (readAllDyn i q v, v, pure ())+instance ArrowChoice DynamicSystem where+  left (DynamicSystem f) = DynamicSystem $ \w i -> case i of+    Left b -> let (c, v, access, f') = f w b in (Left c, v, access, left f')+    Right d -> (Right d, mempty, pure (), left (DynamicSystem f)) -instance ArrowDynamicSystem DynamicSystem where-  runArrowSystemDyn = DynamicSystem+instance ArrowLoop DynamicSystem where+  loop (DynamicSystem f) = DynamicSystem $ \w b ->+    let ((c, d), v, access, f') = f w (b, d) in (c, v, access, loop f') +instance ArrowDynamicReaderSystem DynamicQueryReader DynamicSystem where+  allDyn cIds q = fromDynReaderSystem $ allDyn cIds q+  filterDyn cIds qf q = fromDynReaderSystem $ filterDyn cIds qf q++instance ArrowDynamicSystem DynamicQuery DynamicSystem where+  mapDyn cIds q = DynamicSystem $ \w i ->+    let !v = V.view cIds $ archetypes w+        (o, v') = V.allDyn i q v+     in (o, v', pure (), mapDyn cIds q)+  mapSingleDyn cIds q = DynamicSystem $ \w i ->+    let s =+          mapSingleMaybeDyn cIds q+            >>> arr (fromMaybe (error "Expected a single matching entity."))+     in runSystemDyn s w i+  mapSingleMaybeDyn cIds q = DynamicSystem $ \w i ->+    let !res = V.viewSingle cIds $ archetypes w+        (res', v'') = case res of+          Just v -> let (o, v') = V.singleDyn i q v in (o, v')+          Nothing -> (Nothing, mempty)+     in (res', v'', pure (), mapSingleMaybeDyn cIds q)+  filterMapDyn cIds q f = DynamicSystem $ \w i ->+    let !v = V.filterView cIds f $ archetypes w+        (o, v') = V.allDyn i q v+     in (o, v', pure (), filterMapDyn cIds q f)++instance ArrowQueueSystem Bundle Access DynamicSystem where+  queue f = DynamicSystem $ \_ i -> ((), mempty, f i, queue f)+ raceDyn :: DynamicSystem i a -> DynamicSystem i b -> DynamicSystem i (a, b) raceDyn (DynamicSystem f) (DynamicSystem g) = DynamicSystem $ \w i ->   let fa = f w i       gb = g w i       gbPar = fa `par` gb-      (a, v, fAccess) = fa-      (b, v', gAccess) = gbPar-   in ((a, b), v <> v', fAccess >> gAccess)+      (a, v, fAccess, f') = fa+      (b, v', gAccess, g') = gbPar+   in ((a, b), v <> v', fAccess >> gAccess, raceDyn f' g')++fromDynReaderSystem :: DynamicReaderSystem i o -> DynamicSystem i o+fromDynReaderSystem (DynamicReaderSystem f) = DynamicSystem $ \w i ->+  let (o, access, f') = f w i in (o, mempty, access, fromDynReaderSystem f')
src/Aztecs/ECS/System/Dynamic/Class.hs view
@@ -1,80 +1,21 @@-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FunctionalDependencies #-} -module Aztecs.ECS.System.Dynamic.Class-  ( ArrowDynamicSystem (..),-    DynamicSystem,-    mapDyn',-    mapSingleDyn',-    mapSingleMaybeDyn',-    filterMapDyn',-    queueDyn',-  )-where+module Aztecs.ECS.System.Dynamic.Class (ArrowDynamicSystem (..)) where -import Aztecs.ECS.Access (Access) import Aztecs.ECS.Component (ComponentID)-import Aztecs.ECS.Query.Dynamic (DynamicQuery)-import Aztecs.ECS.System.Dynamic.Reader.Class (ArrowDynamicReaderSystem (..))-import Aztecs.ECS.View (View)-import qualified Aztecs.ECS.View as V-import Aztecs.ECS.World (World (..)) import Aztecs.ECS.World.Archetypes (Node (..))-import Data.Maybe (fromMaybe) import Data.Set (Set) -type DynamicSystem i o = World -> i -> (o, View, Access ())--class (ArrowDynamicReaderSystem arr) => ArrowDynamicSystem arr where-  runArrowSystemDyn :: DynamicSystem i o -> arr i o-+class ArrowDynamicSystem q arr | arr -> q where   -- | Map all matching entities, storing the updated entities.-  mapDyn :: Set ComponentID -> DynamicQuery i o -> arr i [o]-  mapDyn cIds q = runArrowSystemDyn $ mapDyn' cIds q+  mapDyn :: Set ComponentID -> q i o -> arr i [o] -  mapSingleDyn :: Set ComponentID -> DynamicQuery i o -> arr i o-  mapSingleDyn cIds q = runArrowSystemDyn $ mapSingleDyn' cIds q+  mapSingleDyn :: Set ComponentID -> q i o -> arr i o -  mapSingleMaybeDyn :: Set ComponentID -> DynamicQuery i o -> arr i (Maybe o)-  mapSingleMaybeDyn cIds q = runArrowSystemDyn $ mapSingleMaybeDyn' cIds q+  mapSingleMaybeDyn :: Set ComponentID -> q i o -> arr i (Maybe o)    filterMapDyn ::     Set ComponentID ->-    DynamicQuery i o ->+    q i o ->     (Node -> Bool) ->     arr i [o]-  filterMapDyn cIds q f = runArrowSystemDyn $ filterMapDyn' cIds q f--  queueDyn :: (i -> Access ()) -> arr i ()-  queueDyn f = runArrowSystemDyn $ \_ i -> ((), mempty, f i)---- | Map all matching entities, storing the updated entities.-mapDyn' :: Set ComponentID -> DynamicQuery i o -> DynamicSystem i [o]-mapDyn' cIds q w =-  let !v = V.view cIds $ archetypes w-   in \i -> let (o, v') = V.allDyn i q v in (o, v', pure ())--mapSingleDyn' :: Set ComponentID -> DynamicQuery i o -> DynamicSystem i o-mapSingleDyn' cIds q w i =-  let !(maybeO, v, access) = mapSingleMaybeDyn' cIds q w i-      !o = fromMaybe (error "Expected a single matching entity.") maybeO-   in (o, v, access)---- | Map all matching entities, storing the updated entities.-mapSingleMaybeDyn' :: Set ComponentID -> DynamicQuery i o -> DynamicSystem i (Maybe o)-mapSingleMaybeDyn' cIds q w i =-  let !res = V.viewSingle cIds $ archetypes w-   in case res of-        Just v -> let (o, v') = V.singleDyn i q v in (o, v', pure ())-        Nothing -> (Nothing, mempty, pure ())--filterMapDyn' ::-  Set ComponentID ->-  DynamicQuery i o ->-  (Node -> Bool) ->-  DynamicSystem i [o]-filterMapDyn' cIds q f w =-  let !v = V.filterView cIds f $ archetypes w-   in \i -> let (o, v') = V.allDyn i q v in (o, v', pure ())--queueDyn' :: (i -> Access ()) -> DynamicSystem i ()-queueDyn' f _ i = ((), mempty, f i)
src/Aztecs/ECS/System/Dynamic/Reader.hs view
@@ -1,60 +1,70 @@ {-# LANGUAGE BangPatterns #-} {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}  module Aztecs.ECS.System.Dynamic.Reader-  ( -- * Dynamic Systems-    DynamicReaderSystem (..),+  ( DynamicReaderSystem (..),     ArrowDynamicReaderSystem (..),+    ArrowQueueSystem (..),     raceDyn,   ) where -import Aztecs.ECS.Component (ComponentID)+import Aztecs.ECS.Access (Access) import Aztecs.ECS.Query.Dynamic.Reader (DynamicQueryReader) import Aztecs.ECS.System.Dynamic.Reader.Class (ArrowDynamicReaderSystem (..))+import Aztecs.ECS.System.Queue (ArrowQueueSystem (..)) import qualified Aztecs.ECS.View as V-import Aztecs.ECS.World (World (..))-import Aztecs.ECS.World.Archetypes (Node)-import Control.Arrow (Arrow (..))-import Control.Category (Category (..))+import Aztecs.ECS.World.Bundle (Bundle)+import Aztecs.ECS.World.Entities (Entities (..))+import Control.Arrow+import Control.Category import Control.Parallel (par)-import Data.Set (Set)+import Prelude hiding (id, (.))  newtype DynamicReaderSystem i o = DynamicReaderSystem   { -- | Run a dynamic system producing some output-    runReaderSystemDyn :: World -> i -> o+    runReaderSystemDyn :: Entities -> i -> (o, Access (), DynamicReaderSystem i o)   }   deriving (Functor)  instance Category DynamicReaderSystem where-  id = DynamicReaderSystem $ \_ i -> i-  DynamicReaderSystem f . DynamicReaderSystem g = DynamicReaderSystem $ \w i -> let b = g w i in f w b+  id = DynamicReaderSystem $ \_ i -> (i, pure (), id)+  DynamicReaderSystem f . DynamicReaderSystem g = DynamicReaderSystem $ \w i ->+    let (b, gAccess, g') = g w i+        (c, fAccess, f') = f w b+     in (c, gAccess >> fAccess, f' . g')  instance Arrow DynamicReaderSystem where-  arr f = DynamicReaderSystem $ \_ i -> f i-  first (DynamicReaderSystem f) = DynamicReaderSystem $ \w (i, x) -> let a = f w i in (a, x)+  arr f = DynamicReaderSystem $ \_ i -> (f i, pure (), arr f)+  first (DynamicReaderSystem f) = DynamicReaderSystem $ \w (i, x) ->+    let (a, access, f') = f w i in ((a, x), access, first f') -instance ArrowDynamicReaderSystem DynamicReaderSystem where-  allDyn cIds q = DynamicReaderSystem $ allDyn' cIds q-  filterDyn cIds q f = DynamicReaderSystem $ filterDyn' cIds q f+instance ArrowChoice DynamicReaderSystem where+  left (DynamicReaderSystem f) = DynamicReaderSystem $ \w i -> case i of+    Left b -> let (c, access, f') = f w b in (Left c, access, left f')+    Right d -> (Right d, pure (), left (DynamicReaderSystem f)) +instance ArrowLoop DynamicReaderSystem where+  loop (DynamicReaderSystem f) = DynamicReaderSystem $ \w b ->+    let ((c, d), access, f') = f w (b, d) in (c, access, loop f')++instance ArrowDynamicReaderSystem DynamicQueryReader DynamicReaderSystem where+  allDyn cIds q = DynamicReaderSystem $ \w i ->+    let !v = V.view cIds $ archetypes w in (V.readAllDyn i q v, pure (), allDyn cIds q)+  filterDyn cIds q f = DynamicReaderSystem $ \w i ->+    let !v = V.filterView cIds f $ archetypes w+     in (V.readAllDyn i q v, pure (), filterDyn cIds q f)++instance ArrowQueueSystem Bundle Access DynamicReaderSystem where+  queue f = DynamicReaderSystem $ \_ i -> let !a = f i in ((), a, queue f)+ raceDyn :: DynamicReaderSystem i a -> DynamicReaderSystem i b -> DynamicReaderSystem i (a, b) raceDyn (DynamicReaderSystem f) (DynamicReaderSystem g) = DynamicReaderSystem $ \w i ->   let fa = f w i       gb = g w i       gbPar = fa `par` gb-      a = fa-      b = gbPar-   in (a, b)--allDyn' :: Set ComponentID -> DynamicQueryReader i o -> World -> i -> [o]-allDyn' cIds q w = let !v = V.view cIds $ archetypes w in \i -> V.readAllDyn i q v--filterDyn' ::-  Set ComponentID ->-  DynamicQueryReader i o ->-  (Node -> Bool) ->-  World ->-  i ->-  [o]-filterDyn' cIds q f w = let !v = V.filterView cIds f $ archetypes w in \i -> V.readAllDyn i q v+      (a, fAccess, f') = fa+      (b, gAccess, g') = gbPar+   in ((a, b), fAccess >> gAccess, raceDyn f' g')
src/Aztecs/ECS/System/Dynamic/Reader/Class.hs view
@@ -1,17 +1,18 @@+{-# LANGUAGE FunctionalDependencies #-}+ module Aztecs.ECS.System.Dynamic.Reader.Class (ArrowDynamicReaderSystem (..)) where  import Aztecs.ECS.Component (ComponentID)-import Aztecs.ECS.Query.Dynamic.Reader (DynamicQueryReader) import Aztecs.ECS.World.Archetypes (Node) import Control.Arrow (Arrow (..), (>>>)) import Data.Set (Set) -class (Arrow arr) => ArrowDynamicReaderSystem arr where-  allDyn :: Set ComponentID -> DynamicQueryReader i o -> arr i [o]+class (Arrow arr) => ArrowDynamicReaderSystem q arr | arr -> q where+  allDyn :: Set ComponentID -> q i o -> arr i [o] -  filterDyn :: Set ComponentID -> DynamicQueryReader i o -> (Node -> Bool) -> arr i [o]+  filterDyn :: Set ComponentID -> q i o -> (Node -> Bool) -> arr i [o] -  singleDyn :: Set ComponentID -> DynamicQueryReader () a -> arr () a+  singleDyn :: Set ComponentID -> q () a -> arr () a   singleDyn cIds q =     allDyn cIds q       >>> arr
+ src/Aztecs/ECS/System/Queue.hs view
@@ -0,0 +1,31 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}++module Aztecs.ECS.System.Queue (QueueSystem (..), ArrowQueueSystem (..)) where++import Aztecs.ECS.Access (Access)+import Aztecs.ECS.System.Queue.Class (ArrowQueueSystem (..))+import Aztecs.ECS.World.Bundle (Bundle)+import Control.Arrow (Arrow (..))+import Control.Category (Category (..))++-- | System that can queue `Access` to a `World`.+newtype QueueSystem i o = QueueSystem {runQueueSystem :: i -> (o, Access ())}+  deriving (Functor)++instance Category QueueSystem where+  id = QueueSystem $ \i -> (i, pure ())+  QueueSystem f . QueueSystem g = QueueSystem $ \i ->+    let (b, access) = g i+        (c, access') = f b+     in (c, access >> access')++instance Arrow QueueSystem where+  arr f = QueueSystem $ \i -> (f i, pure ())+  first (QueueSystem f) = QueueSystem $ \(b, d) ->+    let (c, access) = f b in ((c, d), access)++instance ArrowQueueSystem Bundle Access QueueSystem where+  queue f = QueueSystem $ \i -> let !a = f i in ((), a)
+ src/Aztecs/ECS/System/Queue/Class.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE FunctionalDependencies #-}++module Aztecs.ECS.System.Queue.Class (ArrowQueueSystem (..)) where++import Aztecs.ECS.Access (MonadAccess)+import Control.Arrow (Arrow (..))++class (MonadAccess b m, Arrow arr) => ArrowQueueSystem b m arr | arr -> m where+  -- | Queue an `Access` to happen after this system schedule.+  queue :: (i -> m ()) -> arr i ()
src/Aztecs/ECS/System/Reader.hs view
@@ -4,39 +4,27 @@ {-# LANGUAGE MultiParamTypeClasses #-}  module Aztecs.ECS.System.Reader-  ( -- * Systems-    ReaderSystem (..),-    queue,--    -- ** Queries--    -- *** Reading-    all,-    filter,-    single,--    -- *** Writing-    map,-    map_,-    filterMap,-    mapSingle,+  ( ReaderSystem (..),+    ArrowReaderSystem (..),+    ArrowQueueSystem (..),   ) where +import Aztecs.ECS.Access (Access) import Aztecs.ECS.Query.Reader-import Aztecs.ECS.System.Class (filterMap, map, mapSingle, map_, queue) import Aztecs.ECS.System.Dynamic.Reader (DynamicReaderSystem, raceDyn) import Aztecs.ECS.System.Dynamic.Reader.Class (ArrowDynamicReaderSystem (..))-import Aztecs.ECS.System.Reader.Class (ArrowReaderSystem (..), all, filter, single)+import Aztecs.ECS.System.Queue (ArrowQueueSystem (..))+import Aztecs.ECS.System.Reader.Class (ArrowReaderSystem (..)) import qualified Aztecs.ECS.World.Archetype as A import Aztecs.ECS.World.Archetypes (Node (..))+import Aztecs.ECS.World.Bundle (Bundle) import Aztecs.ECS.World.Components (ComponentID, Components)-import Control.Arrow (Arrow (..))-import Control.Category (Category (..))+import Control.Arrow+import Control.Category import qualified Data.Foldable as F import Data.Set (Set)-import Prelude hiding (all, filter, id, map, (.))-import qualified Prelude hiding (filter, id, map)+import Prelude hiding (id, (.))  -- | System to process entities. newtype ReaderSystem i o = ReaderSystem@@ -55,13 +43,18 @@ instance Arrow ReaderSystem where   arr f = ReaderSystem $ \cs -> (arr f, mempty, cs)   first (ReaderSystem f) = ReaderSystem $ \cs ->-    let (f', rwsF, cs') = f cs-     in (first f', rwsF, cs')+    let (f', rwsF, cs') = f cs in (first f', rwsF, cs')   f &&& g = ReaderSystem $ \cs ->     let (dynF, rwsA, cs') = runReaderSystem f cs         (dynG, rwsB, cs'') = runReaderSystem g cs'      in (raceDyn dynF dynG, rwsA <> rwsB, cs'') +instance ArrowChoice ReaderSystem where+  left (ReaderSystem f) = ReaderSystem $ \cs -> let (f', rwsF, cs') = f cs in (left f', rwsF, cs')++instance ArrowLoop ReaderSystem where+  loop (ReaderSystem f) = ReaderSystem $ \cs -> let (f', rwsF, cs') = f cs in (loop f', rwsF, cs')+ instance ArrowReaderSystem QueryReader ReaderSystem where   all q = ReaderSystem $ \cs ->     let !(rs, cs', dynQ) = runQueryReader q cs in (allDyn rs dynQ, rs, cs')@@ -72,3 +65,6 @@           F.all (\cId -> A.member cId $ nodeArchetype n) (filterWith dynQf)             && F.all (\cId -> not (A.member cId $ nodeArchetype n)) (filterWithout dynQf)      in (filterDyn rs dynQ qf', rs, cs'')++instance ArrowQueueSystem Bundle Access ReaderSystem where+  queue f = ReaderSystem $ \cs -> (queue f, mempty, cs)
src/Aztecs/ECS/View.hs view
@@ -19,12 +19,12 @@  import Aztecs.ECS.Query.Dynamic (DynamicQuery (..)) import Aztecs.ECS.Query.Dynamic.Reader (DynamicQueryReader (..))-import Aztecs.ECS.World (World)-import qualified Aztecs.ECS.World as W import qualified Aztecs.ECS.World.Archetype as A import Aztecs.ECS.World.Archetypes (ArchetypeID, Archetypes, Node (..)) import qualified Aztecs.ECS.World.Archetypes as AS import Aztecs.ECS.World.Components (ComponentID)+import Aztecs.ECS.World.Entities (Entities)+import qualified Aztecs.ECS.World.Entities as E import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map import Data.Set (Set)@@ -39,10 +39,10 @@  -- | View into all archetypes containing the provided component IDs. view :: Set ComponentID -> Archetypes -> View-view cIds as = View $ AS.lookup cIds as+view cIds as = View $ AS.find cIds as  viewSingle :: Set ComponentID -> Archetypes -> Maybe View-viewSingle cIds as = case Map.toList $ AS.lookup cIds as of+viewSingle cIds as = case Map.toList $ AS.find cIds as of   [a] -> Just . View $ Map.singleton (fst a) (snd a)   _ -> Nothing @@ -52,16 +52,16 @@   (Node -> Bool) ->   Archetypes ->   View-filterView cIds f as = View $ Map.filter f (AS.lookup cIds as)+filterView cIds f as = View $ Map.filter f (AS.find cIds as)  -- | "Un-view" a `View` back into a `World`.-unview :: View -> World -> World-unview v w =-  w-    { W.archetypes =+unview :: View -> Entities -> Entities+unview v es =+  es+    { E.archetypes =         foldl'           (\as (aId, n) -> as {AS.nodes = Map.insert aId n (AS.nodes as)})-          (W.archetypes w)+          (E.archetypes es)           (Map.toList $ viewArchetypes v)     } 
src/Aztecs/ECS/World.hs view
@@ -6,13 +6,12 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}  module Aztecs.ECS.World   ( World (..),     empty,     spawn,-    spawnComponent,-    spawnWithId,     spawnWithArchetypeId,     spawnEmpty,     insert,@@ -25,24 +24,15 @@ where  import Aztecs.ECS.Component-  ( Component (..),-    ComponentID,-  )-import Aztecs.ECS.Entity (EntityID (..))-import Aztecs.ECS.World.Archetype (Bundle (..), DynamicBundle (..))-import qualified Aztecs.ECS.World.Archetype as A-import Aztecs.ECS.World.Archetypes (ArchetypeID, Archetypes, Node (..))-import qualified Aztecs.ECS.World.Archetypes as AS-import Aztecs.ECS.World.Components (Components (..))-import qualified Aztecs.ECS.World.Components as CS-import Control.DeepSeq (NFData)-import Data.Dynamic (Dynamic)+import Aztecs.ECS.Entity+import Aztecs.ECS.World.Archetypes (ArchetypeID)+import Aztecs.ECS.World.Bundle+import Aztecs.ECS.World.Entities (Entities)+import qualified Aztecs.ECS.World.Entities as E+import Control.DeepSeq+import Data.Dynamic import Data.Map (Map)-import qualified Data.Map as Map-import Data.Maybe (fromMaybe)-import qualified Data.Set as Set-import Data.Typeable (Proxy (..), Typeable, typeOf)-import GHC.Generics (Generic)+import GHC.Generics import Prelude hiding (lookup)  #if !MIN_VERSION_base(4,20,0)@@ -51,9 +41,7 @@  -- | World of entities and their components. data World = World-  { archetypes :: !Archetypes,-    components :: !Components,-    entities :: !(Map EntityID ArchetypeID),+  { entities :: Entities,     nextEntityId :: !EntityID   }   deriving (Show, Generic, NFData)@@ -62,184 +50,50 @@ empty :: World empty =   World-    { archetypes = AS.empty,-      components = CS.empty,-      entities = mempty,+    { entities = E.empty,       nextEntityId = EntityID 0     }  spawn :: Bundle -> World -> (EntityID, World) spawn b w =-  let (eId, w') = spawnEmpty w-      (cIds, components', dynB) = unBundle b (components w')-   in case AS.lookupArchetypeId cIds (archetypes w') of-        Just aId -> fromMaybe (eId, w') $ do-          node <- AS.lookupNode aId (archetypes w')-          let arch' = runDynamicBundle dynB eId (nodeArchetype node)-          return-            ( eId,-              w'-                { archetypes = (archetypes w') {AS.nodes = Map.insert aId node {nodeArchetype = arch'} (AS.nodes $ archetypes w)},-                  components = components',-                  entities = Map.insert eId aId (entities w')-                }-            )-        Nothing ->-          let arch' = runDynamicBundle dynB eId A.empty-              (aId, arches) =-                AS.insertArchetype-                  cIds-                  ( Node-                      { nodeComponentIds = cIds,-                        nodeArchetype = arch',-                        nodeAdd = Map.empty,-                        nodeRemove = Map.empty-                      }-                  )-                  (archetypes w')-           in ( eId,-                w'-                  { archetypes = arches,-                    entities = Map.insert eId aId (entities w'),-                    components = components'-                  }-              )---- | Spawn an entity with a component.-spawnComponent :: forall a. (Component a, Typeable (StorageT a)) => a -> World -> (EntityID, World)-spawnComponent c w = case Map.lookup (typeOf (Proxy @a)) (componentIds (components w)) of-  Just cId -> spawnWithId cId c w-  Nothing ->-    let (cId, cs) = CS.insert @a (components w)-     in spawnWithId cId c w {components = cs}+  let e = nextEntityId w+   in (e, w {entities = E.spawn e b $ entities w, nextEntityId = EntityID $ unEntityId e + 1})  -- | Spawn an empty entity. spawnEmpty :: World -> (EntityID, World)-spawnEmpty w = let e = nextEntityId w in (e, w {nextEntityId = EntityID (unEntityId e + 1)})---- | Spawn an entity with a component and its `ComponentID`.-spawnWithId ::-  forall a.-  (Component a, Typeable (StorageT a)) =>-  ComponentID ->-  a ->-  World ->-  (EntityID, World)-spawnWithId cId c w =-  let !(e, w') = spawnEmpty w-   in case AS.lookupArchetypeId (Set.singleton cId) (archetypes w) of-        Just aId -> (e, spawnWithArchetypeId' e aId cId c w')-        Nothing ->-          let !(aId, arches) =-                AS.insertArchetype-                  (Set.singleton cId)-                  ( Node-                      { nodeComponentIds = Set.singleton cId,-                        nodeArchetype = A.insertComponent e cId c A.empty,-                        nodeAdd = Map.empty,-                        nodeRemove = Map.empty-                      }-                  )-                  (archetypes w')-           in (e, w' {archetypes = arches, entities = Map.insert e aId (entities w)})+spawnEmpty w = let e = nextEntityId w in (e, w {nextEntityId = EntityID $ unEntityId e + 1})  -- | Spawn an entity with a component and its `ComponentID` directly into an archetype. spawnWithArchetypeId ::   forall a.-  (Component a, Typeable (StorageT a)) =>-  a ->-  ComponentID ->-  ArchetypeID ->-  World ->-  (EntityID, World)-spawnWithArchetypeId c cId aId w =-  let !(e, w') = spawnEmpty w-   in (e, spawnWithArchetypeId' e aId cId c w')--spawnWithArchetypeId' ::-  forall a.-  (Component a, Typeable (StorageT a)) =>-  EntityID ->+  (Component a) =>   ArchetypeID ->   ComponentID ->   a ->   World ->-  World-spawnWithArchetypeId' e aId cId c w =-  let f n = n {nodeArchetype = A.insertComponent e cId c (nodeArchetype n)}-   in w-        { archetypes = (archetypes w) {AS.nodes = Map.adjust f aId (AS.nodes $ archetypes w)},-          entities = Map.insert e aId (entities w)-        }+  (EntityID, World)+spawnWithArchetypeId aId cId c w =+  let !(e, w') = spawnEmpty w+   in (e, w' {entities = E.spawnWithArchetypeId e aId cId c (entities w')})  -- | Insert a component into an entity.-insert :: forall a. (Component a, Typeable (StorageT a)) => EntityID -> a -> World -> World-insert e c w =-  let !(cId, components') = CS.insert @a (components w)-   in insertWithId e cId c w {components = components'}+insert :: forall a. (Component a) => EntityID -> a -> World -> World+insert e c w = w {entities = E.insert e c (entities w)}  -- | Insert a component into an entity with its `ComponentID`.-insertWithId :: (Component a, Typeable (StorageT a)) => EntityID -> ComponentID -> a -> World -> World-insertWithId e cId c w = case Map.lookup e (entities w) of-  Just aId ->-    let (maybeNextAId, arches) = AS.insert e aId cId c $ archetypes w-        es = case maybeNextAId of-          Just nextAId -> Map.insert e nextAId (entities w)-          Nothing -> entities w-     in w {archetypes = arches, entities = es}-  Nothing -> case AS.lookupArchetypeId (Set.singleton cId) (archetypes w) of-    Just aId -> spawnWithArchetypeId' e aId cId c w-    Nothing ->-      let (aId, arches) =-            AS.insertArchetype-              (Set.singleton cId)-              ( Node-                  { nodeComponentIds = Set.singleton cId,-                    nodeArchetype = A.insertComponent e cId c A.empty,-                    nodeAdd = Map.empty,-                    nodeRemove = Map.empty-                  }-              )-              (archetypes w)-       in w {archetypes = arches, entities = Map.insert e aId (entities w)}+insertWithId :: (Component a) => EntityID -> ComponentID -> a -> World -> World+insertWithId e cId c w = w {entities = E.insertWithId e cId c (entities w)}  lookup :: forall a. (Component a) => EntityID -> World -> Maybe a-lookup e w = do-  !cId <- CS.lookup @a (components w)-  !aId <- Map.lookup e (entities w)-  !node <- AS.lookupNode aId (archetypes w)-  A.lookupComponent e cId (nodeArchetype node)+lookup e w = E.lookup e $ entities w  -- | Insert a component into an entity.-remove :: forall a. (Component a, Typeable (StorageT a)) => EntityID -> World -> (Maybe a, World)-remove e w =-  let !(cId, components') = CS.insert @a (components w)-   in removeWithId @a e cId w {components = components'}+remove :: forall a. (Component a) => EntityID -> World -> (Maybe a, World)+remove e w = let (a, es) = E.remove e (entities w) in (a, w {entities = es}) -removeWithId :: forall a. (Component a, Typeable (StorageT a)) => EntityID -> ComponentID -> World -> (Maybe a, World)-removeWithId e cId w = case Map.lookup e (entities w) of-  Just aId ->-    let (res, as) = AS.remove @a e aId cId $ archetypes w-        (maybeA, es) = case res of-          Just (a, nextAId) -> (Just a, Map.insert e nextAId (entities w))-          Nothing -> (Nothing, entities w)-     in (maybeA, w {archetypes = as, entities = es})-  Nothing -> (Nothing, w)+removeWithId :: forall a. (Component a) => EntityID -> ComponentID -> World -> (Maybe a, World)+removeWithId e cId w = let (a, es) = E.removeWithId e cId (entities w) in (a, w {entities = es})  -- | Despawn an entity, returning its components. despawn :: EntityID -> World -> (Map ComponentID Dynamic, World)-despawn e w =-  let res = do-        !aId <- Map.lookup e (entities w)-        !node <- AS.lookupNode aId (archetypes w)-        return (aId, node)-   in case res of-        Just (aId, node) ->-          let !(dynAcc, arch') = A.remove e (nodeArchetype node)-           in ( dynAcc,-                w-                  { archetypes = (archetypes w) {AS.nodes = Map.insert aId node {nodeArchetype = arch'} (AS.nodes $ archetypes w)},-                    entities = Map.delete e (entities w)-                  }-              )-        Nothing -> (Map.empty, w)+despawn e w = let (a, es) = E.despawn e (entities w) in (a, w {entities = es})
src/Aztecs/ECS/World/Archetype.hs view
@@ -15,8 +15,6 @@ module Aztecs.ECS.World.Archetype   ( Archetype (..),     empty,-    all,-    allMaybe,     entities,     lookupComponent,     lookupStorage,@@ -25,76 +23,24 @@     removeStorages,     insertComponent,     insertAscList,-    withAscList,-    Bundle (..),-    bundle,-    runBundle,-    DynamicBundle (..),-    dynBundle,-    AnyStorage (..),-    anyStorage,   ) where -import Aztecs.ECS.Component (Component (..), ComponentID)-import Aztecs.ECS.Entity (EntityID (..))-import Aztecs.ECS.World.Components (Components)-import qualified Aztecs.ECS.World.Components as CS+import Aztecs.ECS.Component+import Aztecs.ECS.Entity import qualified Aztecs.ECS.World.Storage as S+import Aztecs.ECS.World.Storage.Dynamic import Control.DeepSeq-import Data.Bifunctor (Bifunctor (..))-import Data.Dynamic (Dynamic, Typeable, fromDynamic, toDyn)+import Data.Dynamic import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map-import Data.Maybe (fromMaybe)-import Data.Set (Set)-import qualified Data.Set as Set-import GHC.Generics (Generic)-import Prelude hiding (all, lookup)+import GHC.Generics  #if !MIN_VERSION_base(4,20,0) import Data.Foldable (foldl') #endif -data AnyStorage = AnyStorage-  { storageDyn :: !Dynamic,-    insertDyn :: !(Int -> Dynamic -> Dynamic -> Dynamic),-    removeDyn :: !(Int -> Dynamic -> (Maybe Dynamic, Dynamic)),-    removeAny :: !(Int -> Dynamic -> (Maybe AnyStorage, Dynamic)),-    entitiesDyn :: !(Dynamic -> [Int]),-    storageRnf :: !(Dynamic -> ())-  }--instance Show AnyStorage where-  show s = "AnyStorage " ++ show (storageDyn s)--instance NFData AnyStorage where-  rnf s = storageRnf s (storageDyn s)--anyStorage :: forall s a. (S.Storage s a) => s a -> AnyStorage-anyStorage s =-  AnyStorage-    { storageDyn = toDyn s,-      insertDyn = \i cDyn sDyn ->-        fromMaybe sDyn $ do-          !s' <- fromDynamic @(s a) sDyn-          !c <- fromDynamic cDyn-          return . toDyn $ S.insert i c s',-      removeDyn = \i dyn -> case fromDynamic @(s a) dyn of-        Just s' -> let !(a, b) = S.remove i s' in (fmap toDyn a, toDyn b)-        Nothing -> (Nothing, dyn),-      removeAny = \i dyn -> case fromDynamic @(s a) dyn of-        Just s' -> let !(a, b) = S.remove i s' in (fmap (anyStorage . S.singleton @s i) a, toDyn b)-        Nothing -> (Nothing, dyn),-      entitiesDyn = \dyn -> case fromDynamic @(s a) dyn of-        Just s' -> map fst $ S.all s'-        Nothing -> [],-      storageRnf = \dyn -> case fromDynamic @(s a) dyn of-        Just s' -> rnf s'-        Nothing -> ()-    }--newtype Archetype = Archetype {storages :: Map ComponentID AnyStorage}+newtype Archetype = Archetype {storages :: Map ComponentID DynamicStorage}   deriving (Show, Generic, NFData)  empty :: Archetype@@ -110,109 +56,47 @@   let !storage = case lookupStorage cId arch of         Just s -> S.insert (unEntityId e) c s         Nothing -> S.singleton @(StorageT a) @a (unEntityId e) c-   in arch {storages = Map.insert cId (anyStorage storage) (storages arch)}--all :: (Component a) => ComponentID -> Archetype -> [(EntityID, a)]-all cId arch = fromMaybe [] $ do-  s <- lookupStorage cId arch-  return . map (first EntityID) $ S.all s+   in arch {storages = Map.insert cId (dynStorage storage) (storages arch)}  member :: ComponentID -> Archetype -> Bool member cId arch = Map.member cId (storages arch) -allMaybe :: (Component a) => ComponentID -> Archetype -> [(EntityID, Maybe a)]-allMaybe cId arch = case lookupStorage cId arch of-  Just s -> map (\(i, a) -> (EntityID i, Just a)) $ S.all s-  Nothing -> case Map.toList $ storages arch of-    [] -> []-    (_, s) : _ -> map (\i -> (EntityID i, Nothing)) $ entitiesDyn s (storageDyn s)- entities :: Archetype -> [EntityID] entities arch = case Map.toList $ storages arch of   [] -> []-  (_, s) : _ -> map (\i -> (EntityID i)) $ entitiesDyn s (storageDyn s)+  (_, s) : _ -> map (\i -> (EntityID i)) $ entitiesDyn s  lookupComponent :: forall a. (Component a) => EntityID -> ComponentID -> Archetype -> Maybe a lookupComponent e cId w = lookupStorage cId w >>= S.lookup (unEntityId e) +-- | Insert a list of components into the archetype, sorted in ascending order by their `EntityID`. insertAscList :: forall a. (Component a) => ComponentID -> [(EntityID, a)] -> Archetype -> Archetype insertAscList cId as arch =-  let !storages' =-        Map.insert-          cId-          (anyStorage $ S.fromAscList @(StorageT a) (map (first unEntityId) as))-          (storages arch)-   in arch {storages = storages'}--withAscList :: forall a. (Component a) => ComponentID -> [a] -> Archetype -> Archetype-withAscList cId as arch =-  let !storages' =-        Map.adjust-          ( \s ->-              (anyStorage $ S.fromAscList @(StorageT a) (zip (entitiesDyn s (storageDyn s)) as))-          )-          cId-          (storages arch)-   in arch {storages = storages'}+  let !storage = dynStorage $ S.fromAscList @(StorageT a) (map (\(e, a) -> (unEntityId e, a)) as)+   in arch {storages = Map.insert cId storage (storages arch)}  remove :: EntityID -> Archetype -> (Map ComponentID Dynamic, Archetype) remove e arch =   foldl'     ( \(dynAcc, archAcc) (cId, s) ->-        let !(dynA, dynS) = removeDyn s (unEntityId e) (storageDyn s)+        let !(dynA, dynS) = removeDyn (unEntityId e) s             !dynAcc' = case dynA of               Just d -> Map.insert cId d dynAcc               Nothing -> dynAcc-         in ( dynAcc',-              archAcc {storages = Map.insert cId (s {storageDyn = dynS}) (storages archAcc)}-            )+         in (dynAcc', archAcc {storages = Map.insert cId dynS $ storages archAcc})     )     (Map.empty, arch)     (Map.toList $ storages arch) -removeStorages :: EntityID -> Archetype -> (Map ComponentID AnyStorage, Archetype)+removeStorages :: EntityID -> Archetype -> (Map ComponentID DynamicStorage, Archetype) removeStorages e arch =   foldl'     ( \(dynAcc, archAcc) (cId, s) ->-        let (dynA, dynS) = removeAny s (unEntityId e) (storageDyn s)+        let (dynA, dynS) = removeAny (unEntityId e) s             dynAcc' = case dynA of               Just d -> Map.insert cId d dynAcc               Nothing -> dynAcc-         in ( dynAcc',-              archAcc {storages = Map.insert cId (s {storageDyn = dynS}) (storages archAcc)}-            )+         in (dynAcc', archAcc {storages = Map.insert cId dynS $ storages archAcc})     )     (Map.empty, arch)     (Map.toList $ storages arch)--newtype Bundle = Bundle {unBundle :: Components -> (Set ComponentID, Components, DynamicBundle)}--instance Monoid Bundle where-  mempty = Bundle $ \cs -> (Set.empty, cs, mempty)--instance Semigroup Bundle where-  Bundle b1 <> Bundle b2 = Bundle $ \cs ->-    let (cIds1, cs', d1) = b1 cs-        (cIds2, cs'', d2) = b2 cs'-     in (cIds1 <> cIds2, cs'', d1 <> d2)--bundle :: forall a. (Component a, Typeable (StorageT a)) => a -> Bundle-bundle a = Bundle $ \cs ->-  let (cId, cs') = CS.insert @a cs in (Set.singleton cId, cs', dynBundle cId a)--newtype DynamicBundle = DynamicBundle {runDynamicBundle :: EntityID -> Archetype -> Archetype}--instance Semigroup DynamicBundle where-  DynamicBundle d1 <> DynamicBundle d2 = DynamicBundle $ \eId arch -> d2 eId (d1 eId arch)--instance Monoid DynamicBundle where-  mempty = DynamicBundle $ \_ arch -> arch--dynBundle :: (Component a, Typeable (StorageT a)) => ComponentID -> a -> DynamicBundle-dynBundle cId a = DynamicBundle $ \eId arch -> insertComponent eId cId a arch--runBundle :: Bundle -> Components -> EntityID -> Archetype -> (Components, Archetype)-runBundle b cs eId arch =-  let !(_, cs', d) = unBundle b cs-      !arch' = runDynamicBundle d eId arch-   in (cs', arch')
src/Aztecs/ECS/World/Archetypes.hs view
@@ -20,8 +20,8 @@     insertArchetype,     lookupArchetypeId,     findArchetypeIds,-    lookupNode,     lookup,+    find,     map,     adjustArchetype,     insert,@@ -32,14 +32,13 @@ import Aztecs.ECS.Component (Component (..), ComponentID) import Aztecs.ECS.Entity (EntityID (..)) import Aztecs.ECS.World.Archetype-  ( AnyStorage (..),-    Archetype (..),+  ( Archetype (..),     insertComponent,     removeStorages,   ) import qualified Aztecs.ECS.World.Archetype as A+import Aztecs.ECS.World.Storage.Dynamic (insertDyn, removeDyn) import Control.DeepSeq (NFData (..))-import Data.Data (Typeable) import Data.Dynamic (fromDynamic) import Data.Map.Strict (Map) import qualified Data.Map.Strict as Map@@ -116,73 +115,53 @@   [] -> Set.empty  -- | Lookup `Archetype`s containing a set of `ComponentID`s.-lookup :: Set ComponentID -> Archetypes -> Map ArchetypeID Node-lookup cIds arches =-  Map.fromSet-    (\aId -> nodes arches Map.! aId)-    (findArchetypeIds cIds arches)+find :: Set ComponentID -> Archetypes -> Map ArchetypeID Node+find cIds arches = Map.fromSet (\aId -> nodes arches Map.! aId) (findArchetypeIds cIds arches)  -- | Map over `Archetype`s containing a set of `ComponentID`s. map :: Set ComponentID -> (Archetype -> (a, Archetype)) -> Archetypes -> ([a], Archetypes) map cIds f arches =-  foldl'-    ( \(acc, archAcc) aId ->+  let go (acc, archAcc) aId =         let !node = nodes archAcc Map.! aId             !(a, arch') = f (nodeArchetype node)-         in (a : acc, archAcc {nodes = Map.insert aId (node {nodeArchetype = arch'}) (nodes archAcc)})-    )-    ([], arches)-    (findArchetypeIds cIds arches)+            nodes' = Map.insert aId (node {nodeArchetype = arch'}) (nodes archAcc)+         in (a : acc, archAcc {nodes = nodes'})+   in foldl' go ([], arches) $ findArchetypeIds cIds arches  lookupArchetypeId :: Set ComponentID -> Archetypes -> Maybe ArchetypeID lookupArchetypeId cIds arches = Map.lookup cIds (archetypeIds arches) -lookupNode :: ArchetypeID -> Archetypes -> Maybe Node-lookupNode aId arches = Map.lookup aId (nodes arches)+lookup :: ArchetypeID -> Archetypes -> Maybe Node+lookup aId arches = Map.lookup aId (nodes arches)  -- | Insert a component into an entity with its `ComponentID`. insert ::-  (Component a, Typeable (StorageT a)) =>+  (Component a) =>   EntityID ->   ArchetypeID ->   ComponentID ->   a ->   Archetypes ->   (Maybe ArchetypeID, Archetypes)-insert e aId cId c arches = case lookupNode aId arches of+insert e aId cId c arches = case lookup aId arches of   Just node ->     if Set.member cId (nodeComponentIds node)-      then (Nothing, arches {nodes = Map.adjust (\n -> n {nodeArchetype = insertComponent e cId c (nodeArchetype n)}) aId (nodes arches)})+      then+        let go n = n {nodeArchetype = insertComponent e cId c (nodeArchetype n)}+         in (Nothing, arches {nodes = Map.adjust go aId (nodes arches)})       else case lookupArchetypeId (Set.insert cId (nodeComponentIds node)) arches of         Just nextAId ->           let !(cs, arch') = A.remove e (nodeArchetype node)-              !arches' = arches {nodes = Map.insert aId node {nodeArchetype = arch'} (nodes arches)}+              node' = node {nodeArchetype = arch'}+              !arches' = arches {nodes = Map.insert aId node' (nodes arches)}               f archAcc (itemCId, dyn) =-                archAcc-                  { storages =-                      Map.adjust-                        (\s -> s {storageDyn = insertDyn s (unEntityId e) dyn (storageDyn s)})-                        itemCId-                        (storages archAcc)-                  }-           in ( Just nextAId,-                arches'-                  { nodes =-                      Map.adjust-                        ( \nextNode ->-                            nextNode-                              { nodeArchetype =-                                  insertComponent e cId c $-                                    foldl'-                                      f-                                      (nodeArchetype nextNode)-                                      (Map.toList cs)-                              }-                        )-                        nextAId-                        (nodes $ arches')-                  }-              )+                let go s = insertDyn (unEntityId e) dyn s+                    storages' = Map.adjust go itemCId (storages archAcc)+                 in archAcc {storages = storages'}+              adjustNode nextNode =+                let nextArch = foldl' f (nodeArchetype nextNode) (Map.toList cs)+                 in nextNode {nodeArchetype = insertComponent e cId c nextArch}+           in (Just nextAId, arches' {nodes = Map.adjust adjustNode nextAId (nodes $ arches')})         Nothing ->           let !(s, arch') = removeStorages e (nodeArchetype node)               !n =@@ -192,58 +171,34 @@                     nodeAdd = Map.empty,                     nodeRemove = Map.singleton cId aId                   }-              !(nextAId, arches') = insertArchetype (Set.insert cId (nodeComponentIds node)) n arches-           in ( Just nextAId,-                arches'-                  { nodes =-                      Map.insert-                        aId-                        node-                          { nodeArchetype = arch',-                            nodeAdd = Map.insert cId nextAId (nodeAdd node)-                          }-                        (nodes arches')-                  }-              )+              cIds = Set.insert cId (nodeComponentIds node)+              !(nextAId, arches') = insertArchetype cIds n arches+           in let node' =+                    node {nodeArchetype = arch', nodeAdd = Map.insert cId nextAId (nodeAdd node)}+                  nodes' = Map.insert aId node' (nodes arches')+               in (Just nextAId, arches' {nodes = nodes'})   Nothing -> (Nothing, arches)  remove ::-  (Component a, Typeable (StorageT a)) =>+  (Component a) =>   EntityID ->   ArchetypeID ->   ComponentID ->   Archetypes ->   (Maybe (a, ArchetypeID), Archetypes)-remove e aId cId arches = case lookupNode aId arches of+remove e aId cId arches = case lookup aId arches of   Just node -> case lookupArchetypeId (Set.delete cId (nodeComponentIds node)) arches of     Just nextAId ->       let !(cs, arch') = A.remove e (nodeArchetype node)           !arches' = arches {nodes = Map.insert aId node {nodeArchetype = arch'} (nodes arches)}-          f archAcc (itemCId, dyn) =-            archAcc-              { storages =-                  Map.adjust-                    (\s -> s {storageDyn = insertDyn s (unEntityId e) dyn (storageDyn s)})-                    itemCId-                    (storages archAcc)-              }           (a, cs') = Map.updateLookupWithKey (\_ _ -> Nothing) cId cs+          go' archAcc (itemCId, dyn) =+            let adjustStorage s = insertDyn (unEntityId e) dyn s+             in archAcc {storages = Map.adjust adjustStorage itemCId (storages archAcc)}+          go nextNode =+            nextNode {nodeArchetype = foldl' go' (nodeArchetype nextNode) (Map.toList cs')}        in ( (,nextAId) <$> (a >>= fromDynamic),-            arches'-              { nodes =-                  Map.adjust-                    ( \nextNode ->-                        nextNode-                          { nodeArchetype =-                              foldl'-                                f-                                (nodeArchetype nextNode)-                                (Map.toList cs')-                          }-                    )-                    nextAId-                    (nodes $ arches')-              }+            arches' {nodes = Map.adjust go nextAId (nodes $ arches')}           )     Nothing ->       let !(cs, arch') = removeStorages e (nodeArchetype node)@@ -256,16 +211,8 @@                 nodeRemove = Map.singleton cId aId               }           !(nextAId, arches') = insertArchetype (Set.insert cId (nodeComponentIds node)) n arches-       in ( (,nextAId) <$> (a >>= (\a' -> (fst $ A.removeDyn a' (unEntityId e) (A.storageDyn a')) >>= fromDynamic)),-            arches'-              { nodes =-                  Map.insert-                    aId-                    node-                      { nodeArchetype = arch',-                        nodeAdd = Map.insert cId nextAId (nodeAdd node)-                      }-                    (nodes arches')-              }+          node' = node {nodeArchetype = arch', nodeAdd = Map.insert cId nextAId (nodeAdd node)}+       in ( (,nextAId) <$> (a >>= (\a' -> (fst $ removeDyn (unEntityId e) a') >>= fromDynamic)),+            arches' {nodes = Map.insert aId node' (nodes arches')}           )   Nothing -> (Nothing, arches)
+ src/Aztecs/ECS/World/Bundle.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++module Aztecs.ECS.World.Bundle+  ( Bundle (..),+    MonoidBundle (..),+    MonoidDynamicBundle (..),+    runBundle,+  )+where++import Aztecs.ECS.Component (Component (..), ComponentID)+import Aztecs.ECS.Entity (EntityID)+import Aztecs.ECS.World.Archetype (Archetype)+import Aztecs.ECS.World.Bundle.Class+import Aztecs.ECS.World.Bundle.Dynamic+import Aztecs.ECS.World.Components (Components)+import qualified Aztecs.ECS.World.Components as CS+import Data.Set (Set)+import qualified Data.Set as Set++-- | Bundle of components.+newtype Bundle = Bundle {unBundle :: Components -> (Set ComponentID, Components, DynamicBundle)}++instance Monoid Bundle where+  mempty = Bundle $ \cs -> (Set.empty, cs, mempty)++instance Semigroup Bundle where+  Bundle b1 <> Bundle b2 = Bundle $ \cs ->+    let (cIds1, cs', d1) = b1 cs+        (cIds2, cs'', d2) = b2 cs'+     in (cIds1 <> cIds2, cs'', d1 <> d2)++instance MonoidBundle Bundle where+  bundle :: forall a. (Component a) => a -> Bundle+  bundle a = Bundle $ \cs ->+    let (cId, cs') = CS.insert @a cs in (Set.singleton cId, cs', dynBundle cId a)++instance MonoidDynamicBundle Bundle where+  dynBundle cId c = Bundle $ \cs -> (Set.singleton cId, cs, dynBundle cId c)++-- | Insert a bundle of components into an archetype.+runBundle :: Bundle -> Components -> EntityID -> Archetype -> (Components, Archetype)+runBundle b cs eId arch =+  let !(_, cs', d) = unBundle b cs+      !arch' = runDynamicBundle d eId arch+   in (cs', arch')
+ src/Aztecs/ECS/World/Bundle/Class.hs view
@@ -0,0 +1,11 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}++module Aztecs.ECS.World.Bundle.Class (MonoidBundle (..)) where++import Aztecs.ECS.Component (Component (..))++-- | Monoid bundle of components.+class (Monoid a) => MonoidBundle a where+  -- | Add a component to the bundle.+  bundle :: forall c. (Component c) => c -> a
+ src/Aztecs/ECS/World/Bundle/Dynamic.hs view
@@ -0,0 +1,21 @@+module Aztecs.ECS.World.Bundle.Dynamic+  ( DynamicBundle (..),+    MonoidDynamicBundle (..),+  )+where++import Aztecs.ECS.Entity (EntityID)+import Aztecs.ECS.World.Archetype (Archetype, insertComponent)+import Aztecs.ECS.World.Bundle.Dynamic.Class (MonoidDynamicBundle (..))++-- | Dynamic bundle of components.+newtype DynamicBundle = DynamicBundle {runDynamicBundle :: EntityID -> Archetype -> Archetype}++instance Semigroup DynamicBundle where+  DynamicBundle d1 <> DynamicBundle d2 = DynamicBundle $ \eId arch -> d2 eId (d1 eId arch)++instance Monoid DynamicBundle where+  mempty = DynamicBundle $ \_ arch -> arch++instance MonoidDynamicBundle DynamicBundle where+  dynBundle cId a = DynamicBundle $ \eId arch -> insertComponent eId cId a arch
+ src/Aztecs/ECS/World/Bundle/Dynamic/Class.hs view
@@ -0,0 +1,9 @@+module Aztecs.ECS.World.Bundle.Dynamic.Class (MonoidDynamicBundle (..)) where++import Aztecs.ECS.Component (Component (..))+import Aztecs.ECS.World.Components (ComponentID)++-- | Monoid bundle of dynamic components.+class MonoidDynamicBundle a where+  -- | Add a component to the bundle by its `ComponentID`.+  dynBundle :: (Component c) => ComponentID -> c -> a
+ src/Aztecs/ECS/World/Entities.hs view
@@ -0,0 +1,215 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++module Aztecs.ECS.World.Entities+  ( Entities (..),+    empty,+    spawn,+    spawnComponent,+    spawnWithId,+    spawnWithArchetypeId,+    insert,+    insertWithId,+    lookup,+    remove,+    removeWithId,+    despawn,+  )+where++import Aztecs.ECS.Component+import Aztecs.ECS.Entity+import qualified Aztecs.ECS.World.Archetype as A+import Aztecs.ECS.World.Archetypes (ArchetypeID, Archetypes, Node (..))+import qualified Aztecs.ECS.World.Archetypes as AS+import Aztecs.ECS.World.Bundle+import Aztecs.ECS.World.Bundle.Dynamic+import Aztecs.ECS.World.Components (Components (..))+import qualified Aztecs.ECS.World.Components as CS+import Control.DeepSeq+import Data.Dynamic+import Data.Map (Map)+import qualified Data.Map as Map+import Data.Maybe+import qualified Data.Set as Set+import Data.Typeable+import GHC.Generics+import Prelude hiding (lookup)++#if !MIN_VERSION_base(4,20,0)+import Data.Foldable (foldl')+#endif++-- | World of entities and their components.+data Entities = Entities+  { archetypes :: !Archetypes,+    components :: !Components,+    entities :: !(Map EntityID ArchetypeID)+  }+  deriving (Show, Generic, NFData)++-- | Empty `World`.+empty :: Entities+empty =+  Entities+    { archetypes = AS.empty,+      components = CS.empty,+      entities = mempty+    }++spawn :: EntityID -> Bundle -> Entities -> Entities+spawn eId b w =+  let (cIds, components', dynB) = unBundle b (components w)+   in case AS.lookupArchetypeId cIds (archetypes w) of+        Just aId -> fromMaybe w $ do+          node <- AS.lookup aId $ archetypes w+          let arch' = runDynamicBundle dynB eId (nodeArchetype node)+          return+            w+              { archetypes = (archetypes w) {AS.nodes = Map.insert aId node {nodeArchetype = arch'} (AS.nodes $ archetypes w)},+                components = components',+                entities = Map.insert eId aId (entities w)+              }+        Nothing ->+          let arch' = runDynamicBundle dynB eId A.empty+              (aId, arches) =+                AS.insertArchetype+                  cIds+                  ( Node+                      { nodeComponentIds = cIds,+                        nodeArchetype = arch',+                        nodeAdd = Map.empty,+                        nodeRemove = Map.empty+                      }+                  )+                  (archetypes w)+           in w+                { archetypes = arches,+                  entities = Map.insert eId aId (entities w),+                  components = components'+                }++-- | Spawn an entity with a component.+spawnComponent :: forall a. (Component a) => EntityID -> a -> Entities -> Entities+spawnComponent e c w = case Map.lookup (typeOf (Proxy @a)) (componentIds (components w)) of+  Just cId -> spawnWithId e cId c w+  Nothing ->+    let (cId, cs) = CS.insert @a (components w) in spawnWithId e cId c w {components = cs}++-- | Spawn an entity with a component and its `ComponentID`.+spawnWithId ::+  forall a.+  (Component a) =>+  EntityID ->+  ComponentID ->+  a ->+  Entities ->+  Entities+spawnWithId e cId c w = case AS.lookupArchetypeId (Set.singleton cId) (archetypes w) of+  Just aId -> spawnWithArchetypeId e aId cId c w+  Nothing ->+    let !(aId, arches) =+          AS.insertArchetype+            (Set.singleton cId)+            ( Node+                { nodeComponentIds = Set.singleton cId,+                  nodeArchetype = A.insertComponent e cId c A.empty,+                  nodeAdd = Map.empty,+                  nodeRemove = Map.empty+                }+            )+            (archetypes w)+     in w {archetypes = arches, entities = Map.insert e aId (entities w)}++spawnWithArchetypeId ::+  forall a.+  (Component a) =>+  EntityID ->+  ArchetypeID ->+  ComponentID ->+  a ->+  Entities ->+  Entities+spawnWithArchetypeId e aId cId c w =+  let f n = n {nodeArchetype = A.insertComponent e cId c (nodeArchetype n)}+   in w+        { archetypes = (archetypes w) {AS.nodes = Map.adjust f aId (AS.nodes $ archetypes w)},+          entities = Map.insert e aId (entities w)+        }++-- | Insert a component into an entity.+insert :: forall a. (Component a) => EntityID -> a -> Entities -> Entities+insert e c w =+  let !(cId, components') = CS.insert @a (components w)+   in insertWithId e cId c w {components = components'}++-- | Insert a component into an entity with its `ComponentID`.+insertWithId :: (Component a) => EntityID -> ComponentID -> a -> Entities -> Entities+insertWithId e cId c w = case Map.lookup e (entities w) of+  Just aId ->+    let (maybeNextAId, arches) = AS.insert e aId cId c $ archetypes w+        es = case maybeNextAId of+          Just nextAId -> Map.insert e nextAId (entities w)+          Nothing -> entities w+     in w {archetypes = arches, entities = es}+  Nothing -> case AS.lookupArchetypeId (Set.singleton cId) (archetypes w) of+    Just aId -> spawnWithArchetypeId e aId cId c w+    Nothing ->+      let (aId, arches) =+            AS.insertArchetype+              (Set.singleton cId)+              ( Node+                  { nodeComponentIds = Set.singleton cId,+                    nodeArchetype = A.insertComponent e cId c A.empty,+                    nodeAdd = Map.empty,+                    nodeRemove = Map.empty+                  }+              )+              (archetypes w)+       in w {archetypes = arches, entities = Map.insert e aId (entities w)}++lookup :: forall a. (Component a) => EntityID -> Entities -> Maybe a+lookup e w = do+  !cId <- CS.lookup @a $ components w+  !aId <- Map.lookup e $ entities w+  !node <- AS.lookup aId $ archetypes w+  A.lookupComponent e cId $ nodeArchetype node++-- | Insert a component into an entity.+remove :: forall a. (Component a) => EntityID -> Entities -> (Maybe a, Entities)+remove e w =+  let !(cId, components') = CS.insert @a (components w)+   in removeWithId @a e cId w {components = components'}++removeWithId :: forall a. (Component a) => EntityID -> ComponentID -> Entities -> (Maybe a, Entities)+removeWithId e cId w = case Map.lookup e (entities w) of+  Just aId ->+    let (res, as) = AS.remove @a e aId cId $ archetypes w+        (maybeA, es) = case res of+          Just (a, nextAId) -> (Just a, Map.insert e nextAId (entities w))+          Nothing -> (Nothing, entities w)+     in (maybeA, w {archetypes = as, entities = es})+  Nothing -> (Nothing, w)++-- | Despawn an entity, returning its components.+despawn :: EntityID -> Entities -> (Map ComponentID Dynamic, Entities)+despawn e w =+  let res = do+        !aId <- Map.lookup e $ entities w+        !node <- AS.lookup aId $ archetypes w+        return (aId, node)+   in case res of+        Just (aId, node) ->+          let !(dynAcc, arch') = A.remove e (nodeArchetype node)+           in ( dynAcc,+                w+                  { archetypes = (archetypes w) {AS.nodes = Map.insert aId node {nodeArchetype = arch'} (AS.nodes $ archetypes w)},+                    entities = Map.delete e (entities w)+                  }+              )+        Nothing -> (Map.empty, w)
src/Aztecs/ECS/World/Storage.hs view
@@ -14,8 +14,8 @@   -- | Storage with a single component.   singleton :: Int -> a -> s a -  -- | All components in the storage.-  all :: s a -> [(Int, a)]+  -- | List of all components in the storage.+  toList :: s a -> [(Int, a)]    -- | Insert a component into the storage.   insert :: Int -> a -> s a -> s a@@ -31,7 +31,7 @@  instance (Typeable a, NFData a) => Storage IntMap a where   singleton = IntMap.singleton-  all = IntMap.toList+  toList = IntMap.toList   insert = IntMap.insert   lookup = IntMap.lookup   fromAscList = IntMap.fromAscList
+ src/Aztecs/ECS/World/Storage/Dynamic.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE TypeFamilies #-}++module Aztecs.ECS.World.Storage.Dynamic+  ( DynamicStorage (..),+    dynStorage,+    insertDyn,+    removeDyn,+    removeAny,+    entitiesDyn,+  )+where++import qualified Aztecs.ECS.World.Storage as S+import Control.DeepSeq+import Data.Dynamic+import Data.Maybe++data DynamicStorage = DynamicStorage+  { storageDyn :: !Dynamic,+    insertDyn' :: !(Int -> Dynamic -> Dynamic -> Dynamic),+    removeDyn' :: !(Int -> Dynamic -> (Maybe Dynamic, Dynamic)),+    removeAny' :: !(Int -> Dynamic -> (Maybe DynamicStorage, Dynamic)),+    entitiesDyn' :: !(Dynamic -> [Int]),+    storageRnf :: !(Dynamic -> ())+  }++instance Show DynamicStorage where+  show s = "DynamicStorage " ++ show (storageDyn s)++instance NFData DynamicStorage where+  rnf s = storageRnf s (storageDyn s)++dynStorage :: forall s a. (S.Storage s a) => s a -> DynamicStorage+dynStorage s =+  DynamicStorage+    { storageDyn = toDyn s,+      insertDyn' = \i cDyn sDyn ->+        fromMaybe sDyn $ do+          !s' <- fromDynamic @(s a) sDyn+          !c <- fromDynamic cDyn+          return . toDyn $ S.insert i c s',+      removeDyn' = \i dyn -> case fromDynamic @(s a) dyn of+        Just s' -> let !(a, b) = S.remove i s' in (fmap toDyn a, toDyn b)+        Nothing -> (Nothing, dyn),+      removeAny' = \i dyn -> case fromDynamic @(s a) dyn of+        Just s' -> let !(a, b) = S.remove i s' in (fmap (dynStorage . S.singleton @s i) a, toDyn b)+        Nothing -> (Nothing, dyn),+      entitiesDyn' = \dyn -> case fromDynamic @(s a) dyn of+        Just s' -> map fst $ S.toList s'+        Nothing -> [],+      storageRnf = \dyn -> maybe () rnf (fromDynamic @(s a) dyn)+    }++insertDyn :: Int -> Dynamic -> DynamicStorage -> DynamicStorage+insertDyn i c s = s {storageDyn = insertDyn' s i c (storageDyn s)}++removeDyn :: Int -> DynamicStorage -> (Maybe Dynamic, DynamicStorage)+removeDyn i s = let (a, s') = removeDyn' s i (storageDyn s) in (a, s {storageDyn = s'})++removeAny :: Int -> DynamicStorage -> (Maybe DynamicStorage, DynamicStorage)+removeAny i s = let (a, s') = removeAny' s i (storageDyn s) in (a, s {storageDyn = s'})++entitiesDyn :: DynamicStorage -> [Int]+entitiesDyn s = entitiesDyn' s (storageDyn s)
src/Aztecs/Hierarchy.hs view
@@ -1,5 +1,7 @@ {-# LANGUAGE Arrows #-}+{-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TypeApplications #-} @@ -8,6 +10,10 @@     Children (..),     update,     Hierarchy (..),+    toList,+    foldWithKey,+    mapWithKey,+    mapWithAccum,     hierarchy,     hierarchies,     ParentState (..),@@ -15,18 +21,16 @@   ) where -import Aztecs+import Aztecs.ECS import qualified Aztecs.ECS.Access as A-import Aztecs.ECS.Query (ArrowQuery) import qualified Aztecs.ECS.Query as Q-import Aztecs.ECS.Query.Reader (ArrowQueryReader)-import Aztecs.ECS.System (ArrowReaderSystem, ArrowSystem) import qualified Aztecs.ECS.System as S import Control.Arrow (returnA) import Control.DeepSeq import Control.Monad (when) import Data.Map (Map) import qualified Data.Map as Map+import Data.Maybe (mapMaybe) import Data.Set (Set) import qualified Data.Set as Set import GHC.Generics (Generic)@@ -52,7 +56,11 @@ instance Component ChildState  update ::-  (ArrowQueryReader qr, ArrowQuery q, ArrowReaderSystem qr arr, ArrowSystem q arr) =>+  ( ArrowQueryReader qr,+    ArrowDynamicQueryReader qr,+    ArrowReaderSystem qr arr,+    ArrowQueueSystem b m arr+  ) =>   arr () () update = proc () -> do   parents <-@@ -106,8 +114,9 @@                 when (children /= childState) $ do                   A.insert entity $ ChildState children                   let added = Set.difference children childState-                  -- TODO removed = Set.difference childState children+                      removed = Set.difference childState children                   mapM_ (\e -> A.insert e . Parent $ entity) added+                  mapM_ (A.remove @_ @_ @Parent) removed               Nothing -> do                 A.insert entity $ ChildState children                 mapM_ (\e -> A.insert e . Parent $ entity) children@@ -122,12 +131,32 @@     nodeEntity :: a,     nodeChildren :: [Hierarchy a]   }+  deriving (Functor) +instance Foldable Hierarchy where+  foldMap f n = f (nodeEntity n) <> foldMap (foldMap f) (nodeChildren n)++instance Traversable Hierarchy where+  traverse f n = Node (nodeEntityId n) <$> f (nodeEntity n) <*> traverse (traverse f) (nodeChildren n)++toList :: Hierarchy a -> [(EntityID, a)]+toList n = (nodeEntityId n, nodeEntity n) : concatMap toList (nodeChildren n)++foldWithKey :: (EntityID -> a -> b -> b) -> Hierarchy a -> b -> b+foldWithKey f n b = f (nodeEntityId n) (nodeEntity n) (foldr (foldWithKey f) b (nodeChildren n))++mapWithKey :: (EntityID -> a -> b) -> Hierarchy a -> Hierarchy b+mapWithKey f n = Node (nodeEntityId n) (f (nodeEntityId n) (nodeEntity n)) (map (mapWithKey f) (nodeChildren n))++mapWithAccum :: (EntityID -> a -> b -> (c, b)) -> b -> Hierarchy a -> Hierarchy c+mapWithAccum f b n = case f (nodeEntityId n) (nodeEntity n) b of+  (c, b') -> Node (nodeEntityId n) c (map (mapWithAccum f b') (nodeChildren n))+ hierarchy ::-  (ArrowQueryReader q, ArrowReaderSystem q arr) =>+  (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr) =>   EntityID ->   q i a ->-  arr i [Hierarchy a]+  arr i (Maybe (Hierarchy a)) hierarchy e q = proc i -> do   children <-     S.all@@ -144,9 +173,9 @@  -- | Build all hierarchies of parents to children with the given query. hierarchies ::-  (ArrowQueryReader q, ArrowReaderSystem q arr) =>+  (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr) =>   q i a ->-  arr i [[Hierarchy a]]+  arr i [Hierarchy a] hierarchies q = proc i -> do   children <-     S.all@@ -160,16 +189,16 @@         i   let childMap = Map.fromList children   roots <- S.filter Q.entity $ with @Children <> without @Parent -< ()-  returnA -< map (`hierarchy'` childMap) roots+  returnA -< mapMaybe (`hierarchy'` childMap) roots -hierarchy' :: EntityID -> Map EntityID (Set EntityID, a) -> [Hierarchy a]+hierarchy' :: EntityID -> Map EntityID (Set EntityID, a) -> Maybe (Hierarchy a) hierarchy' e childMap = case Map.lookup e childMap of   Just (cs, a) ->-    let bs = concatMap (`hierarchy'` childMap) (Set.toList cs)-     in [ Node+    let bs = mapMaybe (`hierarchy'` childMap) (Set.toList cs)+     in Just+          Node             { nodeEntityId = e,               nodeEntity = a,               nodeChildren = bs             }-        ]-  Nothing -> []+  Nothing -> Nothing
src/Aztecs/Time.hs view
@@ -8,10 +8,8 @@ import Data.Word (Word32) import GHC.Generics +-- | Time component. newtype Time = Time {elapsedMS :: Word32}-  deriving (Eq, Ord, Num, Show, Generic)+  deriving (Eq, Ord, Num, Show, Generic, NFData)  instance Component Time--instance NFData Time where-  rnf = rwhnf
src/Aztecs/Transform.hs view
@@ -1,26 +1,103 @@+{-# LANGUAGE AllowAmbiguousTypes #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-} -module Aztecs.Transform where+module Aztecs.Transform+  ( -- * Transform+    Transform (..), +    -- ** 2D+    Transform2D,+    transform2d,++    -- * Size+    Size (..),++    -- ** 2D+    Size2D,+    size2D,++    -- * Systems+    update,+    update2d,+    propagate,+    propagate2d,+  )+where+ import Aztecs.ECS+import qualified Aztecs.ECS.Access as A+import qualified Aztecs.ECS.Query as Q+import qualified Aztecs.ECS.System as S+import Aztecs.Hierarchy (Hierarchy, hierarchies, mapWithAccum, toList)+import Control.Arrow (Arrow (..), (>>>)) import Control.DeepSeq import GHC.Generics (Generic) import Linear (V2 (..)) -data Transform = Transform-  { transformPosition :: !(V2 Int),-    transformRotation :: !Float,-    transformScale :: !(V2 Int)+-- | Transform component.+data Transform v r = Transform+  { transformTranslation :: !v,+    transformRotation :: !r,+    transformScale :: !v   }   deriving (Eq, Show, Generic, NFData) -transform :: Transform-transform = Transform (V2 0 0) 0 (V2 1 1)+instance (Num v, Num r) => Semigroup (Transform v r) where+  Transform t1 r1 s1 <> Transform t2 r2 s2 = Transform (t1 + t2) (r1 + r2) (s1 + s2) -instance Component Transform+instance (Num v, Num r) => Monoid (Transform v r) where+  mempty = Transform 0 0 0 -newtype Size = Size {unSize :: V2 Int}+-- | 2D transform component.+type Transform2D = Transform (V2 Int) Int++-- | Empty transform.+transform2d :: Transform2D+transform2d = Transform (V2 0 0) 0 (V2 1 1)++instance Component (Transform (V2 Int) Int)++-- | Size component.+newtype Size v = Size {unSize :: v}   deriving (Generic, NFData) -instance Component Size+type Size2D = Size (V2 Int)++size2D :: Size (V2 Integer)+size2D = Size (V2 0 0)++instance Component (Size (V2 Int))++propagateHierarchy :: (Component a, Monoid a) => Hierarchy a -> Hierarchy a+propagateHierarchy = mapWithAccum (\_ t acc -> let t' = t <> acc in (t', t')) mempty++-- | Propagate and update all hierarchies of transform components.+update ::+  forall q arr b m a.+  ( ArrowQueryReader q,+    ArrowDynamicQueryReader q,+    ArrowReaderSystem q arr,+    ArrowQueueSystem b m arr,+    Component a,+    Monoid a+  ) =>+  arr () ()+update = propagate @_ @_ @a >>> S.queue (mapM_ $ mapM_ (uncurry A.insert) . toList)++-- | Propagate and update all hierarchies of transform components.+update2d :: (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr, ArrowQueueSystem b m arr) => arr () ()+update2d = propagate @_ @_ @Transform2D >>> S.queue (mapM_ $ mapM_ (uncurry A.insert) . toList)++propagate ::+  (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr, Component a, Monoid a) =>+  arr () [Hierarchy a]+propagate = hierarchies Q.fetch >>> arr (map propagateHierarchy)++propagate2d :: (ArrowQueryReader q, ArrowDynamicQueryReader q, ArrowReaderSystem q arr) => arr () [Hierarchy Transform2D]+propagate2d = propagate
test/Main.hs view
@@ -1,15 +1,18 @@ {-# LANGUAGE ApplicativeDo #-}+{-# LANGUAGE Arrows #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE TypeApplications #-}  module Main (main) where  import Aztecs import qualified Aztecs.ECS.Query as Q+import qualified Aztecs.ECS.System as S import qualified Aztecs.ECS.World as W import Aztecs.Hierarchy (Children (..), Parent (..)) import qualified Aztecs.Hierarchy as Hierarchy-import Control.Arrow ((&&&))+import Control.Arrow (returnA, (&&&)) import Control.DeepSeq import qualified Data.Set as Set import GHC.Generics@@ -36,17 +39,20 @@     it "queries three components" $ property prop_queryThreeComponents   describe "Aztecs.ECS.Hierarchy.update" $ do     it "adds Parent components to children" $ property prop_addParents+    it "removes Parent components from removed children" $ property prop_removeParents+  describe "Aztecs.ECS.Schedule" $ do+    it "increments components" prop_quit  prop_queryOneComponent :: [X] -> Expectation prop_queryOneComponent xs =   let w = foldr (\x -> snd . W.spawn (bundle x)) W.empty xs-      (res, _) = Q.all Q.fetch w+      (res, _) = Q.all Q.fetch $ W.entities w    in res `shouldMatchList` xs  prop_queryTwoComponents :: [(X, Y)] -> Expectation prop_queryTwoComponents xys =   let w = foldr (\(x, y) -> snd . W.spawn (bundle x <> bundle y)) W.empty xys-      (res, _) = Q.all (Q.fetch &&& Q.fetch) w+      (res, _) = Q.all (Q.fetch &&& Q.fetch) $ W.entities w    in res `shouldMatchList` xys  prop_queryThreeComponents :: [(X, Y, Z)] -> Expectation@@ -57,13 +63,46 @@         y <- Q.fetch         z <- Q.fetch         pure (x, y, z)-      (res, _) = Q.all q w+      (res, _) = Q.all q $ W.entities w    in res `shouldMatchList` xyzs  prop_addParents :: Expectation prop_addParents = do   let (_, w) = W.spawnEmpty W.empty       (e, w') = W.spawn (bundle . Children $ Set.singleton e) w-  (_, w'') <- runSchedule (system Hierarchy.update) w' ()-  let (res, _) = Q.all Q.fetch w''+  (_, _, w'') <- runSchedule (system Hierarchy.update) w' ()+  let (res, _) = Q.all Q.fetch $ W.entities w''   res `shouldMatchList` [Parent e]++prop_removeParents :: Expectation+prop_removeParents = do+  let (_, w) = W.spawnEmpty W.empty+      (e, w') = W.spawn (bundle . Children $ Set.singleton e) w+  (_, _, w'') <- runSchedule (system Hierarchy.update) w' ()+  let w''' = W.insert e (Children Set.empty) w''+  (_, _, w'''') <- runSchedule (system Hierarchy.update) w''' ()+  let (res, _) = Q.all (Q.fetch @_ @Parent) $ W.entities w''''+  res `shouldMatchList` []++prop_quit :: Expectation+prop_quit = do+  let (_, w) = W.spawn (bundle $ X 1) W.empty+  (_, _, w') <- runSchedule quit w ()+  (x, _, _) <- runSchedule quit w' ()+  x `shouldBe` True++quit :: Schedule IO () Bool+quit = proc () -> do+  rec lastShouldQuit <- delay False -< shouldQuit+      x <-+        system $+          S.mapSingle+            ( proc () -> do+                X x <- Q.fetch -< ()+                Q.set -< X $ x + 1+                returnA -< x+            )+          -<+            ()+      let shouldQuit = (lastShouldQuit || x > 1)+  returnA -< shouldQuit