Files
loop/src/Dodge/Event.hs
T

181 lines
7.5 KiB
Haskell

{- |
Module : Dodge.Event
Description : Direct event handling
Deals with direct events.
This could include individual key or mouse presses.
However, we cannot handle multiple keys held down at once here,
(eg left mouse button + right mouse button)
because these are separate events.
Nor could we handle continuous mouse button input.
Instead we store button presses (in a Map) and deal with the combinations in
the simulation step; in particular see 'updatePressedButtons'.
-}
module Dodge.Event
( handleEvent
) where
import Dodge.Terminal
import Dodge.Tweak
import Dodge.HeldScroll
import Dodge.InputFocus
import Dodge.Combine
import Dodge.Event.Keyboard
import Dodge.Base
import Dodge.Data
import Dodge.PreloadData
import Dodge.Inventory
import Dodge.SoundLogic
import qualified IntMapHelp as IM
import Control.Lens
import Data.Maybe
import qualified Data.Map.Strict as M
import qualified Data.Set as S
import qualified Data.Text as T
import SDL
handleEvent :: Event -> Universe -> IO (Maybe Universe)
handleEvent e = case eventPayload e of
TextInputEvent tev -> return . Just . handleTextInput (textInputEventText tev)
KeyboardEvent kev -> handleKeyboardEvent kev
MouseMotionEvent mmev -> return . handleMouseMotionEvent mmev
MouseButtonEvent mbev -> return . Just . over uvWorld (handleMouseButtonEvent mbev)
MouseWheelEvent mwev -> return . handleMouseWheelEvent mwev
WindowSizeChangedEvent sev -> handleResizeEvent sev
WindowMovedEvent mev -> return . handleWindowMoveEvent mev
_ -> return . Just
handleMouseMotionEvent :: MouseMotionEventData -> Universe -> Maybe Universe
handleMouseMotionEvent mmev u = Just $ u & uvWorld . mousePos .~ V2
(fromIntegral x - 0.5*_windowX cfig)
(0.5*_windowY cfig - fromIntegral y)
where
cfig = _uvConfig u
P (V2 x y) = mouseMotionEventPos mmev
handleMouseButtonEvent :: MouseButtonEventData -> World -> World
handleMouseButtonEvent mbev = case mouseButtonEventMotion mbev of
Released -> mouseButtons . at thebutton .~ Nothing
Pressed -> mouseButtons . at thebutton ?~ False
where
thebutton = mouseButtonEventButton mbev
{- | Sets window position in config. -}
handleWindowMoveEvent :: WindowMovedEventData -> Universe -> Maybe Universe
handleWindowMoveEvent mev = Just
. (uvConfig . windowPosX .~ fromIntegral x)
. (uvConfig . windowPosY .~ fromIntegral y)
where
P (V2 x y) = windowMovedEventPosition mev
{- | Resets the world window size, and resizes the fbo that gets the light map drawn into it. -}
-- using a sideeffect here for the io change seems to work better, more testing
-- later may be a good idea
handleResizeEvent :: WindowSizeChangedEventData -> Universe -> IO (Maybe Universe)
handleResizeEvent sev u = return . Just $ u
& uvConfig . windowX .~ fromIntegral x
& uvConfig . windowY .~ fromIntegral y
& uvIOEffects %~ sideEffectUpdatePreload divRes x y
where
x = fromIntegral x'
y = fromIntegral y'
V2 x' y' = windowSizeChangedEventSize sev
divRes = resFactorNum $ u ^. uvConfig . graphics_resolution_factor
handleMouseWheelEvent :: MouseWheelEventData -> Universe -> Maybe Universe
handleMouseWheelEvent mwev w = case _menuLayers w of
[] -> case mouseWheelEventPos mwev of
V2 _ y -> Just $ w & uvWorld %~ wheelEvent (fromIntegral y)
_ -> Just w
wheelEvent :: Float -> World -> World
wheelEvent y w = case _hudElement $ _hud (_cWorld w) of
DisplayCarte
| rbDown -> w & cWorld . hud . carteZoom %~ min 0.75 . max 0.05 . ((1+y*0.1) * )
| otherwise -> w & cWorld . selLocation %~ (`mod` numLocs) . (+ yi)
DisplayInventory NoSubInventory
-- functions that modify the inventory should be centralised so that
-- this lock can be sensibly applied, perhaps
| _crInvLock (_creatures (_cWorld w) IM.! _yourID (_cWorld w)) -> w
| rbDown -> case (yourItem w ^? _Just . itUse . heldScroll,_rbOptions w) of
(_,EquipOptions{}) -> scrollRBOption y w
(Nothing,_) -> closeObjScrollDir y w
(Just f,_) -> w & cWorld . creatures . ix 0 . crInv . ix (crSel $ you w) %~ doHeldScroll f y (you w)
| lbDown -> w & cWorld . cameraZoom +~ y
| invKeyDown -> changeSwapInvSel yi w
| otherwise -> stopSoundFrom (CrReloadSound 0) $ changeAugInvSel yi w
DisplayInventory TweakInventory
| invKeyDown && rbDown -> w & moveTweakSel yi
| invKeyDown -> stopSoundFrom (CrReloadSound 0) $ changeInvSel yi w
| rbDown -> w & changeTweakParam yi
| otherwise -> w & moveTweakSel yi
DisplayInventory (CombineInventory _) -> w
& cWorld . hud . hudElement . subInventory . combineInvSel . _Just %~ ((`mod` numcombs) . subtract yi)
DisplayInventory (DisplayTerminal tmid)
| rbDown && inTermFocus w -> guardDisconnectedID tmid w $ w
& cWorld . terminals . ix tmid %~ updatetermsubsel
| inTermFocus w -> w
& cWorld . terminals . ix tmid %~ updatetermsel
_ -> w
where
updatetermsel tm = case tm ^? tmInput . tiSel of
Nothing -> tm & tmInput . tiSel .~ (0,0)
Just (i,_) -> let newi = (i - yi) `mod` length (scrollCommands tm)
in tm & setInput newi 0 w
updatetermsubsel tm = case tm ^? tmInput . tiSel of
Nothing -> tm & tmInput . tiSel .~ (0,0)
Just (i,j) -> let newj = (j - yi) `mod` length (getArguments' (scrollCommands tm !! i) tm w)
in tm & setInput i newj w
setInput i j w' tm = tm
& tmInput . tiSel .~ (i,j)
& tmInput . tiText .~ T.pack (_tcString tc ++ " " ++ arg)
where
tc = scrollCommands tm !! i
arg = getArguments' tc tm w' !! j
numcombs = length $ combineItemListYou w
yi = round $ signum y
numLocs = (fst . IM.findMax $ _seenLocations (_cWorld w)) + 1
rbDown = ButtonRight `M.member` _mouseButtons w
lbDown = ButtonLeft `M.member` _mouseButtons w
invKeyDown = ScancodeCapsLock `S.member` _keys w
getArguments' :: TerminalCommand -> Terminal -> World -> [String]
getArguments' tc tm = ("" :) . getArguments tc tm
getArguments :: TerminalCommand -> Terminal -> World -> [String]
getArguments tc tm w = case doTerminalCommandEffect (_tcEffect tc) tm w of
NoArguments {} -> []
OneArgument _ m -> M.keys m
scrollCommands :: Terminal -> [TerminalCommand]
scrollCommands = (nullCommand :) . _tmScrollCommands
nullCommand :: TerminalCommand
nullCommand = TerminalCommand
{ _tcString = ""
, _tcAlias = []
, _tcHelp = ""
, _tcEffect = TerminalCommandEffectNone -- \_ _ -> NoArguments []
}
scrollRBOption :: Float -> World -> World
scrollRBOption y w
| y < 0 = w & rbOptions . opSel %~ (min (length (_opEquip (_rbOptions w))-1) . (+1))
| y > 0 = w & rbOptions . opSel %~ (max 0 . subtract 1)
| otherwise = w
moveTweakSel :: Int -> World -> World
moveTweakSel i w = case yourItem w ^? _Just . itTweaks . tweakParams of
Just l -> w & cWorld . creatures . ix (_yourID (_cWorld w)) . crInv . ix (crSel (you w))
. itTweaks . tweakSel %~ (`mod` length l) . subtract i
_ -> w
changeTweakParam :: Int -> World -> World
changeTweakParam i w = w
& cWorld . creatures . ix (_yourID (_cWorld w)) . crInv . ix (crSel (you w)) %~
( (itTweaks . tweakParams . ix paramid . tweakVal .~ x)
. doTweak (_tweakType params) x)
where
tweaks = _itTweaks . fromJust $ yourItem w
params = _tweakParams tweaks IM.! paramid
x = (_tweakVal params + i) `mod` _tweakMax params
paramid = _tweakSel tweaks