]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/extra/qe4/textures.c
Merge remote-tracking branch 'ttimo/master'
[xonotic/netradiant.git] / tools / quake2 / extra / qe4 / textures.c
diff --git a/tools/quake2/extra/qe4/textures.c b/tools/quake2/extra/qe4/textures.c
new file mode 100644 (file)
index 0000000..21fa8ce
--- /dev/null
@@ -0,0 +1,1147 @@
+/*
+===========================================================================
+Copyright (C) 1997-2006 Id Software, Inc.
+
+This file is part of Quake 2 Tools source code.
+
+Quake 2 Tools source code is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+Quake 2 Tools source code is distributed in the hope that it will be
+useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Quake 2 Tools source code; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+===========================================================================
+*/
+
+#include "qe3.h"
+#include "io.h"
+
+#define        TYP_MIPTEX      68
+static unsigned        tex_palette[256];
+
+static qtexture_t      *notexture;
+
+static qboolean        nomips;
+
+#define        FONT_HEIGHT     10
+
+static HGLRC s_hglrcTexture;
+static HDC      s_hdcTexture;
+
+//int          texture_mode = GL_NEAREST;
+//int          texture_mode = GL_NEAREST_MIPMAP_NEAREST;
+//int          texture_mode = GL_NEAREST_MIPMAP_LINEAR;
+//int          texture_mode = GL_LINEAR;
+//int          texture_mode = GL_LINEAR_MIPMAP_NEAREST;
+int            texture_mode = GL_LINEAR_MIPMAP_LINEAR;
+
+int            texture_extension_number = 1;
+
+// current active texture directory.  if empty, show textures in use
+char           texture_directory[32];  // use if texture_showinuse is false
+qboolean       texture_showinuse;
+
+// texture layout functions
+qtexture_t     *current_texture;
+int                    current_x, current_y, current_row;
+
+int                    texture_nummenus;
+#define                MAX_TEXTUREDIRS 100
+char           texture_menunames[MAX_TEXTUREDIRS][64];
+
+qboolean       g_dontuse;              // set to true to load the texture but not flag as used
+
+void SelectTexture (int mx, int my);
+
+void   Texture_MouseDown (int x, int y, int buttons);
+void   Texture_MouseUp (int x, int y, int buttons);
+void   Texture_MouseMoved (int x, int y, int buttons);
+
+//=====================================================
+
+void SortTextures(void)
+{
+       qtexture_t      *q, *qtemp, *qhead, *qcur, *qprev;
+
+       // standard insertion sort
+       // Take the first texture from the list and
+       // add it to our new list
+       if ( g_qeglobals.d_qtextures == NULL)
+               return;
+
+       qhead = g_qeglobals.d_qtextures;
+       q = g_qeglobals.d_qtextures->next;
+       qhead->next = NULL;
+
+       // while there are still things on the old
+       // list, keep adding them to the new list
+       while (q)
+       {
+               qtemp = q;
+               q = q->next;
+
+               qprev = NULL;
+               qcur = qhead;
+
+               while (qcur)
+               {
+                       // Insert it here?
+                       if (strcmp(qtemp->name, qcur->name) < 0)
+                       {
+                               qtemp->next = qcur;
+                               if (qprev)
+                                       qprev->next = qtemp;
+                               else
+                                       qhead = qtemp;
+                               break;
+                       }
+
+                       // Move on
+
+                       qprev = qcur;
+                       qcur = qcur->next;
+
+
+                       // is this one at the end?
+
+                       if (qcur == NULL)
+                       {
+                               qprev->next = qtemp;
+                               qtemp->next = NULL;
+                       }
+               }
+
+
+       }
+
+       g_qeglobals.d_qtextures = qhead;
+}
+
+//=====================================================
+
+
+/*
+==============
+Texture_InitPalette
+==============
+*/
+void Texture_InitPalette (byte *pal)
+{
+    int                r,g,b,v;
+    int                i;
+       int             inf;
+       byte    gammatable[256];
+       float   gamma;
+
+       gamma = g_qeglobals.d_savedinfo.fGamma;
+
+       if (gamma == 1.0)
+       {
+               for (i=0 ; i<256 ; i++)
+                       gammatable[i] = i;
+       }
+       else
+       {
+               for (i=0 ; i<256 ; i++)
+               {
+                       inf = 255 * pow ( (i+0.5)/255.5 , gamma ) + 0.5;
+                       if (inf < 0)
+                               inf = 0;
+                       if (inf > 255)
+                               inf = 255;
+                       gammatable[i] = inf;
+               }
+       }
+
+    for (i=0 ; i<256 ; i++)
+    {
+               r = gammatable[pal[0]];
+               g = gammatable[pal[1]];
+               b = gammatable[pal[2]];
+               pal += 3;
+
+               v = (r<<24) + (g<<16) + (b<<8) + 255;
+               v = BigLong (v);
+
+               tex_palette[i] = v;
+    }
+}
+
+void SetTexParameters (void)
+{
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode );
+
+       switch ( texture_mode )
+       {
+       case GL_NEAREST:
+       case GL_NEAREST_MIPMAP_NEAREST:
+       case GL_NEAREST_MIPMAP_LINEAR:
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+               break;
+       case GL_LINEAR:
+       case GL_LINEAR_MIPMAP_NEAREST:
+       case GL_LINEAR_MIPMAP_LINEAR:
+               glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+               break;
+       }
+}
+
+/*
+============
+Texture_SetMode
+============
+*/
+void Texture_SetMode(int iMenu)
+{
+       int     i, iMode;
+       HMENU hMenu;
+       qboolean texturing = true;
+
+       hMenu = GetMenu(g_qeglobals.d_hwndMain);
+
+       switch(iMenu) {
+       case ID_VIEW_NEAREST:
+               iMode = GL_NEAREST;
+               break;
+       case ID_VIEW_NEARESTMIPMAP:
+               iMode = GL_NEAREST_MIPMAP_NEAREST;
+               break;
+       case ID_VIEW_LINEAR:
+               iMode = GL_NEAREST_MIPMAP_LINEAR;
+               break;
+       case ID_VIEW_BILINEAR:
+               iMode = GL_LINEAR;
+               break;
+       case ID_VIEW_BILINEARMIPMAP:
+               iMode = GL_LINEAR_MIPMAP_NEAREST;
+               break;
+       case ID_VIEW_TRILINEAR:
+               iMode = GL_LINEAR_MIPMAP_LINEAR;
+               break;
+
+       case ID_TEXTURES_WIREFRAME:
+               iMode = 0;
+               texturing = false;
+               break;
+
+       case ID_TEXTURES_FLATSHADE:
+               iMode = 0;
+               texturing = false;
+               break;
+
+       }
+
+       CheckMenuItem(hMenu, ID_VIEW_NEAREST, MF_BYCOMMAND | MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_VIEW_NEARESTMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_VIEW_LINEAR, MF_BYCOMMAND | MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_VIEW_BILINEARMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_VIEW_BILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_VIEW_TRILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_TEXTURES_WIREFRAME, MF_BYCOMMAND | MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_TEXTURES_FLATSHADE, MF_BYCOMMAND | MF_UNCHECKED);
+
+       CheckMenuItem(hMenu, iMenu, MF_BYCOMMAND | MF_CHECKED);
+
+       g_qeglobals.d_savedinfo.iTexMenu = iMenu;
+       texture_mode = iMode;
+       if ( texturing )
+               SetTexParameters ();
+
+       if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME)
+       {
+               camera.draw_mode = cd_wire;
+               Map_BuildBrushData();
+               Sys_UpdateWindows (W_ALL);
+               return;
+
+       } else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE) {
+
+               camera.draw_mode = cd_solid;
+               Map_BuildBrushData();
+               Sys_UpdateWindows (W_ALL);
+               return;
+       }
+
+       for (i=1 ; i<texture_extension_number ; i++)
+       {
+               glBindTexture( GL_TEXTURE_2D, i );
+               SetTexParameters ();
+       }
+
+       // select the default texture
+       glBindTexture( GL_TEXTURE_2D, 0 );
+
+       glFinish();
+
+       if (camera.draw_mode != cd_texture)
+       {
+               camera.draw_mode = cd_texture;
+               Map_BuildBrushData();
+       }
+
+       Sys_UpdateWindows (W_ALL);
+}
+
+
+/*
+=================
+Texture_LoadTexture
+=================
+*/
+qtexture_t *Texture_LoadTexture (miptex_t *qtex)
+{
+    byte               *source;
+    unsigned   *dest;
+    int                        width, height, i, count;
+       int                     total[3];
+    qtexture_t *q;
+
+    q = qmalloc(sizeof(*q));
+    width = LittleLong(qtex->width);
+    height = LittleLong(qtex->height);
+
+    q->width = width;
+    q->height = height;
+
+       q->flags = qtex->flags;
+       q->value = qtex->value;
+       q->contents = qtex->contents;
+
+       dest = qmalloc (width*height*4);
+
+    count = width*height;
+    source = (byte *)qtex + LittleLong(qtex->offsets[0]);
+
+       // The dib is upside down so we want to copy it into
+       // the buffer bottom up.
+
+       total[0] = total[1] = total[2] = 0;
+    for (i=0 ; i<count ; i++)
+       {
+               dest[i] = tex_palette[source[i]];
+
+               total[0] += ((byte *)(dest+i))[0];
+               total[1] += ((byte *)(dest+i))[1];
+               total[2] += ((byte *)(dest+i))[2];
+       }
+
+       q->color[0] = (float)total[0]/(count*255);
+       q->color[1] = (float)total[1]/(count*255);
+       q->color[2] = (float)total[2]/(count*255);
+
+    q->texture_number = texture_extension_number++;
+
+       glBindTexture( GL_TEXTURE_2D, q->texture_number );
+       SetTexParameters ();
+
+       if (nomips)
+               glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
+       else
+               gluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
+
+       free (dest);
+
+       glBindTexture( GL_TEXTURE_2D, 0 );
+
+    return q;
+}
+
+/*
+===============
+Texture_CreateSolid
+
+Create a single pixel texture of the apropriate color
+===============
+*/
+qtexture_t *Texture_CreateSolid (char *name)
+{
+       byte    data[4];
+       qtexture_t      *q;
+
+    q = qmalloc(sizeof(*q));
+
+       sscanf (name, "(%f %f %f)", &q->color[0], &q->color[1], &q->color[2]);
+
+       data[0] = q->color[0]*255;
+       data[1] = q->color[1]*255;
+       data[2] = q->color[2]*255;
+       data[3] = 255;
+
+       q->width = q->height = 1;
+    q->texture_number = texture_extension_number++;
+       glBindTexture( GL_TEXTURE_2D, q->texture_number );
+       SetTexParameters ();
+
+       if (nomips)
+               glTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       else
+               gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+       glBindTexture( GL_TEXTURE_2D, 0 );
+
+       return q;
+}
+
+
+/*
+=================
+Texture_MakeNotexture
+=================
+*/
+void Texture_MakeNotexture (void)
+{
+    qtexture_t *q;
+    byte               data[4][4];
+
+       notexture = q = qmalloc(sizeof(*q));
+       strcpy (q->name, "notexture");
+    q->width = q->height = 64;
+
+       memset (data, 0, sizeof(data));
+       data[0][2] = data[3][2] = 255;
+
+       q->color[0] = 0;
+       q->color[1] = 0;
+       q->color[2] = 0.5;
+
+    q->texture_number = texture_extension_number++;
+       glBindTexture( GL_TEXTURE_2D, q->texture_number );
+       SetTexParameters ();
+
+       if (nomips)
+               glTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
+       else
+               gluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data);
+
+       glBindTexture( GL_TEXTURE_2D, 0 );
+}
+
+
+
+/*
+===============
+Texture_ForName
+===============
+*/
+qtexture_t *Texture_ForName (char *name)
+{
+    byte    *lump;
+       qtexture_t      *q;
+       char    filename[1024];
+
+//return notexture;
+       for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
+    {
+               if (!strcmp(name,  q->name))
+               {
+                       if (!g_dontuse)
+                               q->inuse = true;
+                   return q;
+               }
+    }
+
+       if (name[0] == '(')
+       {
+               q = Texture_CreateSolid (name);
+               strncpy (q->name, name, sizeof(q->name)-1);
+       }
+       else
+       {
+               // load the file
+               sprintf (filename, "%s/%s.wal",
+                       ValueForKey (g_qeglobals.d_project_entity, "texturepath"),
+                       name);
+               Sys_Printf ("Loading %s\n", name);
+               if (LoadFile (filename, &lump) == -1)
+               {
+                       Sys_Printf ("     load failed!\n");
+                       return notexture;
+               }
+               q = Texture_LoadTexture ((miptex_t *)lump);
+               free (lump);
+               strncpy (q->name, name, sizeof(q->name)-1);
+               StripExtension (q->name);
+       }
+
+       if (!g_dontuse)
+               q->inuse = true;
+       q->next = g_qeglobals.d_qtextures;
+       g_qeglobals.d_qtextures = q;
+
+    return q;
+}
+
+/*
+==================
+FillTextureMenu
+
+==================
+*/
+void FillTextureMenu (void)
+{
+       HMENU   hmenu;
+       int             i;
+       struct _finddata_t fileinfo;
+       int             handle;
+       char    dirstring[1024];
+       char    *path;
+
+       hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_TEXTURE);
+
+       // delete everything
+       for (i=0 ; i<texture_nummenus ; i++)
+               DeleteMenu (hmenu, CMD_TEXTUREWAD+i, MF_BYCOMMAND);
+
+       // add everything
+       path = ValueForKey (g_qeglobals.d_project_entity, "texturepath");
+
+       sprintf (dirstring, "%s/*.*", path);
+
+       handle = _findfirst (dirstring, &fileinfo);
+       if (handle == -1)
+               return;
+
+       do
+       {
+               if (!(fileinfo.attrib & _A_SUBDIR))
+                       continue;
+               if (fileinfo.name[0] == '.')
+                       continue;
+               // add this directory to the menu
+               AppendMenu (hmenu, MF_ENABLED|MF_STRING,
+                       CMD_TEXTUREWAD+texture_nummenus, (LPCTSTR)fileinfo.name);
+               strcpy (texture_menunames[texture_nummenus], fileinfo.name);
+               strcat (texture_menunames[texture_nummenus], "/");
+               if (++texture_nummenus == MAX_TEXTUREDIRS)
+                       break;
+       } while (_findnext( handle, &fileinfo ) != -1);
+
+       _findclose (handle);
+}
+
+
+/*
+==================
+Texture_ClearInuse
+
+A new map is being loaded, so clear inuse markers
+==================
+*/
+void Texture_ClearInuse (void)
+{
+       qtexture_t      *q;
+
+       for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
+    {
+               q->inuse = false;
+       }
+}
+
+
+
+/*
+==============
+Texture_ShowDirectory
+==============
+*/
+void   Texture_ShowDirectory (int menunum)
+{
+       struct _finddata_t fileinfo;
+       int             handle;
+       char    name[1024];
+       char    dirstring[1024];
+
+       texture_showinuse = false;
+       strcpy (texture_directory, texture_menunames[menunum-CMD_TEXTUREWAD]);
+
+       g_qeglobals.d_texturewin.originy = 0;
+       Sys_Status("loading all textures\n", 0);
+
+       // load all .wal files
+       sprintf (dirstring, "%s/textures/%s*.wal",
+               ValueForKey (g_qeglobals.d_project_entity, "basepath"),
+               texture_menunames[menunum-CMD_TEXTUREWAD]);
+
+       Sys_Printf ("Scanning %s\n", dirstring);
+
+       handle = _findfirst (dirstring, &fileinfo);
+       if (handle == -1)
+               return;
+
+       g_dontuse = true;
+       do
+       {
+               sprintf (name, "%s%s", texture_directory, fileinfo.name);
+               StripExtension (name);
+               Texture_ForName (name);
+       } while (_findnext( handle, &fileinfo ) != -1);
+       g_dontuse = false;
+
+       _findclose (handle);
+
+       SortTextures();
+       SetInspectorMode(W_TEXTURE);
+       Sys_UpdateWindows(W_TEXTURE);
+
+       sprintf (name, "Textures: %s", texture_directory);
+       SetWindowText(g_qeglobals.d_hwndEntity, name);
+
+       // select the first texture in the list
+       if (!g_qeglobals.d_texturewin.texdef.name[0])
+               SelectTexture (16, g_qeglobals.d_texturewin.height -16);
+}
+
+/*
+==============
+Texture_ShowInuse
+==============
+*/
+void   Texture_ShowInuse (void)
+{
+       char    name[1024];
+       face_t  *f;
+       brush_t *b;
+
+       texture_showinuse = true;
+
+       g_qeglobals.d_texturewin.originy = 0;
+       Sys_Status("Selecting active textures\n", 0);
+       Texture_ClearInuse ();
+
+       for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next)
+               for (f=b->brush_faces ; f ; f=f->next)
+                       Texture_ForName (f->texdef.name);
+
+       for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next)
+               for (f=b->brush_faces ; f ; f=f->next)
+                       Texture_ForName (f->texdef.name);
+
+       SortTextures();
+       SetInspectorMode(W_TEXTURE);
+       Sys_UpdateWindows (W_TEXTURE);
+
+       sprintf (name, "Textures: in use");
+       SetWindowText(g_qeglobals.d_hwndEntity, name);
+
+       // select the first texture in the list
+       if (!g_qeglobals.d_texturewin.texdef.name[0])
+               SelectTexture (16, g_qeglobals.d_texturewin.height -16);
+}
+
+/*
+============================================================================
+
+TEXTURE LAYOUT
+
+============================================================================
+*/
+
+void Texture_StartPos (void)
+{
+       current_texture = g_qeglobals.d_qtextures;
+       current_x = 8;
+       current_y = -8;
+       current_row = 0;
+}
+
+qtexture_t *Texture_NextPos (int *x, int *y)
+{
+       qtexture_t      *q;
+
+       while (1)
+       {
+               q = current_texture;
+               if (!q)
+                       return q;
+               current_texture = current_texture->next;
+               if (q->name[0] == '(')  // fake color texture
+                       continue;
+               if (q->inuse)
+                       break;                  // allways show in use
+               if (!texture_showinuse && strncmp (q->name, texture_directory, strlen(texture_directory)))
+                       continue;
+               break;
+       }
+
+       if (current_x + q->width > g_qeglobals.d_texturewin.width-8 && current_row)
+       {       // go to the next row unless the texture is the first on the row
+               current_x = 8;
+               current_y -= current_row + FONT_HEIGHT + 4;
+               current_row = 0;
+       }
+
+       *x = current_x;
+       *y = current_y;
+
+       // Is our texture larger than the row? If so, grow the
+       // row height to match it
+
+    if (current_row < q->height)
+               current_row = q->height;
+
+       // never go less than 64, or the names get all crunched up
+       current_x += q->width < 64 ? 64 : q->width;
+       current_x += 8;
+
+       return q;
+}
+
+/*
+============================================================================
+
+  MOUSE ACTIONS
+
+============================================================================
+*/
+
+static int     textures_cursorx, textures_cursory;
+
+
+/*
+============
+Texture_SetTexture
+
+============
+*/
+void Texture_SetTexture (texdef_t *texdef)
+{
+       qtexture_t      *q;
+       int                     x,y;
+       char            sz[256];
+
+       if (texdef->name[0] == '(')
+       {
+               Sys_Status("Can't select an entity texture\n", 0);
+               return;
+       }
+       g_qeglobals.d_texturewin.texdef = *texdef;
+
+       Sys_UpdateWindows (W_TEXTURE);
+       sprintf(sz, "Selected texture: %s\n", texdef->name);
+       Sys_Status(sz, 0);
+       Select_SetTexture(texdef);
+
+// scroll origin so the texture is completely on screen
+       Texture_StartPos ();
+       while (1)
+       {
+               q = Texture_NextPos (&x, &y);
+               if (!q)
+                       break;
+               if (!strcmpi(texdef->name, q->name))
+               {
+                       if (y > g_qeglobals.d_texturewin.originy)
+                       {
+                               g_qeglobals.d_texturewin.originy = y;
+                               Sys_UpdateWindows (W_TEXTURE);
+                               return;
+                       }
+
+                       if (y-q->height-2*FONT_HEIGHT < g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height)
+                       {
+                               g_qeglobals.d_texturewin.originy = y-q->height-2*FONT_HEIGHT+g_qeglobals.d_texturewin.height;
+                               Sys_UpdateWindows (W_TEXTURE);
+                               return;
+                       }
+
+                       return;
+               }
+       }
+}
+
+
+/*
+==============
+SelectTexture
+
+  By mouse click
+==============
+*/
+void SelectTexture (int mx, int my)
+{
+       int             x, y;
+       qtexture_t      *q;
+       texdef_t        tex;
+
+       my += g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height;
+
+       Texture_StartPos ();
+       while (1)
+       {
+               q = Texture_NextPos (&x, &y);
+               if (!q)
+                       break;
+               if (mx > x && mx - x < q->width
+                       && my < y && y - my < q->height + FONT_HEIGHT)
+               {
+                       memset (&tex, 0, sizeof(tex));
+                       tex.scale[0] = 1;
+                       tex.scale[1] = 1;
+                       tex.flags = q->flags;
+                       tex.value = q->value;
+                       tex.contents = q->contents;
+                       strcpy (tex.name, q->name);
+                       Texture_SetTexture (&tex);
+                       return;
+               }
+       }
+
+       Sys_Status("Did not select a texture\n", 0);
+}
+
+/*
+==============
+Texture_MouseDown
+==============
+*/
+void Texture_MouseDown (int x, int y, int buttons)
+{
+       Sys_GetCursorPos (&textures_cursorx, &textures_cursory);
+
+       // lbutton = select texture
+       if (buttons == MK_LBUTTON )
+       {
+               SelectTexture (x, g_qeglobals.d_texturewin.height - 1 - y);
+               return;
+       }
+
+}
+
+/*
+==============
+Texture_MouseUp
+==============
+*/
+void Texture_MouseUp (int x, int y, int buttons)
+{
+}
+
+/*
+==============
+Texture_MouseMoved
+==============
+*/
+void Texture_MouseMoved (int x, int y, int buttons)
+{
+       int scale = 1;
+
+       if ( buttons & MK_SHIFT )
+               scale = 4;
+
+       // rbutton = drag texture origin
+       if (buttons & MK_RBUTTON)
+       {
+               Sys_GetCursorPos (&x, &y);
+               if ( y != textures_cursory)
+               {
+                       g_qeglobals.d_texturewin.originy += ( y-textures_cursory) * scale;
+                       if (g_qeglobals.d_texturewin.originy > 0)
+                               g_qeglobals.d_texturewin.originy = 0;
+                       Sys_SetCursorPos (textures_cursorx, textures_cursory);
+                       Sys_UpdateWindows (W_TEXTURE);
+               }
+               return;
+       }
+}
+
+
+/*
+============================================================================
+
+DRAWING
+
+============================================================================
+*/
+
+int imax(int iFloor, int i) { if (i>iFloor) return iFloor; return i; }
+HFONT ghFont = NULL;
+
+/*
+============
+Texture_Draw2
+============
+*/
+void Texture_Draw2 (int width, int height)
+{
+       qtexture_t      *q;
+       int                     x, y;
+       char            *name;
+
+       glClearColor (
+               g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][0],
+               g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][1],
+               g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][2],
+               0);
+       glViewport (0,0,width,height);
+       glClear (GL_COLOR_BUFFER_BIT);
+       glDisable (GL_DEPTH_TEST);
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity ();
+       glOrtho (0, width, g_qeglobals.d_texturewin.originy-height, g_qeglobals.d_texturewin.originy, -100, 100);
+       glEnable (GL_TEXTURE_2D);
+
+       glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+       g_qeglobals.d_texturewin.width = width;
+       g_qeglobals.d_texturewin.height = height;
+       Texture_StartPos ();
+
+       while (1)
+       {
+               q = Texture_NextPos (&x, &y);
+               if (!q)
+                       break;
+
+               // Is this texture visible?
+               if ( (y-q->height-FONT_HEIGHT < g_qeglobals.d_texturewin.originy)
+                       && (y > g_qeglobals.d_texturewin.originy - height) )
+               {
+
+                       // if in use, draw a background
+                       if (q->inuse && !texture_showinuse)
+                       {
+                               glLineWidth (1);
+                               glColor3f (0.5,1,0.5);
+                               glDisable (GL_TEXTURE_2D);
+
+                               glBegin (GL_LINE_LOOP);
+                               glVertex2f (x-1,y+1-FONT_HEIGHT);
+                               glVertex2f (x-1,y-q->height-1-FONT_HEIGHT);
+                               glVertex2f (x+1+q->width,y-q->height-1-FONT_HEIGHT);
+                               glVertex2f (x+1+q->width,y+1-FONT_HEIGHT);
+                               glEnd ();
+
+                               glEnable (GL_TEXTURE_2D);
+                       }
+
+                       // Draw the texture
+                       glColor3f (1,1,1);
+                       glBindTexture( GL_TEXTURE_2D, q->texture_number );
+                       glBegin (GL_QUADS);
+                       glTexCoord2f (0,0);
+                       glVertex2f (x,y-FONT_HEIGHT);
+                       glTexCoord2f (1,0);
+                       glVertex2f (x+q->width,y-FONT_HEIGHT);
+                       glTexCoord2f (1,1);
+                       glVertex2f (x+q->width,y-FONT_HEIGHT-q->height);
+                       glTexCoord2f (0,1);
+                       glVertex2f (x,y-FONT_HEIGHT-q->height);
+                       glEnd ();
+
+                       // draw the selection border
+                       if (!strcmpi(g_qeglobals.d_texturewin.texdef.name, q->name))
+                       {
+                               glLineWidth (3);
+                               glColor3f (1,0,0);
+                               glDisable (GL_TEXTURE_2D);
+
+                               glBegin (GL_LINE_LOOP);
+                               glVertex2f (x-4,y-FONT_HEIGHT+4);
+                               glVertex2f (x-4,y-FONT_HEIGHT-q->height-4);
+                               glVertex2f (x+4+q->width,y-FONT_HEIGHT-q->height-4);
+                               glVertex2f (x+4+q->width,y-FONT_HEIGHT+4);
+                               glEnd ();
+
+                               glEnable (GL_TEXTURE_2D);
+                               glLineWidth (1);
+                       }
+
+                       // draw the texture name
+                       glColor3f (0,0,0);
+                       glRasterPos2f (x, y-FONT_HEIGHT+2);
+
+                       // don't draw the directory name
+                       for (name = q->name ; *name && *name != '/' && *name != '\\' ; name++)
+                               ;
+                       if (!*name)
+                               name = q->name;
+                       else
+                               name++;
+                       glCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
+               }
+       }
+
+       // reset the current texture
+       glBindTexture( GL_TEXTURE_2D, 0 );
+       glFinish();
+}
+
+/*
+============
+WTexWndProc
+============
+*/
+LONG WINAPI WTex_WndProc (
+    HWND    hWnd,
+    UINT    uMsg,
+    WPARAM  wParam,
+    LPARAM  lParam)
+{
+       int             xPos, yPos;
+    RECT       rect;
+
+    GetClientRect(hWnd, &rect);
+
+    switch (uMsg)
+    {
+       case WM_CREATE:
+        s_hdcTexture = GetDC(hWnd);
+               QEW_SetupPixelFormat(s_hdcTexture, false);
+
+               if ( ( s_hglrcTexture = wglCreateContext( s_hdcTexture ) ) == 0 )
+                       Error( "wglCreateContext in WTex_WndProc failed" );
+
+        if (!wglMakeCurrent( s_hdcTexture, s_hglrcTexture ))
+                       Error ("wglMakeCurrent in WTex_WndProc failed");
+
+               if (!wglShareLists( g_qeglobals.d_hglrcBase, s_hglrcTexture ) )
+                       Error( "wglShareLists in WTex_WndProc failed" );
+
+               return 0;
+
+       case WM_DESTROY:
+               wglMakeCurrent( NULL, NULL );
+               wglDeleteContext( s_hglrcTexture );
+               ReleaseDC( hWnd, s_hdcTexture );
+               return 0;
+
+       case WM_PAINT:
+        {
+                   PAINTSTRUCT ps;
+
+                   BeginPaint(hWnd, &ps);
+
+            if ( !wglMakeCurrent( s_hdcTexture, s_hglrcTexture ) )
+                               Error ("wglMakeCurrent failed");
+                       Texture_Draw2 (rect.right-rect.left, rect.bottom-rect.top);
+                       SwapBuffers(s_hdcTexture);
+
+                   EndPaint(hWnd, &ps);
+        }
+               return 0;
+
+       case WM_MBUTTONDOWN:
+       case WM_RBUTTONDOWN:
+       case WM_LBUTTONDOWN:
+               SetCapture( g_qeglobals.d_hwndTexture );
+               xPos = (short)LOWORD(lParam);  // horizontal position of cursor
+               yPos = (short)HIWORD(lParam);  // vertical position of cursor
+
+               Texture_MouseDown (xPos, yPos, wParam);
+               return 0;
+
+       case WM_MBUTTONUP:
+       case WM_RBUTTONUP:
+       case WM_LBUTTONUP:
+               xPos = (short)LOWORD(lParam);  // horizontal position of cursor
+               yPos = (short)HIWORD(lParam);  // vertical position of cursor
+
+               Texture_MouseUp (xPos, yPos, wParam);
+               if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
+                       ReleaseCapture ();
+               return 0;
+
+       case WM_MOUSEMOVE:
+               xPos = (short)LOWORD(lParam);  // horizontal position of cursor
+               yPos = (short)HIWORD(lParam);  // vertical position of cursor
+
+               Texture_MouseMoved (xPos, yPos, wParam);
+               return 0;
+    }
+
+    return DefWindowProc (hWnd, uMsg, wParam, lParam);
+}
+
+
+
+/*
+==================
+CreateTextureWindow
+
+We need to create a seperate window for the textures
+in the inspector window, because we can't share
+gl and gdi drawing in a single window
+==================
+*/
+#define        TEXTURE_WINDOW_CLASS    "QTEX"
+HWND CreateTextureWindow (void)
+{
+    WNDCLASS   wc;
+       HWND            hwnd;
+
+    /* Register the camera class */
+       memset (&wc, 0, sizeof(wc));
+
+    wc.style         = 0;
+    wc.lpfnWndProc   = (WNDPROC)WTex_WndProc;
+    wc.cbClsExtra    = 0;
+    wc.cbWndExtra    = 0;
+    wc.hInstance     = g_qeglobals.d_hInstance;
+    wc.hIcon         = 0;
+    wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
+    wc.hbrBackground = NULL;
+    wc.lpszMenuName  = 0;
+    wc.lpszClassName = TEXTURE_WINDOW_CLASS;
+
+    if (!RegisterClass (&wc) )
+        Error ("WCam_Register: failed");
+
+       hwnd = CreateWindow (TEXTURE_WINDOW_CLASS ,
+               "Texture View",
+               WS_BORDER|WS_CHILD|WS_VISIBLE,
+               20,
+               20,
+               64,
+               64,     // size
+
+               g_qeglobals.d_hwndEntity,       // parent window
+               0,              // no menu
+               g_qeglobals.d_hInstance,
+               0);
+       if (!hwnd)
+               Error ("Couldn't create texturewindow");
+
+       return hwnd;
+}
+
+/*
+==================
+Texture_Flush
+==================
+*/
+void Texture_Flush (void)
+{
+}
+
+
+/*
+==================
+Texture_Init
+==================
+*/
+void Texture_Init (void)
+{
+       char    name[1024];
+       byte    *pal;
+
+       // load the palette
+       sprintf (name, "%s/pics/colormap.pcx",
+               ValueForKey (g_qeglobals.d_project_entity, "basepath"));
+       Load256Image (name, NULL, &pal, NULL, NULL);
+       if (!pal)
+               Error ("Couldn't load %s", name);
+       Texture_InitPalette (pal);
+       free (pal);
+
+       // create the fallback texture
+       Texture_MakeNotexture ();
+
+       g_qeglobals.d_qtextures = NULL;
+}
+