//
// DX9ViewportC.h
//
// DirectX 9 viewport.
//
// Copyright (c) 2004 memon/moppi productions
//

#ifndef __DEMOPAJA_DX9VIEWPORTC_H__
#define __DEMOPAJA_DX9VIEWPORTC_H__

namespace PajaSystem {
	class DX9ViewportC;
};

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d9.h>
#include "PajaTypes.h"
#include "DeviceInterfaceI.h"
#include "GraphicsViewportI.h"
#include "Vector2C.h"
#include "BBox2C.h"
#include "DX9DeviceC.h"


namespace PajaSystem {

	//! The ID of the OpenGL interface, use this ID to request the interface.
	const PluginClass::ClassIdC	CLASS_DX9_VIEWPORT = PluginClass::ClassIdC( 0, 30001 );


	//! Device interface for DX9
	/*!	The purpose of the device interface for DX9 is to setup
		the area where an effect can draw and to convert coordinates
		from screen (pixel) coordinates to the layout.
	*/
	class DX9ViewportC : public GraphicsViewportI
	{
	public:

		virtual Edit::DataBlockI*				create();
		static DX9ViewportC*					create_new( DX9DeviceC* pD3DDevice );
		virtual PluginClass::ClassIdC			get_class_id() const;
		virtual const char*						get_class_name();

		//! Sets perspective viewport and projection matrix.
		/*!	\param rBBox the bounding box of the effect.
			\param f32FOV FOV on x-axis.
			\param f32Aspect Aspect ration of the viewport.
			\param f32ZNear Near clipping plane.
			\param f32ZFar Far clipping plane.

			This method is a replacement for gluPerspective. Note that the FOV is different.
			Scrissor testing is enabled and the bounding box is used to define the scissor box.
		*/
		virtual void				set_perspective( const PajaTypes::BBox2C& rBBox, PajaTypes::float32 f32FOV, PajaTypes::float32 f32Aspect,
										PajaTypes::float32 f32ZNear, PajaTypes::float32 f32ZFar );

		//! Sets orthographic viewport and projection matrix.
		/*!	\param rBBox the bounding box of the effect.
			\param f32Width Width of the viewport.
			\param f32Height Height of the viewport.
			\param f32ZNear Near clipping plane.
			\param f32ZFar Far clipping plane.

			This method is a replacement for glOrtho.
			Scrissor testing is enabled and the bounding box is used to define the scissor box.
		*/
		virtual void				set_ortho( const PajaTypes::BBox2C& rBBox,
										PajaTypes::float32 f32Left, PajaTypes::float32 f32Right,
										PajaTypes::float32 f32Top, PajaTypes::float32 f32Bottom,
										PajaTypes::float32 f32ZNear = -1, PajaTypes::float32 f32ZFar = 1 );

		virtual void				set_ortho_pixel( const PajaTypes::BBox2C& rBBox, PajaTypes::float32 f32ZNear = -1, PajaTypes::float32 f32ZFar = 1 );

		//! Converts positions in screen pixels to the layout coordinate system.
		virtual PajaTypes::Vector2C	client_to_layout( const PajaTypes::Vector2C& rVec );
		//! Converts positions in layout coordinate system uints to the screen pixels.
		virtual PajaTypes::Vector2C	layout_to_client( const PajaTypes::Vector2C& rVec );
		//! Converts delta values of screen pixels to the layout coordinate system.
		virtual PajaTypes::Vector2C	delta_client_to_layout( const PajaTypes::Vector2C& rVec );
		//! Converts delta values layout coordinate system uints to the screen pixels.
		virtual PajaTypes::Vector2C	delta_layout_to_client( const PajaTypes::Vector2C& rVec );

		//! Returns the viewport (visible are of the demo).
		virtual const PajaTypes::BBox2C&	get_viewport();
		//! Returns the layout (rendering are of the demo).
		virtual const PajaTypes::BBox2C&	get_layout();
		//! Returns the width of the screen in pixels.
		virtual PajaTypes::int32			get_width();
		//! Returns the height of the screen in pixels.
		virtual PajaTypes::int32			get_height();
		//! Returns the pixel aspect ratio.
		virtual PajaTypes::float32			get_pixel_aspect_ratio();

		//! Sets the pixel aspect ratio (height per width).
		virtual void				set_pixel_aspect_ratio( PajaTypes::float32 f32PixelAspect );
		//! Sets the dimension of the OpenGL rendering are in pixels (used internally).
		virtual void				set_dimension( PajaTypes::int32 i32PosX, PajaTypes::int32 i32PosY, PajaTypes::int32 i32Width, PajaTypes::int32 i32Height );
		//! Sets the viewport (used internally).
		virtual void				set_viewport( const PajaTypes::BBox2C& rViewport );
		//! Sets the layout (used internally).
		virtual void				set_layout( const PajaTypes::BBox2C& rLayout );

		//! Resets the last set viewport to the device.
		virtual void				activate();

	protected:
		//! Default constructor (used internally).
		DX9ViewportC( DX9DeviceC* pDevice );
		//! Default destructor.
		virtual ~DX9ViewportC();

	private:
		//! Sets scrissoring to a specified area.
		void						set_scissor( const PajaTypes::BBox2C& rBBox );
		//! Calculates new constants for layout and client mappings.
		void						recalc_mapping();

		DX9DeviceC*			m_pDevice;

		PajaTypes::BBox2C	m_rViewport;			// The viewport size in paja (include pan and zoom).
		PajaTypes::BBox2C	m_rLayout;				// Layout bbox.
		PajaTypes::int32	m_i32Width;				// Actual screen size in pixels.
		PajaTypes::int32	m_i32Height;
		PajaTypes::int32	m_i32PosX;				// Position of lower left corner in pixels.
		PajaTypes::int32	m_i32PosY;
		PajaTypes::float64	m_f64LayoutAspectX;		// Conversion variables.
		PajaTypes::float64	m_f64LayoutAspectY;
		PajaTypes::float64	m_f64ClientAspectX;
		PajaTypes::float64	m_f64ClientAspectY;

		PajaTypes::float32	m_f32PixelsAspect;

		// Current viewport.
		enum ViewportTypeE {
			OPENGL_VIEWPORT_ORTHO = 0,
			OPENGL_VIEWPORT_PERSPECTIVE,
			OPENGL_VIEWPORT_ORTHO_PIXEL,
		};
		PajaTypes::uint32	m_ui32ViewportType;
		PajaTypes::int32	m_i32ScissorX;
		PajaTypes::int32	m_i32ScissorY;
		PajaTypes::int32	m_i32ScissorWidth;
		PajaTypes::int32	m_i32ScissorHeight;
		PajaTypes::float64	m_f64FrustumLeft;
		PajaTypes::float64	m_f64FrustumRight;
		PajaTypes::float64	m_f64FrustumBottom;
		PajaTypes::float64	m_f64FrustumTop;
		PajaTypes::float64	m_f64FrustumNearZ;
		PajaTypes::float64	m_f64FrustumFarZ;
	};

};

#endif // __DX9ViewportC_H__

