#include <conio.h>
#include <stdlib.h>

#include <pr.h>
#include <prgui.h>

#ifdef __3DFX__
#include <pr3dfx.h>
#include <glide.h>
#endif

#ifdef WIN32
#include <winutil.h>
#endif


/* Power Render Example 7

   Description:  Demonstrates spherical collision detection.

   Controls:
   Click and drag the left mouse button to move the objects along the
   x/y axis.

   Click and drag the right mouse button to move the objects along the
   z axis.

   Press space to toggle which object you are moving.

   Press ESC to quit.
*/

                                             
PR_VIEWPORT viewport;                  /* Our viewport structure */
PR_CAMERA *camera;                     /* One camera */
PR_LIGHTLIST userlights;               /* Holds a list of lights */

PR_OBJECT *object_shape;               /* The shape loaded */
PR_ENTITY *ball1;                     
PR_ENTITY *ball2;                     
PR_DWORD  device=0;                    /* Display device */

PR_DWORD active_entity = 0;
PR_ENTITY *active_ptr;


void InitializeDevices (void)
{
#ifdef __MYST__
  if ((device == DEVICE_MYSTIQUE) || (device == DEVICE_ANY))
    device = PR_DetectMystique ();
#endif


#ifdef __3DFX__
  if ((device == DEVICE_3DFX) || (device == DEVICE_ANY))
    device = PR_Detect3Dfx ();
#endif

#if !defined (MSGLIDE) && !defined (WTGLIDE)
  #if defined (MSDD) || defined (WTDD)
    if ((device == DEVICE_D3D) || (device == DEVICE_ANY))
      device = PR_DetectD3D ();   /* Attempt to find the device */
  #endif

  if ((device == DEVICE_SVGA) || (device == DEVICE_ANY))
    device = PR_DetectSVGA ();   /* Attempt to find the device */

  if ((device == DEVICE_VGA) || (device == DEVICE_ANY))
    device = PR_DetectVGA ();   /* Attempt to find the device */
#endif

#ifdef __MYST__
  if (device == DEVICE_MYSTIQUE)
    {
     PR_InitializeMystique ();
     atexit (PR_ShutdownMystique);
    }
#endif

#ifdef __3DFX__
  if (device == DEVICE_3DFX)
    {
     PR_Initialize3Dfx ();
     atexit (PR_Shutdown3Dfx);
    }
#endif

#if !defined (MSGLIDE) && !defined (WTGLIDE)
  #if defined (MSDD) || defined (WTDD)
  if (device == DEVICE_D3D)
    {
     PR_InitializeD3D ();
     atexit (PR_ShutdownD3D);
    }
  #endif
  if (device == DEVICE_SVGA)
    {
     PR_InitializeSVGA ();
     atexit (PR_ShutdownSVGA);
    }
  else if (device == DEVICE_VGA)
    {
     PR_InitializeVGA ();
    }
#endif
}



#if defined (MSDD) || defined (WTDD)
void PR_RestoreAll (void)
{
HRESULT ddrval;

 ddrval = IDirectDrawSurface2_Restore (wgtpdds);

 if (ddrval != DD_OK)
   return;

  PR_LostSurface = 0;
}
#endif


void main (void)
{
PR_DWORD vwidth, vheight;
PR_REAL cenx, ceny, cenz;
PR_UDWORD BLACK;                       /* Color index/value for black */
PR_UDWORD WHITE;                       /* Color index/value for white */


#ifndef WIN32
  while (kbhit ())
    getch ();

#if defined (__3DFX__) || defined (__MYST__)
  printf ("Use 3D hardware? (y/n)\n");
  device = getch ();

  if (device == 'y' || device == 'Y')
    device = DEVICE_ANY;
  else
#endif
     device = DEVICE_SVGA;
#else /* We are in windows */

  /* First check for Direct3D/DDraw */
  #if defined(MSDD) || defined(WTDD)
    device = MessageBox(NULL, "Use Direct3D Hardware?", "Power Render Initialization", MB_YESNO);
    if (device == IDYES)
      {
       device = DEVICE_D3D;
       PR_Settings.Hardware = 1;
      }
    else
      { 
       device = DEVICE_SVGA;
       PR_Settings.Hardware = 0;
      }
 
  /* Next look for specific hardware */
  #elif defined (MSGLIDE) || defined (WTGLIDE)
    device = DEVICE_3DFX;
  #elif defined (MSMYST) || defined (WTMYST)
    device = DEVICE_MYST;
  #endif
#endif



  PR_Initialize (1000);                /* Maximum 1000 triangles per frame */

  InitializeDevices ();

  PR_AllocMaterials (32);              /* Allocate the materials, */
  PR_AllocTextures (32);               /* textures, */
  PR_AllocShadeTables (2);             /* and shade tables */


  vwidth = 640;
  vheight = 480;
  if (PR_SetMode (vwidth, vheight, 60) != MODE_SUCCESS)
    {
     vwidth = PR_VideoModes[0].width;     /* Initialize the video mode */
     vheight = PR_VideoModes[0].height;
     PR_SetMode (vwidth, vheight, 60);
    }

  PR_OpenViewport (&viewport, 0, 0, vwidth-1, vheight-1, VIEW_PLAIN);
  PR_SetViewport (&viewport);          /* Open a full screen viewport */

  /* Load the object */
  PR_SetTexturePath ("..\\data\\");
  PR_SetTablePath ("..\\data\\");
  object_shape = PR_LoadPRO ("..\\data\\sphere.pro", LOAD_NORMAL);
  PR_CenterObject (object_shape, &cenx, &ceny, &cenz);

#if !defined (MSGLIDE) && !defined (WTGLIDE)
  /* Set the palette from the textures loaded */
  wsetpalette (0, 255, global_palette);
#endif

  /* Create the main entity */
  ball1 = PR_CreateEntity (object_shape, "Ball 1");
  ball2 = PR_CreateEntity (object_shape, "Ball 2");

  PR_PositionEntity (ball1, 100, 0, 0);
  PR_PositionEntity (ball2, -200, 0, 0);


  camera = PR_AllocCamera ();          /* Initialize the camera */
  PR_InitializeCamera (camera);
  PR_PositionCameraSource (camera, 0, 0, -900);
  PR_PositionCameraTarget (camera, 0, 0, 0);
  PR_SetCameraMode (camera, CAMFLAG_AIM_TARGET); 
  PR_SetActiveCamera (camera);

 /* Initialize the light */
  PR_AllocLights (&scenelights, 1);
  PR_AllocLights (&userlights, 1);
  PR_SetLightPosition (&userlights, 0, 0, 0, -900);
  PR_SetLightOn (&userlights, 0);
  PR_SetLightType (&userlights, 0, DIRECTIONAL_LIGHT);
  PR_SetLightColor (&userlights, 0, 1.0, 1.0, 1.0);
  PR_SetLightStrength (&userlights, 0, 1.0);
  userlights.NumLights = 1;     /* This sets how many lights are actually used */

  PR_OpenScreen (PR_BACKBUFFER);
  BLACK = PRGFX_MakeColor (0, 0, 0);
  WHITE = PRGFX_MakeColor (63, 63, 63);

  installkbd ();

#ifndef WIN32
  minit ();
#endif

  msetbounds (0, 0, 320, 200);
  msetxy (160, 100);

  /* Set which entity is currently being moved */
  active_entity = 0;
  active_ptr = ball1;

  /* Load a smaller font */
  gui_font = wloadfont ("little.wfn");
  PRGFX_SetTextForeground (WHITE);
  PRGFX_SetTextBackground (BLACK);
  PRGFX_SetTextTransparent (TEXTFGBG);

  /* main program loop */
  while (!kbdon[KEY_ESC])
    {
     #ifdef WIN32
          UpdateMessages ();
         #endif

     #if defined (MSDD) || defined (WTDD)
       if (PR_LostSurface)
         PR_RestoreAll ();
     #endif

     PR_OpenScreen (PR_BACKBUFFER);
     PR_NewFrame ();                   /* Begin a new frame */

     PRGFX_SetColor (BLACK);
     PRGFX_ClearScreen ();             /* Clear the last frame */

     PR_TransformLights (&userlights);


     if (kbdon[KEY_SPACE])             /* Toggle active entity */
       {
        active_entity = !active_entity;
        if (active_entity == 0)
          active_ptr = ball1;
        else
          active_ptr = ball2;

        while (kbdon[KEY_SPACE]) 
          { 
           #ifdef WIN32
             UpdateMessages ();
           #else
             wretrace ();                  
           #endif                 
          };
       }


     if (mouse.but == 1)
       {
        PR_MoveEntity (active_ptr, mouse.mx - 160, 100 - mouse.my, 0);
        msetxy (160, 100);
       }
     else if (mouse.but == 2)
       {
        PR_MoveEntity (active_ptr, 0, 0, 100 - mouse.my);
        msetxy (160, 100);
       }


     PR_TransformEntity (ball1);      /* Transform the entity */
     PR_RenderEntity (ball1);         /* Render the entity */

     PR_TransformEntity (ball2);      /* Transform the entity */
     PR_RenderEntity (ball2);         /* Render the entity */

     PR_RenderFrame ();                /* Draw the scene */

     PRGUI_printf (10, 10, "Moving object %i", active_entity);
     PRGUI_printf (10, 20, "Collision  %i", PR_EntityCollideRadius (ball1, ball2));
     PRGUI_printf (10, 30, "Object 1 Hit Camera %i",
         PR_SphereInEntity (ball1, camera->source.x, camera->source.y, camera->source.z, 20));
     PRGUI_printf (10, 40, "Object 2 Hit Camera %i",
         PR_SphereInEntity (ball2, camera->source.x, camera->source.y, camera->source.z, 20));

     PR_Flip (1);                      /* Show the background page */
    }

  /* Free all allocated memory */
  PR_FreeCamera (camera);
  PR_FreeEntity (ball1);
  PR_FreeEntity (ball2);
  PR_FreeObject (object_shape);
  PR_CloseViewport (&viewport);
  PR_DeleteAllShadeTables ();
  PR_DeleteAllTextures ();
  PR_DeleteAllMaterials ();
  PR_ShutDown ();

  uninstallkbd ();
  mdeinit ();

#ifndef WIN32
  wsetmode (3);                        /* Go back to text mode */
#endif
}

