packages feed

tcod-haskell-0.2.0.0: src/Game/TCOD/ConsoleTypes.hsc

{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE CPP                      #-}
module Game.TCOD.ConsoleTypes(
    TCODConsole(..)
  , TCODKeyCode(..)
  , TCODKey(..)
  , defaultTCODKey
  , tcodKeyTextSize
  , TCODChar(..)
  , TCODColorControl(..)
  , TCODBackgroundFlag(..)
  , TCODKeyStatus(..)
  , TCODFontFlag(..)
  , combineFontFlags
  , TCODRenderer(..)
  , TCODAlignment(..)
  ) where

import Data.Bits
import Data.Char
import Data.Maybe
import Foreign
import Foreign.C
import GHC.Generics

import Game.TCOD.Context as C

import qualified Data.Foldable as F

context tcodContext
#include "libtcod/console_types.h"
include "libtcod/console_types.h"
include "string.h"

-- | Tag to track pointer to `TCOD_console_t`
newtype TCODConsole = TCODConsole { unTCODConsole :: Ptr () }
  deriving (Eq, Ord, Show, Generic)

-- | Names for keyboard keys
data TCODKeyCode =
    KeyNone
  | KeyEscape
  | KeyBackspace
  | KeyTab
  | KeyEnter
  | KeyShift
  | KeyControl
  | KeyAlt
  | KeyPause
  | KeyCapslock
  | KeyPageUp
  | KeyPageDown
  | KeyEnd
  | KeyHome
  | KeyUp
  | KeyLeft
  | KeyRight
  | KeyDown
  | KeyPrintScreen
  | KeyInsert
  | KeyDelete
  | KeyLWin
  | KeyRWin
  | KeyApps
  | Key0
  | Key1
  | Key2
  | Key3
  | Key4
  | Key5
  | Key6
  | Key7
  | Key8
  | Key9
  | KeyKp0
  | KeyKp1
  | KeyKp2
  | KeyKp3
  | KeyKp4
  | KeyKp5
  | KeyKp6
  | KeyKp7
  | KeyKp8
  | KeyKp9
  | KeyKpAdd
  | KeyKpSub
  | KeyKpDiv
  | KeyKpMul
  | KeyKpDec
  | KeyKpEnter
  | KeyF1
  | KeyF2
  | KeyF3
  | KeyF4
  | KeyF5
  | KeyF6
  | KeyF7
  | KeyF8
  | KeyF9
  | KeyF10
  | KeyF11
  | KeyF12
  | KeyNumLock
  | KeyScrollLock
  | KeySpace
  | KeyChar
  | KeyText
  deriving (Eq, Ord, Show, Read, Enum, Bounded, Generic)

tcodKeyTextSize :: Int
tcodKeyTextSize = 32

-- | Key data: special code or character or text
data TCODKey = TCODKey {
  keyCode    :: !TCODKeyCode
, keyChar    :: !(Maybe Char) -- Just if keyCode == KeyChar
, keyText    :: !(Maybe String) -- Just if keyCode == KeyText
, keyPressed :: !Bool -- ^ does this correspond to a key press or key release event ?
, keyLAlt    :: !Bool
, keyLCtrl   :: !Bool
, keyLMeta   :: !Bool
, keyRAlt    :: !Bool
, keyRCtrl   :: !Bool
, keyRMeta   :: !Bool
, keyShift   :: !Bool
} deriving (Eq, Show, Generic)

-- | Get 'TCODKey' with default values
defaultTCODKey :: TCODKey
defaultTCODKey = TCODKey {
    keyCode = KeyNone
  , keyChar = Nothing
  , keyText = Nothing
  , keyPressed = False
  , keyLAlt = False
  , keyLCtrl = False
  , keyLMeta = False
  , keyRAlt = False
  , keyRCtrl = False
  , keyRMeta = False
  , keyShift = False
  }

instance Storable TCODKey where
  sizeOf _ = #{size TCOD_key_t}
  alignment _ = #{alignment TCOD_key_t}
  poke p TCODKey{..} = withCString (take (tcodKeyTextSize-1) $ fromMaybe "" keyText) $ \text' -> do
    #{poke TCOD_key_t, vk} p ((fromIntegral :: Int -> CInt) . fromEnum $ keyCode)
    #{poke TCOD_key_t, c} p ((fromIntegral :: Int -> CChar) . fromMaybe 0 . fmap ord $ keyChar)
    [C.exp| void { strcpy(&(((TCOD_key_t*)$(void* p'))->text[0]), $(const char* text')) } |]
    #{poke TCOD_key_t, pressed} p keyPressed
    #{poke TCOD_key_t, lalt} p keyLAlt
    #{poke TCOD_key_t, lctrl} p keyLCtrl
    #{poke TCOD_key_t, lmeta} p keyLMeta
    #{poke TCOD_key_t, ralt} p keyRAlt
    #{poke TCOD_key_t, rctrl} p keyRCtrl
    #{poke TCOD_key_t, rmeta} p keyRMeta
    #{poke TCOD_key_t, shift} p keyShift
    where p' = castPtr p
  peek p = do
    let p' = castPtr p
    kcode <- toEnum . (fromIntegral :: CInt -> Int) <$> #{peek TCOD_key_t, vk} p
    c <- peekCharField kcode
    txt <- peekTextField kcode =<< [C.exp| char* {&((TCOD_key_t*)$(void* p'))->text[0]}|]
    TCODKey
      <$> (pure kcode)
      <*> (pure c)
      <*> (pure txt)
      <*> (#{peek TCOD_key_t, pressed} p)
      <*> (#{peek TCOD_key_t, lalt} p)
      <*> (#{peek TCOD_key_t, lctrl} p)
      <*> (#{peek TCOD_key_t, lmeta} p)
      <*> (#{peek TCOD_key_t, ralt} p)
      <*> (#{peek TCOD_key_t, rctrl} p)
      <*> (#{peek TCOD_key_t, rmeta} p)
      <*> (#{peek TCOD_key_t, shift} p)
    where
      peekCharField KeyChar = Just . chr . (fromIntegral :: CChar -> Int) <$> #{peek TCOD_key_t, c} p
      peekCharField _ = pure Nothing
      peekTextField KeyText vptr = Just <$> peekCString vptr
      peekTextField _ _ = pure Nothing

-- | Special characters
data TCODChar =
  -- single walls
    CharHline
  | CharVline
  | CharNe
  | CharNw
  | CharSe
  | CharSw
  | CharTeew
  | CharTeee
  | CharTeen
  | CharTees
  | CharCross
  --  double walls
  | CharDhline
  | CharDvline
  | CharDne
  | CharDnw
  | CharDse
  | CharDsw
  | CharDteew
  | CharDteee
  | CharDteen
  | CharDtees
  | CharDcross
  -- blocks
  | CharBlock1
  | CharBlock2
  | CharBlock3
  -- arrows
  | CharArrowN
  | CharArrowS
  | CharArrowE
  | CharArrowW
  -- arrows without tail
  | CharArrow2N
  | CharArrow2S
  | CharArrow2E
  | CharArrow2W
  -- double arrows
  | CharDarrowH
  | CharDarrowV
  -- GUI stuff
  | CharCheckboxUnset
  | CharCheckboxSet
  | CharRadioUnset
  | CharRadioSet
  -- sub-pixel resolution kit
  | CharSubpNw
  | CharSubpNe
  | CharSubpN
  | CharSubpSe
  | CharSubpDiag
  | CharSubpE
  | CharSubpSw
  -- miscellaneous
  | CharSmilie
  | CharSmilieInv
  | CharHeart
  | CharDiamond
  | CharClub
  | CharSpade
  | CharBullet
  | CharBulletInv
  | CharMale
  | CharFemale
  | CharNote
  | CharNoteDouble
  | CharLight
  | CharExclamDouble
  | CharPilcrow
  | CharSection
  | CharPound
  | CharMultiplication
  | CharFunction
  | CharReserved
  | CharHalf
  | CharOneQuarter
  | CharCopyright
  | CharCent
  | CharYen
  | CharCurrency
  | CharThreeQuarters
  | CharDivision
  | CharGrade
  | CharUmlaut
  | CharPow1
  | CharPow3
  | CharPow2
  | CharBulletSquare
  deriving (Eq, Ord, Show, Read, Generic)

instance Enum TCODChar where
  toEnum n = case n of
    196 -> CharHline
    179 -> CharVline
    191 -> CharNe
    218 -> CharNw
    217 -> CharSe
    192 -> CharSw
    180 -> CharTeew
    195 -> CharTeee
    193 -> CharTeen
    194 -> CharTees
    197 -> CharCross
    205 -> CharDhline
    186 -> CharDvline
    187 -> CharDne
    201 -> CharDnw
    188 -> CharDse
    200 -> CharDsw
    185 -> CharDteew
    204 -> CharDteee
    202 -> CharDteen
    203 -> CharDtees
    206 -> CharDcross
    176 -> CharBlock1
    177 -> CharBlock2
    178 -> CharBlock3
    24 -> CharArrowN
    25 -> CharArrowS
    26 -> CharArrowE
    27 -> CharArrowW
    30 -> CharArrow2N
    31 -> CharArrow2S
    16 -> CharArrow2E
    17 -> CharArrow2W
    29 -> CharDarrowH
    18 -> CharDarrowV
    224 -> CharCheckboxUnset
    225 -> CharCheckboxSet
    9 -> CharRadioUnset
    10 -> CharRadioSet
    226 -> CharSubpNw
    227 -> CharSubpNe
    228 -> CharSubpN
    229 -> CharSubpSe
    230 -> CharSubpDiag
    231 -> CharSubpE
    232 -> CharSubpSw
    1 -> CharSmilie
    2 -> CharSmilieInv
    3 -> CharHeart
    4 -> CharDiamond
    5 -> CharClub
    6 -> CharSpade
    7 -> CharBullet
    8 -> CharBulletInv
    11 -> CharMale
    12 -> CharFemale
    13 -> CharNote
    14 -> CharNoteDouble
    15 -> CharLight
    19 -> CharExclamDouble
    20 -> CharPilcrow
    21 -> CharSection
    156 -> CharPound
    158 -> CharMultiplication
    159 -> CharFunction
    169 -> CharReserved
    171 -> CharHalf
    172 -> CharOneQuarter
    184 -> CharCopyright
    189 -> CharCent
    190 -> CharYen
    207 -> CharCurrency
    243 -> CharThreeQuarters
    246 -> CharDivision
    248 -> CharGrade
    249 -> CharUmlaut
    251 -> CharPow1
    252 -> CharPow3
    253 -> CharPow2
    254 -> CharBulletSquare
    _   -> CharSmilie -- default case

  fromEnum v = case v of
    CharHline -> 196
    CharVline -> 179
    CharNe -> 191
    CharNw -> 218
    CharSe -> 217
    CharSw -> 192
    CharTeew -> 180
    CharTeee -> 195
    CharTeen -> 193
    CharTees -> 194
    CharCross -> 197
    CharDhline -> 205
    CharDvline -> 186
    CharDne -> 187
    CharDnw -> 201
    CharDse -> 188
    CharDsw -> 200
    CharDteew -> 185
    CharDteee -> 204
    CharDteen -> 202
    CharDtees -> 203
    CharDcross -> 206
    CharBlock1 -> 176
    CharBlock2 -> 177
    CharBlock3 -> 178
    CharArrowN -> 24
    CharArrowS -> 25
    CharArrowE -> 26
    CharArrowW -> 27
    CharArrow2N -> 30
    CharArrow2S -> 31
    CharArrow2E -> 16
    CharArrow2W -> 17
    CharDarrowH -> 29
    CharDarrowV -> 18
    CharCheckboxUnset -> 224
    CharCheckboxSet -> 225
    CharRadioUnset -> 9
    CharRadioSet -> 10
    CharSubpNw -> 226
    CharSubpNe -> 227
    CharSubpN -> 228
    CharSubpSe -> 229
    CharSubpDiag -> 230
    CharSubpE -> 231
    CharSubpSw -> 232
    CharSmilie -> 1
    CharSmilieInv -> 2
    CharHeart -> 3
    CharDiamond -> 4
    CharClub -> 5
    CharSpade -> 6
    CharBullet -> 7
    CharBulletInv -> 8
    CharMale -> 11
    CharFemale -> 12
    CharNote -> 13
    CharNoteDouble -> 14
    CharLight -> 15
    CharExclamDouble -> 19
    CharPilcrow -> 20
    CharSection -> 21
    CharPound -> 156
    CharMultiplication -> 158
    CharFunction -> 159
    CharReserved -> 169
    CharHalf -> 171
    CharOneQuarter -> 172
    CharCopyright -> 184
    CharCent -> 189
    CharYen -> 190
    CharCurrency -> 207
    CharThreeQuarters -> 243
    CharDivision -> 246
    CharGrade -> 248
    CharUmlaut -> 249
    CharPow1 -> 251
    CharPow3 -> 252
    CharPow2 -> 253
    CharBulletSquare -> 254

-- | Color control flags for console
data TCODColorControl =
    Ctrl_1
  | Ctrl_2
  | Ctrl_3
  | Ctrl_4
  | Ctrl_5
  | CtrlForeRgb
  | CtrlBackRgb
  | CtrlStop
  deriving (Eq, Ord, Show, Read, Generic)

instance Enum TCODColorControl where
  toEnum i = case i of
    1 -> Ctrl_1
    2 -> Ctrl_2
    3 -> Ctrl_3
    4 -> Ctrl_4
    5 -> Ctrl_5
    6 -> CtrlForeRgb
    7 -> CtrlBackRgb
    8 -> CtrlStop
    _ -> CtrlStop

  fromEnum v = case v of
    Ctrl_1 -> 1
    Ctrl_2 -> 2
    Ctrl_3 -> 3
    Ctrl_4 -> 4
    Ctrl_5 -> 5
    CtrlForeRgb -> 6
    CtrlBackRgb -> 7
    CtrlStop -> 8

-- | Background flag
data TCODBackgroundFlag =
    BackgroundNone
  | BackgroundSet
  | BackgroundMultiply
  | BackgroundLighten
  | BackgroundDarken
  | BackgroundScreen
  | BackgroundColorDodge
  | BackgroundColorBurn
  | BackgroundAdd
  | BackgroundAdda
  | BackgroundBurn
  | BackgroundOverlay
  | BackgroundAlph
  | BackgroundDefault
  deriving (Eq, Ord, Show, Read, Enum, Bounded, Generic)

-- | Key status
data TCODKeyStatus = KeyPressed | KeyReleased
  deriving (Eq, Ord, Show, Read, Bounded, Generic)

instance Enum TCODKeyStatus where
  toEnum i = case i of
    1 -> KeyPressed
    2 -> KeyReleased
    _ -> KeyReleased
  fromEnum v = case v of
    KeyPressed -> 1
    KeyReleased -> 2

-- | Custom font flag
data TCODFontFlag =
    FontLayoutAsciiInCol
  | FontLayoutAsciiInRow
  | FontTypeGreyScale
  | FontLayoutTcod
  deriving (Eq, Ord, Show, Read, Bounded, Generic)

instance Enum TCODFontFlag where
  toEnum i = case i of
    1 -> FontLayoutAsciiInCol
    2 -> FontLayoutAsciiInRow
    4 -> FontTypeGreyScale
    8 -> FontLayoutTcod
  fromEnum v = case v of
    FontLayoutAsciiInCol -> 1
    FontLayoutAsciiInRow -> 2
    FontTypeGreyScale -> 4
    FontLayoutTcod -> 8

-- | Assemble flags into int field
combineFontFlags :: Foldable f => f TCODFontFlag -> Int
combineFontFlags = F.foldl' (\acc v -> acc .&. fromEnum v) 0

-- | Availiable renderers
data TCODRenderer =
    RendererGLSL
  | RendererOpenGL
  | RendererSDL
  deriving (Eq, Ord, Show, Read, Enum, Bounded, Generic)

-- | Different text/element alignments
data TCODAlignment =
    AlignLeft
  | AlignRight
  | AlignCenter
  deriving (Eq, Ord, Show, Read, Enum, Bounded, Generic)