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