home *** CD-ROM | disk | FTP | other *** search
/ Total Destruction / Total_Destruction.iso / util / q2source.exe / utils3 / qe4 / textures.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-17  |  24.2 KB  |  1,126 lines

  1. #include "qe3.h"
  2. #include "io.h"
  3.  
  4. #define    TYP_MIPTEX    68
  5. static unsigned    tex_palette[256];
  6.  
  7. static qtexture_t    *notexture;
  8.  
  9. static qboolean    nomips;
  10.  
  11. #define    FONT_HEIGHT    10
  12.  
  13. static HGLRC s_hglrcTexture;
  14. static HDC     s_hdcTexture;
  15.  
  16. //int        texture_mode = GL_NEAREST;
  17. //int        texture_mode = GL_NEAREST_MIPMAP_NEAREST;
  18. //int        texture_mode = GL_NEAREST_MIPMAP_LINEAR;
  19. //int        texture_mode = GL_LINEAR;
  20. //int        texture_mode = GL_LINEAR_MIPMAP_NEAREST;
  21. int        texture_mode = GL_LINEAR_MIPMAP_LINEAR;
  22.  
  23. int        texture_extension_number = 1;
  24.  
  25. // current active texture directory.  if empty, show textures in use
  26. char        texture_directory[32];    // use if texture_showinuse is false
  27. qboolean    texture_showinuse;
  28.  
  29. // texture layout functions
  30. qtexture_t    *current_texture;
  31. int            current_x, current_y, current_row;
  32.  
  33. int            texture_nummenus;
  34. #define        MAX_TEXTUREDIRS    100
  35. char        texture_menunames[MAX_TEXTUREDIRS][64];
  36.  
  37. qboolean    g_dontuse;        // set to true to load the texture but not flag as used
  38.  
  39. void SelectTexture (int mx, int my);
  40.  
  41. void    Texture_MouseDown (int x, int y, int buttons);
  42. void    Texture_MouseUp (int x, int y, int buttons);
  43. void    Texture_MouseMoved (int x, int y, int buttons);
  44.  
  45. //=====================================================
  46.  
  47. void SortTextures(void)
  48. {    
  49.     qtexture_t    *q, *qtemp, *qhead, *qcur, *qprev;
  50.  
  51.     // standard insertion sort
  52.     // Take the first texture from the list and
  53.     // add it to our new list
  54.     if ( g_qeglobals.d_qtextures == NULL)
  55.         return;    
  56.  
  57.     qhead = g_qeglobals.d_qtextures;
  58.     q = g_qeglobals.d_qtextures->next;
  59.     qhead->next = NULL;
  60.     
  61.     // while there are still things on the old
  62.     // list, keep adding them to the new list
  63.     while (q)
  64.     {
  65.         qtemp = q;
  66.         q = q->next;
  67.         
  68.         qprev = NULL;
  69.         qcur = qhead;
  70.  
  71.         while (qcur)
  72.         {
  73.             // Insert it here?
  74.             if (strcmp(qtemp->name, qcur->name) < 0)
  75.             {
  76.                 qtemp->next = qcur;
  77.                 if (qprev)
  78.                     qprev->next = qtemp;
  79.                 else
  80.                     qhead = qtemp;
  81.                 break;
  82.             }
  83.             
  84.             // Move on
  85.  
  86.             qprev = qcur;
  87.             qcur = qcur->next;
  88.  
  89.  
  90.             // is this one at the end?
  91.  
  92.             if (qcur == NULL)
  93.             {
  94.                 qprev->next = qtemp;
  95.                 qtemp->next = NULL;
  96.             }
  97.         }
  98.  
  99.  
  100.     }
  101.  
  102.     g_qeglobals.d_qtextures = qhead;
  103. }
  104.  
  105. //=====================================================
  106.  
  107.  
  108. /*
  109. ==============
  110. Texture_InitPalette
  111. ==============
  112. */
  113. void Texture_InitPalette (byte *pal)
  114. {
  115.     int        r,g,b,v;
  116.     int        i;
  117.     int        inf;
  118.     byte    gammatable[256];
  119.     float    gamma;
  120.  
  121.     gamma = g_qeglobals.d_savedinfo.fGamma;
  122.  
  123.     if (gamma == 1.0)
  124.     {
  125.         for (i=0 ; i<256 ; i++)
  126.             gammatable[i] = i;
  127.     }
  128.     else
  129.     {
  130.         for (i=0 ; i<256 ; i++)
  131.         {
  132.             inf = 255 * pow ( (i+0.5)/255.5 , gamma ) + 0.5;
  133.             if (inf < 0)
  134.                 inf = 0;
  135.             if (inf > 255)
  136.                 inf = 255;
  137.             gammatable[i] = inf;
  138.         }
  139.     }
  140.  
  141.     for (i=0 ; i<256 ; i++)
  142.     {
  143.         r = gammatable[pal[0]];
  144.         g = gammatable[pal[1]];
  145.         b = gammatable[pal[2]];
  146.         pal += 3;
  147.         
  148.         v = (r<<24) + (g<<16) + (b<<8) + 255;
  149.         v = BigLong (v);
  150.         
  151.         tex_palette[i] = v;
  152.     }
  153. }
  154.  
  155. void SetTexParameters (void)
  156. {
  157.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode );
  158.     
  159.     switch ( texture_mode )
  160.     {
  161.     case GL_NEAREST:
  162.     case GL_NEAREST_MIPMAP_NEAREST:
  163.     case GL_NEAREST_MIPMAP_LINEAR:
  164.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  165.         break;
  166.     case GL_LINEAR:
  167.     case GL_LINEAR_MIPMAP_NEAREST:
  168.     case GL_LINEAR_MIPMAP_LINEAR:
  169.         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  170.         break;
  171.     }
  172. }
  173.  
  174. /*
  175. ============
  176. Texture_SetMode
  177. ============
  178. */
  179. void Texture_SetMode(int iMenu)
  180. {
  181.     int    i, iMode;
  182.     HMENU hMenu;
  183.     qboolean texturing = true;
  184.  
  185.     hMenu = GetMenu(g_qeglobals.d_hwndMain);
  186.  
  187.     switch(iMenu) {
  188.     case ID_VIEW_NEAREST:                    
  189.         iMode = GL_NEAREST;
  190.         break;
  191.     case ID_VIEW_NEARESTMIPMAP:
  192.         iMode = GL_NEAREST_MIPMAP_NEAREST;
  193.         break;
  194.     case ID_VIEW_LINEAR:
  195.         iMode = GL_NEAREST_MIPMAP_LINEAR;
  196.         break;
  197.     case ID_VIEW_BILINEAR:
  198.         iMode = GL_LINEAR;
  199.         break;
  200.     case ID_VIEW_BILINEARMIPMAP:
  201.         iMode = GL_LINEAR_MIPMAP_NEAREST;
  202.         break;
  203.     case ID_VIEW_TRILINEAR:
  204.         iMode = GL_LINEAR_MIPMAP_LINEAR;
  205.         break;
  206.  
  207.     case ID_TEXTURES_WIREFRAME:
  208.         iMode = 0;
  209.         texturing = false;
  210.         break;
  211.  
  212.     case ID_TEXTURES_FLATSHADE:
  213.         iMode = 0;
  214.         texturing = false;
  215.         break;
  216.  
  217.     }
  218.  
  219.     CheckMenuItem(hMenu, ID_VIEW_NEAREST, MF_BYCOMMAND | MF_UNCHECKED);
  220.     CheckMenuItem(hMenu, ID_VIEW_NEARESTMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
  221.     CheckMenuItem(hMenu, ID_VIEW_LINEAR, MF_BYCOMMAND | MF_UNCHECKED);
  222.     CheckMenuItem(hMenu, ID_VIEW_BILINEARMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
  223.     CheckMenuItem(hMenu, ID_VIEW_BILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
  224.     CheckMenuItem(hMenu, ID_VIEW_TRILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
  225.     CheckMenuItem(hMenu, ID_TEXTURES_WIREFRAME, MF_BYCOMMAND | MF_UNCHECKED);
  226.     CheckMenuItem(hMenu, ID_TEXTURES_FLATSHADE, MF_BYCOMMAND | MF_UNCHECKED);
  227.  
  228.     CheckMenuItem(hMenu, iMenu, MF_BYCOMMAND | MF_CHECKED);
  229.  
  230.     g_qeglobals.d_savedinfo.iTexMenu = iMenu;
  231.     texture_mode = iMode;
  232.     if ( texturing )
  233.         SetTexParameters ();
  234.  
  235.     if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME)
  236.     {
  237.         camera.draw_mode = cd_wire;
  238.         Map_BuildBrushData();
  239.         Sys_UpdateWindows (W_ALL);
  240.         return;
  241.  
  242.     } else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE) {
  243.  
  244.         camera.draw_mode = cd_solid;
  245.         Map_BuildBrushData();
  246.         Sys_UpdateWindows (W_ALL);
  247.         return;
  248.     }
  249.  
  250.     for (i=1 ; i<texture_extension_number ; i++)
  251.     {
  252.         glBindTexture( GL_TEXTURE_2D, i );
  253.         SetTexParameters ();
  254.     }
  255.  
  256.     // select the default texture
  257.     glBindTexture( GL_TEXTURE_2D, 0 );
  258.  
  259.     glFinish();
  260.  
  261.     if (camera.draw_mode != cd_texture)
  262.     {
  263.         camera.draw_mode = cd_texture;
  264.         Map_BuildBrushData();
  265.     }
  266.  
  267.     Sys_UpdateWindows (W_ALL);
  268. }
  269.  
  270.  
  271. /*
  272. =================
  273. Texture_LoadTexture
  274. =================
  275. */
  276. qtexture_t *Texture_LoadTexture (miptex_t *qtex)
  277. {
  278.     byte        *source;
  279.     unsigned    *dest;
  280.     int            width, height, i, count;
  281.     int            total[3];
  282.     qtexture_t    *q;
  283.     
  284.     q = qmalloc(sizeof(*q));
  285.     width = LittleLong(qtex->width);
  286.     height = LittleLong(qtex->height);
  287.  
  288.     q->width = width;
  289.     q->height = height;
  290.  
  291.     q->flags = qtex->flags;
  292.     q->value = qtex->value;
  293.     q->contents = qtex->contents;
  294.  
  295.     dest = qmalloc (width*height*4);
  296.  
  297.     count = width*height;
  298.     source = (byte *)qtex + LittleLong(qtex->offsets[0]);
  299.  
  300.     // The dib is upside down so we want to copy it into 
  301.     // the buffer bottom up.
  302.  
  303.     total[0] = total[1] = total[2] = 0;
  304.     for (i=0 ; i<count ; i++)
  305.     {
  306.         dest[i] = tex_palette[source[i]];
  307.  
  308.         total[0] += ((byte *)(dest+i))[0];
  309.         total[1] += ((byte *)(dest+i))[1];
  310.         total[2] += ((byte *)(dest+i))[2];
  311.     }
  312.  
  313.     q->color[0] = (float)total[0]/(count*255);
  314.     q->color[1] = (float)total[1]/(count*255);
  315.     q->color[2] = (float)total[2]/(count*255);
  316.  
  317.     q->texture_number = texture_extension_number++;
  318.  
  319.     glBindTexture( GL_TEXTURE_2D, q->texture_number );
  320.     SetTexParameters ();
  321.  
  322.     if (nomips)
  323.         glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
  324.     else
  325.         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
  326.  
  327.     free (dest);
  328.  
  329.     glBindTexture( GL_TEXTURE_2D, 0 );
  330.  
  331.     return q;
  332. }
  333.  
  334. /*
  335. ===============
  336. Texture_CreateSolid
  337.  
  338. Create a single pixel texture of the apropriate color
  339. ===============
  340. */
  341. qtexture_t *Texture_CreateSolid (char *name)
  342. {
  343.     byte    data[4];
  344.     qtexture_t    *q;
  345.  
  346.     q = qmalloc(sizeof(*q));
  347.     
  348.     sscanf (name, "(%f %f %f)", &q->color[0], &q->color[1], &q->color[2]);
  349.  
  350.     data[0] = q->color[0]*255;
  351.     data[1] = q->color[1]*255;
  352.     data[2] = q->color[2]*255;
  353.     data[3] = 255;
  354.  
  355.     q->width = q->height = 1;
  356.     q->texture_number = texture_extension_number++;
  357.     glBindTexture( GL_TEXTURE_2D, q->texture_number );
  358.     SetTexParameters ();
  359.  
  360.     if (nomips)
  361.         glTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  362.     else
  363.         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, data);
  364.  
  365.     glBindTexture( GL_TEXTURE_2D, 0 );
  366.  
  367.     return q;
  368. }
  369.  
  370.  
  371. /*
  372. =================
  373. Texture_MakeNotexture
  374. =================
  375. */
  376. void Texture_MakeNotexture (void)
  377. {
  378.     qtexture_t    *q;
  379.     byte        data[4][4];
  380.  
  381.     notexture = q = qmalloc(sizeof(*q));
  382.     strcpy (q->name, "notexture");
  383.     q->width = q->height = 64;
  384.     
  385.     memset (data, 0, sizeof(data));
  386.     data[0][2] = data[3][2] = 255;
  387.  
  388.     q->color[0] = 0;
  389.     q->color[1] = 0;
  390.     q->color[2] = 0.5;
  391.  
  392.     q->texture_number = texture_extension_number++;
  393.     glBindTexture( GL_TEXTURE_2D, q->texture_number );
  394.     SetTexParameters ();
  395.  
  396.     if (nomips)
  397.         glTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  398.     else
  399.         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data);
  400.  
  401.     glBindTexture( GL_TEXTURE_2D, 0 );
  402. }
  403.  
  404.  
  405.  
  406. /*
  407. ===============
  408. Texture_ForName
  409. ===============
  410. */
  411. qtexture_t *Texture_ForName (char *name)
  412. {
  413.     byte    *lump;
  414.     qtexture_t    *q;
  415.     char    filename[1024];
  416.  
  417. //return notexture;
  418.     for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
  419.     {
  420.         if (!strcmp(name,  q->name))
  421.         {
  422.             if (!g_dontuse)
  423.                 q->inuse = true;
  424.             return q;
  425.         }
  426.     }
  427.  
  428.     if (name[0] == '(')
  429.     {
  430.         q = Texture_CreateSolid (name);
  431.         strncpy (q->name, name, sizeof(q->name)-1);
  432.     }
  433.     else
  434.     {
  435.         // load the file
  436.         sprintf (filename, "%s/%s.wal", 
  437.             ValueForKey (g_qeglobals.d_project_entity, "texturepath"),
  438.             name);
  439.         Sys_Printf ("Loading %s\n", name);
  440.         if (LoadFile (filename, &lump) == -1)
  441.         {
  442.             Sys_Printf ("     load failed!\n");
  443.             return notexture;
  444.         }
  445.         q = Texture_LoadTexture ((miptex_t *)lump);
  446.         free (lump);
  447.         strncpy (q->name, name, sizeof(q->name)-1);
  448.         StripExtension (q->name);
  449.     }
  450.  
  451.     if (!g_dontuse)
  452.         q->inuse = true;
  453.     q->next = g_qeglobals.d_qtextures;
  454.     g_qeglobals.d_qtextures = q;
  455.  
  456.     return q;
  457. }
  458.  
  459. /*
  460. ==================
  461. FillTextureMenu
  462.  
  463. ==================
  464. */
  465. void FillTextureMenu (void)
  466. {
  467.     HMENU    hmenu;
  468.     int        i;
  469.     struct _finddata_t fileinfo;
  470.     int        handle;
  471.     char    dirstring[1024];
  472.     char    *path;
  473.  
  474.     hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_TEXTURE);
  475.  
  476.     // delete everything
  477.     for (i=0 ; i<texture_nummenus ; i++)
  478.         DeleteMenu (hmenu, CMD_TEXTUREWAD+i, MF_BYCOMMAND);
  479.  
  480.     // add everything
  481.     path = ValueForKey (g_qeglobals.d_project_entity, "texturepath");
  482.  
  483.     sprintf (dirstring, "%s/*.*", path);
  484.  
  485.     handle = _findfirst (dirstring, &fileinfo);
  486.     if (handle == -1)
  487.         return;
  488.  
  489.     do
  490.     {
  491.         if (!(fileinfo.attrib & _A_SUBDIR))
  492.             continue;
  493.         if (fileinfo.name[0] == '.')
  494.             continue;
  495.         // add this directory to the menu
  496.         AppendMenu (hmenu, MF_ENABLED|MF_STRING,
  497.             CMD_TEXTUREWAD+texture_nummenus, (LPCTSTR)fileinfo.name);
  498.         strcpy (texture_menunames[texture_nummenus], fileinfo.name);
  499.         strcat (texture_menunames[texture_nummenus], "/");
  500.         if (++texture_nummenus == MAX_TEXTUREDIRS)
  501.             break;
  502.     } while (_findnext( handle, &fileinfo ) != -1);
  503.  
  504.     _findclose (handle);
  505. }
  506.  
  507.  
  508. /*
  509. ==================
  510. Texture_ClearInuse
  511.  
  512. A new map is being loaded, so clear inuse markers
  513. ==================
  514. */
  515. void Texture_ClearInuse (void)
  516. {
  517.     qtexture_t    *q;
  518.  
  519.     for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
  520.     {
  521.         q->inuse = false;
  522.     }
  523. }
  524.  
  525.  
  526.  
  527. /*
  528. ==============
  529. Texture_ShowDirectory
  530. ==============
  531. */
  532. void    Texture_ShowDirectory (int menunum)
  533. {
  534.     struct _finddata_t fileinfo;
  535.     int        handle;
  536.     char    name[1024];
  537.     char    dirstring[1024];
  538.  
  539.     texture_showinuse = false;
  540.     strcpy (texture_directory, texture_menunames[menunum-CMD_TEXTUREWAD]);
  541.  
  542.     g_qeglobals.d_texturewin.originy = 0;
  543.     Sys_Status("loading all textures\n", 0);
  544.  
  545.     // load all .wal files
  546.     sprintf (dirstring, "%s/textures/%s*.wal", 
  547.         ValueForKey (g_qeglobals.d_project_entity, "basepath"),
  548.         texture_menunames[menunum-CMD_TEXTUREWAD]);
  549.  
  550.     Sys_Printf ("Scanning %s\n", dirstring);
  551.  
  552.     handle = _findfirst (dirstring, &fileinfo);
  553.     if (handle == -1)
  554.         return;
  555.  
  556.     g_dontuse = true;
  557.     do
  558.     {
  559.         sprintf (name, "%s%s", texture_directory, fileinfo.name);
  560.         StripExtension (name);
  561.         Texture_ForName (name);
  562.     } while (_findnext( handle, &fileinfo ) != -1);
  563.     g_dontuse = false;
  564.  
  565.     _findclose (handle);
  566.  
  567.     SortTextures();
  568.     SetInspectorMode(W_TEXTURE);
  569.     Sys_UpdateWindows(W_TEXTURE);
  570.  
  571.     sprintf (name, "Textures: %s", texture_directory);
  572.     SetWindowText(g_qeglobals.d_hwndEntity, name);
  573.  
  574.     // select the first texture in the list
  575.     if (!g_qeglobals.d_texturewin.texdef.name[0])
  576.         SelectTexture (16, g_qeglobals.d_texturewin.height -16);
  577. }
  578.  
  579. /*
  580. ==============
  581. Texture_ShowInuse
  582. ==============
  583. */
  584. void    Texture_ShowInuse (void)
  585. {
  586.     char    name[1024];
  587.     face_t    *f;
  588.     brush_t    *b;
  589.  
  590.     texture_showinuse = true;
  591.  
  592.     g_qeglobals.d_texturewin.originy = 0;
  593.     Sys_Status("Selecting active textures\n", 0);
  594.     Texture_ClearInuse ();
  595.  
  596.     for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next)
  597.         for (f=b->brush_faces ; f ; f=f->next)
  598.             Texture_ForName (f->texdef.name);
  599.  
  600.     for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next)
  601.         for (f=b->brush_faces ; f ; f=f->next)
  602.             Texture_ForName (f->texdef.name);
  603.  
  604.     SortTextures();
  605.     SetInspectorMode(W_TEXTURE);
  606.     Sys_UpdateWindows (W_TEXTURE);
  607.  
  608.     sprintf (name, "Textures: in use");
  609.     SetWindowText(g_qeglobals.d_hwndEntity, name);
  610.  
  611.     // select the first texture in the list
  612.     if (!g_qeglobals.d_texturewin.texdef.name[0])
  613.         SelectTexture (16, g_qeglobals.d_texturewin.height -16);
  614. }
  615.  
  616. /*
  617. ============================================================================
  618.  
  619. TEXTURE LAYOUT
  620.  
  621. ============================================================================
  622. */
  623.  
  624. void Texture_StartPos (void)
  625. {
  626.     current_texture = g_qeglobals.d_qtextures;
  627.     current_x = 8;
  628.     current_y = -8;
  629.     current_row = 0;
  630. }
  631.  
  632. qtexture_t *Texture_NextPos (int *x, int *y)
  633. {
  634.     qtexture_t    *q;
  635.  
  636.     while (1)
  637.     {
  638.         q = current_texture;
  639.         if (!q)
  640.             return q;
  641.         current_texture = current_texture->next;
  642.         if (q->name[0] == '(')    // fake color texture
  643.             continue;
  644.         if (q->inuse)
  645.             break;            // allways show in use
  646.         if (!texture_showinuse && strncmp (q->name, texture_directory, strlen(texture_directory)))
  647.             continue;
  648.         break;
  649.     }
  650.  
  651.     if (current_x + q->width > g_qeglobals.d_texturewin.width-8 && current_row)
  652.     {    // go to the next row unless the texture is the first on the row
  653.         current_x = 8;
  654.         current_y -= current_row + FONT_HEIGHT + 4;
  655.         current_row = 0;
  656.     }
  657.  
  658.     *x = current_x;
  659.     *y = current_y;
  660.  
  661.     // Is our texture larger than the row? If so, grow the 
  662.     // row height to match it
  663.  
  664.     if (current_row < q->height)
  665.         current_row = q->height;
  666.  
  667.     // never go less than 64, or the names get all crunched up
  668.     current_x += q->width < 64 ? 64 : q->width;
  669.     current_x += 8;
  670.  
  671.     return q;
  672. }
  673.  
  674. /*
  675. ============================================================================
  676.  
  677.   MOUSE ACTIONS
  678.  
  679. ============================================================================
  680. */
  681.  
  682. static    int    textures_cursorx, textures_cursory;
  683.  
  684.  
  685. /*
  686. ============
  687. Texture_SetTexture
  688.  
  689. ============
  690. */
  691. void Texture_SetTexture (texdef_t *texdef)
  692. {
  693.     qtexture_t    *q;
  694.     int            x,y;
  695.     char        sz[256];
  696.  
  697.     if (texdef->name[0] == '(')
  698.     {
  699.         Sys_Status("Can't select an entity texture\n", 0);
  700.         return;
  701.     }
  702.     g_qeglobals.d_texturewin.texdef = *texdef;
  703.  
  704.     Sys_UpdateWindows (W_TEXTURE);
  705.     sprintf(sz, "Selected texture: %s\n", texdef->name);
  706.     Sys_Status(sz, 0);
  707.     Select_SetTexture(texdef);
  708.  
  709. // scroll origin so the texture is completely on screen
  710.     Texture_StartPos ();
  711.     while (1)
  712.     {
  713.         q = Texture_NextPos (&x, &y);
  714.         if (!q)
  715.             break;
  716.         if (!strcmpi(texdef->name, q->name))
  717.         {
  718.             if (y > g_qeglobals.d_texturewin.originy)
  719.             {
  720.                 g_qeglobals.d_texturewin.originy = y;
  721.                 Sys_UpdateWindows (W_TEXTURE);
  722.                 return;
  723.             }
  724.  
  725.             if (y-q->height-2*FONT_HEIGHT < g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height)
  726.             {
  727.                 g_qeglobals.d_texturewin.originy = y-q->height-2*FONT_HEIGHT+g_qeglobals.d_texturewin.height;
  728.                 Sys_UpdateWindows (W_TEXTURE);
  729.                 return;
  730.             }
  731.  
  732.             return;
  733.         }
  734.     }
  735. }
  736.  
  737.  
  738. /*
  739. ==============
  740. SelectTexture
  741.  
  742.   By mouse click
  743. ==============
  744. */
  745. void SelectTexture (int mx, int my)
  746. {
  747.     int        x, y;
  748.     qtexture_t    *q;
  749.     texdef_t    tex;
  750.  
  751.     my += g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height;
  752.     
  753.     Texture_StartPos ();
  754.     while (1)
  755.     {
  756.         q = Texture_NextPos (&x, &y);
  757.         if (!q)
  758.             break;
  759.         if (mx > x && mx - x < q->width
  760.             && my < y && y - my < q->height + FONT_HEIGHT)
  761.         {
  762.             memset (&tex, 0, sizeof(tex));
  763.             tex.scale[0] = 1;
  764.             tex.scale[1] = 1;
  765.             tex.flags = q->flags;
  766.             tex.value = q->value;
  767.             tex.contents = q->contents;
  768.             strcpy (tex.name, q->name);
  769.             Texture_SetTexture (&tex);
  770.             return;
  771.         }
  772.     }
  773.  
  774.     Sys_Status("Did not select a texture\n", 0);
  775. }
  776.  
  777. /*
  778. ==============
  779. Texture_MouseDown
  780. ==============
  781. */
  782. void Texture_MouseDown (int x, int y, int buttons)
  783. {
  784.     Sys_GetCursorPos (&textures_cursorx, &textures_cursory);
  785.  
  786.     // lbutton = select texture
  787.     if (buttons == MK_LBUTTON )
  788.     {
  789.         SelectTexture (x, g_qeglobals.d_texturewin.height - 1 - y);
  790.         return;
  791.     }
  792.  
  793. }
  794.  
  795. /*
  796. ==============
  797. Texture_MouseUp
  798. ==============
  799. */
  800. void Texture_MouseUp (int x, int y, int buttons)
  801. {
  802. }
  803.  
  804. /*
  805. ==============
  806. Texture_MouseMoved
  807. ==============
  808. */
  809. void Texture_MouseMoved (int x, int y, int buttons)
  810. {
  811.     int scale = 1;
  812.  
  813.     if ( buttons & MK_SHIFT )
  814.         scale = 4;
  815.  
  816.     // rbutton = drag texture origin
  817.     if (buttons & MK_RBUTTON)
  818.     {
  819.         Sys_GetCursorPos (&x, &y);
  820.         if ( y != textures_cursory)
  821.         {
  822.             g_qeglobals.d_texturewin.originy += ( y-textures_cursory) * scale;
  823.             if (g_qeglobals.d_texturewin.originy > 0)
  824.                 g_qeglobals.d_texturewin.originy = 0;
  825.             Sys_SetCursorPos (textures_cursorx, textures_cursory);
  826.             Sys_UpdateWindows (W_TEXTURE);
  827.         }
  828.         return;
  829.     }
  830. }
  831.  
  832.  
  833. /*
  834. ============================================================================
  835.  
  836. DRAWING
  837.  
  838. ============================================================================
  839. */
  840.  
  841. int imax(int iFloor, int i) { if (i>iFloor) return iFloor; return i; }
  842. HFONT ghFont = NULL;
  843.  
  844. /*
  845. ============
  846. Texture_Draw2
  847. ============
  848. */
  849. void Texture_Draw2 (int width, int height)
  850. {
  851.     qtexture_t    *q;
  852.     int            x, y;
  853.     char        *name;
  854.  
  855.     glClearColor (
  856.         g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][0],
  857.         g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][1],
  858.         g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][2],
  859.         0);
  860.     glViewport (0,0,width,height);
  861.     glClear (GL_COLOR_BUFFER_BIT);
  862.     glDisable (GL_DEPTH_TEST);
  863.     glMatrixMode(GL_PROJECTION);
  864.     glLoadIdentity ();
  865.     glOrtho (0, width, g_qeglobals.d_texturewin.originy-height, g_qeglobals.d_texturewin.originy, -100, 100);
  866.     glEnable (GL_TEXTURE_2D);
  867.  
  868.     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  869.     g_qeglobals.d_texturewin.width = width;
  870.     g_qeglobals.d_texturewin.height = height;
  871.     Texture_StartPos ();
  872.  
  873.     while (1)
  874.     {
  875.         q = Texture_NextPos (&x, &y);
  876.         if (!q)
  877.             break;
  878.  
  879.         // Is this texture visible?
  880.         if ( (y-q->height-FONT_HEIGHT < g_qeglobals.d_texturewin.originy)
  881.             && (y > g_qeglobals.d_texturewin.originy - height) )
  882.         {
  883.  
  884.             // if in use, draw a background
  885.             if (q->inuse && !texture_showinuse)
  886.             {
  887.                 glLineWidth (1);
  888.                 glColor3f (0.5,1,0.5);
  889.                 glDisable (GL_TEXTURE_2D);
  890.  
  891.                 glBegin (GL_LINE_LOOP);
  892.                 glVertex2f (x-1,y+1-FONT_HEIGHT);
  893.                 glVertex2f (x-1,y-q->height-1-FONT_HEIGHT);
  894.                 glVertex2f (x+1+q->width,y-q->height-1-FONT_HEIGHT);
  895.                 glVertex2f (x+1+q->width,y+1-FONT_HEIGHT);
  896.                 glEnd ();
  897.  
  898.                 glEnable (GL_TEXTURE_2D);
  899.             }
  900.  
  901.             // Draw the texture
  902.             glColor3f (1,1,1);
  903.             glBindTexture( GL_TEXTURE_2D, q->texture_number );
  904.             glBegin (GL_QUADS);
  905.             glTexCoord2f (0,0);
  906.             glVertex2f (x,y-FONT_HEIGHT);
  907.             glTexCoord2f (1,0);
  908.             glVertex2f (x+q->width,y-FONT_HEIGHT);
  909.             glTexCoord2f (1,1);
  910.             glVertex2f (x+q->width,y-FONT_HEIGHT-q->height);
  911.             glTexCoord2f (0,1);
  912.             glVertex2f (x,y-FONT_HEIGHT-q->height);
  913.             glEnd ();
  914.  
  915.             // draw the selection border
  916.             if (!strcmpi(g_qeglobals.d_texturewin.texdef.name, q->name))
  917.             {
  918.                 glLineWidth (3);
  919.                 glColor3f (1,0,0);
  920.                 glDisable (GL_TEXTURE_2D);
  921.  
  922.                 glBegin (GL_LINE_LOOP);
  923.                 glVertex2f (x-4,y-FONT_HEIGHT+4);
  924.                 glVertex2f (x-4,y-FONT_HEIGHT-q->height-4);
  925.                 glVertex2f (x+4+q->width,y-FONT_HEIGHT-q->height-4);
  926.                 glVertex2f (x+4+q->width,y-FONT_HEIGHT+4);
  927.                 glEnd ();
  928.  
  929.                 glEnable (GL_TEXTURE_2D);
  930.                 glLineWidth (1);
  931.             }
  932.  
  933.             // draw the texture name
  934.             glColor3f (0,0,0);
  935.             glRasterPos2f (x, y-FONT_HEIGHT+2);
  936.  
  937.             // don't draw the directory name
  938.             for (name = q->name ; *name && *name != '/' && *name != '\\' ; name++)
  939.                 ;
  940.             if (!*name)
  941.                 name = q->name;
  942.             else
  943.                 name++;
  944.             glCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
  945.         }
  946.     }
  947.  
  948.     // reset the current texture
  949.     glBindTexture( GL_TEXTURE_2D, 0 );
  950.     glFinish();
  951. }
  952.  
  953. /*
  954. ============
  955. WTexWndProc
  956. ============
  957. */
  958. LONG WINAPI WTex_WndProc (
  959.     HWND    hWnd,
  960.     UINT    uMsg,
  961.     WPARAM  wParam,
  962.     LPARAM  lParam)
  963. {
  964.     int        xPos, yPos;
  965.     RECT    rect;
  966.  
  967.     GetClientRect(hWnd, &rect);
  968.  
  969.     switch (uMsg)
  970.     {
  971.     case WM_CREATE:
  972.         s_hdcTexture = GetDC(hWnd);
  973.         QEW_SetupPixelFormat(s_hdcTexture, false);
  974.  
  975.         if ( ( s_hglrcTexture = wglCreateContext( s_hdcTexture ) ) == 0 )
  976.             Error( "wglCreateContext in WTex_WndProc failed" );
  977.  
  978.         if (!wglMakeCurrent( s_hdcTexture, s_hglrcTexture ))
  979.             Error ("wglMakeCurrent in WTex_WndProc failed");
  980.  
  981.         if (!wglShareLists( g_qeglobals.d_hglrcBase, s_hglrcTexture ) )
  982.             Error( "wglShareLists in WTex_WndProc failed" );
  983.  
  984.         return 0;
  985.  
  986.     case WM_DESTROY:
  987.         wglMakeCurrent( NULL, NULL );
  988.         wglDeleteContext( s_hglrcTexture );
  989.         ReleaseDC( hWnd, s_hdcTexture );
  990.         return 0;
  991.  
  992.     case WM_PAINT:
  993.         { 
  994.             PAINTSTRUCT    ps;
  995.  
  996.             BeginPaint(hWnd, &ps);
  997.  
  998.             if ( !wglMakeCurrent( s_hdcTexture, s_hglrcTexture ) )
  999.                 Error ("wglMakeCurrent failed");
  1000.             Texture_Draw2 (rect.right-rect.left, rect.bottom-rect.top);
  1001.             SwapBuffers(s_hdcTexture);
  1002.  
  1003.             EndPaint(hWnd, &ps);
  1004.         }
  1005.         return 0;
  1006.  
  1007.     case WM_MBUTTONDOWN:
  1008.     case WM_RBUTTONDOWN:
  1009.     case WM_LBUTTONDOWN:
  1010.         SetCapture( g_qeglobals.d_hwndTexture );
  1011.         xPos = (short)LOWORD(lParam);  // horizontal position of cursor 
  1012.         yPos = (short)HIWORD(lParam);  // vertical position of cursor 
  1013.         
  1014.         Texture_MouseDown (xPos, yPos, wParam);
  1015.         return 0;
  1016.  
  1017.     case WM_MBUTTONUP:
  1018.     case WM_RBUTTONUP:
  1019.     case WM_LBUTTONUP:
  1020.         xPos = (short)LOWORD(lParam);  // horizontal position of cursor 
  1021.         yPos = (short)HIWORD(lParam);  // vertical position of cursor 
  1022.         
  1023.         Texture_MouseUp (xPos, yPos, wParam);
  1024.         if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
  1025.             ReleaseCapture ();
  1026.         return 0;
  1027.  
  1028.     case WM_MOUSEMOVE:
  1029.         xPos = (short)LOWORD(lParam);  // horizontal position of cursor 
  1030.         yPos = (short)HIWORD(lParam);  // vertical position of cursor 
  1031.         
  1032.         Texture_MouseMoved (xPos, yPos, wParam);
  1033.         return 0;
  1034.     }
  1035.  
  1036.     return DefWindowProc (hWnd, uMsg, wParam, lParam);
  1037. }
  1038.  
  1039.  
  1040.  
  1041. /*
  1042. ==================
  1043. CreateTextureWindow
  1044.  
  1045. We need to create a seperate window for the textures
  1046. in the inspector window, because we can't share
  1047. gl and gdi drawing in a single window
  1048. ==================
  1049. */
  1050. #define    TEXTURE_WINDOW_CLASS    "QTEX"
  1051. HWND CreateTextureWindow (void)
  1052. {
  1053.     WNDCLASS   wc;
  1054.     HWND        hwnd;
  1055.  
  1056.     /* Register the camera class */
  1057.     memset (&wc, 0, sizeof(wc));
  1058.  
  1059.     wc.style         = 0;
  1060.     wc.lpfnWndProc   = (WNDPROC)WTex_WndProc;
  1061.     wc.cbClsExtra    = 0;
  1062.     wc.cbWndExtra    = 0;
  1063.     wc.hInstance     = g_qeglobals.d_hInstance;
  1064.     wc.hIcon         = 0;
  1065.     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
  1066.     wc.hbrBackground = NULL;
  1067.     wc.lpszMenuName  = 0;
  1068.     wc.lpszClassName = TEXTURE_WINDOW_CLASS;
  1069.  
  1070.     if (!RegisterClass (&wc) )
  1071.         Error ("WCam_Register: failed");
  1072.  
  1073.     hwnd = CreateWindow (TEXTURE_WINDOW_CLASS ,
  1074.         "Texture View",
  1075.         WS_BORDER|WS_CHILD|WS_VISIBLE,
  1076.         20,
  1077.         20,
  1078.         64,
  1079.         64,    // size
  1080.  
  1081.         g_qeglobals.d_hwndEntity,    // parent window
  1082.         0,        // no menu
  1083.         g_qeglobals.d_hInstance,
  1084.         0);
  1085.     if (!hwnd)
  1086.         Error ("Couldn't create texturewindow");
  1087.  
  1088.     return hwnd;
  1089. }
  1090.  
  1091. /*
  1092. ==================
  1093. Texture_Flush
  1094. ==================
  1095. */
  1096. void Texture_Flush (void)
  1097. {
  1098. }
  1099.  
  1100.  
  1101. /*
  1102. ==================
  1103. Texture_Init
  1104. ==================
  1105. */
  1106. void Texture_Init (void)
  1107. {
  1108.     char    name[1024];
  1109.     byte    *pal;
  1110.  
  1111.     // load the palette
  1112.     sprintf (name, "%s/pics/colormap.pcx", 
  1113.         ValueForKey (g_qeglobals.d_project_entity, "basepath"));
  1114.     Load256Image (name, NULL, &pal, NULL, NULL);
  1115.     if (!pal)
  1116.         Error ("Couldn't load %s", name);
  1117.     Texture_InitPalette (pal);
  1118.     free (pal);
  1119.  
  1120.     // create the fallback texture
  1121.     Texture_MakeNotexture ();
  1122.  
  1123.     g_qeglobals.d_qtextures = NULL;
  1124. }
  1125.  
  1126.