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