2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
5 This file is part of Quake 2 Tools source code.
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.
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.
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 ===========================================================================
25 #define SKIN_WINDOW_CLASS "TPSkin"
28 int skinw_width, skinw_height; // size of the window
30 float skin_x = 128, skin_y = 128, skin_z = 100;
32 qboolean skin_lines = false;
34 char tri_filename[1024];
35 char skin_filename[1024];
36 int skin_width, skin_height; // size of the .lbm image
38 unsigned index_texture[1024*512];
41 void UpdateTexture (int offset)
48 BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN);
49 // glTexImage2D (GL_TEXTURE_2D, 0, 3, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgb);
51 glTexSubImage2D (GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, rgb+offset);
55 ===================================================================
59 ===================================================================
62 #define MAX_MODIFY 8192
72 modify_t modify[MAX_MODIFY];
74 void SetSkinModified (void)
78 if (modified && modified_past_autosave)
82 modified_past_autosave = true;
84 sprintf (text, "%s *", skin_filename);
85 SetWindowText (skinwindow, text);
88 void SetSkin (int index, int pixel)
96 m = &modify[undo_index];
98 m->oldvalue = pic[index];
100 modify_index = (++undo_index)&(MAX_MODIFY-1);
103 rgb[index] = selected_rgb;
104 pic[index] = selected_index;
105 UpdateTexture (index);
106 InvalidateRect (skinwindow, NULL, false);
107 InvalidateRect (camerawindow, NULL, false);
119 { // back to unmodified state
121 SetWindowText (skinwindow, skin_filename);
123 m = &modify[undo_index];
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);
131 UpdateTexture (m->offset);
132 InvalidateRect (skinwindow, NULL, false);
133 InvalidateRect (camerawindow, NULL, false);
142 if (undo_index == modify_index)
145 m = &modify[undo_index];
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);
153 UpdateTexture (m->offset);
154 InvalidateRect (skinwindow, NULL, false);
155 InvalidateRect (camerawindow, NULL, false);
162 sprintf (text, "%s *", skin_filename);
163 SetWindowText (skinwindow, text);
167 //===================================================================
173 Load a skin texture and the base.tri from the same directory
176 void Skin_SaveFile (char *name)
182 // back up the current file if it exists
183 sprintf (backup, "%s.bak", name);
185 rename (name, backup);
188 modified_past_autosave = false;
189 modify_index = undo_index = 0;
190 SetWindowText (skinwindow, skin_filename);
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);
206 void Expand256Texture (void)
211 memset (rgb, 0, sizeof(rgb));
212 for (i=0 ; i<skin_height ; i++)
214 for (j=0 ; j<skin_width ; j++)
217 rgb[i*width2+j] = (palette[p*3+0]<<0) + (palette[p*3+1]<<8) + (palette[p*3+2]<<16);
221 BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN);
222 glTexImage2D (GL_TEXTURE_2D, 0, 3, width2, height2, 0, GL_RGBA, GL_UNSIGNED_BYTE, rgb);
225 void SetSizes (int width, int height)
235 skin_height = height;
237 if (skin_width > 1024 || skin_height > 512)
238 Sys_Error ("Skin file is too large");
242 for (i=0 ; i<12 ; i++)
244 if (width2 < skin_width)
246 if (height2 < skin_height)
250 // compatability shit for auto sizing of old skins
251 if (skin_width != 320 || skin_height != 200)
253 skinwidth = skin_width;
254 skinheight = skin_height;
267 Load a skin texture and the base.tri from the same directory
270 void Skin_LoadFile (char *name)
279 modified_past_autosave = false;
280 modify_index = undo_index = 0;
281 strcpy (skin_filename, name);
282 SetWindowText (skinwindow, skin_filename);
287 Load256Image (skin_filename, &lbmpic, &lbmpal, &width, &height);
288 memcpy (palette, lbmpal, sizeof(palette));
291 SetSizes (width, height);
293 memset (pic, 0, sizeof(pic));
294 for (i=0 ; i<skin_height ; i++)
296 for (j=0 ; j<skin_width ; j++)
298 p = lbmpic[i*skin_width + j];
308 Pal_SetIndex (selected_index);
311 // read the polfile and
312 // generate the texture coordinates
314 strcpy (trifile, skin_filename);
315 StripExtension (trifile);
316 strcat (trifile, ".tri");
317 if (FileExists (trifile))
319 LoadTriFile (trifile);
324 ExtractFilePath (name, trifile);
325 strcat (trifile, "base.tri");
326 if (FileExists (trifile))
328 LoadTriFile (trifile);
333 InvalidateRect (palettewindow, NULL, false);
334 InvalidateRect (skinwindow, NULL, false);
335 InvalidateRect (camerawindow, NULL, false);
346 void Skin_Click (int x, int y, qboolean shift)
351 glReadBuffer (GL_BACK);
352 glReadPixels (x, y, 1,1, GL_RGB, GL_UNSIGNED_BYTE, &index);
357 if (index >= width2*height2)
360 if (index == skin_last_index)
361 return; // in same pixel
362 skin_last_index = index;
366 Pal_SetIndex (pic[index]);
370 SetSkin (index, selected_index);
371 UpdateWindow (skinwindow);
375 void DrawModelST (void)
381 glBegin (GL_TRIANGLES);
382 for (i=0 ; i<numfaces ; i++)
384 for (j=0 ; j<3 ; j++)
386 glVertex2f (tmcoords[i][j][0]*width2, (1-tmcoords[i][j][1])*height2);
394 glBegin (GL_POLYGON);
399 glVertex2f (0,height2);
402 glVertex2f (width2,height2);
405 glVertex2f (width2,0);
410 void Skin_Draw (void)
423 glViewport (0,0,skinw_width, skinw_height);
424 glMatrixMode (GL_PROJECTION);
426 gluPerspective (90, (float)skinw_width/skinw_height, 2, 16384);
427 glMatrixMode (GL_MODELVIEW);
429 gluLookAt (skin_x, skin_y, skin_z, skin_x, skin_y, skin_z-1, 0, 1, 0);
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);
443 glDisable (GL_TEXTURE_2D);
444 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
448 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
449 glEnable (GL_TEXTURE_2D);
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);
461 BindTextureEXT (GL_TEXTURE_2D, TEXTURE_SKIN);
469 LONG WINAPI Skin_WndProc (
476 int fwKeys, xPos, yPos;
479 GetClientRect(hWnd, &rect);
480 skinw_width = rect.right-rect.left;
481 skinw_height = rect.bottom-rect.top;
486 skindc = GetDC(hWnd);
487 bSetupPixelFormat(skindc);
493 BeginPaint(hWnd, &ps);
494 if (!wglMakeCurrent( skindc, baseRC ))
495 Sys_Error ("wglMakeCurrent failed");
502 skin_last_index = -1;
504 if (GetTopWindow(mainwindow) != hWnd)
505 BringWindowToTop(hWnd);
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)) );
521 fwKeys = wParam; // key flags
522 if (! (fwKeys & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
528 static int oldx, oldy;
532 if (wParam & MK_LBUTTON)
538 if (!(wParam & (MK_RBUTTON|MK_MBUTTON)))
548 SetCursorPos (oldx, oldy);
550 if (wParam == (MK_RBUTTON|MK_CONTROL) )
552 if (abs(dx) > abs(dy))
556 InvalidateRect (skinwindow, NULL, false);
558 if (wParam == MK_RBUTTON)
562 InvalidateRect (skinwindow, NULL, false);
568 InvalidateRect(camerawindow, NULL, false);
570 case WM_NCCALCSIZE:// don't let windows copy pixels
571 lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
574 DestroyWindow (hWnd);
578 /* pass all unhandled messages to DefWindowProc */
579 lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
583 /* return 1 if handled message, 0 if not */
593 void WSkin_Create (HINSTANCE hInstance)
597 /* Register the camera class */
598 memset (&wc, 0, sizeof(wc));
601 wc.lpfnWndProc = (WNDPROC)Skin_WndProc;
604 wc.hInstance = hInstance;
606 wc.hCursor = LoadCursor (NULL,IDC_ARROW);
607 wc.hbrBackground = NULL;
609 wc.lpszClassName = SKIN_WINDOW_CLASS;
611 if (!RegisterClass (&wc) )
612 Sys_Error ("RegisterClass failed");
614 skinwindow = CreateWindow (SKIN_WINDOW_CLASS ,
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
626 Error ("Couldn't create skinwindow");
628 // RestoreWindowState(palettewindow, "palettewindow");
629 ShowWindow (skinwindow, SW_SHOWDEFAULT);
634 ===================================================================
638 ===================================================================
644 #define RESAMPLE_WINDOW_CLASS "TPResample"
651 LONG WINAPI Resample_WndProc (
660 resampledc = GetDC(hWnd);
661 bSetupPixelFormat(resampledc);
665 return DefWindowProc (hWnd, uMsg, wParam, lParam);
673 void ResampleWindow (HINSTANCE hInstance)
676 static qboolean registered;
681 /* Register the camera class */
682 memset (&wc, 0, sizeof(wc));
685 wc.lpfnWndProc = (WNDPROC)Resample_WndProc;
688 wc.hInstance = hInstance;
690 wc.hCursor = LoadCursor (NULL,IDC_ARROW);
691 wc.hbrBackground = NULL;
693 wc.lpszClassName = RESAMPLE_WINDOW_CLASS;
695 if (!RegisterClass (&wc) )
696 Sys_Error ("RegisterClass failed");
699 resamplewindow = CreateWindow (RESAMPLE_WINDOW_CLASS ,
702 0, 0, width2+32, height2+32, // size
703 NULL, // parent window
708 Error ("Couldn't create skinwindow");
710 ShowWindow (resamplewindow, SW_SHOWDEFAULT);
714 void OutlineTexture (byte *pic)
719 byte oldpic[1024*512];
721 memcpy (oldpic, pic, width2*height2);
725 for (i=0 ; i<height2 ; i++)
727 for (j=0 ; j<width2 ; j++)
729 if (oldpic[i*width2+j] != empty)
731 for (x=-1 ; x<=1 ; x++)
733 for (y=-1 ; y<=1 ; y++)
735 if (i+y < 0 || i+y >= height2)
737 if (j+x < 0 || j+x >= width2)
739 if (oldpic[(i+y)*width2 + j+x] != empty)
741 pic[i*width2+j] = oldpic[(i+y)*width2 + j+x];
751 void ResampleSkin (void)
754 static float oldtmcoords[10000][3][2];
755 static int newindex[1024*512];
756 static byte oldpic[1024*512];
758 // open a window of the texture size
759 ResampleWindow (main_instance);
761 // get new S/T from current frame
762 memcpy (oldtmcoords, tmcoords, numfaces*3*2*4);
765 // draw all the triangles with the index texture
766 if (!wglMakeCurrent( resampledc, baseRC ))
767 Sys_Error ("wglMakeCurrent failed");
769 glViewport (0,0,width2, height2);
770 glClearColor (0,0,0,0);
771 glClear (GL_COLOR_BUFFER_BIT);
773 glMatrixMode (GL_PROJECTION);
775 glOrtho (0, width2, 0, height2, -100, 100);
776 glMatrixMode (GL_MODELVIEW);
780 glDisable (GL_DEPTH_TEST);
781 glDisable (GL_CULL_FACE);
782 BindTextureEXT (GL_TEXTURE_2D, TEXTURE_INDEX);
784 glDisable(GL_TEXTURE_2D);
785 glBegin (GL_LINE_LOOP);
787 glVertex3f (skin_width-1,0,10);
788 glVertex3f (skin_width-1,skin_height-1,10);
789 glVertex3f (1,skin_height-1,10);
791 glEnable(GL_TEXTURE_2D);
793 glBegin (GL_TRIANGLES);
794 for (i=0 ; i<numfaces ; i++)
796 for (j=0 ; j<3 ; j++)
798 glTexCoord2f (oldtmcoords[i][j][0], oldtmcoords[i][j][1]);
799 glVertex3f (tmcoords[i][j][0]*width2, tmcoords[i][j][1]*height2, 10);
803 SwapBuffers (resampledc);
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];
814 OutlineTexture (pic);
817 InvalidateRect (skinwindow, NULL, false);
818 InvalidateRect (camerawindow, NULL, false);
821 strcpy (skin_filename, tri_filename);
822 StripExtension (skin_filename);
823 strcat (skin_filename, ".lbm");
827 wglMakeCurrent (NULL, NULL);
828 DestroyWindow (resamplewindow);
832 ===================================================================
836 ===================================================================
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
852 SetWindowText(GetDlgItem(hwndDlg, IDC_WIDTH), "320");
853 SetWindowText(GetDlgItem(hwndDlg, IDC_HEIGHT), "200");
856 switch (LOWORD(wParam))
860 GetWindowText(GetDlgItem(hwndDlg, IDC_WIDTH), sz, 255);
862 GetWindowText(GetDlgItem(hwndDlg, IDC_HEIGHT), sz, 255);
864 SetSizes (width, height);
865 EndDialog(hwndDlg, 1);
869 EndDialog(hwndDlg, 0);
882 if (!DialogBox(main_instance, (char *)IDD_NEWSKIN, mainwindow, NewSkinDlgProc))
885 // open a window of the texture size
886 ResampleWindow (main_instance);
888 // get new S/T from current frame
891 // draw all the triangles
892 if (!wglMakeCurrent( resampledc, baseRC ))
893 Sys_Error ("wglMakeCurrent failed");
895 glViewport (0,0,width2, height2);
896 glClearColor (0,0,0,0);
897 glClear (GL_COLOR_BUFFER_BIT);
899 glMatrixMode (GL_PROJECTION);
901 glOrtho (0, width2, 0, height2, -100, 100);
902 glMatrixMode (GL_MODELVIEW);
906 glDisable (GL_DEPTH_TEST);
907 glDisable (GL_CULL_FACE);
908 glDisable (GL_TEXTURE_2D);
910 for (i=0 ; i<numfaces ; i++)
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);
919 SwapBuffers (resampledc);
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++)
930 OutlineTexture (pic);
934 InvalidateRect (skinwindow, NULL, false);
935 InvalidateRect (camerawindow, NULL, false);
938 strcpy (skin_filename, tri_filename);
939 StripExtension (skin_filename);
940 strcat (skin_filename, ".lbm");
944 wglMakeCurrent (NULL, NULL);
945 DestroyWindow (resamplewindow);