{-| This module provides every single type defined within the spice framework. This allows people to write functions on data structures without being concerned about recursive imports (and thereby being unable to compile) due to the fact that this file does not and WILL NEVER import any other local libraries. -} module FRP.Spice.Internal.Types where -------------------- -- Global Imports -- import qualified Data.Map.Strict as Map import Graphics.Rendering.OpenGL import Graphics.UI.GLFW as GLFW import Control.Applicative import FRP.Elerea.Param import Data.Default import Data.Monoid ---------- -- Code -- {-| A data type that can be composed (so long as the data stored is a Monoid) in do-notation. -} data DoListT a b = DoListT a b {-| A type synonym for the @'DoListT'@ that should be used. -} type DoList a = DoListT a () {-| A Functor instance to satisfy the Applicative's requirements. -} instance Functor (DoListT a) where fmap fn (DoListT a b) = DoListT a $ fn b {-| An Applicative instance to satisfy the Monad's requirements in the future. -} instance Monoid a => Applicative (DoListT a) where pure b = DoListT mempty b (DoListT a' bfn) <*> (DoListT a b) = DoListT (a `mappend` a') $ bfn b {-| The Monad instance to allow the DoList to compose through do-notation. -} instance Monoid a => Monad (DoListT a) where return = pure (DoListT a b) >>= fn = let (DoListT a' b') = fn b in DoListT (mappend a a') b' {-| The config that is used to define the GLFW window's properties. -} data WindowConfig = WindowConfig { getWindowWidth :: Int , getWindowHeight :: Int , getWindowFullscreen :: Bool , getWindowTitle :: String } {-| The default state for a @'WindowConfig'@. -} instance Default WindowConfig where def = WindowConfig { getWindowWidth = 640 , getWindowHeight = 480 , getWindowFullscreen = False , getWindowTitle = "Spice Application" } {-| A data type representing a color as 4 floats (r, g, b, a) representing red, green, blue, and the alpha channel respectively. The floats should range from 0 to 1, representing 0 to 255 in more classical representations. -} data Color = Color { colorRed :: Float , colorGreen :: Float , colorBlue :: Float , colorAlpha :: Float } {-| A data type that stores two values. It can be used to perform basic vector logic. It should be noted that the @'Vector'@ logic provided in this library is not linear-algebra style vector logic. -} data Vector a = Vector a a {-| The default state for a @'Vector'@. -} instance Default a => Default (Vector a) where def = Vector def def {-| A functor instance to apply a function onto both values stored in a @'Vector'@. -} instance Functor Vector where fmap fn (Vector x y) = Vector (fn x) (fn y) {-| An applicative instance to allow one to write functions on @'Vector'@s that have separate functions for both values. -} instance Applicative Vector where pure a = Vector a a (Vector fnx fny) <*> (Vector x y) = Vector (fnx x) (fny y) {-| A wrapper around the sinks for the mouse position, mouse buttons, and keyboard keys. -} data Sinks = Sinks { mousePosSink :: Vector Float -> IO () , mouseButtonSink :: Map.Map MouseButton (Bool -> IO ()) , keySink :: Map.Map Key (Bool -> IO ()) } {-| A data structure that represents the current state of the input. Used in the @'InputContainer'@ along with the @'Sink'@ to handle all input -- updating and referencing. -} data Input = Input { mousePos :: Vector Float , mouseButton :: Map.Map MouseButton Bool , key :: Map.Map Key Bool } {-| The container for both @'Sink'@ and @'Input'@. The @'Input'@ is stored within a @'Signal'@ so it may be used within the FRP/Elerea part of the framework. -} data InputContainer = InputContainer { getSinks :: Sinks , getInput :: Signal Input } {-| Containing all of the necessary information for rendering an image on screen (aside from the position where the sprite should be rendered.) -} data Sprite = Sprite { spriteTex :: TextureObject , spriteSize :: Vector Float } {-| Representing the loading of an asset into the game framework. -} data LoadAsset = LoadSprite FilePath {-| A @'DoList'@ synonym for @'LoadAsset'@. -} type LoadAssets = DoList [LoadAsset] {-| Storing the loaded assets in a single data structure. -} data Assets = Assets { sprites :: Map.Map FilePath Sprite } {-| The default state for an @'Assets'@. -} instance Default Assets where def = Assets { sprites = Map.fromList [] } {-| A type synonym to imply that functions performed in this function should solely render. -} type Scene = IO () {-| A type synonym to make the delta time (in the @'Game'@ definition) more self documenting. -} type DeltaTime = Float {-| The requirements for a given data structure to be used as a game within the framework. -} class Game a where update :: DeltaTime -> Input -> a -> a render :: Assets -> a -> Scene loadAssets :: a -> LoadAssets