/* =========================================================================== 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 ; iwidth); 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 ; icolor[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 ; inext) { 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; }