packages feed

mischief-ecs-0.2.0.0: src/Mischief/ECS/Components/Required.hs

{-# LANGUAGE AllowAmbiguousTypes #-}

module Mischief.ECS.Components.Required (require, requireAll, toBundleElement) where

import Data.Data
import Data.Default
import Data.Set (Set)
import Data.Set qualified as Set
import Mischief.ECS.Components

class RequiredBundle b where
  defaultBundleData :: Proxy b -> Set DefaultComponentType

instance RequiredBundle () where
  defaultBundleData :: Proxy () -> Set DefaultComponentType
  defaultBundleData _ = Set.empty

instance {-# OVERLAPPABLE #-} (Component c, Default c) => RequiredBundle c where
  defaultBundleData :: Proxy c -> Set DefaultComponentType
  defaultBundleData _ = Set.singleton $ DefaultComponentType $ Proxy @c

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1) => RequiredBundle (b0, b1) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2) => RequiredBundle (b0, b1, b2) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3) => RequiredBundle (b0, b1, b2, b3) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4) => RequiredBundle (b0, b1, b2, b3, b4) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5) => RequiredBundle (b0, b1, b2, b3, b4, b5) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7, RequiredBundle b8) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7, b8) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7, defaultBundleData $ Proxy @b8]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7, RequiredBundle b8, RequiredBundle b9) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7, defaultBundleData $ Proxy @b8, defaultBundleData $ Proxy @b9]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7, RequiredBundle b8, RequiredBundle b9, RequiredBundle b10) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7, defaultBundleData $ Proxy @b8, defaultBundleData $ Proxy @b9, defaultBundleData $ Proxy @b10]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7, RequiredBundle b8, RequiredBundle b9, RequiredBundle b10, RequiredBundle b11) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7, defaultBundleData $ Proxy @b8, defaultBundleData $ Proxy @b9, defaultBundleData $ Proxy @b10, defaultBundleData $ Proxy @b11]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7, RequiredBundle b8, RequiredBundle b9, RequiredBundle b10, RequiredBundle b11, RequiredBundle b12) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7, defaultBundleData $ Proxy @b8, defaultBundleData $ Proxy @b9, defaultBundleData $ Proxy @b10, defaultBundleData $ Proxy @b11, defaultBundleData $ Proxy @b12]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7, RequiredBundle b8, RequiredBundle b9, RequiredBundle b10, RequiredBundle b11, RequiredBundle b12, RequiredBundle b13) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7, defaultBundleData $ Proxy @b8, defaultBundleData $ Proxy @b9, defaultBundleData $ Proxy @b10, defaultBundleData $ Proxy @b11, defaultBundleData $ Proxy @b12, defaultBundleData $ Proxy @b13]

instance {-# OVERLAPPING #-} (RequiredBundle b0, RequiredBundle b1, RequiredBundle b2, RequiredBundle b3, RequiredBundle b4, RequiredBundle b5, RequiredBundle b6, RequiredBundle b7, RequiredBundle b8, RequiredBundle b9, RequiredBundle b10, RequiredBundle b11, RequiredBundle b12, RequiredBundle b13, RequiredBundle b14) => RequiredBundle (b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14) where
  defaultBundleData _ = Set.unions [defaultBundleData $ Proxy @b0, defaultBundleData $ Proxy @b1, defaultBundleData $ Proxy @b2, defaultBundleData $ Proxy @b3, defaultBundleData $ Proxy @b4, defaultBundleData $ Proxy @b5, defaultBundleData $ Proxy @b6, defaultBundleData $ Proxy @b7, defaultBundleData $ Proxy @b8, defaultBundleData $ Proxy @b9, defaultBundleData $ Proxy @b10, defaultBundleData $ Proxy @b11, defaultBundleData $ Proxy @b12, defaultBundleData $ Proxy @b13, defaultBundleData $ Proxy @b14]

require :: forall b. (RequiredBundle b) => Set DefaultComponentType
require = defaultBundleData (Proxy @b)

requireAll :: forall c. (Component c) => Set DefaultComponentType
requireAll = requireAll' $ required @c

requireAll' :: Set DefaultComponentType -> Set DefaultComponentType
requireAll' !set =
  let !nextSet = expandAll set
   in if null nextSet then set else requireAll' $ Set.union set nextSet

expandAll :: Set DefaultComponentType -> Set DefaultComponentType
expandAll !set =
  let !newSet = Set.unions $ map expandOne (Set.toList set)
   in Set.difference newSet set

expandOne :: DefaultComponentType -> Set DefaultComponentType
expandOne (DefaultComponentType (_ :: (Proxy c))) = required @c

toBundleElement :: DefaultComponentType -> BundleElement ErasedComponent
toBundleElement (DefaultComponentType (_ :: (Proxy c))) = BundleElement (ComponentRep $ ComponentType $ Proxy @c) $ ErasedComponent $ def @c