131 lines
5.0 KiB
Haskell
131 lines
5.0 KiB
Haskell
{- |
|
|
Module : Dodge.Event
|
|
Description : Direct event handling
|
|
|
|
Deals with direct events.
|
|
This includes individual key or mouse presses, but /not/ continuous held down input.
|
|
We cannot handle multiple keys held down at once here,
|
|
(eg left mouse button + right mouse button)
|
|
because these are separate events.
|
|
Instead we store the events in a set, and deal with the combinations in
|
|
"Dodge.Update".
|
|
-}
|
|
module Dodge.Event
|
|
( handleEvent
|
|
) where
|
|
import Dodge.Event.Keyboard
|
|
import Dodge.Event.Menu
|
|
import Dodge.Data
|
|
import Dodge.Base
|
|
import Dodge.CreatureAction
|
|
import Dodge.SoundLogic
|
|
import Dodge.Inventory
|
|
import Geometry
|
|
import Preload.Update
|
|
|
|
import Control.Lens
|
|
import Data.Maybe
|
|
import Data.Char
|
|
import Data.List
|
|
import Data.Function (on)
|
|
import qualified Data.Set as S
|
|
import qualified Data.IntMap.Strict as IM
|
|
import SDL
|
|
|
|
handleEvent :: World -> Event -> Maybe World
|
|
handleEvent = flip handleEvent'
|
|
|
|
handleEvent' :: Event -> World -> Maybe World
|
|
handleEvent' e = case eventPayload e of
|
|
KeyboardEvent kev -> handleKeyboardEvent kev
|
|
MouseMotionEvent mmev -> handleMouseMotionEvent mmev
|
|
MouseButtonEvent mbev -> handleMouseButtonEvent mbev
|
|
MouseWheelEvent mwev -> handleMouseWheelEvent mwev
|
|
WindowSizeChangedEvent sev -> handleResizeEvent sev
|
|
_ -> Just
|
|
|
|
handleMouseMotionEvent :: MouseMotionEventData -> World -> Maybe World
|
|
handleMouseMotionEvent mmev w
|
|
= Just $ w & mousePos .~ (fromIntegral x - 0.5*_windowX w
|
|
,0.5*_windowY w - fromIntegral y
|
|
)
|
|
where P (V2 x y) = mouseMotionEventPos mmev
|
|
|
|
handleMouseButtonEvent :: MouseButtonEventData -> World -> Maybe World
|
|
handleMouseButtonEvent mbev w = case mouseButtonEventMotion mbev of
|
|
Released -> Just $ over mouseButtons (S.delete but) w
|
|
Pressed -> handlePressedMouseButton but
|
|
$ over mouseButtons (S.insert but) w
|
|
where but = mouseButtonEventButton mbev
|
|
|
|
handleMouseWheelEvent :: MouseWheelEventData -> World -> Maybe World
|
|
handleMouseWheelEvent mwev w = case _menuLayers w of
|
|
[] -> case mouseWheelEventPos mwev of
|
|
V2 x y | y > 0 -> Just (wheelUpEvent w)
|
|
| y < 0 -> Just (wheelDownEvent w)
|
|
| otherwise -> Just w
|
|
_ -> Just w
|
|
|
|
handleResizeEvent :: WindowSizeChangedEventData -> World -> Maybe World
|
|
handleResizeEvent sev = Just
|
|
. set windowX (fromIntegral x)
|
|
. set windowY (fromIntegral y)
|
|
. over sideEffects ( resizeSpareFBO (fromIntegral x) (fromIntegral y) : )
|
|
where
|
|
V2 x y = windowSizeChangedEventSize sev
|
|
|
|
handlePressedMouseButton :: MouseButton -> World -> Maybe World
|
|
handlePressedMouseButton but w
|
|
| but == ButtonMiddle || _carteDisplay w
|
|
= Just $ w & clickMousePos .~ _mousePos w
|
|
| otherwise = Just w
|
|
|
|
wheelUpEvent :: World -> World
|
|
wheelUpEvent w = case _carteDisplay w of
|
|
True | rbDown -> w & carteZoom .~ min 0.75 (z+(0.1*z))
|
|
| otherwise -> w & selLocation %~ (`mod` numLocs) . (\i -> i - 1)
|
|
_ | rbDown -> fromMaybe (closeObjScrollUp w)
|
|
$ (yourItem w ^? itScrollUp)
|
|
<*> pure (_crInvSel (you w))
|
|
<*> pure w
|
|
| lbDown -> w & cameraZoom +~ 0.1
|
|
| otherwise -> upInvPos w
|
|
where
|
|
rbDown = ButtonRight `S.member` _mouseButtons w
|
|
lbDown = ButtonLeft `S.member` _mouseButtons w
|
|
z = _carteZoom w
|
|
numLocs = (fst . IM.findMax $ _seenLocations w) + 1
|
|
|
|
wheelDownEvent :: World -> World
|
|
wheelDownEvent w = case _carteDisplay w of
|
|
True | rbDown -> w & carteZoom .~ max 0.05 (z-(0.1*z))
|
|
| otherwise -> w & selLocation %~ (`mod` numLocs) . (\i -> i + 1)
|
|
False | rbDown -> fromMaybe (closeObjScrollDown w)
|
|
$ (yourItem w ^? itScrollDown)
|
|
<*> pure (_crInvSel (you w))
|
|
<*> pure w
|
|
| lbDown -> w {_cameraZoom = max (_cameraZoom w - 0.1) 0.01}
|
|
| otherwise -> downInvPos w
|
|
where
|
|
rbDown = ButtonRight `S.member` _mouseButtons w
|
|
lbDown = ButtonLeft `S.member` _mouseButtons w
|
|
z = _carteZoom w
|
|
numLocs = (fst . IM.findMax $ _seenLocations w) + 1
|
|
|
|
upInvPos :: World -> World
|
|
upInvPos w = stopSoundFrom (CrReloadSound 0) $ set (creatures . ix (_yourID w) . crInvSel) x w
|
|
where is = IM.keys $ _crInv $ _creatures w IM.! _yourID w
|
|
isis = is ++ is
|
|
x = before (_crInvSel (you w)) isis
|
|
downInvPos :: World -> World
|
|
downInvPos w = stopSoundFrom (CrReloadSound 0) $ set (creatures . ix (_yourID w) . crInvSel) x w
|
|
where is = IM.keys $ _crInv $ _creatures w IM.! _yourID w
|
|
isis = is ++ is
|
|
x = after (_crInvSel (you w)) isis
|
|
|
|
-- these are incomplete: should put in error case here!
|
|
before y (x:z:ys) | y == z = x
|
|
| otherwise = before y (z:ys)
|
|
after y (x:z:ys) | y == x = z
|
|
| otherwise = after y (z:ys)
|