packages feed

aztecs-transform 0.2.0.0 → 0.3.0

raw patch · 4 files changed

+166/−64 lines, 4 filesdep +containersdep −aztecs-hierarchydep −mtldep ~aztecsPVP ok

version bump matches the API change (PVP)

Dependencies added: containers

Dependencies removed: aztecs-hierarchy, mtl

Dependency ranges changed: aztecs

API changes (from Hackage documentation)

- Data.Aztecs.Transform: Size :: V2 Int -> Size
- Data.Aztecs.Transform: Transform :: !V2 Int -> !Float -> !V2 Int -> Transform
- Data.Aztecs.Transform: [transformPosition] :: Transform -> !V2 Int
- Data.Aztecs.Transform: [transformRotation] :: Transform -> !Float
- Data.Aztecs.Transform: [transformScale] :: Transform -> !V2 Int
- Data.Aztecs.Transform: [unSize] :: Size -> V2 Int
- Data.Aztecs.Transform: data Transform
- Data.Aztecs.Transform: instance Data.Aztecs.Component.Component Data.Aztecs.Transform.Size
- Data.Aztecs.Transform: instance Data.Aztecs.Component.Component Data.Aztecs.Transform.Transform
- Data.Aztecs.Transform: instance GHC.Classes.Eq Data.Aztecs.Transform.Transform
- Data.Aztecs.Transform: instance GHC.Show.Show Data.Aztecs.Transform.Transform
- Data.Aztecs.Transform: newtype Size
- Data.Aztecs.Transform: transform :: Transform
+ Aztecs.Transform: GlobalTransform :: Transform t s r -> GlobalTransform t s r
+ Aztecs.Transform: Size :: a -> Size a
+ Aztecs.Transform: Transform :: t -> s -> r -> Transform t s r
+ Aztecs.Transform: [transformRotation] :: Transform t s r -> r
+ Aztecs.Transform: [transformScale] :: Transform t s r -> s
+ Aztecs.Transform: [transformTranslation] :: Transform t s r -> t
+ Aztecs.Transform: [unGlobalTransform] :: GlobalTransform t s r -> Transform t s r
+ Aztecs.Transform: [unSize] :: Size a -> a
+ Aztecs.Transform: data Transform t s r
+ Aztecs.Transform: instance (GHC.Base.Monad m, Data.Typeable.Internal.Typeable a) => Aztecs.ECS.Component.Component m (Aztecs.Transform.Size a)
+ Aztecs.Transform: instance (GHC.Base.Monad m, Data.Typeable.Internal.Typeable t, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable r) => Aztecs.ECS.Component.Component m (Aztecs.Transform.GlobalTransform t s r)
+ Aztecs.Transform: instance (GHC.Base.Monad m, Data.Typeable.Internal.Typeable t, Data.Typeable.Internal.Typeable s, Data.Typeable.Internal.Typeable r, GHC.Num.Num t, GHC.Num.Num s, GHC.Num.Num r) => Aztecs.ECS.Component.Component m (Aztecs.Transform.Transform t s r)
+ Aztecs.Transform: instance (GHC.Num.Num t, GHC.Num.Num s, GHC.Num.Num r) => GHC.Base.Monoid (Aztecs.Transform.Transform t s r)
+ Aztecs.Transform: instance (GHC.Num.Num t, GHC.Num.Num s, GHC.Num.Num r) => GHC.Base.Semigroup (Aztecs.Transform.Transform t s r)
+ Aztecs.Transform: instance (GHC.Show.Show t, GHC.Show.Show s, GHC.Show.Show r) => GHC.Show.Show (Aztecs.Transform.GlobalTransform t s r)
+ Aztecs.Transform: instance (GHC.Show.Show t, GHC.Show.Show s, GHC.Show.Show r) => GHC.Show.Show (Aztecs.Transform.Transform t s r)
+ Aztecs.Transform: instance GHC.Show.Show a => GHC.Show.Show (Aztecs.Transform.Size a)
+ Aztecs.Transform: newtype GlobalTransform t s r
+ Aztecs.Transform: newtype Size a
+ Aztecs.Transform: transform :: (Num t, Num s, Num r) => Transform t s r
+ Aztecs.Transform: transform2d :: Transform2D
+ Aztecs.Transform: type GlobalTransform2D = GlobalTransform V2 Int V2 Float Float
+ Aztecs.Transform: type Size2D = Size V2 Float
+ Aztecs.Transform: type Transform2D = Transform V2 Int V2 Float Float

Files

LICENSE view
@@ -1,29 +1,29 @@-Copyright (c) 2024, Matt Hunzinger---Redistribution and use in source and binary forms, with or without-modification, are permitted provided that the following conditions are met:--    * Redistributions of source code must retain the above copyright-      notice, this list of conditions and the following disclaimer.--    * Redistributions in binary form must reproduce the above-      copyright notice, this list of conditions and the following-      disclaimer in the documentation and/or other materials provided-      with the distribution.--    * Neither the name of the copyright holder nor the names of its-      contributors may be used to endorse or promote products derived-      from this software without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT-HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+Copyright (c) 2024, Matt Hunzinger
+
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of the copyright holder nor the names of its
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
aztecs-transform.cabal view
@@ -1,33 +1,26 @@ cabal-version: 2.4 name:          aztecs-transform-version:       0.2.0.0+version:       0.3.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+synopsis:      Transform components for Aztecs+description:   Transform components for the Aztecs game engine and ECS category:      Game Engine  source-repository head     type:     git-    location: https://github.com/matthunz/aztecs.git+    location: https://github.com/matthunz/aztecs-transform.git  library-    exposed-modules:-        Data.Aztecs.Transform+    exposed-modules:  Aztecs.Transform     hs-source-dirs:   src     default-language: Haskell2010     ghc-options:      -Wall     build-depends:         base >=4.6 && <5,-        aztecs >= 0.5,-        aztecs-hierarchy >= 0.1,-        mtl >=2,-        linear >= 1+        aztecs >=0.16 && <0.17,+        containers >=0.6 && <0.9,+        linear >=1
+ src/Aztecs/Transform.hs view
@@ -0,0 +1,130 @@+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE TypeApplications #-}
+
+-- |
+-- Module      : Aztecs.Transform
+-- Copyright   : (c) Matt Hunzinger, 2025
+-- License     : BSD-style (see the LICENSE file in the distribution)
+--
+-- Maintainer  : matt@hunzinger.me
+-- Stability   : provisional
+-- Portability : non-portable (GHC extensions)
+module Aztecs.Transform
+  ( -- * Components
+
+    -- ** 2D
+    Transform2D,
+    transform2d,
+    GlobalTransform2D,
+    Size2D,
+
+    -- ** Generic
+    Transform (..),
+    GlobalTransform (..),
+    transform,
+    Size (..),
+
+    module Linear
+  )
+where
+
+import Aztecs.ECS
+import Aztecs.Hierarchy
+import Control.Monad
+import Data.Data (Typeable)
+import qualified Data.Set as Set
+import Linear
+import Prelude hiding (lookup)
+
+type GlobalTransform2D = GlobalTransform (V2 Int) (V2 Float) Float
+
+newtype GlobalTransform t s r = GlobalTransform {unGlobalTransform :: Transform t s r}
+  deriving (Show)
+
+instance
+  (Monad m, Typeable t, Typeable s, Typeable r) =>
+  Component m (GlobalTransform t s r)
+
+type Size2D = Size (V2 Float)
+
+newtype Size a = Size {unSize :: a}
+  deriving (Show)
+
+instance (Monad m, Typeable a) => Component m (Size a)
+
+type Transform2D = Transform (V2 Int) (V2 Float) Float
+
+data Transform t s r = Transform
+  { transformTranslation :: t,
+    transformScale :: s,
+    transformRotation :: r
+  }
+  deriving (Show)
+
+instance (Num t, Num s, Num r) => Semigroup (Transform t s r) where
+  Transform t1 s1 r1 <> Transform t2 s2 r2 = Transform (t1 + t2) (s1 * s2) (r1 + r2)
+
+instance (Num t, Num s, Num r) => Monoid (Transform t s r) where
+  mempty = Transform 0 1 0
+
+instance
+  (Monad m, Typeable t, Typeable s, Typeable r, Num t, Num s, Num r) =>
+  Component m (Transform t s r)
+  where
+  componentOnInsert e localT = do
+    globalT <- computeGlobalTransform e localT
+    insertUntracked e . bundle $ GlobalTransform @t @s @r globalT
+    propagateToChildren e globalT
+
+  componentOnChange e _ newLocalT = do
+    globalT <- computeGlobalTransform e newLocalT
+    insertUntracked e . bundle $ GlobalTransform @t @s @r globalT
+    propagateToChildren e globalT
+
+  componentOnRemove e _ = void $ remove @_ @(GlobalTransform t s r) e
+
+-- | Propagate a global transform to all children of an entity.
+propagateToChildren ::
+  forall m t s r.
+  (Monad m, Typeable t, Typeable s, Typeable r, Num t, Num s, Num r) =>
+  EntityID ->
+  Transform t s r ->
+  Access m ()
+propagateToChildren parentE parentGlobal = do
+  maybeChildren <- lookup @_ @Children parentE
+  case maybeChildren of
+    Nothing -> return ()
+    Just children -> mapM_ propagateToChild (Set.toList $ unChildren children)
+  where
+    propagateToChild :: EntityID -> Access m ()
+    propagateToChild childE = do
+      maybeLocalT <- lookup @_ @(Transform t s r) childE
+      case maybeLocalT of
+        Nothing -> return ()
+        Just localT -> do
+          let childGlobal = localT <> parentGlobal
+          insertUntracked childE . bundle $ GlobalTransform @t @s @r childGlobal
+          propagateToChildren childE childGlobal
+
+-- | Compute the global transform for an entity based on its local transform and parent.
+computeGlobalTransform ::
+  forall m t s r.
+  (Monad m, Typeable t, Typeable s, Typeable r, Num t, Num s, Num r) =>
+  EntityID ->
+  Transform t s r ->
+  Access m (Transform t s r)
+computeGlobalTransform e localT = do
+  maybeParent <- lookup @_ @Parent e
+  case maybeParent of
+    Nothing -> return localT
+    Just (Parent parentE) -> do
+      maybeParentGlobal <- lookup @_ @(GlobalTransform t s r) parentE
+      return $ localT <> maybe mempty unGlobalTransform maybeParentGlobal
+
+transform2d :: Transform2D
+transform2d = transform
+
+transform :: (Num t, Num s, Num r) => Transform t s r
+transform = mempty
− src/Data/Aztecs/Transform.hs
@@ -1,21 +0,0 @@-module Data.Aztecs.Transform where--import Data.Aztecs-import Linear (V2 (..))--data Transform = Transform-  { transformPosition :: !(V2 Int),-    transformRotation :: !Float,-    transformScale :: !(V2 Int)-  }-  deriving (Eq, Show)--transform :: Transform-transform = Transform (V2 0 0) 0 (V2 1 1)--instance Component Transform---newtype Size = Size {unSize :: V2 Int}--instance Component Size