{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE ScopedTypeVariables, Rank2Types #-}

-- | Handling the current viewport during rendering.
module Graphics.Gloss.Internals.Render.ViewPort
	( withViewPort )
where
import	Graphics.Gloss.Internals.Interface.Backend
import	Graphics.Gloss.Internals.Interface.ViewPort
import	Graphics.Rendering.OpenGL					(GLfloat, ($=))
import	qualified Graphics.Rendering.OpenGL.GL				as GL

import	Data.IORef							(IORef)

-- | Perform a rendering action whilst using the given viewport
withViewPort
	:: forall a . Backend a
	=> IORef a
	-> ViewPort 		-- ^ The viewport to use.
	-> IO () 		-- ^ The rendering action to perform.
	-> IO ()

withViewPort backendRef port action
 = do
 	GL.matrixMode	$= GL.Projection
	GL.preservingMatrix
	 $ do
		-- setup the co-ordinate system
	 	GL.loadIdentity
		(sizeX, sizeY) 	<- getWindowDimensions backendRef
		let (sx, sy)	= (fromIntegral sizeX / 2, fromIntegral sizeY / 2)

		GL.ortho (-sx) sx (-sy) sy 0 (-100)
	
		-- draw the world
		GL.matrixMode 	$= GL.Modelview 0
		GL.preservingMatrix
		 $ do
			GL.loadIdentity
			let rotate :: GLfloat	= realToFrac $ viewPortRotate port
			let transX :: GLfloat	= realToFrac $ fst $ viewPortTranslate port
			let transY :: GLfloat   = realToFrac $ snd $ viewPortTranslate port
		 	let scale  :: GLfloat	= realToFrac $ viewPortScale port

			-- apply the global view transforms
			GL.scale     scale  scale  1
			GL.rotate    rotate (GL.Vector3 0 0 1)
			GL.translate (GL.Vector3 transX transY 0)

			-- call the client render action
			action 

		GL.matrixMode	$= GL.Projection
	
	GL.matrixMode	$= GL.Modelview 0