2016-10-31 22:47:16 +00:00
|
|
|
{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveFunctor #-}
|
2016-03-25 15:58:46 +00:00
|
|
|
module Affection.Types
|
2016-12-08 17:22:29 +00:00
|
|
|
( Affection
|
|
|
|
, AffectionData(..)
|
2016-10-31 22:47:16 +00:00
|
|
|
, AffectionConfig(..)
|
2016-11-02 00:14:53 +00:00
|
|
|
, AffectionState(..)
|
2016-10-31 22:47:16 +00:00
|
|
|
-- , AffectionDraw(..)
|
|
|
|
-- , Draw(..)
|
2016-11-13 12:39:25 +00:00
|
|
|
, AffectionStateInner
|
2016-10-31 22:47:16 +00:00
|
|
|
-- , AffectionDrawInner(..)
|
|
|
|
, InitComponents(..)
|
|
|
|
-- , Loop(..)
|
2017-06-26 04:57:02 +00:00
|
|
|
-- , RGBA(..)
|
2016-12-08 17:22:29 +00:00
|
|
|
, DrawType(..)
|
2016-12-11 16:38:03 +00:00
|
|
|
, DrawRequest(..)
|
2016-12-23 13:18:39 +00:00
|
|
|
, RequestPersist(..)
|
2016-12-20 10:29:03 +00:00
|
|
|
, Angle(..)
|
2017-06-26 04:57:02 +00:00
|
|
|
-- , ConvertAngle(..)
|
2016-12-12 02:34:57 +00:00
|
|
|
-- | Particle system
|
|
|
|
, Particle(..)
|
2016-12-13 10:08:49 +00:00
|
|
|
, ParticleSystem(..)
|
2016-12-25 07:14:51 +00:00
|
|
|
, ParticleStorage(..)
|
2016-11-13 12:39:25 +00:00
|
|
|
-- | Convenience exports
|
|
|
|
, liftIO
|
2016-12-12 02:34:57 +00:00
|
|
|
, SDL.WindowConfig(..)
|
|
|
|
, SDL.defaultWindow
|
2016-12-08 17:22:29 +00:00
|
|
|
-- | GEGL reexports
|
|
|
|
, G.GeglRectangle(..)
|
|
|
|
, G.GeglBuffer(..)
|
2016-03-25 15:58:46 +00:00
|
|
|
) where
|
|
|
|
|
2016-10-31 22:47:16 +00:00
|
|
|
import qualified SDL.Init as SDL
|
|
|
|
import qualified SDL.Video as SDL
|
2017-02-17 16:15:06 +00:00
|
|
|
import qualified SDL.Event as SDL
|
2016-10-31 22:47:16 +00:00
|
|
|
import qualified Data.Text as T
|
2017-03-21 11:04:56 +00:00
|
|
|
import Data.Map.Strict as M
|
2016-12-21 03:28:57 +00:00
|
|
|
|
2016-12-08 17:22:29 +00:00
|
|
|
import qualified GEGL as G
|
2016-12-21 03:28:57 +00:00
|
|
|
import qualified BABL as B
|
2016-10-31 22:47:16 +00:00
|
|
|
|
|
|
|
import Control.Monad.IO.Class
|
|
|
|
import Control.Monad.State
|
2017-03-20 04:24:02 +00:00
|
|
|
import qualified Control.Monad.Parallel as MP
|
2016-11-13 12:39:25 +00:00
|
|
|
-- import Control.Monad.Reader
|
2016-10-31 22:47:16 +00:00
|
|
|
|
2016-11-13 12:39:25 +00:00
|
|
|
-- import Control.Concurrent.MVar
|
2016-10-31 22:47:16 +00:00
|
|
|
|
2017-02-19 21:28:10 +00:00
|
|
|
import Foreign.Ptr (Ptr)
|
|
|
|
|
2016-10-31 22:47:16 +00:00
|
|
|
-- | Configuration for the aplication. needed at startup.
|
|
|
|
data AffectionConfig us = AffectionConfig
|
2016-11-04 15:06:16 +00:00
|
|
|
{ initComponents :: InitComponents
|
|
|
|
-- ^ SDL components to initialize at startup
|
|
|
|
, windowTitle :: T.Text
|
|
|
|
-- ^ Window title
|
|
|
|
, windowConfig :: SDL.WindowConfig
|
|
|
|
-- ^ Window configuration
|
2017-03-23 03:31:10 +00:00
|
|
|
, canvasSize :: Maybe (Int, Int)
|
|
|
|
-- ^ size of the texture canvas
|
2016-12-11 19:24:16 +00:00
|
|
|
, preLoop :: Affection us ()
|
|
|
|
-- ^ Actions to be performed, before loop starts
|
2017-03-23 03:34:04 +00:00
|
|
|
, eventLoop :: SDL.EventPayload -> Affection us ()
|
2017-03-16 19:12:41 +00:00
|
|
|
-- ^ Main update function. Takes fractions of a second as input.
|
2017-03-23 03:29:48 +00:00
|
|
|
, updateLoop :: Double -> Affection us ()
|
2017-03-16 19:12:41 +00:00
|
|
|
-- ^ Main update function. Takes fractions of a second as input.
|
2016-12-11 19:24:16 +00:00
|
|
|
, drawLoop :: Affection us ()
|
2016-11-04 15:06:16 +00:00
|
|
|
-- ^ Function for updating graphics.
|
2017-03-23 03:34:04 +00:00
|
|
|
, loadState :: IO us
|
2016-11-04 15:06:16 +00:00
|
|
|
-- ^ Provide your own load function to create this data.
|
2016-11-13 12:39:25 +00:00
|
|
|
, cleanUp :: us -> IO ()
|
|
|
|
-- ^ Provide your own finisher function to clean your data.
|
2016-10-31 22:47:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-21 03:28:57 +00:00
|
|
|
-- | Components to initialize in SDL.
|
|
|
|
data InitComponents
|
|
|
|
= All
|
|
|
|
| Only [SDL.InitFlag]
|
|
|
|
|
2016-10-31 22:47:16 +00:00
|
|
|
-- | Main type for defining the look, feel and action of the whole application.
|
|
|
|
data AffectionData us = AffectionData
|
2016-11-04 15:06:16 +00:00
|
|
|
-- { affectionConfig :: AffectionConfig us -- ^ Application configuration.
|
|
|
|
{ quitEvent :: Bool -- ^ Loop breaker.
|
2016-10-31 22:47:16 +00:00
|
|
|
, userState :: us -- ^ State data provided by user
|
|
|
|
, drawWindow :: SDL.Window -- ^ SDL window
|
2017-02-23 21:54:26 +00:00
|
|
|
, windowRenderer :: SDL.Renderer -- ^ Internal renderer of window
|
2017-03-22 15:59:24 +00:00
|
|
|
, drawTexture :: SDL.Texture -- ^ SDL Texture to draw to
|
2016-12-21 03:28:57 +00:00
|
|
|
, drawFormat :: B.BablFormatPtr -- ^ Target format
|
2016-12-11 19:24:16 +00:00
|
|
|
, drawStack :: [DrawRequest] -- ^ Stack of 'DrawRequest's to be processed
|
2017-02-24 16:11:52 +00:00
|
|
|
, drawDimensions :: (Int, Int) -- ^ Dimensions of target surface
|
2017-02-19 21:28:10 +00:00
|
|
|
, drawStride :: Int -- ^ Stride of target buffer
|
|
|
|
, drawCPP :: Int -- ^ Number of components per pixel
|
2016-12-25 07:14:51 +00:00
|
|
|
, elapsedTime :: Double -- ^ Elapsed time in seconds
|
2017-06-26 04:57:02 +00:00
|
|
|
, deltaTime :: Double -- ^ Elapsed time in seconds since last tick
|
2017-07-29 00:47:26 +00:00
|
|
|
, sysTime :: TimeSpec -- ^ System time (NOT the time on the clock)
|
2017-07-29 00:40:41 +00:00
|
|
|
, pausedTime :: Bool -- ^ Should the update loop be executed?
|
2016-10-31 22:47:16 +00:00
|
|
|
}
|
|
|
|
|
2016-12-11 16:38:03 +00:00
|
|
|
-- | This datatype stores information about areas of a 'G.GeglBuffer' to be updated
|
|
|
|
data DrawRequest = DrawRequest
|
2016-12-21 03:28:57 +00:00
|
|
|
{ requestArea :: G.GeglRectangle -- ^ The area to update
|
2016-12-11 19:24:16 +00:00
|
|
|
, requestBuffer :: G.GeglBuffer -- ^ Buffer to draw
|
2016-12-23 13:18:39 +00:00
|
|
|
, requestPersist :: RequestPersist -- ^ Shall the drawRequest persist
|
2016-12-11 16:38:03 +00:00
|
|
|
}
|
2016-10-31 22:47:16 +00:00
|
|
|
|
2016-12-23 13:18:39 +00:00
|
|
|
data RequestPersist
|
2017-03-05 15:39:37 +00:00
|
|
|
= Persist
|
2016-12-24 00:13:00 +00:00
|
|
|
| Kill (Maybe G.GeglNode)
|
2016-12-23 13:18:39 +00:00
|
|
|
|
2016-12-21 03:28:57 +00:00
|
|
|
-- | A type for storing 'DrawRequest' results to be executed frequently. TODO
|
|
|
|
data DrawAsset = DrawAsset
|
2016-10-31 22:47:16 +00:00
|
|
|
|
|
|
|
-- | Inner 'StateT' monad for the update state
|
2016-11-02 00:14:53 +00:00
|
|
|
-- type AffectionStateInner us m a = StateT (AffectionData us) m a
|
|
|
|
type AffectionStateInner us m a = StateT us m a
|
2016-10-31 22:47:16 +00:00
|
|
|
|
|
|
|
-- | Affection's state monad
|
|
|
|
newtype AffectionState us m a = AffectionState
|
|
|
|
{ runState :: AffectionStateInner us m a }
|
2016-11-02 00:14:53 +00:00
|
|
|
deriving (Functor, Applicative, Monad, MonadIO, MonadState us)
|
2016-10-31 22:47:16 +00:00
|
|
|
|
2017-03-20 04:24:02 +00:00
|
|
|
instance MP.MonadParallel m => MP.MonadParallel (AffectionState us m)
|
|
|
|
|
2016-12-08 17:22:29 +00:00
|
|
|
type Affection us a = AffectionState (AffectionData us) IO a
|
|
|
|
|
2016-10-31 22:47:16 +00:00
|
|
|
-- -- | Inner 'StateT' monad of Affection
|
|
|
|
-- type AffectionInner us od a = StateT (AffectionState us od) IO a
|
|
|
|
--
|
|
|
|
-- -- | Affection state monad
|
|
|
|
-- newtype Affection us od a = Affection
|
|
|
|
-- { runAffection :: AffectionInner us od a }
|
|
|
|
-- deriving (Functor, Applicative, Monad, MonadState (AffectionState us od))
|
|
|
|
--
|
|
|
|
-- -- | Inner drawing monad of Affection.
|
|
|
|
-- type AffectionDrawInner ds a = ReaderT (Draw ds) a
|
|
|
|
--
|
|
|
|
-- -- | Affectiondrawinf reader monad.
|
|
|
|
-- newtype AffectionDraw ds a = AffectionDraw
|
|
|
|
-- { runDraw :: (ds -> a) }
|
|
|
|
-- deriving (Functor, Applicative, Monad, MonadReader ds)
|
|
|
|
--
|
|
|
|
-- -- | Loop state monad to hold elapsed time per frame
|
|
|
|
-- newtype Loop f a = Loop
|
|
|
|
-- { runLoop :: f -> (a, f) }
|
|
|
|
-- deriving (Functor, Applicative, Monad, MonadState (Loop f))
|
|
|
|
|
2017-06-26 04:57:02 +00:00
|
|
|
-- data RGBA = RGBA
|
|
|
|
-- { r :: Int
|
|
|
|
-- , g :: Int
|
|
|
|
-- , b :: Int
|
|
|
|
-- , a :: Int
|
|
|
|
-- }
|
2016-12-08 17:22:29 +00:00
|
|
|
|
|
|
|
-- | Type for defining the draw type of draw functions
|
|
|
|
data DrawType
|
2017-02-17 16:15:06 +00:00
|
|
|
-- | Fill the specified area completely with color
|
|
|
|
= Fill
|
|
|
|
-- | only draw the outline of the area
|
|
|
|
| Line
|
2016-12-08 17:22:29 +00:00
|
|
|
{ lineWidth :: Int -- ^ Width of line in pixels
|
|
|
|
}
|
2016-12-12 02:34:57 +00:00
|
|
|
|
2017-06-26 04:57:02 +00:00
|
|
|
type Angle = Double
|
|
|
|
|
|
|
|
-- -- | Type for defining angles
|
|
|
|
-- data Angle
|
|
|
|
-- = Rad Double -- ^ Angle in radians
|
|
|
|
-- | Deg Double -- ^ Angle in degrees
|
|
|
|
-- deriving (Show)
|
|
|
|
--
|
|
|
|
-- -- | Typeclass for converting Angles from 'Deg' to 'Rad' and vice versa.
|
|
|
|
-- class ConvertAngle a where
|
|
|
|
-- toRad :: a -> a -- Convert to 'Rad'
|
|
|
|
-- toDeg :: a -> a -- Convert to 'Deg'
|
|
|
|
--
|
|
|
|
-- instance ConvertAngle Angle where
|
|
|
|
-- toRad (Deg x) = Rad $ x * pi / 180
|
|
|
|
-- toRad x = x
|
|
|
|
--
|
|
|
|
-- toDeg (Rad x) = Deg $ x * 180 / pi
|
|
|
|
-- toDeg x = x
|
|
|
|
--
|
|
|
|
-- instance Eq Angle where
|
|
|
|
-- (==) (Deg x) (Deg y) = x == y
|
|
|
|
-- (==) (Rad x) (Rad y) = x == y
|
|
|
|
-- (==) dx@(Deg _) ry@(Rad _) = dx == toDeg ry
|
|
|
|
-- (==) rx@(Rad _) dy@(Deg _) = toDeg rx == dy
|
2016-12-20 10:29:03 +00:00
|
|
|
|
2016-12-12 02:34:57 +00:00
|
|
|
-- | A single particle
|
|
|
|
data Particle = Particle
|
2016-12-25 07:14:51 +00:00
|
|
|
{ particleTimeToLive :: Double
|
2016-12-20 10:29:03 +00:00
|
|
|
-- ^ Time to live in seconds
|
2016-12-25 07:14:51 +00:00
|
|
|
, particleCreation :: Double
|
|
|
|
-- ^ Creation time of particle in seconds form program start
|
2016-12-23 13:18:39 +00:00
|
|
|
, particlePosition :: (Double, Double)
|
2016-12-20 10:29:03 +00:00
|
|
|
-- ^ Position of particle on canvas
|
2016-12-23 13:18:39 +00:00
|
|
|
, particleRotation :: Angle
|
2016-12-20 10:29:03 +00:00
|
|
|
-- ^ Particle rotation
|
2016-12-23 13:18:39 +00:00
|
|
|
, particleVelocity :: (Int, Int)
|
2016-12-20 10:29:03 +00:00
|
|
|
-- ^ particle velocity as vector of pixels per second
|
2016-12-23 13:18:39 +00:00
|
|
|
, particlePitchRate :: Angle
|
2016-12-20 10:29:03 +00:00
|
|
|
-- ^ Rotational velocity of particle in angle per second
|
2016-12-23 13:18:39 +00:00
|
|
|
, particleRootNode :: G.GeglNode
|
|
|
|
-- ^ Root 'G.GeglNode' of 'Particle'
|
|
|
|
, particleNodeGraph :: Map String G.GeglNode
|
|
|
|
-- ^ Node Graph of 'G.GeglNodes' per particle
|
|
|
|
, particleStackCont :: G.GeglNode
|
|
|
|
-- ^ 'G.GeglNode' to connect other 'Particle's to
|
|
|
|
, particleDrawFlange :: G.GeglNode
|
|
|
|
-- ^ 'G.GeglNode' to connect draw actions to
|
2017-02-17 16:15:06 +00:00
|
|
|
} deriving (Eq)
|
2016-12-13 10:08:49 +00:00
|
|
|
|
2016-12-25 07:14:51 +00:00
|
|
|
-- | The particle system
|
2016-12-13 10:08:49 +00:00
|
|
|
data ParticleSystem = ParticleSystem
|
2016-12-25 07:14:51 +00:00
|
|
|
{ partSysParts :: ParticleStorage
|
|
|
|
, partSysNode :: G.GeglNode
|
|
|
|
, partSysBuffer :: G.GeglBuffer
|
|
|
|
}
|
|
|
|
|
|
|
|
-- | The particle storage datatype
|
|
|
|
data ParticleStorage = ParticleStorage
|
|
|
|
{ partStorLatest :: Maybe Particle -- ^ The particle stored last
|
|
|
|
, partStorList :: [Particle] -- ^ List of particles in ascending order of remaining lifetime
|
2016-12-13 10:08:49 +00:00
|
|
|
}
|