textures.c 24 KB

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