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

#include <pr.h>

#if defined (MSGLIDE) || defined (WTGLIDE)
 #include <glide.h>
 #include <pr3dfx.h>
 #include "winutil.h"
 #include <windows.h>
#elif defined (WIN32)
 #include "winutil.h"
 #include <windows.h>
#else
 #ifdef __3DFX__
  #include <glide.h>
  #include <pr3dfx.h>
  #include <fxgui.h>
 #endif
#endif

#include <prgui.h>



/*

       /=========\ /========\ ||        || /========  /=======\
       ||       || ||      || ||        || ||         ||      ||
       ||       || ||      || ||        || ||         ||      ||
       ||       || ||      || ||        || ||         ||      ||
       ||       || ||      || ||   ||   || ||         ||      //
       |=========/ ||      || ||   ||   || |=======   |=====<<
       ||          ||      || ||   ||   || ||         ||      \\
       ||          ||      || ||   ||   || ||         ||       ||
       ||          ||      || ||   ||   || ||         ||       ||
       ||          \========/ \==========/ \========= ||       ||

--------------------------------<===>----------------------------------

    /=======\   /========= |\     || |======\  /========= /=======\
    ||      ||  ||         ||\    || ||    \ \ ||         ||      ||
    ||      ||  ||         || \   || ||     || ||         ||      ||
    ||      ||  ||         ||  \  || ||     || ||         ||      ||
    ||      //  ||         ||   \ || ||     || ||         ||      //
    |======<<   |======    ||\   \|| ||     || |======    |======<<
    ||      \\  ||         || \   || ||     || ||         ||      \\
    ||       || ||         ||  \  || ||     || ||         ||       ||
    ||       || ||         ||   \ || ||    / / ||         ||       ||
    ||       || |========= ||    \|| |======/  |========= ||       ||

Texture Edit Utility

Allows you to edit the texture on each face.

 Revision History:
 Sept 2. 1996: Created
 Dec 22. 1996: Add new 3Dfx support */


PR_DWORD    device;
PR_DWORD    texnum;
char        objectfile[80];           /* Name of the texture */
PR_OBJECT * object;                   /* Shape definition of the PRO file */
PR_ENTITY * obj1;                     /* One instance of the shape */
PR_LIGHTLIST userlights;              /* We only use 1 light */

PR_VIEWPORT viewport;                 /* A single viewport */
PR_CAMERA * newcam;                   /* Our camera */
PR_REAL     camscale;                 /* Used for moving */
PR_REAL     camdist;                  /* distance from object */     
PR_REAL     cenx, ceny, cenz;

PR_REAL     rot_x, rot_y, rot_z;      /* Object Rotation */

PR_REAL     texture_width = 0;
PR_REAL     texture_height = 0;
PR_REAL     u_scale, v_scale;
PR_REAL     shades = 0;
PR_UCHAR    nonwrap;                  /* 1 = nonwrapping textures */

PR_DWORD    start_screen, end_screen;

PR_DWORD    mouse_mode;
#define MODE_ROBJECT 0
#define MODE_CAMERA 1

PR_DWORD    select_segment;
PR_DWORD    select_face;
PR_DWORD    select_vertex;
PR_DWORD    select_material;
PR_SEGMENT  *seg;
PR_MATERIAL *mater;
PR_FACE *   face;


#define LSHIFT 42                  /* Key Codes */
#define CTRL 29
#define ALT 56
#define SPACE 57
#define ESC 1

/* Button positions */
#define SMINUS 460,40,480,52
#define SPLUS  572,40,592,52
#define SDISPW 415,41
#define SDISPLAY 515,41

#define FMINUS 460,62,480,74
#define FPLUS  572,62,592,74
#define FDISPW 415,63
#define FDISPLAY 515,63

#define VMINUS 460,86,480,98
#define VPLUS  572,86,592,98
#define VDISPW 415,87
#define VDISPLAY 515,87

#define MMINUS 460,108,480,120
#define MPLUS  572,108,592,120
#define MDISPW 415,109
#define MDISPLAY 515,109

#define CMINUS 460,130,480,142
#define CPLUS  572,130,592,142
#define CDISPW 415,131
#define CDISPLAY 515,131


#define TUMINUS 460,130,480,142
#define TUPLUS  572,130,592,142
#define TUDISPW 415,131
#define TUDISPLAY 505,131

#define TVMINUS 460,152,480,164
#define TVPLUS  572,152,592,164
#define TVDISPW 415,153
#define TVDISPLAY 505,153

#define SWROBJECT 480,360,572,375
#define SWCAMERA  480,380,572,395

#define SAVE 460,410,592,430
#define QUIT 460,450,592,470

#define DISPWIDTH 410
#define DISPHEIGHT 356
#define DISPLAY 0,0,409,355

#define TWINDOW 416,157,636,357


PR_REAL u[3];           /* Floating point UV coordinates */
PR_REAL v[3];
PR_REAL col[3];         /* Floating point color values */
PR_REAL utiling, outiling; /* Tiling values */
PR_REAL vtiling, ovtiling; /* Tiling values */

block textureblock;
block texturework;

#define WSIZE 222
#define HSIZE 202

void SwitchUV (void);

typedef struct
{
  PR_REAL sMult;
  PR_REAL tMult;
} TexFactors;


TexFactors AspectToTexCoordFactors[7] = {
  { 1.0f,        1.0f / 8.0f },  /* GR_ASPECT_8x1 */
  { 1.0f,        1.0f / 4.0f },  /* GR_ASPECT_4x1 */
  { 1.0f,        1.0f / 2.0f },  /* GR_ASPECT_2x1 */
  { 1.0f,        1.0f        },  /* GR_ASPECT_1x1 */
  { 1.0f / 2.0f, 1.0f        },  /* GR_ASPECT_1x2 */
  { 1.0f / 4.0f, 1.0f        },  /* GR_ASPECT_1x4 */
  { 1.0f / 8.0f, 1.0f        }   /* GR_ASPECT_1x8 */
};


void SetTextureScale (void)
{
PR_DWORD asp;

  if (PR_Settings.RealUV)
    {
     /* Find the aspect ratio */
     if (texture_width > texture_height)
       {
        switch ((PR_DWORD)(texture_width / texture_height))
          {
           case 1: asp = 3;
                   break;
           case 2: asp = 2;
                   break;
           case 4: asp = 1;
                   break;
           case 8: asp = 0;
                   break;
           default: asp = -1;
          }
       }
     else
       {
        switch ((PR_DWORD)(texture_height / texture_width))
          {
           case 1: asp = 3;
                   break;
           case 2: asp = 4;
                   break;
           case 4: asp = 5;
                   break;
           case 8: asp = 6;
                   break;   
           default: asp = -1;
          }
       }

     u_scale = PR_Settings.MaxUV * AspectToTexCoordFactors[asp].sMult;
     v_scale = PR_Settings.MaxUV * AspectToTexCoordFactors[asp].tMult;
    }
}


void SwitchMaterial (void)
{
PR_FACE_DATA_REAL *fdata;

  mater = &PR_ObjectMaterialList[select_material];

  texture_width = PR_WorldTextures[mater->texture_number].width;
  texture_height = PR_WorldTextures[mater->texture_number].height;

  SetTextureScale ();

  /* Wrapping texture if you used a width of 256 */
  if (texture_width == 256)
    nonwrap = 0;
  else
    nonwrap = 1;

  if (PR_Settings.RealUV)
    {
     shades = 1;
     fdata = (PR_FACE_DATA_REAL *)&face->face_data;
     fdata->u[0] = u[0] * u_scale;
     fdata->v[0] = v[0] * v_scale;
     fdata->col[0] = col[0] * shades;
     fdata->u[1] = u[1] * u_scale;
     fdata->v[1] = v[1] * v_scale;
     fdata->col[1] = col[1] * shades;
     fdata->u[2] = u[2] * u_scale;
     fdata->v[2] = v[2] * v_scale;
     fdata->col[2] = col[2] * shades;
    }
  else
    {
     shades = mater->render_shades;
     face->face_data.u[0] = u[0] * texture_width * 65536.0;
     face->face_data.v[0] = v[0] * texture_height * 65536.0;
     face->face_data.col[0] = col[0] * shades * 65536.0;
     face->face_data.u[1] = u[1] * texture_width * 65536.0;
     face->face_data.v[1] = v[1] * texture_height * 65536.0;
     face->face_data.col[1] = col[1] * shades * 65536.0;
     face->face_data.u[2] = u[2] * texture_width * 65536.0;
     face->face_data.v[2] = v[2] * texture_height * 65536.0;
     face->face_data.col[2] = col[2] * shades * 65536.0;
    }

  SwitchUV ();
}



void SwitchFace (void)
{
  select_material = face->material;
  mater = &PR_ObjectMaterialList[select_material];

  if (PR_Settings.RealUV)
    shades = 1.0;
  else
    shades = mater->render_shades;

  texture_width = PR_WorldTextures[mater->texture_number].width;
  texture_height = PR_WorldTextures[mater->texture_number].height;

  SetTextureScale ();

  /* Wrapping texture if you used a width of 256 */
  if (texture_width == 256)
    nonwrap = 0;
  else
    nonwrap = 1;

  SwitchUV ();
}


void DrawTriangle (void)
{
PR_REAL x, y, x2, y2;
PR_DWORD i;

  PR_SetConstantZ (1);

  for (i = start_screen; i <= end_screen; i++)
    {
     PR_OpenScreen (i);

     #ifndef WIN32
     if (PR_OutputDevice.pages == 1)
       PR_OpenScreen (PR_FRONTBUFFER);
     #endif

     PRGFX_Clip (415, 156, 636, 357);

     PRGFX_SetColor (GUI_WHITE);
     x = u[0] * WSIZE + 415;
     y = v[0] * HSIZE + 156;
     x2 = u[1] * WSIZE + 415;
     y2 = v[1] * HSIZE + 156;
     PRGFX_Line (x, y, x2, y2);

     PRGFX_Clip (415, 156, 636, 357);
     if (select_vertex == 0)
       PRGFX_Rectangle (x-3, y-3, x+3, y+3);
     if (select_vertex == 1)
       PRGFX_Rectangle (x2-3, y2-3, x2+3, y2+3);

     x = x2;
     y = y2;
     x2 = u[2] * WSIZE + 415;
     y2 = v[2] * HSIZE + 156;
     PRGFX_Line (x, y, x2, y2);
     if (select_vertex == 2)
       PRGFX_Rectangle (x2-3, y2-3, x2+3, y2+3);

     x = x2;
     y = y2;
     x2 = u[0] * WSIZE + 415;
     y2 = v[0] * HSIZE + 156;
     PRGFX_Line (x, y, x2, y2);
    }

}


void DrawTexture (void)
/* Draws the texture, scaled to fit in the preview box */
{
PR_DWORD i;

  SwitchUV ();

  PRGFX_Clip (0, 0, 639, 479);
  PR_SetConstantZ (1);

  for (i = start_screen; i <= end_screen; i++)
    {
     PR_OpenScreen (i);

     #ifndef WIN32
     if (PR_OutputDevice.pages == 1)
       PR_OpenScreen (PR_FRONTBUFFER);
     #endif

     if (device == DEVICE_D3D)
       {
        PR_OpenScreen (PR_BACKBUFFER);
        PR_NewFrame ();      
           }

     PRGFX_ResizeTexture (415, 156, 415+221, 156+201, mater->texture_number, 0);

     if (device == DEVICE_D3D)
       {
        PR_RenderFrame ();
        PR_Flip(1);
           }

    }


  DrawTriangle ();

  PRGFX_Clip (0, 0, 639, 479);
}


void SwitchUV (void)
/* Load up the new floating point based texture coordinates */
{
PR_REAL minu, maxu;
PR_REAL minv, maxv;
PR_REAL du, dv;
PR_FACE_DATA_REAL *fdata;
PR_REAL oo64;
PR_REAL oowidth;
PR_REAL ooheight;
PR_REAL ooshades;

  ooshades = 1.0f/ shades;

  if (PR_Settings.RealUV)
    {
     oowidth = 1.0f/ u_scale;
     ooheight = 1.0f/ v_scale;
     fdata = (PR_FACE_DATA_REAL *)&face->face_data;
     u[0] = (fdata->u[0]) * oowidth;
     u[1] = (fdata->u[1]) * oowidth;
     u[2] = (fdata->u[2]) * oowidth;
     v[0] = (fdata->v[0]) * ooheight;
     v[1] = (fdata->v[1]) * ooheight;
     v[2] = (fdata->v[2]) * ooheight;
     col[0] = (fdata->col[0]) * ooshades;
     col[1] = (fdata->col[1]) * ooshades;
     col[2] = (fdata->col[2]) * ooshades;
    }
  else
    {
     oowidth = 1.0f/ texture_width;
     ooheight = 1.0f/ texture_height;
     oo64 = 1.0f/65536.0f;
     u[0] = ((PR_REAL)face->face_data.u[0] * oo64) * oowidth;
     u[1] = ((PR_REAL)face->face_data.u[1] * oo64) * oowidth;
     u[2] = ((PR_REAL)face->face_data.u[2] * oo64) * oowidth;
     v[0] = ((PR_REAL)face->face_data.v[0] * oo64) * ooheight;
     v[1] = ((PR_REAL)face->face_data.v[1] * oo64) * ooheight;
     v[2] = ((PR_REAL)face->face_data.v[2] * oo64) * ooheight;
     col[0] = (PR_REAL)face->face_data.col[0] * oo64 * ooshades;
     col[1] = (PR_REAL)face->face_data.col[1] * oo64 * ooshades;
     col[2] = (PR_REAL)face->face_data.col[2] * oo64 * ooshades;
    }

  /* Find the extents of the mapping */
  minu = u[0];
  if (u[1] < minu)
    minu = u[1];
  if (u[2] < minu)
    minu = u[2];

  minv = v[0];
  if (v[1] < minv)
    minv = v[1];
  if (v[2] < minv)
    minv = v[2];

  maxu = u[0];
  if (u[1] > maxu)
    maxu = u[1];
  if (u[2] > maxu)
    maxu = u[2];

  maxv = v[0];
  if (v[1] > maxv)
    maxv = v[1];
  if (v[2] > maxv)
    maxv = v[2];

  du = maxu - minu;
  dv = maxv - minv;

  if (du < 1)                   /* Make sure texture is shown at least once */
    du = 1;
  if (dv < 1)
    dv = 1;

  outiling = utiling;
  ovtiling = vtiling;
  utiling = du;
  vtiling = dv;

  if (u[0] < 0)
    u[0] = 0;
  if (u[1] < 0)
    u[1] = 0;
  if (u[2] < 0)
    u[2] = 0;

  if (v[0] < 0)
    v[0] = 0;
  if (v[1] < 0)
    v[1] = 0;
  if (v[2] < 0)
    v[2] = 0;

  if (u[0] > 1)
    u[0] = 1;
  if (u[1] > 1)
    u[1] = 1;
  if (u[2] > 1)
    u[2] = 1;

  if (v[0] > 1)
    v[0] = 1;
  if (v[1] > 1)
    v[1] = 1;
  if (v[2] > 1)
    v[2] = 1;
}



void Program_Initialize (void)
/* Initialize the program */
{
color workpal[256];

  textureblock = wallocblock (222, 202);
  texturework = wallocblock (222, 202);

  setlib (NULL);
  PRGUI_GoUserPath ();

#if !defined (MSGLIDE) && !defined (WTGLIDE)
  /* Fix the palettes so the texture uses the GUI's palette */
  wreadpalette (0, 6, workpal);
  memcpy (&workpal[6], &global_palette[6], 250 * 3);

  wsetpalette (0, 255, workpal);
#endif
  
  //  wremap (workpal, PR_WorldTextures[0].image, global_palette);

  rot_x = 0;
  rot_y = 0;
  rot_z = 0;

  select_segment = 0;
  select_face = 0;
  select_vertex = 0;
  select_material = 0;

  seg = &object->segment_list[select_segment];
  face = &seg->face_list[select_face];
  mater = &PR_ObjectMaterialList[select_material];
}





void DisplayVars (void)
/* Displays the variables that you can change with the buttons */
{
PR_DWORD i;

  PRGFX_SetTextForeground (GUI_GREY1);
  PRGFX_SetTextBackground (GUI_GREY3);
  PRGFX_SetTextTransparent (TEXTFGBG);

  for (i = start_screen; i <= end_screen; i++)
    {
     PR_OpenScreen (i);

     PRGUI_printf (SDISPLAY, "%4i  ", select_segment);
     PRGUI_printf (FDISPLAY, "%4i  ", select_face);
     PRGUI_printf (VDISPLAY, "%4i  ", select_vertex);
     PRGUI_printf (MDISPLAY, "%4i  ", select_material);
     PRGUI_printf (CDISPLAY, "%4.0f  ", col[select_vertex] * 100);
    }
}



void DrawMode (void)
/* Draws a red box around the movement buttons */
{
PR_DWORD dy, y;
PR_DWORD i;

  PRGUI_HideMouse ();

  for (i = start_screen; i <= end_screen; i++)
    {
     PR_OpenScreen (i);
     for (y = 0; y < 2; y++)
       {
        if (mouse_mode == y) 
          PRGFX_SetColor (GUI_RED);
        else
          PRGFX_SetColor (GUI_BLACK);
  
        dy = 359 + y * 20;
        PRGFX_Rectangle (479, dy, 573, dy + 17);
       }
    }

  PRGUI_ShowMouse ();
}



void InitMenu (void)
/* Draw the initial menu */
{
block logo;
color pal[256];
PR_DWORD i;

  for (i = 0; i < PR_OutputDevice.pages; i++)
    {
     PR_OpenScreen (i);
     PRGFX_Clip (0, 0, 639, 479);
     PRGFX_SetColor (GUI_BLACK);
     PRGFX_Bar (0, 0, 639, 479);

     PRGFX_SetColor (GUI_GREY1);
     PRGFX_Bar (0, 377, 639, 479-67);
     PRGFX_SetColor (GUI_GREY2);
     PRGFX_Bar (0, 357, 639, 479-77);

     PRGUI_GoStartPath ();
     setlib ("guidata.prl");
     if (PR_OutputDevice.bitdepth == 8)
       logo = wloadpcx ("prbw.pcx", pal);
     else
       logo = wloadpcx ("prcol.pcx", pal);

     if (logo == NULL)
       PRGUI_Error ("Cannot find the Power Render logo file.");
     PRGFX_Clip (0, 0, 639, 479);
     PR_BeginScreen ();
     PRGFX_PutBlock8bit (0, 479-67, logo, pal, 1);
     PR_EndScreen ();
     wfreeblock (logo);


     gui_font = wloadfont ("guifont.wfn");
     setlib (NULL);

     PRGUI_Button (412, 0, 639, 479);


     PRGFX_SetTextForeground (GUI_GREY1);
     PRGFX_SetTextBackground (GUI_GREY3);
     PRGFX_SetTextTransparent (TEXTFGBG);
     PRGUI_printf (520, 5,  "TEXSET 1.0");
     PRGUI_printf (420, 15, "File");
     PRGUI_printf (450, 15, ":");
     PRGUI_printf (460, 15, "%s", objectfile);

     /* Segment */
     PRGUI_textbutton (SMINUS, "-");
     PRGUI_textbutton (SPLUS, "+");
     PRGUI_printf (SDISPW, "Segment");

     /* Face */
     PRGUI_textbutton (FMINUS, "-");
     PRGUI_textbutton (FPLUS, "+");
     PRGUI_printf (FDISPW, "Face");

     /* Vertex */
     PRGUI_textbutton (VMINUS, "-");
     PRGUI_textbutton (VPLUS, "+");
     PRGUI_printf (VDISPW, "Vertex");

     /* Material */
     PRGUI_textbutton (MMINUS, "-");
     PRGUI_textbutton (MPLUS, "+");
     PRGUI_printf (MDISPW, "Material");

     /* Color */
     PRGUI_textbutton (CMINUS, "-");
     PRGUI_textbutton (CPLUS, "+");
     PRGUI_printf (CDISPW, "Shade");

     PRGUI_textbutton (SWROBJECT, "Rot Object");
     PRGUI_textbutton (SWCAMERA,  "Camera");

     PRGUI_textbutton (QUIT, "Quit");
     PRGUI_textbutton (SAVE, "Save");

     PRGFX_SetColor (GUI_BLACK);
     PRGFX_Bar (415, 156, 636, 357);

     DisplayVars ();
 
     mouse_mode = MODE_ROBJECT;
     DrawMode ();
    }
}


void Init3D (void)
{
  /* Open the 3D viewport */
  PR_OpenViewport (&viewport, 0, 0, DISPWIDTH-1, DISPHEIGHT-1, VIEW_PLAIN);
  PR_SetViewport (&viewport);

  /* Set up a camera */
  newcam = PR_AllocCamera ();
  PR_InitializeCamera (newcam);

  camdist = -object->bbox.radius;
  camscale = object->bbox.radius / 100;
  PR_PositionCameraSource (newcam, 0, 0, camdist);
  newcam->rotation.y = 180;
  PR_SetCameraMode (newcam, CAMFLAG_ANGLE_BASED);

  obj1 = PR_CreateEntity (object, "OBJ1");
  PR_ScaleEntity (obj1, 1, 1, 1);

  PR_SetActiveCamera (newcam);
}


void Display3D (void)
{
PR_VERTEX_DATA *v1;
PR_VERTEX_DATA *v2;
PR_VERTEX_DATA *v3;

  newcam->source.z = camdist;
  PR_SetActiveCamera (newcam);

  PR_OpenScreen (PR_BACKBUFFER);
  PRGFX_Clip (active_viewport.topx,
              active_viewport.topy,
              active_viewport.bottomx,
              active_viewport.bottomy);

  PRGFX_SetColor (GUI_BLACK);
  if (device == DEVICE_D3D)
    PRGFX_ClearScreen ();
  else
    PRGFX_Bar (active_viewport.topx,
               active_viewport.topy,
               active_viewport.bottomx,
               active_viewport.bottomy);

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

  PR_SetLightPosition (&userlights, 0, newcam->source.x, newcam->source.y, newcam->source.z);
  PR_TransformLights (&userlights);

  PR_TransformEntity (obj1);
  PR_RenderEntity (obj1);

  PR_RenderFrame ();

  /* Now draw the triangle */
  v1 = face->vertex1->vdata;
  v2 = face->vertex2->vdata;
  v3 = face->vertex3->vdata;
  if (!(v1->flags | v2->flags | v3->flags))
    {
     PRGFX_SetColor (GUI_WHITE);
     PRGFX_Line (v1->sx, v1->sy, v2->sx, v2->sy);
     PRGFX_Line (v2->sx, v2->sy, v3->sx, v3->sy);
     PRGFX_Line (v3->sx, v3->sy, v1->sx, v1->sy);

     if (select_vertex == 0)
       PRGFX_Rectangle (v1->sx - 3, v1->sy - 3, v1->sx + 3, v1->sy + 3);
     if (select_vertex == 1)
       PRGFX_Rectangle (v2->sx - 3, v2->sy - 3, v2->sx + 3, v2->sy + 3);
     if (select_vertex == 2)
       PRGFX_Rectangle (v3->sx - 3, v3->sy - 3, v3->sx + 3, v3->sy + 3);
    }

  PR_Flip (1);
  PRGFX_Clip (0, 0, 639, 479);
}


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

 ddrval = IDirectDrawSurface2_Restore (wgtpdds);

 if (ddrval != DD_OK)
   return;

  InitMenu ();
  Display3D ();
  DrawTexture ();
  DisplayVars ();
  PR_LostSurface = 0;
}
#endif


void program_loop (void)
/* Controls the user input */
{
PR_DWORD x, y;
PR_DWORD choice, quit = 0;
PR_FACE_DATA_REAL *fdata;

  Display3D ();
  PRGUI_ShowMouse ();

  while ((!quit) && (!kbdon[ESC]))
   {
#ifdef WIN32
          UpdateMessages ();
#endif

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

    if (PRGUI_HitButton (QUIT))
      {
       quit = !PRGUI_ChoiceDialog ("Are you sure you want to quit?",
                    NULL, NULL, "Yes", "No");
      }



    if ((PRGUI_HitButton (SWROBJECT) | (kbdon[SPACE])) && (mouse_mode != MODE_ROBJECT))
      {
       mouse_mode = MODE_ROBJECT;
       DrawMode ();
      }
    else if ((PRGUI_HitButton (SWCAMERA) | (kbdon[KEY_Z])) && (mouse_mode != MODE_CAMERA))
      {
       mouse_mode = MODE_CAMERA;
       DrawMode ();
      }
      
    if (PRGUI_HitButton (TWINDOW) && mouse.but == 1)
      {
       msetbounds (TWINDOW);
       PRGUI_HideMouse ();
       while (mouse.but)
         {
#ifdef WIN32
                  UpdateMessages ();
#endif

                  x = mouse.mx;
          y = mouse.my;

          if (PR_Settings.RealUV)
            {
             fdata = (PR_FACE_DATA_REAL *)&face->face_data;
             fdata->u[select_vertex] = (((PR_REAL)x - 415.0)/WSIZE) *
                                      u_scale;
             fdata->v[select_vertex] = (((PR_REAL)y - 156.0)/HSIZE) *
                                      v_scale;
            }
          else
            {
             face->face_data.u[select_vertex] = (((PR_REAL)x - 415.0)/WSIZE) *
                                      texture_width * 65536.0;
             face->face_data.v[select_vertex] = (((PR_REAL)y - 156.0)/HSIZE) *
                                      texture_height * 65536.0;
}

          DrawTexture ();
          Display3D ();
         }
        msetbounds (0, 0, 637 - mouse_width, 477 - mouse_height);
        PRGUI_ShowMouse ();
      }
    else if (PRGUI_HitButton (TWINDOW) && mouse.but == 2)
      {
       select_vertex++;
       if (select_vertex > 2)
         select_vertex = 0;

       PRGUI_HideMouse ();              /* Update the display */
       DrawTexture ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       PRGUI_WaitTicks (10);
      }

    /* Check the 3D display window */
    if (PRGUI_HitButton (DISPLAY))
      {
       PRGUI_HideMouse ();
       x = mouse.mx;
       y = mouse.my;

       if (mouse_mode == MODE_ROBJECT)   /* Normal object rotation */
         {
          msetxy (204, 178);

          while (mouse.but)
            {
#ifdef WIN32
                  UpdateMessages ();
#endif

                          if (mouse.but == 1)
               {
                rot_x = 178 - mouse.my;
                rot_y = 204 - mouse.mx;
               }
             else if (mouse.but == 2)
                rot_z = 204 - mouse.mx;

             PR_RotateEntity (obj1, rot_x, rot_y, rot_z);
             msetxy (204, 178);

             Display3D ();
            }
         }
       else if (mouse_mode == MODE_CAMERA)     /* Camera */
         {
          msetxy (204, 178);

          while (mouse.but)
            {
#ifdef WIN32
                  UpdateMessages ();
#endif
             if (mouse.but == 1)
               { 
                newcam->source.x += (204 - mouse.mx) * 10;
                newcam->source.y -= (178 - mouse.my) * 10;
                newcam->dest.x = newcam->source.x;
                newcam->dest.y = newcam->source.y;
               }
             else if (mouse.but == 2)
               camdist -= (178 - mouse.my) * camscale;

             msetxy (204, 178);

             Display3D ();
            }
         }

       PRGUI_ShowMouse ();
      }

    /* Check the variable buttons */
    if ((PRGUI_HitButton (SMINUS)) && (select_segment > 0))
      {
       select_segment--;
       seg = &object->segment_list[select_segment];

       if (select_face > seg->num_faces - 1)
         select_face = seg->num_faces - 1;
       face = &seg->face_list[select_face];


       PRGUI_HideMouse ();              /* Update the display */
       SwitchFace ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       if (mouse.but == 2)              /* Delay depending on which button */
         PRGUI_WaitTicks (1);
       else
         PRGUI_WaitTicks (10);
      }
    else if ((PRGUI_HitButton (SPLUS)) && (select_segment < object->num_segments-1))
      {
       select_segment++;
       seg = &object->segment_list[select_segment];

       if (select_face > seg->num_faces - 1)
         select_face = seg->num_faces - 1;
       face = &seg->face_list[select_face];

       PRGUI_HideMouse ();              /* Update the display */
       SwitchFace ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       if (mouse.but == 2)              /* Delay depending on which button */
         PRGUI_WaitTicks (1);
       else
         PRGUI_WaitTicks (10);
      }
    else if ((PRGUI_HitButton (FMINUS)) && (select_face > 0))
      {
       select_face--;
       face = &seg->face_list[select_face];

       PRGUI_HideMouse ();              /* Update the display */
       SwitchFace ();
       DrawTexture ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       if (mouse.but == 2)              /* Delay depending on which button */
         PRGUI_WaitTicks (1);
       else
         PRGUI_WaitTicks (10);
      }
    else if ((PRGUI_HitButton (FPLUS)) && (select_face < seg->num_faces-1))
      {
       select_face++;
       face = &seg->face_list[select_face];

       PRGUI_HideMouse ();              /* Update the display */
       SwitchFace ();
       DrawTexture ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       if (mouse.but == 2)              /* Delay depending on which button */
         PRGUI_WaitTicks (1);
       else
         PRGUI_WaitTicks (10);
      }
    else if (PRGUI_HitButton (VMINUS))
      {
       select_vertex--;
       if (select_vertex < 0)
         select_vertex = 2;

       PRGUI_HideMouse ();              /* Update the display */
       DrawTexture ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       PRGUI_WaitTicks (10);
      }
    else if (PRGUI_HitButton (VPLUS))
      {
       select_vertex++;
       if (select_vertex > 2)
         select_vertex = 0;

       PRGUI_HideMouse ();              /* Update the display */
       DrawTexture ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       PRGUI_WaitTicks (10);
      }
    else if (PRGUI_HitButton (MMINUS))
      {
       select_material--;
       if (select_material < 0)
         select_material = LPRO_ImportMaterialCount-1;

       face->material = select_material;
       face->backmaterial = select_material;

       PRGUI_HideMouse ();              /* Update the display */
       SwitchMaterial ();
       DrawTexture ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();

       PRGUI_WaitTicks (20);
      }
    else if (PRGUI_HitButton (MPLUS))
      {
       select_material++;
       if (select_material > LPRO_ImportMaterialCount-1)
         select_material = 0;

       face->material = select_material;
       face->backmaterial = select_material;

       PRGUI_HideMouse ();              /* Update the display */
       SwitchMaterial ();
       DrawTexture ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();
       PRGUI_WaitTicks (20);
      }
    else if (PRGUI_HitButton (CMINUS))
      {
       col[select_vertex] -= 0.01;
       if (col[select_vertex] < 0)
         col[select_vertex] = 0;

       PRGUI_HideMouse ();              /* Update the display */
       SwitchMaterial ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();
      }
    else if (PRGUI_HitButton (CPLUS))
      {
       col[select_vertex] += 0.01;
       if (col[select_vertex] > 1)
         col[select_vertex] = 1;

       PRGUI_HideMouse ();              /* Update the display */
       SwitchMaterial ();
       DisplayVars ();
       Display3D ();
       PRGUI_ShowMouse ();
      }
    else if (PRGUI_HitButton (TUMINUS))
      {
       PRGUI_HideMouse ();              /* Update the display */
       DisplayVars ();
       PRGUI_ShowMouse ();
      }
    else if (PRGUI_HitButton (TUPLUS))
      {
       PRGUI_HideMouse ();              /* Update the display */
       DisplayVars ();
       PRGUI_ShowMouse ();
      }
    else if (PRGUI_HitButton (TVMINUS))
      {
       PRGUI_HideMouse ();              /* Update the display */
       DisplayVars ();
       PRGUI_ShowMouse ();
      }
    else if (PRGUI_HitButton (TVPLUS))
      {
       PRGUI_HideMouse ();              /* Update the display */
       DisplayVars ();
       PRGUI_ShowMouse ();
      }
    else if (PRGUI_HitButton (SAVE))
      {
       choice = !PRGUI_ChoiceDialog ("Are you sure you want to save your changes?",
                     "(Data may be lost)", NULL, "Yes", "No");
       if (choice)
         {
          PRGUI_GoUserPath ();
          PR_SavePRO (objectfile, object, SAVE_USED_MATERIALS);
         }
       noclick ();
      }
   }

  PRGUI_HideMouse ();
}



void initialize_lights (void)
{
  /* Initialize the lights */
  PR_AllocLights (&userlights, 1);
  PR_AllocLights (&scenelights, 1);

  PR_SetLightPosition (&userlights, 0, 0, 0, 10000);
  PR_SetLightOn (&userlights, 0);
  PR_SetLightColor (&userlights, 0, 1.0, 1.0, 1.0);
  PR_SetLightType (&userlights, 0, DIRECTIONAL_LIGHT);
  PR_SetLightStrength (&userlights, 0, 1.0);
  userlights.NumLights = 1;
}


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 ();
     atexit (PR_ShutdownVGA);
    }
#endif
}


void main (int argc, char *argv[])
{
//  PR_SetDebugFile ("debug", REPORT_ERRORS | REPORT_ACTIONS);
  PRGUI_InitPath (argv[0]);

  if (argc < 2)
    {
         PR_FatalError ("TEXSET Utility    version "
                        PR_VERSION_NUMBER
                        "\nCopyright 1997 Egerter Software\n\n"
                        "Usage: \n"
                        "TEXSET filename.PRO\n", "TEXSET");
    }

  printf ("TEXSET Utility    version ");
  printf (PR_VERSION_NUMBER);
  printf ("\nCopyright 1997 Egerter Software\n\n");


#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 (7500);

  PRGUI_GoStartPath ();
  setlib ("guidata.prl");

  InitializeDevices ();

  PR_AllocMaterials (512);
  PR_AllocShadeTables (32);
  PR_AllocTextures (256);

#ifndef WIN32
 #ifdef __3DFX__
   if (device == DEVICE_3DFX)
     PRGUI_Initialize3Dfx ();
 #endif
 #ifdef __MYST__
   if (device == DEVICE_MYSTIQUE)
     PRGUI_InitializeMystique ();
#endif
   if (device == DEVICE_SVGA)
   PRGUI_InitializeSVGA ();
#endif

#ifdef WIN32
  #if defined (MSGLIDE) || defined (WTGLIDE)
     PRGUI_Initialize3Dfx ();
  #endif
  #if defined (MSDD) || defined (WTDD)
    if (device == DEVICE_D3D)
      PRGUI_InitializeD3D ();
    else
      PRGUI_InitializeSVGA ();
  #endif
#endif


  if (PR_OutputDevice.pages == 1)
    {
     start_screen = PR_FRONTBUFFER;
     end_screen = PR_FRONTBUFFER;
    }
  else 
    {
     start_screen = PR_FRONTBUFFER;
     end_screen = PR_BACKBUFFER;
    }

  PRGUI_GoUserPath ();
  setlib (NULL);

  PR_Settings.LoadPalette = 1;
  strcpy (objectfile, argv[1]);
  object = PR_LoadPRO (argv[1], LOAD_NORMAL);
  if (object == NULL)
    PR_FatalError ("An error has occurred when loading the PRO file.", "TEXSET");

  PRGUI_InitTimer ();
  Program_Initialize ();
  installkbd ();

  initialize_lights ();

  InitMenu ();
  SwitchFace ();
  SwitchMaterial ();

  Init3D ();
  DrawTexture ();

  PRGUI_HideMouse ();
  Display3D ();
  PRGUI_ShowMouse ();

  PRGUI_GoUserPath ();

  program_loop ();

  uninstallkbd ();
  PRGUI_DeinitTimer ();
}



