module Graphics.Gloss.Data.ViewPort
        ( ViewPort(..)
        , viewPortInit
        , applyViewPortToPicture
        , invertViewPort )
where
import Graphics.Gloss.Data.Picture
import qualified Graphics.Gloss.Data.Point.Arithmetic as Pt


-- | The 'ViewPort' represents the global transformation applied to the displayed picture.
--      When the user pans, zooms, or rotates the display then this changes the 'ViewPort'.
data ViewPort
        = ViewPort {
        -- | Global translation.
          ViewPort -> (Float, Float)
viewPortTranslate     :: !(Float, Float)

        -- | Global rotation (in degrees).
        , ViewPort -> Float
viewPortRotate        :: !Float

        -- | Global scaling (of both x and y coordinates).
        , ViewPort -> Float
viewPortScale         :: !Float
        }


-- | The initial state of the viewport.
viewPortInit :: ViewPort
viewPortInit :: ViewPort
viewPortInit
        = ViewPort :: (Float, Float) -> Float -> Float -> ViewPort
ViewPort
        { viewPortTranslate :: (Float, Float)
viewPortTranslate     = (Float
0, Float
0)
        , viewPortRotate :: Float
viewPortRotate        = Float
0
        , viewPortScale :: Float
viewPortScale         = Float
1
        }


-- | Translates, rotates, and scales an image according to the 'ViewPort'.
applyViewPortToPicture :: ViewPort  -> Picture -> Picture
applyViewPortToPicture :: ViewPort -> Picture -> Picture
applyViewPortToPicture
        ViewPort { viewPortScale :: ViewPort -> Float
viewPortScale        = Float
vscale
                 , viewPortTranslate :: ViewPort -> (Float, Float)
viewPortTranslate    = (Float
transX, Float
transY)
                 , viewPortRotate :: ViewPort -> Float
viewPortRotate       = Float
vrotate }
        = Float -> Float -> Picture -> Picture
Scale Float
vscale Float
vscale (Picture -> Picture) -> (Picture -> Picture) -> Picture -> Picture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Picture -> Picture
Rotate Float
vrotate (Picture -> Picture) -> (Picture -> Picture) -> Picture -> Picture
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Float -> Picture -> Picture
Translate Float
transX Float
transY


-- | Takes a point using screen coordinates, and uses the `ViewPort` to convert
--   it to Picture coordinates. This is the inverse of `applyViewPortToPicture`
--   for points.
invertViewPort :: ViewPort -> Point -> Point
invertViewPort :: ViewPort -> (Float, Float) -> (Float, Float)
invertViewPort
        ViewPort { viewPortScale :: ViewPort -> Float
viewPortScale        = Float
vscale
                 , viewPortTranslate :: ViewPort -> (Float, Float)
viewPortTranslate    = (Float, Float)
vtrans
                 , viewPortRotate :: ViewPort -> Float
viewPortRotate       = Float
vrotate }
        (Float, Float)
pos
        = Float -> (Float, Float) -> (Float, Float)
rotateV (Float -> Float
degToRad Float
vrotate) (Float -> (Float, Float) -> (Float, Float)
mulSV (Float
1 Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
vscale) (Float, Float)
pos) (Float, Float) -> (Float, Float) -> (Float, Float)
Pt.- (Float, Float)
vtrans


-- | Convert degrees to radians
degToRad :: Float -> Float
degToRad :: Float -> Float
degToRad Float
d      = Float
d Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
forall a. Floating a => a
pi Float -> Float -> Float
forall a. Fractional a => a -> a -> a
/ Float
180
{-# INLINE degToRad #-}


-- | Multiply a vector by a scalar.
mulSV :: Float -> Vector -> Vector
mulSV :: Float -> (Float, Float) -> (Float, Float)
mulSV Float
s (Float
x, Float
y)
        = (Float
s Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
x, Float
s Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float
y)
{-# INLINE mulSV #-}


-- | Rotate a vector by an angle (in radians). +ve angle is counter-clockwise.
rotateV :: Float -> Vector -> Vector
rotateV :: Float -> (Float, Float) -> (Float, Float)
rotateV Float
r (Float
x, Float
y)
 =      (  Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
- Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin Float
r
        ,  Float
x Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
sin Float
r Float -> Float -> Float
forall a. Num a => a -> a -> a
+ Float
y Float -> Float -> Float
forall a. Num a => a -> a -> a
* Float -> Float
forall a. Floating a => a -> a
cos Float
r)
{-# INLINE rotateV #-}