gloss-1.0.0.0: Graphics/Gloss/Internals/Interface/ViewPort/KeyMouse.hs
{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE PatternGuards #-}
module Graphics.Gloss.Internals.Interface.ViewPort.KeyMouse
(callback_viewPort_keyMouse)
where
import Graphics.Gloss.ViewPort
import Graphics.Gloss.Geometry.Angle
import Graphics.Gloss.Geometry.Vector
import Graphics.Gloss.Internals.Interface.ViewPort.Command
import Graphics.Gloss.Internals.Interface.Callback
import qualified Graphics.Gloss.Internals.Interface.ViewPort.ControlState as VPC
import qualified Graphics.UI.GLUT as GLUT
import qualified Graphics.Rendering.OpenGL.GL as GL
import Data.IORef
import Control.Monad
-- | Callback to handle keyboard and mouse button events
-- for controlling the viewport.
callback_viewPort_keyMouse
:: IORef ViewPort -- ^ ref to ViewPort state
-> IORef VPC.State -- ^ ref to ViewPort Control state
-> Callback
callback_viewPort_keyMouse portRef controlRef
= KeyMouse (viewPort_keyMouse portRef controlRef)
viewPort_keyMouse portRef controlRef key keyState keyMods pos
= do commands <- controlRef `getsIORef` VPC.stateCommands
{- putStr $ "keyMouse key = " ++ show key ++ "\n"
++ "keyMouse keyState = " ++ show keyState ++ "\n"
++ "keyMouse keyMods = " ++ show keyMods ++ "\n"
-}
viewPort_keyMouse2 commands portRef controlRef key keyState keyMods pos
viewPort_keyMouse2
commands portRef controlRef
key keyState keyMods
pos
-- restore viewport
| isCommand commands CRestore key keyMods
, keyState == GLUT.Down
= do portRef `modifyIORef` \s -> s
{ viewPortScale = 1
, viewPortTranslate = (0, 0)
, viewPortRotate = 0 }
GLUT.postRedisplay Nothing
-- zoom ----------------------------------------
-- zoom out
| isCommand commands CBumpZoomOut key keyMods
, keyState == GLUT.Down
= controlZoomOut portRef controlRef
-- zoom in
| isCommand commands CBumpZoomIn key keyMods
, keyState == GLUT.Down
= controlZoomIn portRef controlRef
-- bump -------------------------------------
-- bump left
| isCommand commands CBumpLeft key keyMods
, keyState == GLUT.Down
= motionBump portRef controlRef (20, 0)
-- bump right
| isCommand commands CBumpRight key keyMods
, keyState == GLUT.Down
= motionBump portRef controlRef (-20, 0)
-- bump up
| isCommand commands CBumpUp key keyMods
, keyState == GLUT.Down
= motionBump portRef controlRef (0, 20)
-- bump down
| isCommand commands CBumpDown key keyMods
, keyState == GLUT.Down
= motionBump portRef controlRef (0, -20)
-- bump clockwise
| isCommand commands CBumpClockwise key keyMods
, keyState == GLUT.Down
= do portRef `modifyIORef` \s -> s {
viewPortRotate
= (\r -> r + 5)
$ viewPortRotate s }
GLUT.postRedisplay Nothing
-- bump anti-clockwise
| isCommand commands CBumpCClockwise key keyMods
, keyState == GLUT.Down
= do portRef `modifyIORef` \s -> s {
viewPortRotate
= (\r -> r - 5)
$ viewPortRotate s }
GLUT.postRedisplay Nothing
-- translation --------------------------------------
-- start
| isCommand commands CTranslate key keyMods
, keyState == GLUT.Down
= do let GL.Position posX posY = pos
controlRef `modifyIORef` \s -> s {
VPC.stateTranslateMark
= Just ( fromIntegral posX
, fromIntegral posY) }
GLUT.postRedisplay Nothing
-- end
| isCommand commands CTranslate key keyMods
, keyState == GLUT.Up
= do controlRef `modifyIORef` \s -> s {
VPC.stateTranslateMark = Nothing }
GLUT.postRedisplay Nothing
-- rotation ---------------------------------------
-- start
| isCommand commands CRotate key keyMods
, keyState == GLUT.Down
= do let GL.Position posX posY = pos
controlRef `modifyIORef` \s -> s {
VPC.stateRotateMark
= Just ( fromIntegral posX
, fromIntegral posY) }
GLUT.postRedisplay Nothing
-- end
| isCommand commands CRotate key keyMods
, keyState == GLUT.Up
= do controlRef `modifyIORef` \s -> s {
VPC.stateRotateMark = Nothing }
GLUT.postRedisplay Nothing
-- carry on
| otherwise
= return ()
controlZoomIn portRef controlRef
= do scaleStep <- controlRef `getsIORef` VPC.stateScaleStep
portRef `modifyIORef` \s -> s {
viewPortScale = viewPortScale s * scaleStep }
GLUT.postRedisplay Nothing
controlZoomOut portRef controlRef
= do scaleStep <- controlRef `getsIORef` VPC.stateScaleStep
portRef `modifyIORef` \s -> s {
viewPortScale = viewPortScale s / scaleStep }
GLUT.postRedisplay Nothing
motionBump
portRef controlRef
(bumpX, bumpY)
= do
(transX, transY)
<- portRef `getsIORef` viewPortTranslate
s <- portRef `getsIORef` viewPortScale
r <- portRef `getsIORef` viewPortRotate
let offset = (bumpX / s, bumpY / s)
let (oX, oY) = rotateV (degToRad r) offset
portRef `modifyIORef` \s -> s
{ viewPortTranslate
= ( transX - oX
, transY + oY) }
GLUT.postRedisplay Nothing
getsIORef ref fun
= liftM fun $ readIORef ref