{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
module Aztecs.ECS.Query.Dynamic.Reader
(
DynamicQueryReader (..),
DynamicQueryReaderF (..),
allDyn,
filterDyn,
singleDyn,
singleMaybeDyn,
DynamicQueryFilter (..),
)
where
import Aztecs.ECS.Component
import Aztecs.ECS.Query.Dynamic.Reader.Class
import Aztecs.ECS.World.Archetype (Archetype)
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.Entities (Entities (..))
import qualified Data.Map as Map
import Data.Set (Set)
import qualified Data.Set as Set
import GHC.Stack
newtype DynamicQueryReader a = DynamicQueryReader
{
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader :: Archetype -> [a]
}
deriving ((forall a b.
(a -> b) -> DynamicQueryReader a -> DynamicQueryReader b)
-> (forall a b. a -> DynamicQueryReader b -> DynamicQueryReader a)
-> Functor DynamicQueryReader
forall a b. a -> DynamicQueryReader b -> DynamicQueryReader a
forall a b.
(a -> b) -> DynamicQueryReader a -> DynamicQueryReader b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
$cfmap :: forall a b.
(a -> b) -> DynamicQueryReader a -> DynamicQueryReader b
fmap :: forall a b.
(a -> b) -> DynamicQueryReader a -> DynamicQueryReader b
$c<$ :: forall a b. a -> DynamicQueryReader b -> DynamicQueryReader a
<$ :: forall a b. a -> DynamicQueryReader b -> DynamicQueryReader a
Functor)
instance Applicative DynamicQueryReader where
{-# INLINE pure #-}
pure :: forall a. a -> DynamicQueryReader a
pure a
a = (Archetype -> [a]) -> DynamicQueryReader a
forall a. (Archetype -> [a]) -> DynamicQueryReader a
DynamicQueryReader ((Archetype -> [a]) -> DynamicQueryReader a)
-> (Archetype -> [a]) -> DynamicQueryReader a
forall a b. (a -> b) -> a -> b
$ \Archetype
arch -> Int -> a -> [a]
forall a. Int -> a -> [a]
replicate (Set EntityID -> Int
forall a. Set a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Set EntityID -> Int) -> Set EntityID -> Int
forall a b. (a -> b) -> a -> b
$ Archetype -> Set EntityID
A.entities Archetype
arch) a
a
{-# INLINE (<*>) #-}
DynamicQueryReader (a -> b)
f <*> :: forall a b.
DynamicQueryReader (a -> b)
-> DynamicQueryReader a -> DynamicQueryReader b
<*> DynamicQueryReader a
g = (Archetype -> [b]) -> DynamicQueryReader b
forall a. (Archetype -> [a]) -> DynamicQueryReader a
DynamicQueryReader ((Archetype -> [b]) -> DynamicQueryReader b)
-> (Archetype -> [b]) -> DynamicQueryReader b
forall a b. (a -> b) -> a -> b
$ \Archetype
arch ->
((a -> b) -> a -> b) -> [a -> b] -> [a] -> [b]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
($) (DynamicQueryReader (a -> b) -> Archetype -> [a -> b]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader (a -> b)
f Archetype
arch) ([a] -> [b]) -> [a] -> [b]
forall a b. (a -> b) -> a -> b
$ DynamicQueryReader a -> Archetype -> [a]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader a
g Archetype
arch
instance DynamicQueryReaderF DynamicQueryReader where
{-# INLINE entity #-}
entity :: DynamicQueryReader EntityID
entity = (Archetype -> [EntityID]) -> DynamicQueryReader EntityID
forall a. (Archetype -> [a]) -> DynamicQueryReader a
DynamicQueryReader ((Archetype -> [EntityID]) -> DynamicQueryReader EntityID)
-> (Archetype -> [EntityID]) -> DynamicQueryReader EntityID
forall a b. (a -> b) -> a -> b
$ \Archetype
arch -> Set EntityID -> [EntityID]
forall a. Set a -> [a]
Set.toList (Set EntityID -> [EntityID]) -> Set EntityID -> [EntityID]
forall a b. (a -> b) -> a -> b
$ Archetype -> Set EntityID
A.entities Archetype
arch
{-# INLINE fetchDyn #-}
fetchDyn :: forall a. Component a => ComponentID -> DynamicQueryReader a
fetchDyn ComponentID
cId = (Archetype -> [a]) -> DynamicQueryReader a
forall a. (Archetype -> [a]) -> DynamicQueryReader a
DynamicQueryReader ((Archetype -> [a]) -> DynamicQueryReader a)
-> (Archetype -> [a]) -> DynamicQueryReader a
forall a b. (a -> b) -> a -> b
$ \Archetype
arch -> ComponentID -> Archetype -> [a]
forall a. Component a => ComponentID -> Archetype -> [a]
A.lookupComponentsAsc ComponentID
cId Archetype
arch
{-# INLINE fetchMaybeDyn #-}
fetchMaybeDyn :: forall a.
Component a =>
ComponentID -> DynamicQueryReader (Maybe a)
fetchMaybeDyn ComponentID
cId = (Archetype -> [Maybe a]) -> DynamicQueryReader (Maybe a)
forall a. (Archetype -> [a]) -> DynamicQueryReader a
DynamicQueryReader ((Archetype -> [Maybe a]) -> DynamicQueryReader (Maybe a))
-> (Archetype -> [Maybe a]) -> DynamicQueryReader (Maybe a)
forall a b. (a -> b) -> a -> b
$ \Archetype
arch -> case ComponentID -> Archetype -> Maybe [a]
forall a. Component a => ComponentID -> Archetype -> Maybe [a]
A.lookupComponentsAscMaybe ComponentID
cId Archetype
arch of
Just [a]
as -> (a -> Maybe a) -> [a] -> [Maybe a]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Maybe a
forall a. a -> Maybe a
Just [a]
as
Maybe [a]
Nothing -> Int -> Maybe a -> [Maybe a]
forall a. Int -> a -> [a]
replicate (Set EntityID -> Int
forall a. Set a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Set EntityID -> Int) -> Set EntityID -> Int
forall a b. (a -> b) -> a -> b
$ Archetype -> Set EntityID
A.entities Archetype
arch) Maybe a
forall a. Maybe a
Nothing
data DynamicQueryFilter = DynamicQueryFilter
{
DynamicQueryFilter -> Set ComponentID
filterWith :: !(Set ComponentID),
DynamicQueryFilter -> Set ComponentID
filterWithout :: !(Set ComponentID)
}
instance Semigroup DynamicQueryFilter where
DynamicQueryFilter Set ComponentID
withA Set ComponentID
withoutA <> :: DynamicQueryFilter -> DynamicQueryFilter -> DynamicQueryFilter
<> DynamicQueryFilter Set ComponentID
withB Set ComponentID
withoutB =
Set ComponentID -> Set ComponentID -> DynamicQueryFilter
DynamicQueryFilter (Set ComponentID
withA Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> Set ComponentID
withB) (Set ComponentID
withoutA Set ComponentID -> Set ComponentID -> Set ComponentID
forall a. Semigroup a => a -> a -> a
<> Set ComponentID
withoutB)
instance Monoid DynamicQueryFilter where
mempty :: DynamicQueryFilter
mempty = Set ComponentID -> Set ComponentID -> DynamicQueryFilter
DynamicQueryFilter Set ComponentID
forall a. Monoid a => a
mempty Set ComponentID
forall a. Monoid a => a
mempty
allDyn :: Set ComponentID -> DynamicQueryReader a -> Entities -> [a]
allDyn :: forall a.
Set ComponentID -> DynamicQueryReader a -> Entities -> [a]
allDyn Set ComponentID
cIds DynamicQueryReader a
q Entities
es =
if Set ComponentID -> Bool
forall a. Set a -> Bool
Set.null Set ComponentID
cIds
then DynamicQueryReader a -> Archetype -> [a]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader a
q Archetype
A.empty {A.entities = Map.keysSet $ entities es}
else
let go :: Node -> [a]
go Node
n = DynamicQueryReader a -> Archetype -> [a]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader a
q (Archetype -> [a]) -> Archetype -> [a]
forall a b. (a -> b) -> a -> b
$ Node -> Archetype
AS.nodeArchetype Node
n
in (Node -> [a]) -> Map ArchetypeID Node -> [a]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Node -> [a]
go (Set ComponentID -> Archetypes -> Map ArchetypeID Node
AS.find Set ComponentID
cIds (Archetypes -> Map ArchetypeID Node)
-> Archetypes -> Map ArchetypeID Node
forall a b. (a -> b) -> a -> b
$ Entities -> Archetypes
archetypes Entities
es)
filterDyn :: Set ComponentID -> (Node -> Bool) -> DynamicQueryReader a -> Entities -> [a]
filterDyn :: forall a.
Set ComponentID
-> (Node -> Bool) -> DynamicQueryReader a -> Entities -> [a]
filterDyn Set ComponentID
cIds Node -> Bool
f DynamicQueryReader a
q Entities
es =
if Set ComponentID -> Bool
forall a. Set a -> Bool
Set.null Set ComponentID
cIds
then DynamicQueryReader a -> Archetype -> [a]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader a
q Archetype
A.empty {A.entities = Map.keysSet $ entities es}
else
let go :: Node -> [a]
go Node
n = DynamicQueryReader a -> Archetype -> [a]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader a
q (Archetype -> [a]) -> Archetype -> [a]
forall a b. (a -> b) -> a -> b
$ Node -> Archetype
AS.nodeArchetype Node
n
in (Node -> [a]) -> Map ArchetypeID Node -> [a]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Node -> [a]
go ((Node -> Bool) -> Map ArchetypeID Node -> Map ArchetypeID Node
forall a k. (a -> Bool) -> Map k a -> Map k a
Map.filter Node -> Bool
f (Map ArchetypeID Node -> Map ArchetypeID Node)
-> Map ArchetypeID Node -> Map ArchetypeID Node
forall a b. (a -> b) -> a -> b
$ Set ComponentID -> Archetypes -> Map ArchetypeID Node
AS.find Set ComponentID
cIds (Archetypes -> Map ArchetypeID Node)
-> Archetypes -> Map ArchetypeID Node
forall a b. (a -> b) -> a -> b
$ Entities -> Archetypes
archetypes Entities
es)
singleDyn :: (HasCallStack) => Set ComponentID -> DynamicQueryReader a -> Entities -> a
singleDyn :: forall a.
HasCallStack =>
Set ComponentID -> DynamicQueryReader a -> Entities -> a
singleDyn Set ComponentID
cIds DynamicQueryReader a
q Entities
es = case Set ComponentID -> DynamicQueryReader a -> Entities -> Maybe a
forall a.
Set ComponentID -> DynamicQueryReader a -> Entities -> Maybe a
singleMaybeDyn Set ComponentID
cIds DynamicQueryReader a
q Entities
es of
Just a
a -> a
a
Maybe a
_ -> [Char] -> a
forall a. HasCallStack => [Char] -> a
error [Char]
"singleDyn: expected a single entity"
singleMaybeDyn :: Set ComponentID -> DynamicQueryReader a -> Entities -> Maybe a
singleMaybeDyn :: forall a.
Set ComponentID -> DynamicQueryReader a -> Entities -> Maybe a
singleMaybeDyn Set ComponentID
cIds DynamicQueryReader a
q Entities
es =
if Set ComponentID -> Bool
forall a. Set a -> Bool
Set.null Set ComponentID
cIds
then case Map EntityID ArchetypeID -> [EntityID]
forall k a. Map k a -> [k]
Map.keys (Map EntityID ArchetypeID -> [EntityID])
-> Map EntityID ArchetypeID -> [EntityID]
forall a b. (a -> b) -> a -> b
$ Entities -> Map EntityID ArchetypeID
entities Entities
es of
[EntityID
eId] -> case DynamicQueryReader a -> Archetype -> [a]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader a
q (Archetype -> [a]) -> Archetype -> [a]
forall a b. (a -> b) -> a -> b
$ EntityID -> Archetype
A.singleton EntityID
eId of
[a
a] -> a -> Maybe a
forall a. a -> Maybe a
Just a
a
[a]
_ -> Maybe a
forall a. Maybe a
Nothing
[EntityID]
_ -> Maybe a
forall a. Maybe a
Nothing
else case Map ArchetypeID Node -> [Node]
forall k a. Map k a -> [a]
Map.elems (Map ArchetypeID Node -> [Node]) -> Map ArchetypeID Node -> [Node]
forall a b. (a -> b) -> a -> b
$ Set ComponentID -> Archetypes -> Map ArchetypeID Node
AS.find Set ComponentID
cIds (Archetypes -> Map ArchetypeID Node)
-> Archetypes -> Map ArchetypeID Node
forall a b. (a -> b) -> a -> b
$ Entities -> Archetypes
archetypes Entities
es of
[Node
n] -> case DynamicQueryReader a -> Archetype -> [a]
forall a. DynamicQueryReader a -> Archetype -> [a]
runDynQueryReader DynamicQueryReader a
q (Archetype -> [a]) -> Archetype -> [a]
forall a b. (a -> b) -> a -> b
$ Node -> Archetype
AS.nodeArchetype Node
n of
[a
a] -> a -> Maybe a
forall a. a -> Maybe a
Just a
a
[a]
_ -> Maybe a
forall a. Maybe a
Nothing
[Node]
_ -> Maybe a
forall a. Maybe a
Nothing