/*===========================================================================
 *
 * D3DAPP.H - Dave Humphrey (uesp@m0use.net), 30 October 2000
 *
 *=========================================================================*/
#ifndef __D3DAPP_H
#define __D3DAPP_H

	/* Required Includes */
#include "d3dcom.h"
#include "ddsurfmode.h"


/*===========================================================================
 *
 * Begin Defines
 *
 *=========================================================================*/

	/* Sets the use of exlcusive or normal mode for the application */
  #define D3D_EXCLUSIVE_MODE FALSE

	/* Defines for querying Direct3D/DirectDraw objects */
  #define IID_CD3DMeshBuilder IID_IDirect3DRMMeshBuilder

/*===========================================================================
 *		End of Defines
 *=========================================================================*/


/*===========================================================================
 *
 * Begin Type and Structure Definitions
 *
 *=========================================================================*/

	/* Callback function types */
  typedef boolean (*D3D_BUILDSCENE_PROC) (void);
  typedef boolean (*D3D_SELECTOBJECT_PROC)  (const DWORD ObjectAppData, const unsigned long FaceIndex); 

/*===========================================================================
 *		End of Type and Structure Definitions
 *=========================================================================*/


/*===========================================================================
 *
 * Class CD3DApp Definition
 *
 * Definition for a standard Direct3D application.
 * 
 *=========================================================================*/
class CD3DApp {

  /*---------- Begin Protected Class Members ------------------------*/
protected:
  boolean	QuitMain;		/* Quit WinMain event loop */
  boolean	Minimized;		/* Is the window currently minimized? */
  boolean	Initialized;		/* Has the app been initialized? */
  boolean	ResizingDisabled;	/* Can the window be resized? */
  boolean	Dithering;		/* Are we dithering the output? */
  boolean	AntiAlias;		/* Are we antialiasing the output? */
  boolean	AllowMovement;		/* Can the camera be moved? */
  boolean	DisplayFrameRate;	/* Are we displaying the frame rate in the view? */
  boolean	Activated;		/* Is the window activated */
  boolean	FollowSurface;		/* Attempt to follow surfaces below the camera */
      
  LARGE_INTEGER PerformanceFreq;	/* Timing/counter options */
  LARGE_INTEGER LastRenderCounter;
  boolean	UsePerformanceCounter;
  clock_t	LastRenderTick;

  d3dcolor_t	OldSelectedFaceColor;	/* Previous color of the selected face */
  boolean	AllowSelectObject;	/* Can the user 'select' objects? */
  boolean	CallBackOnSelectObject;	/* Call user callback function when selecting objects */
  boolean	HasSelectedObject;	/* Is there an object selected at the moment? */
  CD3DFace*	pSelectedFace;		/* Currently selected face object */
  CD3DVisual*	pSelectedVisual;	/* Currently selected visual object */
  d3dpickdesc_t	SelectedPickDesc;	/* Description of the selected face */

  d3drenderq_t  RenderQuality;		/* Current shade mode, fill mode and lighting state */
  d3dtextureq_t TextureQuality;		/* Current texture interpolation */

  d3dvalue_t	MovementSpeed;		/* How far can the camera move per second? */
  d3dvalue_t	RotationSpeed;		/* How many radians per second can we turn? */
  d3dvalue_t	FrameRate;		/* Output frames per second */
  d3dvalue_t	ViewBackLength;		/* The back clipping plane for the view */
  d3dvalue_t	CameraHeight;		/* Default height of the camera above the surface */

  HWND		hMainWindow;		/* Handle to the main window */
  HINSTANCE	hInstance;		/* Instance handle of this application */
  HACCEL	hAccelerator;		/* Application accelerator table handle */

  int		BitsPerPixel;		/* Bit depth of the current display */

  char*		pAcceleratorName;	/* Accelerator resource name */
  char*		pIconName;		/* Icon resource name */
  char*		pMenuName;		/* Menu resource name for the window */
  char*		pClassName;		/* Class name for the window */
  char*		pWindowCaption;		/* Caption for the window */

  CDDSurfaceMode* pCurrentSurfaceMode;	/* The current surface mode object, if any */
  boolean	  InSurfaceMode;	/* Are we displaying a DD surface currently? */


  /*---------- Begin Public Class Members ---------------------------*/
public:

  CDirect3D*	        pDirect3D;	/* Direct3DRM object */
  CDDClipper*		pDDClipper;	/* DirectDrawClipper object */
  CD3DDevice*		pDevice;	/* Direct3DRM device */
  CD3DView*		pView;		/* Direct3DRM viewport through which we view the scene */
  CD3DFrame*		pScene;		/* Master frame in which others are placed */
  CD3DFrame*		pCamera;	/* Frame describing the users POV */

	/* Exclusive mode specific variables */
  #if D3D_EXCLUSIVE_MODE
    CDDSurface*		pPrimarySurface;/* Front surface for exclusive mode */
    CDDSurface*		pBackSurface;	/* Back buffer surface for exclusive mode */
    CDirectDraw*	pDirectDraw;	/* Direct draw object for exclusive mode */
    CDDSurfaceDesc	ddSurfaceDesc;	/* Surface description of primary DD surface */
    LPDIRECT3DRM	pDirect3D1;	/* Required by exclusive mode */
  #endif

	/* The windows message handler function (public so its easier to set) */
  WNDPROC		pWindowProc;

	/* Called to build the initial scene after D3D initialization */
  D3D_BUILDSCENE_PROC	pBuildScene;

	/* Called to display plane information on plane selection */
  D3D_SELECTOBJECT_PROC pOnSelectObjectCallBack;
  

  /*---------- Begin Protected Class Methods ------------------------*/
protected:

	/* Create and initialize the required frames */
  boolean CreateCameraFrame (void);
  boolean CreateSceneFrame (void);

	/* Creates the device, view, and clipper objects */
  boolean CreateDevice    (void);
  boolean CreateDevice    (const int Width, const int Height);
  boolean CreateView      (void);
  boolean CreateDDClipper (void);

	/* Creates the application window */
  boolean CreateMainWindow (void);

	/* Direct3D specific intialization */
  boolean D3DInitialization (void);

	/* Draws the frame rate to the output window */
  boolean DrawFrameRate (void);

	/* Get and release the main display device context */
  HDC     GetDisplayDC     (void);
  boolean ReleaseDisplayDC (HDC hDC);

	/* Event handlers */
  virtual boolean OnActivate	  (LRESULT& Result, WPARAM wParam);
  virtual boolean OnDisplayChange (LRESULT& Result, HWND hWindow);
  virtual boolean OnKeyDown	  (LRESULT& Result, int KeyCode);
  virtual boolean OnKeyUp	  (LRESULT& Result, int KeyCode);
  virtual boolean OnLButtonDown	  (LRESULT& Result, int KeyFlags, int XPos, int YPos);
  virtual boolean OnPaint	  (LRESULT& Result, HWND hWindow);
  virtual boolean OnSize	  (LRESULT& Result, int Width, int Height);

	/* Record the BPP of the main window */
  boolean UpdateBitsPerPixel (void);


	/* Exclusive mode specific routines */	
  #if D3D_EXCLUSIVE_MODE

	/* Initialize Direct3D in exclusive mode */
    boolean CreateD3DExclusiveMode (void);

	/* Create the primary and back buffer surfaces */
    boolean CreateExModeSurfaces (void);

  #endif

  
  /*---------- Begin Public Class Methods ---------------------------*/
public:
  
	/* Class Constructor/Destructor */
  CD3DApp();
  ~CD3DApp() { Destroy(); }
  void Destroy (void);

	/* Determines whether we should/can render the scene */
  boolean CanRenderScene (void) { return (!IsMinimized() && !InSurfaceMode && IsActivated() && IsInitialized() && !QuitMain); }

	/* Standard WinMain function */
  int D3DWinMain (HINSTANCE ThisInstance, HINSTANCE PrevInstance, 
		  LPSTR CommandLine,	  int CommandShow);

  	/* Attempt to get the camera to follow the surface */
  boolean DoFollowSurface (void);

    	/* Find a surface below/above the given point in the main frame */
  boolean FindSurface (CD3DFrame* pRefFrame, const d3dvector_t& SourcePoint, d3dvector_t& pDestPoint);

	/* Return the time since the last render */
  float GetElapsedRenderTime (void);

	/* Get class members */
  boolean  GetDisplayFrameRate (void) { return (DisplayFrameRate); }
  HWND     GetMainWindowHandle (void) { return (hMainWindow); }
  D3DVALUE GetMovementSpeed    (void) { return (MovementSpeed); }

	/* Get Direct3D/Draw objects */
  CDDSurface*  GetPrimarySurface (void);
  CDirectDraw* GetDirectDraw     (void);

	/* Returns a position in front of the current camera in scene coordinates */
  boolean GetPositionInFrontOfCamera (d3dvector_t& Vector, CD3DFrame* pRefFrame);

	/* Handles window messages as per WindowProc() */
  virtual boolean HandleMessages (LRESULT& Result, HWND hWindow, UINT Message, WPARAM wParam, LPARAM lParam);

	/* Initializes the application and Direct3D */
  virtual boolean Initialize (HINSTANCE ThisInstance, int CommandShow);

	/* Check states */
  boolean IsMinimized     (void) { return (Minimized); }
  boolean IsInitialized   (void) { return (Initialized); }
  boolean IsActivated     (void) { return (Activated); }
  boolean HasSelected     (void) { return (HasSelectedObject); }
  boolean IsInSurfaceMode (void) { return (boolean)(InSurfaceMode && pCurrentSurfaceMode != NULL); }

	/* Applies the 'tick' to the scene for moving/rotating objects */
  virtual boolean MoveScene (void);

	/* Attempt to pick objects in the given viewport */
  virtual boolean PickObjects (CD3DView* pViewport, const int XPos, const int YPos);

	/* Render one frame of the scene to the current view */
  virtual boolean Render (void);

	/* Resets the time of the last render */
  virtual void ResetLastRender (void) { LastRenderTick = 0; LastRenderCounter.QuadPart = 0; }

	/* Destroys any current surface mode object */
  virtual void RemoveSurfaceMode (void);

	/* Attempt to set the currently selected object */
  boolean SelectObject (CD3DVisual* pVisual, CD3DFace* pFace, d3dpickdesc_t& PickDesc);

	/* Set the resource name strings */
  void SetAcceleratorName  (const char* pString) { DestroyPointer(pAcceleratorName); pAcceleratorName = CreateString(pString); }
  void SetIconName         (const char* pString) { DestroyPointer(pIconName);	     pIconName = CreateString(pString); }
  void SetMenuName         (const char* pString) { DestroyPointer(pMenuName);	     pMenuName = CreateString(pString); }
  void SetClassName        (const char* pString) { DestroyPointer(pClassName);	     pClassName = CreateString(pString); }
  void SetWindowCaption    (const char* pString) { DestroyPointer(pWindowCaption);   pWindowCaption = CreateString(pString); }

	/* Set class members */
  void SetDisplayFrameRate  (const boolean Value)   { DisplayFrameRate = Value; }
  void SetAllowSelectObject (const boolean Value)   { AllowSelectObject = Value; }
  void SetMovementSpeed     (const d3dvalue_t Speed)  { MovementSpeed = Speed; }
  void SetViewBackLength    (const d3dvalue_t Length) { ViewBackLength = Length; if (pView) pView->SetBack(ViewBackLength); }
  void SetCallBackOnSelectObject (const boolean Value) { CallBackOnSelectObject = Value; }

	/* Update the render state */
  boolean SetRenderState (void);

	/* Change the fill mode */
  boolean SetFillMode(d3dfillmode_t FillMode);

	/* Sets the current surface mode of the output display */
  boolean SetSurfaceMode (CDDSurfaceMode* pSurfaceMode);

  	/* Terminates all D3D objects */
  void TerminateApp (void);

	/* Destroys the currently selected objects, if any */
  void UnSelectObject (void);

 };
/*===========================================================================
 *		End of Class CD3DApp
 *=========================================================================*/


#endif
/*===========================================================================
 *		End of File D3DAPP.H
 *=========================================================================*/