packages feed

pine-0.1.0.3: src/Pine/Internal/Types.hs

module Pine.Internal.Types where

import qualified SDL -- (Event, Rectangle(..), WindowConfig, Keycode(..))
import qualified SDL.Vect as SDLV
import Foreign.C.Types (CInt)
import Data.Int (Int32)
import Linear (V2)

import Data.Semigroup
import Control.Monad.State -- see below

data Event
  = Load -- ^ very first event to be called
  | Step -- ^ Other events may be called multiple times per frame, but the Step event occurs once per frame
  | KeyPressed  SDL.Keycode
  | KeyReleased SDL.Keycode
  | KeyState --(Key -> Bool)
  | MousePosition (V2 Int32)
  | MouseMoved (V2 Int32)
  | MouseClick MouseButton
  | MouseScroll -- WIP
  | WindowPosition (Double, Double)
  | WindowResized (Double,Double)
  | WindowMinimized
--  | AudioState AudioState
  | WindowClose
  | SDLEvent SDL.Event--(raw SDL data, shouldn't be used typically)
  deriving (Eq, Show)

data MouseButton = MouseLeft | MouseRight | MouseMiddle deriving (Eq, Show)

data Return = Cont | Log String | Quit | QuitWithLog String -- change config settings (like resize window), show/hide mouse

-- | Most apps or games do not run forever, and sometimes people like to log things while building up a project.
-- In order for the user of this framework to do that, they must be able to send values back to the main control loop.
type PineState s = State s Return

cont,quit :: PineState s
cont = pure Cont
quit = pure Quit

contLog,quitLog :: String -> PineState s
contLog s = pure $ Log s
quitLog s = pure $ QuitWithLog s


-- | Drawable class contains the draw function, which takes a type and converts it into a `Scene`
class Drawable d where
  draw :: d -> Scene

type DeltaTime = Double

-- | Stateful class contains initial and update functions. Any objects in your game, including the overrall world, will update according to events that occur
class Stateful s where
  update :: DeltaTime -> Event -> PineState s

-- | An Image which is converted into a `Texture`
data Image = Image
  { imageSrc  :: FilePath -- ^ source file
  , imageQuad :: Maybe (SDL.Rectangle CInt) -- ^ quad, or Nothing for entire image
  , imageRect :: Maybe (SDL.Rectangle CInt) -- ^ location and dimensions, or Nothing to fit entire window
  } deriving (Eq, Show) -- put in other info later (like dimensions, quads, etc)

-- | Construct a rectangle
rect :: ()
     => CInt -- ^ x
     -> CInt -- ^ y
     -> CInt -- ^ w
     -> CInt -- ^ h
     -> SDL.Rectangle CInt
rect x y w h = SDL.Rectangle (SDLV.P $ SDLV.V2 x y) (SDLV.V2 w h)


-- | Create an image from a file
newImage :: ()
         => FilePath -- ^ The source of the image file
         -> Maybe (SDL.Rectangle CInt) -- ^ A quad or Nothing for the whole image
         -> Maybe (SDL.Rectangle CInt) -> Image -- ^ The rendering target: The location of the image on the window and its size, or Nothing to take up the whole window.
newImage = Image

newtype Audio = Audio -- WIP
  { audiosrc :: FilePath
  } deriving (Eq, Show)

data AudioState = Playing Audio | Stopped Audio deriving (Eq, Show) --WIP

data Playback = Playback Audio | Continue Audio | Stop Audio deriving (Eq, Show) -- WIP

data Media = MImage Image | MAudio | MText deriving (Eq, Show) -- WIP (TODO: replace instances of Image in Scene with Media

-- | A Scene can be empty, a single `Image`, or a group of `Image`s. (WIP: Later text and other stuff will be added)
data Scene = EmptyScene | SingleScene Media | MultiScene [Media] deriving (Eq, Show)

instance Semigroup Scene where
  (<>) (SingleScene img1) (SingleScene img2) = MultiScene [img1,img2]
  (<>) (MultiScene imgs1) (MultiScene imgs2) = MultiScene $ imgs1 <> imgs2
  (<>) (SingleScene img) (MultiScene imgs) = MultiScene $ img:imgs
  (<>) (MultiScene imgs) (SingleScene img) = MultiScene $ imgs <> [img]
  (<>) EmptyScene c = c
  (<>) c EmptyScene = c

instance Monoid Scene where
  mempty = EmptyScene
  mappend = (<>)

-- | Convert a single `Image` into a `Scene`
fromImage :: Image -> Scene
fromImage = SingleScene . MImage