]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/texpaint/win_skin.c
Merge branch 'master' into divVerent/farplanedist-sky-fix
[xonotic/netradiant.git] / tools / quake2 / extra / texpaint / win_skin.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 "texpaint.h"
24
25 #define SKIN_WINDOW_CLASS       "TPSkin"
26
27 HDC             skindc;
28 int             skinw_width, skinw_height;      // size of the window
29
30 float   skin_x = 128, skin_y = 128, skin_z = 100;
31
32 qboolean        skin_lines = false;
33
34 char    tri_filename[1024];
35 char    skin_filename[1024];
36 int             skin_width, skin_height;        // size of the .lbm image
37
38 unsigned        index_texture[1024*512];
39
40
41 void UpdateTexture (int offset)
42 {
43         int             x, y;
44
45         y = offset / width2;
46         x = offset % width2;
47
48         BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN);
49 //      glTexImage2D (GL_TEXTURE_2D, 0, 3, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgb);
50
51         glTexSubImage2D (GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgb+offset);
52 }
53
54 /*
55 ===================================================================
56
57   TEXEL MODIFICATION
58
59 ===================================================================
60 */
61
62 #define MAX_MODIFY      8192
63
64 typedef struct
65 {
66         int             offset;
67         int             oldvalue;
68 } modify_t;
69
70 int                     modify_index;
71 int                     undo_index;
72 modify_t        modify[MAX_MODIFY];
73
74 void SetSkinModified (void)
75 {
76         char    text[1024];
77
78         if (modified && modified_past_autosave)
79                 return;
80
81         modified = true;
82         modified_past_autosave = true;
83
84         sprintf (text, "%s *", skin_filename);
85         SetWindowText (skinwindow, text);
86 }
87
88 void SetSkin (int index, int pixel)
89 {
90         modify_t        *m;
91
92         if (!modified)
93                 SetSkinModified ();
94
95         // save undo info
96         m = &modify[undo_index];
97         m->offset = index;
98         m->oldvalue = pic[index];
99
100         modify_index = (++undo_index)&(MAX_MODIFY-1);
101
102         // modify it
103         rgb[index] = selected_rgb;
104         pic[index] = selected_index;
105         UpdateTexture (index);
106         InvalidateRect (skinwindow, NULL, false);
107         InvalidateRect (camerawindow, NULL, false);
108 }
109
110 void Undo (void)
111 {
112         modify_t        *m;
113         int                     temp;
114
115         if (!undo_index)
116                 return;
117
118         if (!--undo_index)
119         {       // back to unmodified state
120                 modified = false;
121                 SetWindowText (skinwindow, skin_filename);
122         }
123         m = &modify[undo_index];
124
125         // modify it
126         temp = pic[m->offset];
127         pic[m->offset] = m->oldvalue;
128         rgb[m->offset] = palette[m->oldvalue*3] +
129                 (palette[m->oldvalue*3+1]<<8) + (palette[m->oldvalue*3+2]<<16);
130         m->oldvalue = temp;
131         UpdateTexture (m->offset);
132         InvalidateRect (skinwindow, NULL, false);
133         InvalidateRect (camerawindow, NULL, false);
134
135 }
136
137 void Redo (void)
138 {
139         modify_t        *m;
140         int                     temp;
141
142         if (undo_index == modify_index)
143                 return;
144
145         m = &modify[undo_index];
146
147         // modify it
148         temp = pic[m->offset];
149         pic[m->offset] = m->oldvalue;
150         rgb[m->offset] = palette[m->oldvalue*3] +
151                 (palette[m->oldvalue*3+1]<<8) + (palette[m->oldvalue*3+2]<<16);
152         m->oldvalue = temp;
153         UpdateTexture (m->offset);
154         InvalidateRect (skinwindow, NULL, false);
155         InvalidateRect (camerawindow, NULL, false);
156
157         if (!undo_index++)
158         {       // modified again
159                 char    text[1024];
160
161                 modified = true;
162                 sprintf (text, "%s *", skin_filename);
163                 SetWindowText (skinwindow, text);
164         }
165 }
166
167 //===================================================================
168
169 /*
170 =============
171 Skin_SaveFile
172
173 Load a skin texture and the base.tri from the same directory
174 =============
175 */
176 void Skin_SaveFile (char *name)
177 {
178         byte    *data;
179         int             i, j;
180         char    backup[1024];
181
182         // back up the current file if it exists
183         sprintf (backup, "%s.bak", name);
184         remove (backup);
185         rename (name, backup);
186
187         modified = false;
188         modified_past_autosave = false;
189         modify_index = undo_index = 0;
190         SetWindowText (skinwindow, skin_filename);
191
192         data = malloc(skin_width*skin_height);
193         for (i=0 ; i<skin_height ; i++)
194                 memcpy (data + i*skin_width, pic + i*width2, skin_width);
195         Save256Image (name, data, palette, skin_width, skin_height);
196
197         free(data);
198 }
199
200 /*
201 =============
202 Expand256Texture
203
204 =============
205 */
206 void Expand256Texture (void)
207 {
208         int             i, j;
209         int             p;
210
211         memset (rgb, 0, sizeof(rgb));
212         for (i=0 ; i<skin_height ; i++)
213         {
214                 for (j=0 ; j<skin_width ; j++)
215                 {
216                         p = pic[i*width2+j];
217                         rgb[i*width2+j] = (palette[p*3+0]<<0) + (palette[p*3+1]<<8) + (palette[p*3+2]<<16);
218                 }
219         }
220
221         BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN);
222         glTexImage2D (GL_TEXTURE_2D, 0, 3, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgb);
223 }
224
225 void SetSizes (int width, int height)
226 {
227         int             i;
228
229         if (width < 32)
230                 width = 16;
231         if (height < 32)
232                 height = 16;
233
234         skin_width = width;
235         skin_height = height;
236
237         if (skin_width > 1024 || skin_height > 512)
238                 Sys_Error ("Skin file is too large");
239
240         width2 = 1;
241         height2 = 1;
242         for (i=0 ; i<12 ; i++)
243         {
244                 if (width2 < skin_width)
245                         width2<<=1;
246                 if (height2 < skin_height)
247                         height2<<=1;
248         }
249
250         // compatability shit for auto sizing of old skins
251         if (skin_width != 320 || skin_height != 200)
252         {
253                 skinwidth = skin_width;
254                 skinheight = skin_height;
255         }
256         else
257         {
258                 skinwidth = 0;
259                 skinheight = 0;
260         }
261 }
262
263 /*
264 =============
265 Skin_LoadFile
266
267 Load a skin texture and the base.tri from the same directory
268 =============
269 */
270 void Skin_LoadFile (char *name)
271 {
272         int             i, j, p;
273         byte    *lbmpic;
274         byte    *lbmpal;
275         char    trifile[1024];
276         int             width, height;
277
278         modified = false;
279         modified_past_autosave = false;
280         modify_index = undo_index = 0;
281         strcpy (skin_filename, name);
282         SetWindowText (skinwindow, skin_filename);
283
284         //
285         // read the texture
286         //
287         Load256Image (skin_filename, &lbmpic, &lbmpal, &width, &height);
288         memcpy (palette, lbmpal, sizeof(palette));
289         free (lbmpal);
290
291         SetSizes (width, height);
292
293         memset (pic, 0, sizeof(pic));
294         for (i=0 ; i<skin_height ; i++)
295         {
296                 for (j=0 ; j<skin_width ; j++)
297                 {
298                         p = lbmpic[i*skin_width + j];
299                         pic[i*width2+j] = p;
300                 }
301         }
302         free (lbmpic);
303
304         Expand256Texture ();
305
306         InitIndexTexture ();
307
308         Pal_SetIndex (selected_index);
309
310         //
311         // read the polfile and
312         // generate the texture coordinates
313         //
314         strcpy (trifile, skin_filename);
315         StripExtension (trifile);
316         strcat (trifile, ".tri");
317         if (FileExists (trifile))
318         {
319                 LoadTriFile (trifile);
320                 CalcTmCoords ();
321         }
322         else
323         {
324                 ExtractFilePath (name, trifile);
325                 strcat (trifile, "base.tri");
326                 if (FileExists (trifile))
327                 {
328                         LoadTriFile (trifile);
329                         CalcTmCoords ();
330                 }
331         }
332
333         InvalidateRect (palettewindow, NULL, false);
334         InvalidateRect (skinwindow, NULL, false);
335         InvalidateRect (camerawindow, NULL, false);
336
337 }
338
339
340 /*
341 =============
342 Skin_Click
343 =============
344 */
345 int             skin_last_index;
346 void Skin_Click (int x, int y, qboolean shift)
347 {
348         int             index;
349
350         index = 0;
351         glReadBuffer (GL_BACK);
352         glReadPixels (x, y, 1,1, GL_RGB, GL_UNSIGNED_BYTE, &index);
353
354         index--;
355         if (index == -1)
356                 return;
357         if (index >= width2*height2)
358                 return;
359
360         if (index == skin_last_index)
361                 return;         // in same pixel
362         skin_last_index = index;
363
364         if (shift)
365         {
366                 Pal_SetIndex (pic[index]);
367                 return;
368         }
369
370         SetSkin (index, selected_index);
371         UpdateWindow (skinwindow);
372 }
373
374
375 void DrawModelST (void)
376 {
377         int             i, j;
378
379         glColor4f (1,1,1,1);
380
381         glBegin (GL_TRIANGLES);
382         for (i=0 ; i<numfaces ; i++)
383         {
384                 for (j=0 ; j<3 ; j++)
385                 {
386                         glVertex2f (tmcoords[i][j][0]*width2, (1-tmcoords[i][j][1])*height2);
387                 }
388         }
389         glEnd ();
390 }
391
392 void DrawSkin (void)
393 {
394         glBegin (GL_POLYGON);
395         glTexCoord2f (0,1);
396         glVertex2f (0,0);
397
398         glTexCoord2f (0,0);
399         glVertex2f (0,height2);
400
401         glTexCoord2f (1,0);
402         glVertex2f (width2,height2);
403
404         glTexCoord2f (1,1);
405         glVertex2f (width2,0);
406         glEnd ();
407
408 }
409
410 void Skin_Draw (void)
411 {
412         int             x, y;
413         float   aspect;
414         float   xs, ys;
415         int             c;
416
417         //
418         // draw it
419         //
420         if (skin_z < 20)
421                 skin_z = 20;
422
423         glViewport (0,0,skinw_width, skinw_height);
424         glMatrixMode (GL_PROJECTION);
425         glLoadIdentity ();
426         gluPerspective (90,  (float)skinw_width/skinw_height,  2,  16384);
427         glMatrixMode (GL_MODELVIEW);
428         glLoadIdentity ();
429         gluLookAt (skin_x, skin_y, skin_z,   skin_x, skin_y, skin_z-1,  0, 1, 0);
430
431         glClearColor (0.3,0.3,0.3,1);
432         glClear (GL_COLOR_BUFFER_BIT);
433         glDisable (GL_DEPTH_TEST);
434         glDisable (GL_CULL_FACE);
435         glEnable (GL_TEXTURE_2D);
436
437         glColor4f (1,1,1,1);
438
439         DrawSkin ();
440
441         if (skin_lines)
442         {
443                 glDisable (GL_TEXTURE_2D);
444                 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
445
446                 DrawModelST ();
447
448                 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
449                 glEnable (GL_TEXTURE_2D);
450         }
451
452         SwapBuffers(skindc);
453
454
455         // now fill the back buffer with the index texture
456         glClearColor (0,0,0,0);
457         glClear (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
458         BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX);
459         DrawSkin ();
460
461         BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN);
462 }
463
464 /*
465 ============
466 Skin_WndProc
467 ============
468 */
469 LONG WINAPI Skin_WndProc (
470     HWND    hWnd,
471     UINT    uMsg,
472     WPARAM  wParam,
473     LPARAM  lParam)
474 {
475     LONG    lRet = 1;
476         int             fwKeys, xPos, yPos;
477     RECT        rect;
478
479     GetClientRect(hWnd, &rect);
480         skinw_width = rect.right-rect.left;
481         skinw_height = rect.bottom-rect.top;
482
483     switch (uMsg)
484     {
485         case WM_CREATE:
486         skindc = GetDC(hWnd);
487             bSetupPixelFormat(skindc);
488                 break;
489         case WM_PAINT:
490         {
491                     PAINTSTRUCT ps;
492
493                     BeginPaint(hWnd, &ps);
494             if (!wglMakeCurrent( skindc, baseRC ))
495                                 Sys_Error ("wglMakeCurrent failed");
496                         Skin_Draw ();
497                     EndPaint(hWnd, &ps);
498         }
499                 break;
500
501         case WM_LBUTTONDOWN:
502                 skin_last_index = -1;
503 draw:
504                 if (GetTopWindow(mainwindow) != hWnd)
505                         BringWindowToTop(hWnd);
506
507                 SetFocus (skinwindow);
508                 SetCapture (skinwindow);
509                 fwKeys = wParam;        // key flags
510                 xPos = (short)LOWORD(lParam);  // horizontal position of cursor
511                 yPos = (short)HIWORD(lParam);  // vertical position of cursor
512                 yPos = (int)rect.bottom - 1 - yPos;
513         if (!wglMakeCurrent( skindc, baseRC ))
514                         Sys_Error ("wglMakeCurrent failed");
515                 Skin_Click (xPos, yPos, !!(wParam&(MK_SHIFT|MK_CONTROL)) );
516                 break;
517
518         case WM_MBUTTONUP:
519         case WM_RBUTTONUP:
520         case WM_LBUTTONUP:
521                 fwKeys = wParam;        // key flags
522                 if (! (fwKeys & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
523                         ReleaseCapture ();
524                 break;
525
526         case WM_MOUSEMOVE:
527                 {
528                         static int      oldx, oldy;
529                         int             dx, dy;
530                         POINT   pt;
531
532                         if (wParam & MK_LBUTTON)
533                                 goto draw;
534
535                         GetCursorPos (&pt);
536                         xPos = pt.x;
537                         yPos = pt.y;
538                         if (!(wParam & (MK_RBUTTON|MK_MBUTTON)))
539                         {
540                                 oldx = xPos;
541                                 oldy = yPos;
542                                 break;
543                         }
544                         dx = xPos-oldx;
545                         dy = oldy-yPos;
546                         if (!dx && !dy)
547                                 break;
548                         SetCursorPos (oldx, oldy);
549
550                         if (wParam == (MK_RBUTTON|MK_CONTROL) )
551                         {
552                                 if (abs(dx) > abs(dy))
553                                         skin_z += 0.25*dx;
554                                 else
555                                         skin_z += 0.25*dy;
556                                 InvalidateRect (skinwindow, NULL, false);
557                         }
558                         if (wParam == MK_RBUTTON)
559                         {
560                                 skin_x -= 0.25*dx;
561                                 skin_y -= 0.25*dy;
562                                 InvalidateRect (skinwindow, NULL, false);
563                         }
564                 }
565                 break;
566
567     case WM_SIZE:
568                 InvalidateRect(camerawindow, NULL, false);
569         break;
570         case WM_NCCALCSIZE:// don't let windows copy pixels
571                 lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
572                 return WVR_REDRAW;
573         case WM_CLOSE:
574         DestroyWindow (hWnd);
575             break;
576
577     default:
578         /* pass all unhandled messages to DefWindowProc */
579         lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
580     break;
581     }
582
583     /* return 1 if handled message, 0 if not */
584     return lRet;
585 }
586
587
588 /*
589 ==============
590 WSkin_Create
591 ==============
592 */
593 void WSkin_Create (HINSTANCE hInstance)
594 {
595     WNDCLASS   wc;
596
597     /* Register the camera class */
598         memset (&wc, 0, sizeof(wc));
599
600     wc.style         = 0;
601     wc.lpfnWndProc   = (WNDPROC)Skin_WndProc;
602     wc.cbClsExtra    = 0;
603     wc.cbWndExtra    = 0;
604     wc.hInstance     = hInstance;
605     wc.hIcon         = 0;
606     wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
607     wc.hbrBackground = NULL;
608     wc.lpszMenuName  = 0;
609     wc.lpszClassName = SKIN_WINDOW_CLASS;
610
611     if (!RegisterClass (&wc) )
612         Sys_Error ("RegisterClass failed");
613
614         skinwindow = CreateWindow (SKIN_WINDOW_CLASS ,
615                 "Skin View",
616                 QE3_STYLE,
617                 (int)(screen_width*0.5),
618                 (int)(screen_height*0.2),
619                 (int)(screen_width*0.5),
620                 (int)(screen_height*0.8),       // size
621                 mainwindow,     // parent window
622                 0,              // no menu
623                 hInstance,
624                 0);
625         if (!skinwindow)
626                 Error ("Couldn't create skinwindow");
627
628 //      RestoreWindowState(palettewindow, "palettewindow");
629     ShowWindow (skinwindow, SW_SHOWDEFAULT);
630 }
631
632
633 /*
634 ===================================================================
635
636   SKIN RESAMPLING
637
638 ===================================================================
639 */
640
641 HWND    resamplewindow;
642 HDC             resampledc;
643
644 #define RESAMPLE_WINDOW_CLASS   "TPResample"
645
646 /*
647 ============
648 Resample_WndProc
649 ============
650 */
651 LONG WINAPI Resample_WndProc (
652     HWND    hWnd,
653     UINT    uMsg,
654     WPARAM  wParam,
655     LPARAM  lParam)
656 {
657     switch (uMsg)
658     {
659         case WM_CREATE:
660                 resampledc = GetDC(hWnd);
661             bSetupPixelFormat(resampledc);
662                 break;
663         }
664
665         return  DefWindowProc (hWnd, uMsg, wParam, lParam);
666 }
667
668 /*
669 ==============
670 ResampleWindow
671 ==============
672 */
673 void ResampleWindow (HINSTANCE hInstance)
674 {
675     WNDCLASS   wc;
676         static qboolean registered;
677
678         if (!registered)
679         {
680                 registered = true;
681                 /* Register the camera class */
682                 memset (&wc, 0, sizeof(wc));
683
684                 wc.style         = 0;
685                 wc.lpfnWndProc   = (WNDPROC)Resample_WndProc;
686                 wc.cbClsExtra    = 0;
687                 wc.cbWndExtra    = 0;
688                 wc.hInstance     = hInstance;
689                 wc.hIcon         = 0;
690                 wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
691                 wc.hbrBackground = NULL;
692                 wc.lpszMenuName  = 0;
693                 wc.lpszClassName = RESAMPLE_WINDOW_CLASS;
694
695                 if (!RegisterClass (&wc) )
696                         Sys_Error ("RegisterClass failed");
697         }
698
699         resamplewindow = CreateWindow (RESAMPLE_WINDOW_CLASS ,
700                 "ResampleWindow",
701                 WS_OVERLAPPED,
702                 0, 0, width2+32, height2+32,    // size
703                 NULL,   // parent window
704                 0,              // no menu
705                 hInstance,
706                 0);
707         if (!resamplewindow)
708                 Error ("Couldn't create skinwindow");
709
710     ShowWindow (resamplewindow, SW_SHOWDEFAULT);
711 }
712
713
714 void OutlineTexture (byte *pic)
715 {
716         int             i, j;
717         int             x, y;
718         int             empty;
719         byte    oldpic[1024*512];
720
721         memcpy (oldpic, pic, width2*height2);
722
723         empty = oldpic[0];
724
725         for (i=0 ; i<height2 ; i++)
726         {
727                 for (j=0 ; j<width2 ; j++)
728                 {
729                         if (oldpic[i*width2+j] != empty)
730                                 continue;
731                         for (x=-1 ; x<=1 ; x++)
732                         {
733                                 for (y=-1 ; y<=1 ; y++)
734                                 {
735                                         if (i+y < 0 || i+y >= height2)
736                                                 continue;
737                                         if (j+x < 0 || j+x >= width2)
738                                                 continue;
739                                         if (oldpic[(i+y)*width2 + j+x] != empty)
740                                         {
741                                                 pic[i*width2+j] = oldpic[(i+y)*width2 + j+x];
742                                                 goto done;
743                                         }
744                                 }
745                         }
746 done: ;
747                 }
748         }
749 }
750
751 void ResampleSkin (void)
752 {
753         int             i, j;
754         static  float   oldtmcoords[10000][3][2];
755         static  int             newindex[1024*512];
756         static  byte    oldpic[1024*512];
757
758         // open a window of the texture size
759         ResampleWindow (main_instance);
760
761         // get new S/T from current frame
762         memcpy (oldtmcoords, tmcoords, numfaces*3*2*4);
763         CalcTmCoords ();
764
765         // draw all the triangles with the index texture
766     if (!wglMakeCurrent( resampledc, baseRC ))
767                 Sys_Error ("wglMakeCurrent failed");
768
769         glViewport (0,0,width2, height2);
770         glClearColor (0,0,0,0);
771         glClear (GL_COLOR_BUFFER_BIT);
772
773         glMatrixMode (GL_PROJECTION);
774         glLoadIdentity ();
775         glOrtho (0, width2, 0, height2, -100, 100);
776         glMatrixMode (GL_MODELVIEW);
777         glLoadIdentity ();
778
779         glColor4f (1,1,1,1);
780         glDisable (GL_DEPTH_TEST);
781         glDisable (GL_CULL_FACE);
782         BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX);
783 #if 0
784         glDisable(GL_TEXTURE_2D);
785         glBegin (GL_LINE_LOOP);
786         glVertex3f (1,1,10);
787         glVertex3f (skin_width-1,0,10);
788         glVertex3f (skin_width-1,skin_height-1,10);
789         glVertex3f (1,skin_height-1,10);
790         glEnd ();
791         glEnable(GL_TEXTURE_2D);
792 #endif
793         glBegin (GL_TRIANGLES);
794         for (i=0 ; i<numfaces ; i++)
795         {
796                 for (j=0 ; j<3 ; j++)
797                 {
798                         glTexCoord2f (oldtmcoords[i][j][0], oldtmcoords[i][j][1]);
799                         glVertex3f (tmcoords[i][j][0]*width2, tmcoords[i][j][1]*height2, 10);
800                 }
801         }
802         glEnd ();
803         SwapBuffers (resampledc);
804
805         // build the new color texture
806         memcpy (oldpic, pic, width2*height2);
807         glReadBuffer (GL_FRONT);
808         glReadPixels (0,0,width2,height2,GL_RGBA,GL_UNSIGNED_BYTE, &newindex);
809         for (i=0 ; i<height2 ; i++)
810                 for (j=0 ; j<width2 ; j++)
811                         pic[i*width2+j] = oldpic[newindex[i*width2+j]&0xffffff];
812
813         // outline it
814         OutlineTexture (pic);
815         Expand256Texture ();
816
817         InvalidateRect (skinwindow, NULL, false);
818         InvalidateRect (camerawindow, NULL, false);
819
820         // change name
821         strcpy (skin_filename, tri_filename);
822         StripExtension (skin_filename);
823         strcat (skin_filename, ".lbm");
824
825         SetSkinModified ();
826
827         wglMakeCurrent (NULL, NULL);
828         DestroyWindow (resamplewindow);
829 }
830
831 /*
832 ===================================================================
833
834   NEW SKIN
835
836 ===================================================================
837 */
838
839 BOOL CALLBACK NewSkinDlgProc (
840     HWND hwndDlg,       // handle to dialog box
841     UINT uMsg,  // message
842     WPARAM wParam,      // first message parameter
843     LPARAM lParam       // second message parameter
844    )
845 {
846         char sz[256];
847         int             width, height;
848
849         switch (uMsg)
850     {
851         case WM_INITDIALOG:
852                 SetWindowText(GetDlgItem(hwndDlg, IDC_WIDTH), "320");
853                 SetWindowText(GetDlgItem(hwndDlg, IDC_HEIGHT), "200");
854                 return TRUE;
855         case WM_COMMAND:
856                 switch (LOWORD(wParam))
857                 {
858
859                 case IDOK:
860                         GetWindowText(GetDlgItem(hwndDlg, IDC_WIDTH), sz, 255);
861                         width = atoi(sz);
862                         GetWindowText(GetDlgItem(hwndDlg, IDC_HEIGHT), sz, 255);
863                         height = atoi(sz);
864                         SetSizes (width, height);
865                         EndDialog(hwndDlg, 1);
866                         return TRUE;
867
868                 case IDCANCEL:
869                         EndDialog(hwndDlg, 0);
870                         return TRUE;
871                 }
872         }
873         return FALSE;
874 }
875
876
877 void NewSkin (void)
878 {
879         int             i, j;
880         byte    *buf;
881
882         if (!DialogBox(main_instance, (char *)IDD_NEWSKIN, mainwindow, NewSkinDlgProc))
883                 return;
884
885         // open a window of the texture size
886         ResampleWindow (main_instance);
887
888         // get new S/T from current frame
889         CalcTmCoords ();
890
891         // draw all the triangles
892     if (!wglMakeCurrent( resampledc, baseRC ))
893                 Sys_Error ("wglMakeCurrent failed");
894
895         glViewport (0,0,width2, height2);
896         glClearColor (0,0,0,0);
897         glClear (GL_COLOR_BUFFER_BIT);
898
899         glMatrixMode (GL_PROJECTION);
900         glLoadIdentity ();
901         glOrtho (0, width2, 0, height2, -100, 100);
902         glMatrixMode (GL_MODELVIEW);
903         glLoadIdentity ();
904
905         glColor4f (1,1,1,1);
906         glDisable (GL_DEPTH_TEST);
907         glDisable (GL_CULL_FACE);
908         glDisable (GL_TEXTURE_2D);
909
910         for (i=0 ; i<numfaces ; i++)
911         {
912                 glColor3f ((i&255)/255.0, (i&255)/255.0, (i&255)/255.0);
913                 glBegin (GL_TRIANGLES);
914                 for (j=0 ; j<3 ; j++)
915                         glVertex3f (tmcoords[i][j][0]*width2, tmcoords[i][j][1]*height2, 10);
916                 glEnd ();
917         }
918
919         SwapBuffers (resampledc);
920
921         // build the new color texture
922         glReadBuffer (GL_FRONT);
923         buf = malloc(width2*height2*4);
924         glReadPixels (0,0,width2,height2,GL_RGBA,GL_UNSIGNED_BYTE, buf);
925         for (i=0 ; i<width2*height2 ; i++)
926                 pic[i] = buf[i*4];
927         free (buf);
928
929         // outline it
930         OutlineTexture (pic);
931         Expand256Texture ();
932         InitIndexTexture ();
933
934         InvalidateRect (skinwindow, NULL, false);
935         InvalidateRect (camerawindow, NULL, false);
936
937         // change name
938         strcpy (skin_filename, tri_filename);
939         StripExtension (skin_filename);
940         strcat (skin_filename, ".lbm");
941
942         SetSkinModified ();
943
944         wglMakeCurrent (NULL, NULL);
945         DestroyWindow (resamplewindow);
946 }