TexWnd.cpp 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena 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 III Arena 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 Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // TexWnd.cpp : implementation file
  19. //
  20. #include "stdafx.h"
  21. #include <assert.h>
  22. #include "Radiant.h"
  23. #include "TexWnd.h"
  24. #include "qe3.h"
  25. #include "io.h"
  26. #include "PrefsDlg.h"
  27. #include "shaderinfo.h"
  28. #include "pakstuff.h"
  29. #include "str.h"
  30. #include "PrefsDlg.h"
  31. Str m_gStr;
  32. #ifdef _DEBUG
  33. #define new DEBUG_NEW
  34. #undef THIS_FILE
  35. static char THIS_FILE[] = __FILE__;
  36. #endif
  37. qtexture_t *Texture_ForNamePath(char* name, char* pFullPath);
  38. #define TYP_MIPTEX 68
  39. static unsigned tex_palette[256];
  40. qtexture_t *notexture = NULL;
  41. qtexture_t *g_pluginTexture = NULL;
  42. static qboolean nomips = false;
  43. #define FONT_HEIGHT 10
  44. HGLRC s_hglrcTexture = NULL;
  45. HDC s_hdcTexture = NULL;
  46. //int texture_mode = GL_NEAREST;
  47. //int texture_mode = GL_NEAREST_MIPMAP_NEAREST;
  48. //int texture_mode = GL_NEAREST_MIPMAP_LINEAR;
  49. //int texture_mode = GL_LINEAR;
  50. //int texture_mode = GL_LINEAR_MIPMAP_NEAREST;
  51. int texture_mode = GL_LINEAR_MIPMAP_LINEAR;
  52. // this is the global counter for GL bind numbers
  53. int texture_extension_number = 1;
  54. int g_nCurrentTextureMenuName;
  55. int g_nTextureOffset = 0;
  56. // current active texture directory. if empty, show textures in use
  57. char texture_directory[128]; // use if texture_showinuse is false
  58. qboolean texture_showinuse;
  59. bool g_bFilterEnabled = false;
  60. CString g_strFilter;
  61. // texture layout functions
  62. qtexture_t *current_texture = NULL;
  63. int current_x, current_y, current_row;
  64. int texture_nummenus;
  65. #define MAX_TEXTUREDIRS 128
  66. char texture_menunames[MAX_TEXTUREDIRS][128];
  67. qboolean g_dontuse = true; // set to true to load the texture but not flag as used
  68. // void SelectTexture (int mx, int my, bool bShift = false);
  69. void SelectTexture (int mx, int my, bool bShift, bool bFitScale=false);
  70. void Texture_MouseDown (int x, int y, int buttons);
  71. void Texture_MouseUp (int x, int y, int buttons);
  72. void Texture_MouseMoved (int x, int y, int buttons);
  73. CPtrArray g_lstShaders;
  74. CPtrArray g_lstSkinCache;
  75. struct SkinInfo
  76. {
  77. CString m_strName;
  78. int m_nTextureBind;
  79. SkinInfo(const char *pName, int n)
  80. {
  81. m_strName = pName;
  82. m_nTextureBind = n;
  83. };
  84. SkinInfo(){};
  85. };
  86. // checks wether a qtexture_t exists for a given name
  87. //++timo FIXME: is this really any use? redundant.
  88. bool ShaderQTextureExists(const char *pName)
  89. {
  90. for (qtexture_t *q=g_qeglobals.d_qtextures ; q ; q=q->next)
  91. {
  92. if (!strcmp(q->name, pName))
  93. {
  94. return true;
  95. }
  96. }
  97. return false;
  98. }
  99. CShaderInfo* hasShader(const char *pName)
  100. {
  101. int nSize = g_lstShaders.GetSize();
  102. for (int i = 0; i < nSize; i++)
  103. {
  104. CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
  105. if (pInfo != NULL)
  106. {
  107. if (pInfo->m_strName.CompareNoCase(pName) == 0)
  108. {
  109. return pInfo;
  110. }
  111. }
  112. }
  113. return NULL;
  114. }
  115. // gets active texture extension
  116. //
  117. // FIXME: fix this to be generic from project file
  118. //
  119. int GetTextureExtensionCount()
  120. {
  121. return 2;
  122. }
  123. const char* GetTextureExtension(int nIndex)
  124. {
  125. if ( nIndex == 0)
  126. {
  127. _QERTextureInfo *pInfo = g_pParentWnd->GetPlugInMgr().GetTextureInfo();
  128. const char *pTex = (pInfo != NULL) ? pInfo->m_TextureExtension : NULL;
  129. return (pTex == NULL) ? (g_PrefsDlg.m_bHiColorTextures == FALSE) ? "wal" : "tga" : pTex;
  130. }
  131. // return jpg for 2nd extension
  132. return "jpg";
  133. }
  134. void SortTextures(void)
  135. {
  136. qtexture_t *q, *qtemp, *qhead, *qcur, *qprev;
  137. // standard insertion sort
  138. // Take the first texture from the list and
  139. // add it to our new list
  140. if ( g_qeglobals.d_qtextures == NULL)
  141. return;
  142. qhead = g_qeglobals.d_qtextures;
  143. q = g_qeglobals.d_qtextures->next;
  144. qhead->next = NULL;
  145. // while there are still things on the old
  146. // list, keep adding them to the new list
  147. while (q)
  148. {
  149. qtemp = q;
  150. q = q->next;
  151. qprev = NULL;
  152. qcur = qhead;
  153. while (qcur)
  154. {
  155. // Insert it here?
  156. if (strcmp(qtemp->name, qcur->name) < 0)
  157. {
  158. qtemp->next = qcur;
  159. if (qprev)
  160. qprev->next = qtemp;
  161. else
  162. qhead = qtemp;
  163. break;
  164. }
  165. // Move on
  166. qprev = qcur;
  167. qcur = qcur->next;
  168. // is this one at the end?
  169. if (qcur == NULL)
  170. {
  171. qprev->next = qtemp;
  172. qtemp->next = NULL;
  173. }
  174. }
  175. }
  176. g_qeglobals.d_qtextures = qhead;
  177. }
  178. /*
  179. ==============
  180. Texture_InitPalette
  181. ==============
  182. */
  183. void Texture_InitPalette (byte *pal)
  184. {
  185. int r,g,b,v;
  186. int i;
  187. int inf;
  188. byte gammatable[256];
  189. float gamma;
  190. gamma = g_qeglobals.d_savedinfo.fGamma;
  191. if (gamma == 1.0)
  192. {
  193. for (i=0 ; i<256 ; i++)
  194. gammatable[i] = i;
  195. }
  196. else
  197. {
  198. for (i=0 ; i<256 ; i++)
  199. {
  200. inf = 255 * pow ( (float)( (i+0.5)/255.5 ), gamma ) + 0.5;
  201. if (inf < 0)
  202. inf = 0;
  203. if (inf > 255)
  204. inf = 255;
  205. gammatable[i] = inf;
  206. }
  207. }
  208. for (i=0 ; i<256 ; i++)
  209. {
  210. r = gammatable[pal[0]];
  211. g = gammatable[pal[1]];
  212. b = gammatable[pal[2]];
  213. pal += 3;
  214. v = (r<<24) + (g<<16) + (b<<8) + 255;
  215. v = BigLong (v);
  216. tex_palette[i] = v;
  217. }
  218. }
  219. void SetTexParameters (void)
  220. {
  221. qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, texture_mode );
  222. switch ( texture_mode )
  223. {
  224. case GL_NEAREST:
  225. case GL_NEAREST_MIPMAP_NEAREST:
  226. case GL_NEAREST_MIPMAP_LINEAR:
  227. qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  228. break;
  229. case GL_LINEAR:
  230. case GL_LINEAR_MIPMAP_NEAREST:
  231. case GL_LINEAR_MIPMAP_LINEAR:
  232. qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  233. break;
  234. }
  235. }
  236. /*
  237. ============
  238. Texture_SetMode
  239. ============
  240. */
  241. void Texture_SetMode(int iMenu)
  242. {
  243. int i, iMode;
  244. HMENU hMenu;
  245. qboolean texturing = true;
  246. hMenu = GetMenu(g_qeglobals.d_hwndMain);
  247. switch(iMenu) {
  248. case ID_VIEW_NEAREST:
  249. iMode = GL_NEAREST;
  250. break;
  251. case ID_VIEW_NEARESTMIPMAP:
  252. iMode = GL_NEAREST_MIPMAP_NEAREST;
  253. break;
  254. case ID_VIEW_LINEAR:
  255. iMode = GL_NEAREST_MIPMAP_LINEAR;
  256. break;
  257. case ID_VIEW_BILINEAR:
  258. iMode = GL_LINEAR;
  259. break;
  260. case ID_VIEW_BILINEARMIPMAP:
  261. iMode = GL_LINEAR_MIPMAP_NEAREST;
  262. break;
  263. case ID_VIEW_TRILINEAR:
  264. iMode = GL_LINEAR_MIPMAP_LINEAR;
  265. break;
  266. case ID_TEXTURES_WIREFRAME:
  267. iMode = 0;
  268. texturing = false;
  269. break;
  270. case ID_TEXTURES_FLATSHADE:
  271. iMode = 0;
  272. texturing = false;
  273. break;
  274. }
  275. CheckMenuItem(hMenu, ID_VIEW_NEAREST, MF_BYCOMMAND | MF_UNCHECKED);
  276. CheckMenuItem(hMenu, ID_VIEW_NEARESTMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
  277. CheckMenuItem(hMenu, ID_VIEW_LINEAR, MF_BYCOMMAND | MF_UNCHECKED);
  278. CheckMenuItem(hMenu, ID_VIEW_BILINEARMIPMAP, MF_BYCOMMAND | MF_UNCHECKED);
  279. CheckMenuItem(hMenu, ID_VIEW_BILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
  280. CheckMenuItem(hMenu, ID_VIEW_TRILINEAR, MF_BYCOMMAND | MF_UNCHECKED);
  281. CheckMenuItem(hMenu, ID_TEXTURES_WIREFRAME, MF_BYCOMMAND | MF_UNCHECKED);
  282. CheckMenuItem(hMenu, ID_TEXTURES_FLATSHADE, MF_BYCOMMAND | MF_UNCHECKED);
  283. CheckMenuItem(hMenu, iMenu, MF_BYCOMMAND | MF_CHECKED);
  284. g_qeglobals.d_savedinfo.iTexMenu = iMenu;
  285. texture_mode = iMode;
  286. if (g_PrefsDlg.m_bSGIOpenGL)
  287. {
  288. if (s_hdcTexture && s_hglrcTexture)
  289. {
  290. //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
  291. if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
  292. Error ("wglMakeCurrent in LoadTexture failed");
  293. }
  294. else
  295. return;
  296. }
  297. if ( texturing )
  298. SetTexParameters ();
  299. if ( !texturing && iMenu == ID_TEXTURES_WIREFRAME)
  300. {
  301. g_pParentWnd->GetCamera()->Camera().draw_mode = cd_wire;
  302. Map_BuildBrushData();
  303. Sys_UpdateWindows (W_ALL);
  304. return;
  305. } else if ( !texturing && iMenu == ID_TEXTURES_FLATSHADE) {
  306. g_pParentWnd->GetCamera()->Camera().draw_mode = cd_solid;
  307. Map_BuildBrushData();
  308. Sys_UpdateWindows (W_ALL);
  309. return;
  310. }
  311. for (i=1 ; i<texture_extension_number ; i++)
  312. {
  313. qglBindTexture( GL_TEXTURE_2D, i );
  314. SetTexParameters ();
  315. }
  316. // select the default texture
  317. qglBindTexture( GL_TEXTURE_2D, 0 );
  318. qglFinish();
  319. if (g_pParentWnd->GetCamera()->Camera().draw_mode != cd_texture)
  320. {
  321. g_pParentWnd->GetCamera()->Camera().draw_mode = cd_texture;
  322. Map_BuildBrushData();
  323. }
  324. Sys_UpdateWindows (W_ALL);
  325. }
  326. /*
  327. ================
  328. R_MipMap
  329. Operates in place, quartering the size of the texture
  330. ================
  331. */
  332. void R_MipMap (byte *in, int &width, int &height)
  333. {
  334. int i, j;
  335. byte *out;
  336. int row;
  337. row = width * 4;
  338. width >>= 1;
  339. height >>= 1;
  340. out = in;
  341. for (i=0 ; i<height ; i++, in+=row)
  342. {
  343. for (j=0 ; j<width ; j++, out+=4, in+=8)
  344. {
  345. out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
  346. out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
  347. out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
  348. out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
  349. }
  350. }
  351. }
  352. /*
  353. =================
  354. Texture_LoadTexture
  355. =================
  356. */
  357. //++timo NOTE: miptex_t is used only for .WAL format .. a bit outdated
  358. qtexture_t *Texture_LoadTexture (miptex_t *qtex)
  359. {
  360. byte *source;
  361. unsigned char *dest;
  362. int width, height, i, count;
  363. int total[3];
  364. qtexture_t *q;
  365. width = LittleLong(qtex->width);
  366. height = LittleLong(qtex->height);
  367. q = (qtexture_t*)qmalloc(sizeof(*q));
  368. q->width = width;
  369. q->height = height;
  370. q->flags = qtex->flags;
  371. q->value = qtex->value;
  372. q->contents = qtex->contents;
  373. dest = (unsigned char*)qmalloc (width*height*4);
  374. count = width*height;
  375. source = (byte *)qtex + LittleLong(qtex->offsets[0]);
  376. // The dib is upside down so we want to copy it into
  377. // the buffer bottom up.
  378. total[0] = total[1] = total[2] = 0;
  379. for (i=0 ; i<count ; i++)
  380. {
  381. dest[i] = tex_palette[source[i]];
  382. total[0] += ((byte *)(dest+i))[0];
  383. total[1] += ((byte *)(dest+i))[1];
  384. total[2] += ((byte *)(dest+i))[2];
  385. }
  386. q->color[0] = (float)total[0]/(count*255);
  387. q->color[1] = (float)total[1]/(count*255);
  388. q->color[2] = (float)total[2]/(count*255);
  389. q->texture_number = texture_extension_number++;
  390. if (g_qeglobals.bSurfacePropertiesPlugin)
  391. {
  392. // Timo
  393. // Surface properties plugins can store their own data in an IPluginQTexture
  394. q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
  395. GETPLUGINTEXDEF(q)->InitForMiptex( qtex );
  396. }
  397. //++timo is the m_bSGIOpenGL parameter still taken into account?
  398. if (g_PrefsDlg.m_bSGIOpenGL)
  399. {
  400. //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
  401. if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
  402. Error ("wglMakeCurrent in LoadTexture failed");
  403. }
  404. qglBindTexture( GL_TEXTURE_2D, q->texture_number );
  405. //Handle3DfxTexturing(q, width, height, dest);
  406. SetTexParameters ();
  407. int nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
  408. while (nCount-- > 0)
  409. {
  410. if (width > 16 && height > 16)
  411. {
  412. R_MipMap(dest, width, height);
  413. }
  414. else
  415. {
  416. break;
  417. }
  418. }
  419. if (g_PrefsDlg.m_bSGIOpenGL)
  420. {
  421. if (nomips)
  422. {
  423. qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
  424. }
  425. else
  426. qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
  427. }
  428. else
  429. {
  430. if (nomips)
  431. qglTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, dest);
  432. else
  433. qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, width, height,GL_RGBA, GL_UNSIGNED_BYTE, dest);
  434. }
  435. free (dest);
  436. qglBindTexture( GL_TEXTURE_2D, 0 );
  437. return q;
  438. }
  439. /*
  440. =================
  441. Texture_LoadTexture
  442. =================
  443. */
  444. qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char* pPath, int nFlags, int nContents, int nValue )
  445. {
  446. int i, j, inf;
  447. byte gammatable[256];
  448. float fGamma = g_qeglobals.d_savedinfo.fGamma;
  449. qtexture_t* q = (qtexture_t*)qmalloc(sizeof(*q));
  450. q->width = nWidth;
  451. q->height = nHeight;
  452. q->flags = nFlags;
  453. q->value = nValue;
  454. q->contents = nContents;
  455. int nCount = nWidth * nHeight;
  456. float total[3];
  457. total[0] = total[1] = total[2] = 0.0f;
  458. //++timo FIXME: move gamma table initialization somewhere else!
  459. if (fGamma == 1.0)
  460. {
  461. for (i=0 ; i<256 ; i++)
  462. gammatable[i] = i;
  463. }
  464. else
  465. {
  466. for (i=0 ; i<256 ; i++)
  467. {
  468. inf = 255 * pow ( (float)( (i+0.5)/255.5 ), fGamma ) + 0.5;
  469. if (inf < 0)
  470. inf = 0;
  471. if (inf > 255)
  472. inf = 255;
  473. gammatable[i] = inf;
  474. }
  475. }
  476. // all targas are stored internally as 32bit so rgba = 4 bytes
  477. for (i = 0 ; i < (nCount * 4) ; i += 4)
  478. {
  479. for (j = 0; j < 3; j++)
  480. {
  481. total[j] += (pPixels+i)[j];
  482. byte b = (pPixels+i)[j];
  483. (pPixels+i)[j] = gammatable[b];
  484. }
  485. }
  486. q->color[0] = total[0] / (nCount * 255);
  487. q->color[1] = total[1] / (nCount * 255);
  488. q->color[2] = total[2] / (nCount * 255);
  489. q->texture_number = texture_extension_number++;
  490. if (g_qeglobals.bSurfacePropertiesPlugin)
  491. {
  492. // Timo
  493. // Surface properties plugins can store their own data in an IPluginQTexture
  494. q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
  495. GETPLUGINTEXDEF(q)->SetDefaultTexdef();
  496. }
  497. if (g_PrefsDlg.m_bSGIOpenGL)
  498. {
  499. //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
  500. if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
  501. Error ("wglMakeCurrent in LoadTexture failed");
  502. }
  503. qglBindTexture( GL_TEXTURE_2D, q->texture_number );
  504. //Handle3DfxTexturing(q, width, height, dest);
  505. SetTexParameters();
  506. nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
  507. while (nCount-- > 0)
  508. {
  509. if (nWidth > 16 && nHeight > 16)
  510. {
  511. R_MipMap(pPixels, nWidth, nHeight);
  512. }
  513. else
  514. {
  515. break;
  516. }
  517. }
  518. if (g_PrefsDlg.m_bSGIOpenGL)
  519. {
  520. if (nomips)
  521. {
  522. qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
  523. }
  524. else
  525. qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
  526. }
  527. else
  528. {
  529. if (nomips)
  530. qglTexImage2D(GL_TEXTURE_2D, 0, 4, nWidth, nHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
  531. else
  532. qgluBuild2DMipmaps(GL_TEXTURE_2D, 4, nWidth, nHeight,GL_RGBA, GL_UNSIGNED_BYTE, pPixels);
  533. }
  534. qglBindTexture( GL_TEXTURE_2D, 0 );
  535. return q;
  536. }
  537. qtexture_t *Texture_LoadTGATexture (unsigned char* pPixels, int nWidth, int nHeight, char *pPath)
  538. {
  539. CString strName;
  540. CString strPath;
  541. ExtractPath_and_Filename(pPath, strPath, strName);
  542. AddSlash(strPath);
  543. strPath += "textureinfo.ini";
  544. strName.MakeLower();
  545. StripExtension (strName.GetBuffer(0));
  546. strName.ReleaseBuffer();
  547. int nFlags = GetPrivateProfileInt(strName, "Flags", 0, strPath);
  548. int nValue = GetPrivateProfileInt(strName, "Value", 0, strPath);
  549. int nContents = GetPrivateProfileInt(strName, "Contents", 0, strPath);
  550. return Texture_LoadTGATexture(pPixels, nWidth, nHeight, pPath, nFlags, nValue, nContents);
  551. }
  552. void Texture_LoadFromPlugIn(LPVOID vp)
  553. {
  554. g_pluginTexture = notexture;
  555. _QERTextureLoad *pLoad = reinterpret_cast<_QERTextureLoad*>(vp);
  556. if (pLoad != NULL)
  557. {
  558. qtexture_t *q;
  559. q = Texture_LoadTGATexture(pLoad->m_pRGBA, pLoad->m_nWidth, pLoad->m_nHeight, NULL, pLoad->m_nFlags, pLoad->m_nContents, pLoad->m_nValue);
  560. if (q != NULL)
  561. {
  562. // to save duplicate code (since one always ends up getting forgotten and out of sync) this is now done later by caller
  563. // strcpy (q->name, pLoad->m_pName);
  564. // StripExtension (q->name);
  565. // if (!g_dontuse)
  566. // q->inuse = true;
  567. // q->next = g_qeglobals.d_qtextures;
  568. // g_qeglobals.d_qtextures = q;
  569. g_pluginTexture = q;
  570. }
  571. }
  572. }
  573. /*
  574. ===============
  575. Texture_CreateSolid
  576. Create a single pixel texture of the apropriate color
  577. ===============
  578. */
  579. qtexture_t *Texture_CreateSolid (const char *name)
  580. {
  581. byte data[4];
  582. qtexture_t *q;
  583. q = (qtexture_t*)qmalloc(sizeof(*q));
  584. if (g_qeglobals.bSurfacePropertiesPlugin)
  585. {
  586. // Timo
  587. // Surface properties plugins can store their own data in an IPluginQTexture
  588. q->pData = g_SurfaceTable.m_pfnQTextureAlloc( q );
  589. GETPLUGINTEXDEF(q)->SetDefaultTexdef();
  590. }
  591. sscanf (name, "(%f %f %f)", &q->color[0], &q->color[1], &q->color[2]);
  592. data[0] = q->color[0]*255;
  593. data[1] = q->color[1]*255;
  594. data[2] = q->color[2]*255;
  595. data[3] = 255;
  596. q->width = q->height = 1;
  597. //q->width = q->height = 2;
  598. q->texture_number = texture_extension_number++;
  599. qglBindTexture( GL_TEXTURE_2D, q->texture_number );
  600. SetTexParameters ();
  601. if (g_PrefsDlg.m_bSGIOpenGL)
  602. {
  603. qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  604. }
  605. else
  606. {
  607. if (nomips)
  608. qglTexImage2D(GL_TEXTURE_2D, 0, 3, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  609. else
  610. qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 1, 1,GL_RGBA, GL_UNSIGNED_BYTE, data);
  611. }
  612. qglBindTexture( GL_TEXTURE_2D, 0 );
  613. return q;
  614. }
  615. /*
  616. =================
  617. Texture_MakeDefault
  618. =================
  619. */
  620. qtexture_t* Texture_MakeDefault (void)
  621. {
  622. qtexture_t *q;
  623. byte data[4][4];
  624. if (g_PrefsDlg.m_bSGIOpenGL)
  625. {
  626. if (s_hdcTexture && s_hglrcTexture)
  627. {
  628. //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
  629. if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
  630. Error ("wglMakeCurrent in LoadTexture failed");
  631. }
  632. else
  633. return NULL;
  634. }
  635. q = (qtexture_t*)qmalloc(sizeof(*q));
  636. strcpy (q->name, "notexture");
  637. q->width = q->height = 64;
  638. memset (data, 0, sizeof(data));
  639. data[0][2] = data[3][2] = 255;
  640. q->color[0] = 0;
  641. q->color[1] = 0;
  642. q->color[2] = 0.5;
  643. q->texture_number = texture_extension_number++;
  644. qglBindTexture( GL_TEXTURE_2D, q->texture_number );
  645. SetTexParameters ();
  646. if (nomips)
  647. qglTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  648. else
  649. VERIFY(qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data) == 0);
  650. qglBindTexture( GL_TEXTURE_2D, 0 );
  651. return q;
  652. }
  653. /*
  654. =================
  655. Texture_MakeNotexture
  656. =================
  657. */
  658. void Texture_MakeNotexture (void)
  659. {
  660. notexture = Texture_MakeDefault();
  661. // Timo
  662. // Surface properties plugins can store their own data in an IPluginQTexture
  663. if (g_qeglobals.bSurfacePropertiesPlugin)
  664. {
  665. notexture->pData = g_SurfaceTable.m_pfnQTextureAlloc( notexture );
  666. GETPLUGINTEXDEF(notexture)->SetDefaultTexdef();
  667. }
  668. }
  669. void DemandLoadShaderTexture(qtexture_t *q, CShaderInfo *pShader)
  670. {
  671. char cWork[1024];
  672. char cWork2[1024];
  673. strcpy(cWork, (pShader->m_strTextureName.GetLength() > 0) ? pShader->m_strTextureName : pShader->m_strName);
  674. StripExtension(cWork);
  675. // TTimo: if the shader has a m_fTransValue != 1.0f, ignore the alpha channel when loading the texture
  676. // in some cases (common/weapclip) the 32bit .tga has an empty alpha channel,
  677. // causing a display bug in the camera view (brush does not seemed drawn since alpha==0 for the texture)
  678. // NOTE: the workaround is not perfect, the same texture may have been loaded earlier with it's alpha channel
  679. q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, false);
  680. if (q == NULL || q == notexture) {
  681. sprintf(cWork2, "%s/%s",ValueForKey(g_qeglobals.d_project_entity, "basepath"), cWork);
  682. q = Texture_ForNamePath( cWork, cWork2);
  683. if (q == NULL || q == notexture) {
  684. q = Texture_ForName (cWork, false, true, pShader->m_fTransValue != 1.0f, true, true);
  685. }
  686. }
  687. if (q != NULL && q != notexture)
  688. {
  689. pShader->m_pQTexture = q;
  690. strcpy(q->shadername, pShader->m_strShaderName);
  691. q->bFromShader = true;
  692. q->fTrans = pShader->m_fTransValue;
  693. q->nShaderFlags = pShader->m_nFlags;
  694. strcpy(q->name, pShader->m_strName );
  695. }
  696. else
  697. {
  698. Sys_Printf("Could not load shader editor image %s\n", cWork);
  699. }
  700. }
  701. void LoadShader(char* pFilename, qtexture_t *q)
  702. {
  703. char* pBuff = NULL;
  704. CString strTexture;
  705. int nSize = LoadFile(pFilename, reinterpret_cast<void**>(&pBuff));
  706. if (nSize == -1)
  707. {
  708. nSize = PakLoadAnyFile(pFilename, reinterpret_cast<void**>(&pBuff));
  709. }
  710. if (nSize > 0)
  711. {
  712. StartTokenParsing(pBuff);
  713. while (GetToken(true))
  714. {
  715. // first token should be the path + name.. (from base)
  716. CShaderInfo *pShader = new CShaderInfo();
  717. pShader->setName(token);
  718. pShader->m_strShaderName = pFilename;
  719. strTexture = token;
  720. bool bGood = true;
  721. float fTrans = 1.0;
  722. GetToken(true);
  723. if (strcmp(token, "{"))
  724. {
  725. bGood = false;
  726. break;
  727. }
  728. else
  729. {
  730. // we need to read until we hit a balanced }
  731. int nMatch = 1;
  732. while (nMatch > 0 && GetToken(true))
  733. {
  734. if (strcmp(token, "{") == 0)
  735. {
  736. nMatch++;
  737. }
  738. else if (strcmp(token, "}") == 0)
  739. {
  740. nMatch--;
  741. }
  742. else if (strcmpi(token, "qer_nocarve") == 0)
  743. {
  744. pShader->m_nFlags |= QER_NOCARVE;
  745. }
  746. else if (strcmpi(token, "qer_trans") == 0)
  747. {
  748. if (GetToken(true))
  749. {
  750. fTrans = atof(token);
  751. }
  752. pShader->m_nFlags |= QER_TRANS;
  753. }
  754. else if (strcmpi(token, "qer_editorimage") == 0)
  755. {
  756. if (GetToken(true))
  757. {
  758. char* pTex = copystring(token);
  759. QE_ConvertDOSToUnixName( pTex, pTex );
  760. CString str = pTex;
  761. free (pTex);
  762. FindReplace(str, "textures/", "");
  763. FindReplace(str, ".tga", "");
  764. int nPos = str.Find('/');
  765. if (nPos == -1)
  766. {
  767. nPos = str.Find('\\');
  768. }
  769. if (nPos >= 0)
  770. {
  771. pShader->m_strTextureName = str;
  772. pShader->m_strTextureName.MakeLower(); //avoid problems with case
  773. /*
  774. else
  775. {
  776. CString strPath = str.Left(nPos+1);
  777. DeferredShaderLoad *deferred = new DeferredShaderLoad(str, pShader->m_strName, strPath);
  778. g_lstDeferred.Add(deferred);
  779. }
  780. */
  781. }
  782. }
  783. }
  784. else if (strcmpi(token, "surfaceparm") == 0)
  785. {
  786. //--while (GetToken(false))
  787. //--{
  788. //--
  789. //--}
  790. if (GetToken(true))
  791. {
  792. // next token should be a surface parm
  793. //--if (strcmpi(token, "trans") == 0)
  794. //--{
  795. //-- fTrans = 0.33;
  796. //--}
  797. if (strcmpi(token, "fog") == 0)
  798. {
  799. if (fTrans == 1.0) // has not been explicitly set by qer_trans
  800. {
  801. fTrans = 0.35;
  802. }
  803. }
  804. }
  805. }
  806. }
  807. if (nMatch != 0)
  808. {
  809. bGood = false;
  810. break;
  811. }
  812. }
  813. //--if (bGood && q)
  814. if (bGood)
  815. {
  816. pShader->m_fTransValue = fTrans;
  817. g_lstShaders.Add(pShader);
  818. int n = g_PrefsDlg.m_nShader;
  819. if (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_ALL || (g_PrefsDlg.m_nShader == CPrefsDlg::SHADER_COMMON && strstr(pShader->m_strName, "common" )))
  820. {
  821. // new
  822. if (pShader->m_strTextureName.GetLength() > 0)
  823. {
  824. if (!ShaderQTextureExists(pShader->m_strName))
  825. {
  826. DemandLoadShaderTexture(q, pShader);
  827. }
  828. }
  829. }
  830. // end new
  831. //--q->bFromShader = true;
  832. //--q->fTrans = fTrans;
  833. //--// good texture here
  834. //--//Sys_Printf("Test load texture %s\n", strTexture);
  835. //--// FIXME.. this is a load of crap
  836. //--strcpy(dirstring, strTexture);
  837. //--QE_ConvertDOSToUnixName(dirstring, dirstring);
  838. //--strTexture = dirstring;
  839. //--FindReplace(strTexture, "textures/", "");
  840. //--qtexture_t *q = Texture_ForName (strTexture.GetBuffer(0));
  841. //--if (q != NULL)
  842. //--{
  843. //-- q->bFromShader = true;
  844. //-- q->fTrans = fTrans;
  845. //--}
  846. }
  847. else
  848. {
  849. Sys_Printf("Error parsing shader at texture %s\n", strTexture);
  850. }
  851. }
  852. free (pBuff);
  853. }
  854. else
  855. {
  856. Sys_Printf("Unabled to read shader %s\n", pFilename);
  857. }
  858. }
  859. extern bool DoesFileExist(const char* pBuff, long& lSize);
  860. CShaderInfo* SetNameShaderInfo(qtexture_t* q, const char* pPath, const char* pName)
  861. {
  862. CShaderInfo *pInfo = hasShader(pName);
  863. if (pInfo)
  864. {
  865. strcpy(q->shadername, pInfo->m_strShaderName);
  866. q->bFromShader = true;
  867. q->fTrans = pInfo->m_fTransValue;
  868. q->nShaderFlags = pInfo->m_nFlags;
  869. }
  870. else
  871. {
  872. q->shadername[0] = 0;
  873. }
  874. strncpy (q->name, pName, sizeof(q->name) - 1);
  875. StripExtension (q->name);
  876. return pInfo;
  877. }
  878. void ReplaceQTexture(qtexture_t *pOld, qtexture_t *pNew, brush_t *pList)
  879. {
  880. for (brush_t* pBrush = pList->next ; pBrush != pList; pBrush = pBrush->next)
  881. {
  882. if (pBrush->patchBrush)
  883. {
  884. Patch_ReplaceQTexture(pBrush, pOld, pNew);
  885. }
  886. if (pBrush->terrainBrush)
  887. {
  888. Terrain_ReplaceQTexture(pBrush->pTerrain, pOld, pNew);
  889. }
  890. for (face_t* pFace = pBrush->brush_faces; pFace; pFace = pFace->next)
  891. {
  892. if (pFace->d_texture == pOld)
  893. {
  894. pFace->d_texture = pNew;
  895. }
  896. }
  897. //Brush_Build(pBrush);
  898. }
  899. }
  900. void Texture_Remove(qtexture_t *q)
  901. {
  902. qtexture_t* pTex = g_qeglobals.d_qtextures->next;
  903. if (q == g_qeglobals.d_qtextures) // it is the head
  904. {
  905. g_qeglobals.d_qtextures->next = q->next->next;
  906. g_qeglobals.d_qtextures = q->next;
  907. }
  908. else
  909. {
  910. qtexture_t* pLast = g_qeglobals.d_qtextures;
  911. while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
  912. {
  913. if (pTex == q)
  914. {
  915. pLast->next = q->next;
  916. break;
  917. }
  918. pLast = pTex;
  919. pTex = pTex->next;
  920. }
  921. }
  922. qglDeleteTextures(1, reinterpret_cast<const unsigned int*>(&q->texture_number));
  923. if (g_qeglobals.bSurfacePropertiesPlugin)
  924. {
  925. // Timo
  926. // Surface properties plugin
  927. #ifdef _DEBUG
  928. if ( !q->pData )
  929. Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
  930. #endif
  931. if ( q->pData )
  932. GETPLUGINTEXDEF(q)->DecRef();
  933. }
  934. free(q);
  935. }
  936. /*
  937. =================
  938. Texture_MakeNoShadertexture
  939. Make a default black/red check pattern texture
  940. =================
  941. */
  942. qtexture_t * Texture_MakeNoshadertexture( const char *name )
  943. {
  944. qtexture_t *q;
  945. byte data[4][4];
  946. notexture = q = (qtexture_t*)qmalloc(sizeof(*q));
  947. q->width = q->height = 64;
  948. q->fTrans = 1;
  949. q = (qtexture_t*)qmalloc(sizeof(*q));
  950. strcpy (q->name, name);
  951. q->width = q->height = 64;
  952. q->fTrans = 1;
  953. memset (data, 0, sizeof(data));
  954. data[0][0] = data[3][0] = 255;
  955. q->color[0] = 0;
  956. q->color[1] = 0;
  957. q->color[2] = 0.5;
  958. q->texture_number = texture_extension_number++;
  959. qglBindTexture( GL_TEXTURE_2D, q->texture_number );
  960. SetTexParameters ();
  961. if (nomips)
  962. qglTexImage2D(GL_TEXTURE_2D, 0, 3, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
  963. else
  964. VERIFY(qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, 2, 2,GL_RGBA, GL_UNSIGNED_BYTE, data) == 0);
  965. qglBindTexture( GL_TEXTURE_2D, 0 );
  966. return q;
  967. }
  968. /*
  969. ===============
  970. Texture_ForName
  971. ===============
  972. */
  973. //bReload is set to true when called from DemandLoadShaderTexture because it should never re-use
  974. //an already loaded texture
  975. qtexture_t *Texture_ForName (const char *name, bool bReplace, bool bShader, bool bNoAlpha, bool bReload, bool makeShader)
  976. {
  977. byte *lump;
  978. qtexture_t *q = NULL;
  979. char filename[1024];
  980. if (name == NULL || strlen(name) == 0)
  981. return notexture;
  982. qtexture_t *pRemove = NULL;
  983. if (!bReload)
  984. {
  985. for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
  986. {
  987. if (!strcmp(name, q->name))
  988. {
  989. if (bReplace)
  990. {
  991. pRemove = q;
  992. //Texture_Remove(q);
  993. break;
  994. }
  995. else
  996. {
  997. #ifdef _DEBUG
  998. // if the texture is already in memory, then the bNoAlpha flag doesn't have any influence
  999. if (bNoAlpha)
  1000. Sys_Printf("WARNING: bNoAlpha flag on an already loaded texture\n");
  1001. #endif
  1002. if (!g_dontuse)
  1003. {
  1004. q->inuse = true;
  1005. }
  1006. return q;
  1007. }
  1008. }
  1009. }
  1010. }
  1011. // did not find it in the standard list
  1012. // skip entity names (
  1013. if (!bShader && name[0] != '(')
  1014. {
  1015. CShaderInfo* pShader = hasShader(name);
  1016. if (pShader)
  1017. {
  1018. if (pShader->m_pQTexture == NULL)
  1019. {
  1020. DemandLoadShaderTexture(q, pShader);
  1021. }
  1022. q = pShader->m_pQTexture;
  1023. //Sys_Printf ("used Shader %s.\n", pShader->m_strName);
  1024. }
  1025. if ( q != NULL)
  1026. {
  1027. return q;
  1028. }
  1029. }
  1030. if (name[0] == '(')
  1031. {
  1032. q = Texture_CreateSolid (name);
  1033. strncpy (q->name, name, sizeof(q->name)-1);
  1034. }
  1035. else
  1036. {
  1037. // FIXME: this is a mess.. need to move consolidate stuff
  1038. // down to a single routine..
  1039. //
  1040. // if plugins have a texture loader
  1041. // {
  1042. //
  1043. // }
  1044. // else
  1045. //
  1046. if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
  1047. {
  1048. // rad: 12/19/98
  1049. // if the plugin is not a wad style then we need to treat it normally
  1050. // otherwise return without trying to explicitly load the texture
  1051. // as it should have been loaded by the wad style plugin at init time
  1052. CString strTex = GetTextureExtension(0);
  1053. sprintf (filename, "%s\\%s.%s", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name, strTex);
  1054. if (!g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
  1055. {
  1056. g_pParentWnd->GetPlugInMgr().LoadTexture(filename);
  1057. if (g_pluginTexture)
  1058. q = g_pluginTexture;
  1059. }
  1060. else
  1061. {
  1062. return notexture;
  1063. // wadstyle.. if we get here then we do not have it
  1064. }
  1065. }
  1066. else
  1067. // we need to try several formats here, or would it be better if we are given a complete name
  1068. if (g_PrefsDlg.m_bHiColorTextures == TRUE)
  1069. {
  1070. char cWork[1024];
  1071. sprintf (filename, "%s/%s.tga", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name);
  1072. QE_ConvertDOSToUnixName( cWork, filename );
  1073. strcpy(filename, cWork);
  1074. Sys_Printf ("Loading %s...", name);
  1075. unsigned char* pPixels = NULL;
  1076. int nWidth;
  1077. int nHeight;
  1078. LoadImage(filename, &pPixels, &nWidth, &nHeight);
  1079. if (pPixels == NULL)
  1080. {
  1081. // try jpg
  1082. // blatant assumption of .tga should be fine since we sprintf'd it above
  1083. int nLen = strlen(filename);
  1084. filename[nLen-3] = 'j';
  1085. filename[nLen-2] = 'p';
  1086. filename[nLen-1] = 'g';
  1087. LoadImage(filename, &pPixels, &nWidth, &nHeight);
  1088. }
  1089. if (pPixels)
  1090. {
  1091. // if we were asked to ignore alpha channel, do it now (.TGA is the only supported file type with alpha channel)
  1092. //if (bNoAlpha)
  1093. if (TRUE)
  1094. {
  1095. unsigned char* iPix = pPixels;
  1096. int nCount = nWidth * nHeight;
  1097. for(iPix=pPixels+3; iPix-pPixels < nCount*4; iPix+=4)
  1098. *iPix = 255;
  1099. }
  1100. // we'll be binding the GL texture now
  1101. // need to check we are using a right GL context
  1102. // with GL plugins that have their own window, the GL context may be the plugin's, in which case loading textures will bug
  1103. HDC currentHDC = qwglGetCurrentDC();
  1104. HGLRC currentHGLRC = qwglGetCurrentContext();
  1105. //++timo FIXME: this may duplicate with qtexture_t* WINAPI QERApp_Texture_ForName (const char *name)
  1106. //++timo FIXME: we need a list of lawfull GL contexts or something?
  1107. // I'd rather always use the same GL context for binding...
  1108. if (currentHDC != g_qeglobals.d_hdcBase || currentHGLRC != g_qeglobals.d_hglrcBase)
  1109. qwglMakeCurrent( g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase );
  1110. q = Texture_LoadTGATexture(pPixels, nWidth, nHeight, NULL, 0, 0, 0);
  1111. //++timo I don't set back the GL context .. I don't know how safe it is
  1112. //qwglMakeCurrent( currentHDC, currentHGLRC );
  1113. //++timo storing the filename .. will be removed by shader code cleanup
  1114. // this is dirty, and we sure miss some places were we should fill the filename info
  1115. strcpy( q->filename, name );
  1116. SetNameShaderInfo(q, filename, name);
  1117. Sys_Printf ("done.\n", name);
  1118. free(pPixels);
  1119. }
  1120. }
  1121. else
  1122. {
  1123. // load the file
  1124. sprintf (filename, "%s/%s.wal", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), name);
  1125. Sys_Printf ("Loading %s...", name);
  1126. if (LoadFile (filename, (void**)&lump) == -1)
  1127. {
  1128. sprintf (filename, "%s.wal", name);
  1129. Sys_Printf("failed.. trying pak0.pak..");
  1130. if(!PakLoadFile(filename, (void**)&lump))
  1131. {
  1132. Sys_Printf (" load failed!\n");
  1133. return notexture;
  1134. }
  1135. }
  1136. Sys_Printf("successful.\n");
  1137. q = Texture_LoadTexture ((miptex_t *)lump);
  1138. free (lump);
  1139. strncpy (q->name, name, sizeof(q->name)-1);
  1140. StripExtension (q->name);
  1141. }
  1142. if (g_PrefsDlg.m_bSGIOpenGL)
  1143. {
  1144. if(!q)
  1145. return notexture;
  1146. }
  1147. }// name[0] != '('
  1148. if(!q) // safety
  1149. {
  1150. if (bShader && !makeShader) {
  1151. return q;
  1152. }
  1153. if (bShader)
  1154. {
  1155. q = Texture_MakeNoshadertexture( name );
  1156. Sys_Printf("failed, using default shader\n");
  1157. }
  1158. else
  1159. {
  1160. q = Texture_MakeDefault();
  1161. Sys_Printf("failed, using default\n");
  1162. }
  1163. }
  1164. strncpy (q->name, name, sizeof(q->name)-1);
  1165. if (name[0] != '(')
  1166. {
  1167. StripExtension (q->name);
  1168. }
  1169. if (!g_dontuse)
  1170. q->inuse = true;
  1171. q->next = g_qeglobals.d_qtextures;
  1172. g_qeglobals.d_qtextures = q;
  1173. if (pRemove != NULL)
  1174. {
  1175. ReplaceQTexture(pRemove, q, &active_brushes);
  1176. ReplaceQTexture(pRemove, q, &filtered_brushes);
  1177. Texture_Remove(pRemove);
  1178. }
  1179. return q;
  1180. }
  1181. /*
  1182. ===============
  1183. Texture_ForNamePath
  1184. ===============
  1185. */
  1186. qtexture_t *Texture_ForNamePath(char* name, char* pFullPath)
  1187. {
  1188. byte *lump;
  1189. qtexture_t *q;
  1190. char filename[1024];
  1191. if (strlen(name) == 0)
  1192. return notexture;
  1193. for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
  1194. {
  1195. if (!strcmp(name, q->name))
  1196. {
  1197. if (!g_dontuse)
  1198. q->inuse = true;
  1199. return q;
  1200. }
  1201. }
  1202. if (name[0] == '(')
  1203. {
  1204. q = Texture_CreateSolid (name);
  1205. strncpy (q->name, name, sizeof(q->name)-1);
  1206. }
  1207. else
  1208. {
  1209. // load the file
  1210. if (g_PrefsDlg.m_bHiColorTextures == TRUE)
  1211. {
  1212. char cWork[1024];
  1213. if (strstr(pFullPath, ".tga") == NULL) {
  1214. sprintf(filename, "%s%s", pFullPath, ".tga");
  1215. } else {
  1216. strcpy(filename, pFullPath);
  1217. }
  1218. QE_ConvertDOSToUnixName( cWork, filename );
  1219. strcpy(filename, cWork);
  1220. Sys_Printf ("Loading %s...", name);
  1221. unsigned char* pPixels = NULL;
  1222. int nWidth;
  1223. int nHeight;
  1224. LoadImage(filename, &pPixels, &nWidth, &nHeight);
  1225. if (!pPixels)
  1226. {
  1227. // try jpg
  1228. // blatant assumption of .tga should be fine since we sprintf'd it above
  1229. int nLen = strlen(filename);
  1230. filename[nLen-3] = 'j';
  1231. filename[nLen-2] = 'p';
  1232. filename[nLen-1] = 'g';
  1233. LoadImage(filename, &pPixels, &nWidth, &nHeight);
  1234. }
  1235. if (pPixels)
  1236. {
  1237. q = Texture_LoadTGATexture(pPixels, nWidth, nHeight, NULL, 0, 0, 0);
  1238. //++timo storing the filename .. will be removed by shader code cleanup
  1239. // this is dirty, and we sure miss some places were we should fill the filename info
  1240. // NOTE: we store relative path, need to extract it
  1241. strcpy( q->filename, name );
  1242. }
  1243. else
  1244. {
  1245. return notexture;
  1246. }
  1247. free(pPixels);
  1248. }
  1249. else
  1250. {
  1251. sprintf(filename, "%s%s", pFullPath, ".wal");
  1252. Sys_Printf ("Loading %s...", name);
  1253. if (LoadFile (filename, (void**)&lump) == -1)
  1254. {
  1255. Sys_Printf (" load failed!\n");
  1256. return notexture;
  1257. }
  1258. Sys_Printf("successful.\n");
  1259. q = Texture_LoadTexture ((miptex_t *)lump);
  1260. free (lump);
  1261. }
  1262. if (g_PrefsDlg.m_bSGIOpenGL)
  1263. {
  1264. if(!q)
  1265. return notexture;
  1266. }
  1267. strncpy (q->name, name, sizeof(q->name)-1);
  1268. StripExtension (q->name);
  1269. }
  1270. if (!g_dontuse)
  1271. q->inuse = true;
  1272. q->next = g_qeglobals.d_qtextures;
  1273. g_qeglobals.d_qtextures = q;
  1274. return q;
  1275. }
  1276. /*
  1277. ==================
  1278. FillTextureMenu
  1279. ==================
  1280. */
  1281. void FillTextureMenu (CStringArray* pArray)
  1282. {
  1283. HMENU hmenu;
  1284. int i;
  1285. struct _finddata_t fileinfo;
  1286. int handle;
  1287. char dirstring[1024];
  1288. char *path;
  1289. DIRLIST *list = NULL, *temp;
  1290. if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
  1291. {
  1292. if (g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
  1293. return;
  1294. }
  1295. hmenu = GetSubMenu (GetMenu(g_qeglobals.d_hwndMain), MENU_TEXTURE);
  1296. // delete everything
  1297. for (i=0 ; i<texture_nummenus ; i++)
  1298. DeleteMenu (hmenu, CMD_TEXTUREWAD+i, MF_BYCOMMAND);
  1299. texture_nummenus = 0;
  1300. // add everything
  1301. if (g_qeglobals.d_project_entity)
  1302. {
  1303. //--if (g_PrefsDlg.m_bUseShaders)
  1304. //--{
  1305. //-- path = ValueForKey (g_qeglobals.d_project_entity, "basepath");
  1306. //-- sprintf (dirstring, "%s/scripts/*.shader", path);
  1307. //--
  1308. //--}
  1309. //--else
  1310. //--{
  1311. path = ValueForKey (g_qeglobals.d_project_entity, "texturepath");
  1312. sprintf (dirstring, "%s/*.*", path);
  1313. //--}
  1314. handle = _findfirst (dirstring, &fileinfo);
  1315. if (handle != -1)
  1316. {
  1317. do
  1318. {
  1319. //--if (g_PrefsDlg.m_bUseShaders)
  1320. //--{
  1321. //-- if ((fileinfo.attrib & _A_SUBDIR))
  1322. //-- continue;
  1323. //--}
  1324. //--else
  1325. //--{
  1326. if (!(fileinfo.attrib & _A_SUBDIR))
  1327. continue;
  1328. if (fileinfo.name[0] == '.')
  1329. continue;
  1330. //--}
  1331. // add this directory to the menu
  1332. AddToDirListAlphabetized(&list, fileinfo.name, FROMDISK);
  1333. } while (_findnext( handle, &fileinfo ) != -1);
  1334. _findclose (handle);
  1335. }
  1336. //--if (!g_PrefsDlg.m_bUseShaders)
  1337. //--{
  1338. GetPackTextureDirs(&list);
  1339. //--}
  1340. for(temp = list; temp; temp = temp->next)
  1341. {
  1342. AppendMenu (hmenu, MF_ENABLED|MF_STRING, CMD_TEXTUREWAD+texture_nummenus, (LPCTSTR)temp->dirname);
  1343. strcpy (texture_menunames[texture_nummenus], temp->dirname);
  1344. //--if (!g_PrefsDlg.m_bUseShaders)
  1345. //--{
  1346. strcat (texture_menunames[texture_nummenus], "/");
  1347. //--}
  1348. if (pArray)
  1349. pArray->Add(temp->dirname);
  1350. if (++texture_nummenus == MAX_TEXTUREDIRS)
  1351. break;
  1352. }
  1353. ClearDirList(&list);
  1354. }
  1355. }
  1356. /*
  1357. ==================
  1358. Texture_ClearInuse
  1359. A new map is being loaded, so clear inuse markers
  1360. ==================
  1361. */
  1362. void Texture_ClearInuse (void)
  1363. {
  1364. qtexture_t *q;
  1365. for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
  1366. {
  1367. q->inuse = false;
  1368. }
  1369. }
  1370. void LoadShadersFromDir(const char *pPath)
  1371. {
  1372. int nSize = g_lstShaders.GetSize();
  1373. for (int i = 0; i < nSize; i++)
  1374. {
  1375. CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
  1376. if (pInfo != NULL)
  1377. {
  1378. if (strstr(pInfo->m_strName, pPath) && pInfo->m_pQTexture == NULL && strstr(pInfo->m_strName, "models/player") == NULL)
  1379. {
  1380. qtexture_t *q = NULL;
  1381. DemandLoadShaderTexture(q, pInfo);
  1382. }
  1383. }
  1384. }
  1385. }
  1386. /*
  1387. ==============
  1388. Texture_ShowDirectory
  1389. ==============
  1390. */
  1391. void Texture_ShowDirectory (int menunum, bool bLinked)
  1392. {
  1393. struct _finddata_t fileinfo;
  1394. int handle;
  1395. char name[1024];
  1396. char dirstring[1024];
  1397. char linkstring[1024];
  1398. FILELIST *list = NULL, *temp;
  1399. CString strTemp;
  1400. //Texture_Flush(false);
  1401. //Select_Deselect();
  1402. Texture_ClearInuse();
  1403. texture_showinuse = false;
  1404. strcpy (texture_directory, texture_menunames[menunum-CMD_TEXTUREWAD]);
  1405. if (g_pParentWnd->GetPlugInMgr().GetTextureInfo() != NULL)
  1406. {
  1407. if (g_pParentWnd->GetPlugInMgr().GetTextureInfo()->m_bWadStyle)
  1408. return;
  1409. }
  1410. // new
  1411. /*
  1412. if (!g_PrefsDlg.m_bShaderTest)
  1413. {
  1414. g_dontuse = true; // needed because this next piece of code calls Texture_ForName() internally! -slc
  1415. LoadDeferred(texture_directory);
  1416. g_dontuse = false;
  1417. }
  1418. */
  1419. if (g_PrefsDlg.m_bHiColorTextures == FALSE)
  1420. {
  1421. }
  1422. g_qeglobals.d_texturewin.originy = 0;
  1423. //--if (g_PrefsDlg.m_bUseShaders)
  1424. //--{
  1425. //-- sprintf (dirstring, "%s/scripts/%s", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_directory);
  1426. //-- Sys_Printf("loading textures from shader %s\n", dirstring);
  1427. //-- LoadShader(dirstring);
  1428. //--}
  1429. //--else
  1430. //--{
  1431. Sys_Status("Loading textures\n", 0);
  1432. // load all image files
  1433. sprintf (linkstring, "%s/textures/%stextureinfo.ini", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_menunames[menunum-CMD_TEXTUREWAD]);
  1434. for (int nExt = 0; nExt < GetTextureExtensionCount(); nExt++)
  1435. {
  1436. sprintf (dirstring, "%s/textures/%s*.%s", ValueForKey (g_qeglobals.d_project_entity, "basepath"), texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
  1437. Sys_Printf ("Scanning %s\n", dirstring);
  1438. handle = _findfirst (dirstring, &fileinfo);
  1439. if (handle == -1)
  1440. {
  1441. sprintf(dirstring, "%s/%s*.%s", ValueForKey (g_qeglobals.d_project_entity, "texturepath"), texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
  1442. handle = _findfirst (dirstring, &fileinfo);
  1443. }
  1444. if (handle != -1)
  1445. {
  1446. do
  1447. {
  1448. sprintf (name, "%s%s", texture_directory, fileinfo.name);
  1449. AddToFileListAlphabetized(&list, name, FROMDISK, 0, false);
  1450. } while (_findnext( handle, &fileinfo ) != -1);
  1451. _findclose (handle);
  1452. }
  1453. else
  1454. {
  1455. sprintf (dirstring, "%s*.%s", texture_menunames[menunum-CMD_TEXTUREWAD],GetTextureExtension(nExt));
  1456. GetPackFileList(&list, dirstring);
  1457. }
  1458. }
  1459. g_dontuse = true;
  1460. for(temp = list; temp; temp = temp->next)
  1461. {
  1462. if(temp->offset == -1)
  1463. sprintf(name, "%s", temp->filename);
  1464. else
  1465. sprintf(name, "%s%s", texture_menunames[menunum-CMD_TEXTUREWAD], temp->filename);
  1466. StripExtension (name);
  1467. strTemp = name;
  1468. strTemp.MakeLower();
  1469. if ( strTemp.Find(".specular") >= 0 ||
  1470. strTemp.Find(".glow") >= 0 ||
  1471. strTemp.Find(".bump") >= 0 ||
  1472. strTemp.Find(".diffuse") >= 0 ||
  1473. strTemp.Find(".blend") >= 0 ||
  1474. strTemp.Find(".alpha") >= 0
  1475. )
  1476. continue;
  1477. else
  1478. {
  1479. Texture_ForName (name, true);
  1480. }
  1481. }
  1482. ClearFileList(&list);
  1483. //--}
  1484. g_dontuse = false;
  1485. if (!bLinked)
  1486. {
  1487. for (int k = 0; k < 10; k++)
  1488. {
  1489. sprintf(name, "Path%d", k);
  1490. if (GetPrivateProfileString("Include", name, "", dirstring, 1024, linkstring) > 0)
  1491. {
  1492. Texture_ShowDirectory(dirstring, true);
  1493. }
  1494. }
  1495. LoadShadersFromDir(texture_directory);
  1496. SortTextures();
  1497. sprintf (name, "Textures: %s", texture_directory);
  1498. SetWindowText(g_qeglobals.d_hwndEntity, name);
  1499. // select the first texture in the list
  1500. if (!g_qeglobals.d_texturewin.texdef.name[0])
  1501. SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
  1502. }
  1503. }
  1504. // this can be combined with the above, but per usual i am in a hurry
  1505. //
  1506. void Texture_ShowDirectory (char* pPath, bool bLinked)
  1507. {
  1508. struct _finddata_t fileinfo;
  1509. int handle;
  1510. char name[1024];
  1511. char dirstring[1024];
  1512. char linkstring[1024];
  1513. FILELIST *list = NULL, *temp;
  1514. //Texture_Flush(false);
  1515. texture_showinuse = false;
  1516. Texture_ClearInuse();
  1517. strcpy (texture_directory, pPath);
  1518. if (g_PrefsDlg.m_bHiColorTextures == FALSE)
  1519. {
  1520. }
  1521. g_qeglobals.d_texturewin.originy = 0;
  1522. Sys_Status("loading all textures\n", 0);
  1523. // load all .wal files
  1524. for (int nExt = 0; nExt < GetTextureExtensionCount(); nExt++)
  1525. {
  1526. sprintf(dirstring, "%s*.%s", pPath,GetTextureExtension(nExt));
  1527. Sys_Printf ("Scanning %s\n", dirstring);
  1528. handle = _findfirst (dirstring, &fileinfo);
  1529. if (handle != -1)
  1530. {
  1531. do
  1532. {
  1533. sprintf (name, "%s%s", texture_directory, fileinfo.name);
  1534. AddToFileListAlphabetized(&list, name, FROMDISK, 0, false);
  1535. } while (_findnext( handle, &fileinfo ) != -1);
  1536. _findclose (handle);
  1537. }
  1538. else
  1539. {
  1540. //sprintf (dirstring, "%s*.wal", texture_menunames[menunum-CMD_TEXTUREWAD]);
  1541. //if(!GetPackFileList(&list, dirstring))
  1542. return;
  1543. }
  1544. }
  1545. g_dontuse = true;
  1546. for(temp = list; temp; temp = temp->next)
  1547. {
  1548. if(temp->offset == -1)
  1549. sprintf(name, "%s", temp->filename);
  1550. else
  1551. sprintf(name, "%s%s", pPath, temp->filename);
  1552. StripExtension (name);
  1553. int nLen = strlen(name)-1;
  1554. ASSERT(nLen > 0);
  1555. while (name[nLen] != '\\')
  1556. nLen--;
  1557. // found first one
  1558. nLen--;
  1559. ASSERT(nLen > 0);
  1560. while (name[nLen] != '\\')
  1561. nLen--;
  1562. ASSERT(nLen >= 0);
  1563. QE_ConvertDOSToUnixName(name, name);
  1564. Texture_ForName(&name[nLen+1]);
  1565. }
  1566. ClearFileList(&list);
  1567. g_dontuse = false;
  1568. SortTextures();
  1569. if (!bLinked)
  1570. {
  1571. for (int k = 0; k < 10; k++)
  1572. {
  1573. sprintf(name, "Path%d", k);
  1574. if (GetPrivateProfileString("Include", name, "", dirstring, 1024, linkstring) > 0)
  1575. {
  1576. Texture_ShowDirectory(dirstring, true);
  1577. }
  1578. }
  1579. sprintf (name, "Textures: %s", texture_directory);
  1580. SetWindowText(g_qeglobals.d_hwndEntity, name);
  1581. // select the first texture in the list
  1582. if (!g_qeglobals.d_texturewin.texdef.name[0])
  1583. SelectTexture (16, g_qeglobals.d_texturewin.height -16 ,false);
  1584. }
  1585. }
  1586. void Texture_ResetPosition()
  1587. {
  1588. SelectTexture (16, g_qeglobals.d_texturewin.height -16 ,false);
  1589. g_qeglobals.d_texturewin.originy = 0;
  1590. }
  1591. /*
  1592. ==================
  1593. Texture_SetInuse
  1594. ==================
  1595. */
  1596. void Texture_SetInuse (void)
  1597. {
  1598. qtexture_t *q;
  1599. for (q=g_qeglobals.d_qtextures ; q ; q=q->next)
  1600. {
  1601. q->inuse = true;
  1602. }
  1603. }
  1604. /*
  1605. ==============
  1606. Texture_ShowAll
  1607. ==============
  1608. */
  1609. void Texture_ShowAll()
  1610. {
  1611. Texture_SetInuse();
  1612. Sys_Printf("Showing all textures...\n");
  1613. Sys_UpdateWindows (W_TEXTURE);
  1614. }
  1615. /*
  1616. ==============
  1617. Texture_ShowInuse
  1618. ==============
  1619. */
  1620. void Texture_ShowInuse (void)
  1621. {
  1622. face_t *f;
  1623. brush_t *b;
  1624. char name[1024];
  1625. texture_showinuse = true;
  1626. g_dontuse = false;
  1627. g_qeglobals.d_texturewin.originy = 0;
  1628. Texture_ClearInuse();
  1629. Sys_Status("Selecting active textures\n", 0);
  1630. for (b=active_brushes.next ; b != NULL && b != &active_brushes ; b=b->next)
  1631. {
  1632. if (b->patchBrush)
  1633. {
  1634. Texture_ForName(b->pPatch->d_texture->name);
  1635. }
  1636. else
  1637. {
  1638. for (f=b->brush_faces ; f ; f=f->next)
  1639. {
  1640. Texture_ForName (f->texdef.name);
  1641. }
  1642. }
  1643. }
  1644. for (b=selected_brushes.next ; b != NULL && b != &selected_brushes ; b=b->next)
  1645. {
  1646. if (b->patchBrush)
  1647. {
  1648. Texture_ForName(b->pPatch->d_texture->name);
  1649. }
  1650. else
  1651. {
  1652. for (f=b->brush_faces ; f ; f=f->next)
  1653. {
  1654. Texture_ForName (f->texdef.name);
  1655. }
  1656. }
  1657. }
  1658. SortTextures();
  1659. //SetInspectorMode(W_TEXTURE);
  1660. Sys_UpdateWindows (W_TEXTURE);
  1661. sprintf (name, "Textures: in use");
  1662. SetWindowText(g_qeglobals.d_hwndEntity, name);
  1663. // select the first texture in the list
  1664. if (!g_qeglobals.d_texturewin.texdef.name[0])
  1665. {
  1666. SelectTexture (16, g_qeglobals.d_texturewin.height -16, false);
  1667. }
  1668. }
  1669. /*
  1670. ============================================================================
  1671. TEXTURE LAYOUT
  1672. ============================================================================
  1673. */
  1674. void Texture_StartPos (void)
  1675. {
  1676. current_texture = g_qeglobals.d_qtextures;
  1677. current_x = 8;
  1678. current_y = -8;
  1679. current_row = 0;
  1680. }
  1681. qtexture_t *Texture_NextPos (int *x, int *y)
  1682. {
  1683. qtexture_t *q;
  1684. while (1)
  1685. {
  1686. q = current_texture;
  1687. if (!q)
  1688. return q;
  1689. current_texture = current_texture->next;
  1690. if (q->name[0] == '(') // fake color texture
  1691. continue;
  1692. if (g_bFilterEnabled)
  1693. {
  1694. CString strName = q->name;
  1695. int nPos = strName.Find('\\');
  1696. if (nPos == -1)
  1697. nPos = strName.Find('/');
  1698. if (nPos >= 0)
  1699. strName = strName.Right(strName.GetLength() - nPos - 1);
  1700. if (strnicmp(g_strFilter.GetBuffer(0), strName, g_strFilter.GetLength()) == 0)
  1701. break;
  1702. else
  1703. continue;
  1704. }
  1705. if (q->bFromShader && g_PrefsDlg.m_bShowShaders == FALSE)
  1706. {
  1707. continue;
  1708. }
  1709. if (q->inuse)
  1710. break; // always show in use
  1711. if (!texture_showinuse && !strnicmp (q->name, texture_directory, strlen(texture_directory)))
  1712. break;
  1713. continue;
  1714. }
  1715. int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
  1716. int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
  1717. if (current_x + nWidth > g_qeglobals.d_texturewin.width-8 && current_row)
  1718. { // go to the next row unless the texture is the first on the row
  1719. current_x = 8;
  1720. current_y -= current_row + FONT_HEIGHT + 4;
  1721. current_row = 0;
  1722. }
  1723. *x = current_x;
  1724. *y = current_y;
  1725. // Is our texture larger than the row? If so, grow the
  1726. // row height to match it
  1727. if (current_row < nHeight)
  1728. current_row = nHeight;
  1729. // never go less than 64, or the names get all crunched up
  1730. current_x += nWidth < 64 ? 64 : nWidth;
  1731. current_x += 8;
  1732. return q;
  1733. }
  1734. /*
  1735. ============================================================================
  1736. MOUSE ACTIONS
  1737. ============================================================================
  1738. */
  1739. static int textures_cursorx, textures_cursory;
  1740. /*
  1741. ============
  1742. Texture_SetTexture
  1743. brushprimit_texdef must be understood as a qtexture_t with width=2 height=2 ( the default one )
  1744. ============
  1745. */
  1746. void Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, IPluginTexdef *pTexdef, bool bSetSelection )
  1747. {
  1748. qtexture_t *q;
  1749. int x,y;
  1750. if (texdef->name[0] == '(')
  1751. {
  1752. Sys_Status("Can't select an entity texture\n", 0);
  1753. return;
  1754. }
  1755. g_qeglobals.d_texturewin.texdef = *texdef;
  1756. g_qeglobals.d_texturewin.texdef.flags &= ~SURF_KEEP;
  1757. g_qeglobals.d_texturewin.texdef.contents &= ~CONTENTS_KEEP;
  1758. // store the texture coordinates for new brush primitive mode
  1759. // be sure that all the callers are using the default 2x2 texture
  1760. if (g_qeglobals.m_bBrushPrimitMode)
  1761. {
  1762. g_qeglobals.d_texturewin.brushprimit_texdef = *brushprimit_texdef;
  1763. }
  1764. // surface properties plugin
  1765. if (g_qeglobals.bSurfacePropertiesPlugin)
  1766. {
  1767. if (g_qeglobals.d_texturewin.pTexdef)
  1768. {
  1769. // decrement reference count
  1770. static_cast<IPluginTexdef *>(g_qeglobals.d_texturewin.pTexdef)->DecRef();
  1771. g_qeglobals.d_texturewin.pTexdef = NULL;
  1772. }
  1773. if (pTexdef)
  1774. {
  1775. g_qeglobals.d_texturewin.pTexdef = pTexdef->Copy();
  1776. }
  1777. }
  1778. Sys_UpdateWindows (W_TEXTURE);
  1779. g_dlgFind.updateTextures(texdef->name);
  1780. if (!g_dlgFind.isOpen() && bSetSelection)
  1781. {
  1782. Select_SetTexture(texdef,brushprimit_texdef,bFitScale);
  1783. }
  1784. //plugins: send a message telling that the selected texture may have changed
  1785. DispatchRadiantMsg( RADIANT_TEXTURE );
  1786. // scroll origin so the texture is completely on screen
  1787. Texture_StartPos ();
  1788. while (1)
  1789. {
  1790. q = Texture_NextPos (&x, &y);
  1791. if (!q)
  1792. break;
  1793. int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
  1794. int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
  1795. if (!strcmpi(texdef->name, q->name))
  1796. {
  1797. if (y > g_qeglobals.d_texturewin.originy)
  1798. {
  1799. g_qeglobals.d_texturewin.originy = y;
  1800. Sys_UpdateWindows (W_TEXTURE);
  1801. return;
  1802. }
  1803. if (y-nHeight-2*FONT_HEIGHT < g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height)
  1804. {
  1805. g_qeglobals.d_texturewin.originy = y-nHeight-2*FONT_HEIGHT+g_qeglobals.d_texturewin.height;
  1806. Sys_UpdateWindows (W_TEXTURE);
  1807. return;
  1808. }
  1809. return;
  1810. }
  1811. }
  1812. }
  1813. HWND FindEditWindow()
  1814. {
  1815. HWND hwnd = FindWindow("TEditPadForm", NULL);
  1816. HWND hwndEdit = NULL;
  1817. if (hwnd != NULL)
  1818. {
  1819. HWND hwndTab = FindWindowEx(hwnd, NULL, "TTabControl", NULL);
  1820. if (hwndTab != NULL)
  1821. {
  1822. hwndEdit = FindWindowEx(hwndTab, NULL, "TRicherEdit", NULL);
  1823. }
  1824. }
  1825. return hwndEdit;
  1826. }
  1827. void Delay(float fSeconds)
  1828. {
  1829. DWORD dw = ::GetTickCount();
  1830. DWORD dwTil = dw + (fSeconds * 1000);
  1831. while (::GetTickCount() < dwTil)
  1832. {
  1833. MSG msg;
  1834. if (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
  1835. {
  1836. TranslateMessage(&msg);
  1837. DispatchMessage(&msg);
  1838. }
  1839. }
  1840. }
  1841. void ViewShader(const char *pFile, const char *pName)
  1842. {
  1843. CString str;
  1844. char* pBuff = NULL;
  1845. int nSize = LoadFile(pFile, reinterpret_cast<void**>(&pBuff));
  1846. if (nSize == -1)
  1847. {
  1848. nSize = PakLoadAnyFile(pFile, reinterpret_cast<void**>(&pBuff));
  1849. }
  1850. if (nSize > 0)
  1851. {
  1852. str = pBuff;
  1853. }
  1854. int nStart = 0;
  1855. if (str.GetLength() > 0)
  1856. {
  1857. CString strFind = pName;
  1858. CString strLook = str;
  1859. strLook.MakeLower();
  1860. strFind.MakeLower();
  1861. int n = strLook.Find(strFind);
  1862. if (n >= 0)
  1863. {
  1864. nStart = n;
  1865. }
  1866. }
  1867. CString s= "editpad ";
  1868. s += pFile;
  1869. WinExec(s, SW_SHOWNORMAL);
  1870. Delay(1.5);
  1871. HWND hwndEdit = FindEditWindow();
  1872. if (hwndEdit != NULL)
  1873. {
  1874. PostMessage(hwndEdit, EM_SETSEL, nStart, nStart);
  1875. }
  1876. else
  1877. {
  1878. Sys_Printf("Unable to load shader editor.\n");
  1879. }
  1880. }
  1881. /*
  1882. ==============
  1883. SelectTexture
  1884. By mouse click
  1885. ==============
  1886. */
  1887. void SelectTexture (int mx, int my, bool bShift, bool bFitScale)
  1888. {
  1889. int x, y;
  1890. qtexture_t *q;
  1891. texdef_t tex;
  1892. brushprimit_texdef_t brushprimit_tex;
  1893. my += g_qeglobals.d_texturewin.originy-g_qeglobals.d_texturewin.height;
  1894. Texture_StartPos ();
  1895. while (1)
  1896. {
  1897. q = Texture_NextPos (&x, &y);
  1898. if (!q)
  1899. break;
  1900. int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
  1901. int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
  1902. if (mx > x && mx - x < nWidth
  1903. && my < y && y - my < nHeight + FONT_HEIGHT)
  1904. {
  1905. if (bShift)
  1906. {
  1907. if (g_PrefsDlg.m_bHiColorTextures && q->shadername[0] != 0)
  1908. {
  1909. //CString s = "notepad ";
  1910. //s += q->shadername;
  1911. //WinExec(s, SW_SHOWNORMAL);
  1912. ViewShader(q->shadername, q->name);
  1913. }
  1914. }
  1915. memset (&tex, 0, sizeof(tex));
  1916. memset (&brushprimit_tex, 0, sizeof(brushprimit_tex));
  1917. if (g_qeglobals.m_bBrushPrimitMode)
  1918. {
  1919. // brushprimit fitted to a 2x2 texture
  1920. brushprimit_tex.coords[0][0] = 1.0f;
  1921. brushprimit_tex.coords[1][1] = 1.0f;
  1922. }
  1923. else
  1924. {
  1925. tex.scale[0] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
  1926. tex.scale[1] = (g_PrefsDlg.m_bHiColorTextures) ? 0.5 : 1;
  1927. }
  1928. tex.flags = q->flags;
  1929. tex.value = q->value;
  1930. tex.contents = q->contents;
  1931. //strcpy (tex.name, q->name);
  1932. tex.SetName(q->name);
  1933. Texture_SetTexture ( &tex, &brushprimit_tex, bFitScale, GETPLUGINTEXDEF(q));
  1934. CString strTex;
  1935. CString strName = q->name;
  1936. //int nPos = strName.Find('\\');
  1937. //if (nPos == -1)
  1938. // nPos = strName.Find('/');
  1939. //if (nPos >= 0)
  1940. // strName = strName.Right(strName.GetLength() - nPos - 1);
  1941. strTex.Format("%s W: %i H: %i", strName.GetBuffer(0), q->width, q->height);
  1942. g_pParentWnd->SetStatusText(3, strTex);
  1943. return;
  1944. }
  1945. }
  1946. Sys_Status("Did not select a texture\n", 0);
  1947. }
  1948. /*
  1949. ==============
  1950. Texture_MouseDown
  1951. ==============
  1952. */
  1953. void Texture_MouseDown (int x, int y, int buttons)
  1954. {
  1955. Sys_GetCursorPos (&textures_cursorx, &textures_cursory);
  1956. // lbutton = select texture
  1957. if (buttons == MK_LBUTTON || buttons == (MK_LBUTTON | MK_SHIFT) || buttons == (MK_LBUTTON | MK_CONTROL))
  1958. {
  1959. SelectTexture (x, g_qeglobals.d_texturewin.height - 1 - y, buttons & MK_SHIFT, buttons & MK_CONTROL);
  1960. UpdateSurfaceDialog();
  1961. UpdatePatchInspector();
  1962. }
  1963. }
  1964. /*
  1965. ==============
  1966. Texture_MouseUp
  1967. ==============
  1968. */
  1969. void Texture_MouseUp (int x, int y, int buttons)
  1970. {
  1971. }
  1972. /*
  1973. ==============
  1974. Texture_MouseMoved
  1975. ==============
  1976. */
  1977. void Texture_MouseMoved (int x, int y, int buttons)
  1978. {
  1979. int scale = 1;
  1980. if ( buttons & MK_SHIFT )
  1981. scale = 4;
  1982. // rbutton = drag texture origin
  1983. if (buttons & MK_RBUTTON)
  1984. {
  1985. Sys_GetCursorPos (&x, &y);
  1986. if ( y != textures_cursory)
  1987. {
  1988. g_qeglobals.d_texturewin.originy += ( y-textures_cursory) * scale;
  1989. if (g_qeglobals.d_texturewin.originy > 0)
  1990. g_qeglobals.d_texturewin.originy = 0;
  1991. Sys_SetCursorPos (textures_cursorx, textures_cursory);
  1992. CWnd *pWnd = CWnd::FromHandle(g_qeglobals.d_hwndTexture);
  1993. if (g_PrefsDlg.m_bTextureScrollbar && pWnd != NULL)
  1994. {
  1995. pWnd->SetScrollPos(SB_VERT, abs(g_qeglobals.d_texturewin.originy));
  1996. }
  1997. InvalidateRect(g_qeglobals.d_hwndTexture, NULL, false);
  1998. UpdateWindow (g_qeglobals.d_hwndTexture);
  1999. }
  2000. return;
  2001. }
  2002. }
  2003. /*
  2004. ============================================================================
  2005. DRAWING
  2006. ============================================================================
  2007. */
  2008. int imax(int iFloor, int i) { if (i>iFloor) return iFloor; return i; }
  2009. HFONT ghFont = NULL;
  2010. /*
  2011. ============
  2012. Texture_Draw2
  2013. ============
  2014. */
  2015. void Texture_Draw2 (int width, int height)
  2016. {
  2017. qtexture_t *q;
  2018. int x, y;
  2019. char *name;
  2020. qglClearColor (
  2021. g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][0],
  2022. g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][1],
  2023. g_qeglobals.d_savedinfo.colors[COLOR_TEXTUREBACK][2],
  2024. 0);
  2025. qglViewport (0,0,width,height);
  2026. qglMatrixMode(GL_PROJECTION);
  2027. qglLoadIdentity ();
  2028. qglClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  2029. qglDisable (GL_DEPTH_TEST);
  2030. qglDisable(GL_BLEND);
  2031. qglOrtho (0, width, g_qeglobals.d_texturewin.originy-height, g_qeglobals.d_texturewin.originy, -100, 100);
  2032. qglEnable (GL_TEXTURE_2D);
  2033. qglPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
  2034. g_qeglobals.d_texturewin.width = width;
  2035. g_qeglobals.d_texturewin.height = height;
  2036. Texture_StartPos ();
  2037. while (1)
  2038. {
  2039. q = Texture_NextPos (&x, &y);
  2040. if (!q)
  2041. break;
  2042. int nWidth = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->width * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->width;
  2043. int nHeight = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? q->height * ((float)g_PrefsDlg.m_nTextureScale / 100) : q->height;
  2044. // Is this texture visible?
  2045. if ( (y-nHeight-FONT_HEIGHT < g_qeglobals.d_texturewin.originy)
  2046. && (y > g_qeglobals.d_texturewin.originy - height) )
  2047. {
  2048. // if in use, draw a background
  2049. if ((q->inuse && !texture_showinuse) || q->bFromShader)
  2050. {
  2051. qglLineWidth (1);
  2052. if (q->bFromShader)
  2053. {
  2054. qglColor3f (1,1,1);
  2055. }
  2056. else
  2057. {
  2058. qglColor3f (0.5,1,0.5);
  2059. }
  2060. qglDisable (GL_TEXTURE_2D);
  2061. qglBegin (GL_LINE_LOOP);
  2062. qglVertex2f (x-1,y+1-FONT_HEIGHT);
  2063. qglVertex2f (x-1,y-nHeight-1-FONT_HEIGHT);
  2064. qglVertex2f (x+1+nWidth,y-nHeight-1-FONT_HEIGHT);
  2065. qglVertex2f (x+1+nWidth,y+1-FONT_HEIGHT);
  2066. qglEnd ();
  2067. qglEnable (GL_TEXTURE_2D);
  2068. }
  2069. // Draw the texture
  2070. float fScale = (g_PrefsDlg.m_bHiColorTextures == TRUE) ? ((float)g_PrefsDlg.m_nTextureScale / 100) : 1.0;
  2071. qglBindTexture( GL_TEXTURE_2D, q->texture_number );
  2072. QE_CheckOpenGLForErrors();
  2073. qglColor3f (1,1,1);
  2074. qglBegin (GL_QUADS);
  2075. qglTexCoord2f (0,0);
  2076. qglVertex2f (x,y-FONT_HEIGHT);
  2077. qglTexCoord2f (1,0);
  2078. qglVertex2f (x+nWidth,y-FONT_HEIGHT);
  2079. qglTexCoord2f (1,1);
  2080. qglVertex2f (x+nWidth,y-FONT_HEIGHT-nHeight);
  2081. qglTexCoord2f (0,1);
  2082. qglVertex2f (x,y-FONT_HEIGHT-nHeight);
  2083. qglEnd ();
  2084. // draw the selection border
  2085. if (!strcmpi(g_qeglobals.d_texturewin.texdef.name, q->name))
  2086. {
  2087. qglLineWidth (3);
  2088. qglColor3f (1,0,0);
  2089. qglDisable (GL_TEXTURE_2D);
  2090. qglBegin (GL_LINE_LOOP);
  2091. qglVertex2f (x-4,y-FONT_HEIGHT+4);
  2092. qglVertex2f (x-4,y-FONT_HEIGHT-nHeight-4);
  2093. qglVertex2f (x+4+nWidth,y-FONT_HEIGHT-nHeight-4);
  2094. qglVertex2f (x+4+nWidth,y-FONT_HEIGHT+4);
  2095. qglEnd ();
  2096. qglEnable (GL_TEXTURE_2D);
  2097. qglLineWidth (1);
  2098. }
  2099. // draw the texture name
  2100. qglColor3f (0,0,0);
  2101. qglRasterPos2f (x, y-FONT_HEIGHT+2);
  2102. // don't draw the directory name
  2103. for (name = q->name ; *name && *name != '/' && *name != '\\' ; name++)
  2104. ;
  2105. if (!*name)
  2106. name = q->name;
  2107. else
  2108. name++;
  2109. if (g_PrefsDlg.m_bHiColorTextures && q->shadername[0] != 0)
  2110. {
  2111. // slow as shit
  2112. CString s = "[";
  2113. s += name;
  2114. s += "]";
  2115. qglCallLists (s.GetLength(), GL_UNSIGNED_BYTE, s.GetBuffer(0));
  2116. }
  2117. else
  2118. {
  2119. qglCallLists (strlen(name), GL_UNSIGNED_BYTE, name);
  2120. }
  2121. }
  2122. }
  2123. g_qeglobals.d_texturewin.m_nTotalHeight = abs(y) + 100;
  2124. // reset the current texture
  2125. qglBindTexture( GL_TEXTURE_2D, 0 );
  2126. qglFinish();
  2127. }
  2128. void Texture_Init (bool bHardInit)
  2129. {
  2130. char name[1024];
  2131. byte *pal = NULL;
  2132. if (g_PrefsDlg.m_bHiColorTextures == FALSE)
  2133. {
  2134. // load the palette
  2135. sprintf (name, "%s/pics/colormap.pcx", ValueForKey (g_qeglobals.d_project_entity, "basepath"));
  2136. Load256Image (name, NULL, &pal, NULL, NULL);
  2137. if (!pal)
  2138. {
  2139. // before dropping out, try to load it from the QERadiant directory
  2140. CString strFile = g_strAppPath;
  2141. AddSlash(strFile);
  2142. strFile += "colormap.pcx";
  2143. Load256Image (strFile.GetBuffer(0), NULL, &pal, NULL, NULL);
  2144. if (!pal)
  2145. Sys_Printf ("Couldn't load %s or %s", name, strFile);
  2146. }
  2147. else
  2148. {
  2149. Texture_InitPalette (pal);
  2150. free (pal);
  2151. }
  2152. }
  2153. // create the fallback texture
  2154. if (bHardInit)
  2155. {
  2156. Texture_MakeNotexture();
  2157. g_qeglobals.d_qtextures = NULL;
  2158. }
  2159. LoadShaders();
  2160. }
  2161. void Texture_FlushUnused()
  2162. {
  2163. CWaitCursor cursor;
  2164. Texture_ShowInuse();
  2165. if (g_qeglobals.d_qtextures)
  2166. {
  2167. qtexture_t* pTex = g_qeglobals.d_qtextures->next;
  2168. qtexture_t *pPrev = g_qeglobals.d_qtextures;
  2169. while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
  2170. {
  2171. qtexture_t* pNextTex = pTex->next;
  2172. if (g_qeglobals.bSurfacePropertiesPlugin)
  2173. {
  2174. // Timo
  2175. // Surface properties plugin
  2176. #ifdef _DEBUG
  2177. if ( !pTex->pData )
  2178. Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
  2179. #endif
  2180. if ( pTex->pData && pTex->inuse )
  2181. GETPLUGINTEXDEF(pTex)->DecRef();
  2182. }
  2183. if (!pTex->inuse)
  2184. {
  2185. unsigned int nTexture = pTex->texture_number;
  2186. qglDeleteTextures(1, &nTexture);
  2187. pPrev->next = pNextTex;
  2188. free(pTex);
  2189. }
  2190. else
  2191. {
  2192. pPrev = pTex;
  2193. }
  2194. pTex = pNextTex;
  2195. }
  2196. }
  2197. }
  2198. void Texture_Cleanup(CStringList *pList)
  2199. {
  2200. if (g_qeglobals.d_qtextures)
  2201. {
  2202. qtexture_t* pTex = g_qeglobals.d_qtextures->next;
  2203. while (pTex != NULL && pTex != g_qeglobals.d_qtextures)
  2204. {
  2205. qtexture_t* pNextTex = pTex->next;
  2206. if (pList)
  2207. {
  2208. if (pTex->name[0] != '(')
  2209. {
  2210. pList->AddTail(pTex->name);
  2211. }
  2212. }
  2213. if (g_qeglobals.bSurfacePropertiesPlugin)
  2214. {
  2215. // Timo
  2216. // Surface properties plugin
  2217. #ifdef _DEBUG
  2218. if ( !pTex->pData )
  2219. Sys_Printf("WARNING: found a qtexture_t* with no IPluginQTexture\n");
  2220. #endif
  2221. if ( pTex->pData )
  2222. GETPLUGINTEXDEF(pTex)->DecRef();
  2223. }
  2224. free(pTex);
  2225. pTex = pNextTex;
  2226. }
  2227. }
  2228. int nSize = g_lstSkinCache.GetSize();
  2229. for (int i = 0; i < nSize; i++)
  2230. {
  2231. SkinInfo *pInfo = reinterpret_cast<SkinInfo*>(g_lstSkinCache.GetAt(i));
  2232. delete pInfo;
  2233. }
  2234. }
  2235. /*
  2236. ==================
  2237. Texture_Flush
  2238. ==================
  2239. */
  2240. void Texture_Flush (bool bReload)
  2241. {
  2242. if (!ConfirmModified())
  2243. return;
  2244. Map_New ();
  2245. CWaitCursor cursor;
  2246. CStringList strList;
  2247. Texture_Init(false);
  2248. Texture_Cleanup(&strList);
  2249. GLuint* pGln = new GLuint[texture_extension_number-1];
  2250. qglGenTextures(texture_extension_number-1, pGln);
  2251. QE_CheckOpenGLForErrors();
  2252. qglDeleteTextures(texture_extension_number-1, pGln);
  2253. QE_CheckOpenGLForErrors();
  2254. delete []pGln;
  2255. texture_extension_number = 1;
  2256. g_qeglobals.d_qtextures = NULL;
  2257. if (bReload)
  2258. {
  2259. POSITION pos = strList.GetHeadPosition();
  2260. while (pos)
  2261. {
  2262. CString strTex = strList.GetNext(pos);
  2263. Texture_ForName (strTex.GetBuffer(0));
  2264. }
  2265. }
  2266. }
  2267. /////////////////////////////////////////////////////////////////////////////
  2268. // CTexWnd
  2269. IMPLEMENT_DYNCREATE(CTexWnd, CWnd);
  2270. CTexWnd::CTexWnd()
  2271. {
  2272. m_bNeedRange = true;
  2273. }
  2274. CTexWnd::~CTexWnd()
  2275. {
  2276. }
  2277. BEGIN_MESSAGE_MAP(CTexWnd, CWnd)
  2278. //{{AFX_MSG_MAP(CTexWnd)
  2279. ON_WM_CREATE()
  2280. ON_WM_SIZE()
  2281. ON_WM_PARENTNOTIFY()
  2282. ON_WM_TIMER()
  2283. ON_WM_KEYDOWN()
  2284. ON_WM_KEYUP()
  2285. ON_WM_PAINT()
  2286. ON_WM_VSCROLL()
  2287. ON_COMMAND(ID_TEXTURES_FLUSH, OnTexturesFlush)
  2288. ON_BN_CLICKED(1200, OnShaderClick)
  2289. //}}AFX_MSG_MAP
  2290. END_MESSAGE_MAP()
  2291. /////////////////////////////////////////////////////////////////////////////
  2292. // CTexWnd message handlers
  2293. /*
  2294. ============
  2295. WTexWndProc
  2296. ============
  2297. */
  2298. LONG WINAPI TexWndProc (
  2299. HWND hWnd,
  2300. UINT uMsg,
  2301. WPARAM wParam,
  2302. LPARAM lParam)
  2303. {
  2304. int xPos, yPos;
  2305. RECT rect;
  2306. GetClientRect(hWnd, &rect);
  2307. switch (uMsg)
  2308. {
  2309. case WM_CREATE:
  2310. s_hdcTexture = GetDC(hWnd);
  2311. QEW_SetupPixelFormat(s_hdcTexture, false);
  2312. if ( ( s_hglrcTexture = qwglCreateContext( s_hdcTexture ) ) == 0 )
  2313. Error( "wglCreateContext in WTex_WndProc failed" );
  2314. if (!qwglShareLists( g_qeglobals.d_hglrcBase, s_hglrcTexture ) )
  2315. Error( "wglShareLists in WTex_WndProc failed" );
  2316. if (!qwglMakeCurrent( s_hdcTexture, s_hglrcTexture ))
  2317. Error ("wglMakeCurrent in WTex_WndProc failed");
  2318. g_qeglobals.d_hwndTexture = hWnd;
  2319. return 0;
  2320. case WM_DESTROY:
  2321. //wglMakeCurrent( NULL, NULL );
  2322. //wglDeleteContext( s_hglrcTexture );
  2323. ReleaseDC( hWnd, s_hdcTexture );
  2324. return 0;
  2325. #if 0
  2326. case WM_PAINT:
  2327. {
  2328. PAINTSTRUCT ps;
  2329. BeginPaint(hWnd, &ps);
  2330. if ( !qwglMakeCurrent( s_hdcTexture, s_hglrcTexture ) )
  2331. //if ( !wglMakeCurrent( ps.hdc, s_hglrcTexture ) )
  2332. {
  2333. Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
  2334. Sys_Printf("Please restart Q3Radiant if the Texture view is not working\n");
  2335. }
  2336. else
  2337. {
  2338. Texture_Draw2 (rect.right-rect.left, rect.bottom-rect.top - g_nTextureOffset);
  2339. qwglSwapBuffers(s_hdcTexture);
  2340. TRACE("Texture Paint\n");
  2341. }
  2342. EndPaint(hWnd, &ps);
  2343. }
  2344. return 0;
  2345. #endif
  2346. case WM_MBUTTONDOWN:
  2347. case WM_RBUTTONDOWN:
  2348. case WM_LBUTTONDOWN:
  2349. SetCapture( g_qeglobals.d_hwndTexture );
  2350. xPos = (short)LOWORD(lParam); // horizontal position of cursor
  2351. yPos = (short)HIWORD(lParam); // vertical position of cursor
  2352. Texture_MouseDown (xPos, yPos - g_nTextureOffset, wParam);
  2353. return 0;
  2354. case WM_MBUTTONUP:
  2355. case WM_RBUTTONUP:
  2356. case WM_LBUTTONUP:
  2357. xPos = (short)LOWORD(lParam); // horizontal position of cursor
  2358. yPos = (short)HIWORD(lParam); // vertical position of cursor
  2359. Texture_MouseUp (xPos, yPos - g_nTextureOffset, wParam);
  2360. if (! (wParam & (MK_LBUTTON|MK_RBUTTON|MK_MBUTTON)))
  2361. ReleaseCapture ();
  2362. return 0;
  2363. case WM_MOUSEMOVE:
  2364. xPos = (short)LOWORD(lParam); // horizontal position of cursor
  2365. yPos = (short)HIWORD(lParam); // vertical position of cursor
  2366. Texture_MouseMoved (xPos, yPos - g_nTextureOffset, wParam);
  2367. return 0;
  2368. }
  2369. return DefWindowProc (hWnd, uMsg, wParam, lParam);
  2370. }
  2371. BOOL CTexWnd::PreCreateWindow(CREATESTRUCT& cs)
  2372. {
  2373. WNDCLASS wc;
  2374. HINSTANCE hInstance = AfxGetInstanceHandle();
  2375. if (::GetClassInfo(hInstance, TEXTURE_WINDOW_CLASS, &wc) == FALSE)
  2376. {
  2377. // Register a new class
  2378. memset (&wc, 0, sizeof(wc));
  2379. wc.style = CS_NOCLOSE | CS_OWNDC;
  2380. wc.lpszClassName = TEXTURE_WINDOW_CLASS;
  2381. wc.hCursor = LoadCursor (NULL,IDC_ARROW);
  2382. wc.lpfnWndProc = TexWndProc;
  2383. if (AfxRegisterClass(&wc) == FALSE)
  2384. Error ("CZWnd RegisterClass: failed");
  2385. }
  2386. cs.lpszClass = TEXTURE_WINDOW_CLASS;
  2387. cs.lpszName = "TEX";
  2388. if (cs.style != QE3_CHILDSTYLE && cs.style != QE3_STYLE)
  2389. cs.style = QE3_SPLITTER_STYLE;
  2390. return CWnd::PreCreateWindow(cs);
  2391. }
  2392. int CTexWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
  2393. {
  2394. if (CWnd::OnCreate(lpCreateStruct) == -1)
  2395. return -1;
  2396. CRect rctEdit(8, 5, 20, 20);
  2397. g_nTextureOffset = 0;
  2398. /*
  2399. if (g_PrefsDlg.m_bShaderTest)
  2400. {
  2401. m_wndShaders.Create("Show Shaders", WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX, rctEdit, this, 1200);
  2402. m_wndShaders.ModifyStyleEx(0, WS_EX_CLIENTEDGE, 0);
  2403. m_wndShaders.SetCheck(g_PrefsDlg.m_bShowShaders);
  2404. g_nTextureOffset = 25;
  2405. }
  2406. */
  2407. rctEdit.SetRect(8, g_nTextureOffset, 20, 20);
  2408. m_wndFilter.Create(WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_LEFT, rctEdit, this, 1201);
  2409. m_wndFilter.ModifyStyleEx(0, WS_EX_CLIENTEDGE, 0);
  2410. m_wndFilter.SetTexWnd(this);
  2411. g_nTextureOffset += 25;
  2412. if (!g_PrefsDlg.m_bTextureWindow)
  2413. {
  2414. m_wndFilter.ShowWindow(SW_HIDE);
  2415. g_nTextureOffset -= 25;
  2416. }
  2417. ShowScrollBar(SB_VERT, g_PrefsDlg.m_bTextureScrollbar);
  2418. m_bNeedRange = true;
  2419. return 0;
  2420. }
  2421. void CTexWnd::OnSize(UINT nType, int cx, int cy)
  2422. {
  2423. CWnd::OnSize(nType, cx, cy);
  2424. CRect rctClient;
  2425. GetClientRect(rctClient);
  2426. /*
  2427. if (g_PrefsDlg.m_bShaderTest && m_wndShaders.GetSafeHwnd())
  2428. {
  2429. m_wndShaders.SetWindowPos(NULL, rctClient.left + 8, rctClient.top + 5, rctClient.right - 16, 20, 0);
  2430. }
  2431. */
  2432. m_wndFilter.SetWindowPos(NULL, rctClient.left + 8, rctClient.top + 25, rctClient.right - 16, 20, 0);
  2433. m_bNeedRange = true;
  2434. }
  2435. void CTexWnd::OnShaderClick()
  2436. {
  2437. g_PrefsDlg.m_bShowShaders = (m_wndShaders.GetCheck() != 0);
  2438. g_PrefsDlg.SavePrefs();
  2439. RedrawWindow();
  2440. }
  2441. void CTexWnd::OnParentNotify(UINT message, LPARAM lParam)
  2442. {
  2443. CWnd::OnParentNotify(message, lParam);
  2444. }
  2445. int g_nLastLen = 0;
  2446. int g_nTimerHandle = -1;
  2447. char g_cLastChar;
  2448. void CTexWnd::UpdateFilter(const char* pFilter)
  2449. {
  2450. if (g_nTimerHandle > 0)
  2451. KillTimer(1);
  2452. g_bFilterEnabled = false;
  2453. if (pFilter)
  2454. {
  2455. g_strFilter = pFilter;
  2456. if (g_strFilter.GetLength() > 0)
  2457. {
  2458. g_bFilterEnabled = true;
  2459. if (g_pParentWnd->CurrentStyle() == QR_QE4 || g_pParentWnd->CurrentStyle() == QR_4WAY)
  2460. {
  2461. if (g_strFilter.GetLength() > g_nLastLen)
  2462. {
  2463. g_cLastChar = toupper(g_strFilter.GetAt(g_strFilter.GetLength()-1));
  2464. if (g_cLastChar == 'N' || g_cLastChar == 'O') // one of the other popups
  2465. {
  2466. g_nTimerHandle = SetTimer(1, 800, NULL); // half second timer
  2467. }
  2468. }
  2469. }
  2470. }
  2471. g_nLastLen = g_strFilter.GetLength();
  2472. SortTextures();
  2473. }
  2474. Sys_UpdateWindows (W_TEXTURE);
  2475. }
  2476. void CTexWnd::UpdatePrefs()
  2477. {
  2478. if (!g_PrefsDlg.m_bTextureWindow)
  2479. {
  2480. m_wndFilter.ShowWindow(SW_HIDE);
  2481. g_nTextureOffset = 0;
  2482. }
  2483. else
  2484. {
  2485. m_wndFilter.ShowWindow(SW_SHOW);
  2486. g_nTextureOffset = 25;
  2487. }
  2488. ShowScrollBar(SB_VERT, g_PrefsDlg.m_bTextureScrollbar);
  2489. m_bNeedRange = true;
  2490. Invalidate();
  2491. UpdateWindow();
  2492. }
  2493. void CTexWnd::FocusEdit()
  2494. {
  2495. if (m_wndFilter.IsWindowVisible())
  2496. m_wndFilter.SetFocus();
  2497. }
  2498. void CTexWnd::OnTimer(UINT nIDEvent)
  2499. {
  2500. KillTimer(1);
  2501. g_nLastLen = 0;
  2502. g_nTimerHandle = -1;
  2503. ::SetFocus(g_qeglobals.d_hwndEntity);
  2504. ::PostMessage(g_qeglobals.d_hwndEntity, WM_CHAR, g_cLastChar, 0);
  2505. }
  2506. void CTexWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  2507. {
  2508. g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags);
  2509. //CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
  2510. }
  2511. void CTexWnd::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  2512. {
  2513. g_pParentWnd->HandleKey(nChar, nRepCnt, nFlags, false);
  2514. }
  2515. void CTexWnd::OnPaint()
  2516. {
  2517. CPaintDC dc(this); // device context for painting
  2518. CRect rctClient;
  2519. GetClientRect(rctClient);
  2520. int nOld = g_qeglobals.d_texturewin.m_nTotalHeight;
  2521. if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
  2522. //if ( !qwglMakeCurrent(dc.m_hDC, s_hglrcTexture ) )
  2523. {
  2524. Sys_Printf("ERROR: wglMakeCurrent failed..\n ");
  2525. Sys_Printf("Please restart Q3Radiant if the Texture view is not working\n");
  2526. }
  2527. else
  2528. {
  2529. Texture_Draw2 (rctClient.right-rctClient.left, rctClient.bottom-rctClient.top - g_nTextureOffset);
  2530. qwglSwapBuffers(s_hdcTexture);
  2531. TRACE("Texture Paint\n");
  2532. }
  2533. if (g_PrefsDlg.m_bTextureScrollbar && (m_bNeedRange || g_qeglobals.d_texturewin.m_nTotalHeight != nOld))
  2534. {
  2535. m_bNeedRange = false;
  2536. SetScrollRange(SB_VERT, 0, g_qeglobals.d_texturewin.m_nTotalHeight, TRUE);
  2537. }
  2538. }
  2539. void CTexWnd::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  2540. {
  2541. CWnd::OnVScroll(nSBCode, nPos, pScrollBar);
  2542. int n = GetScrollPos(SB_VERT);;
  2543. switch (nSBCode)
  2544. {
  2545. case SB_LINEUP :
  2546. {
  2547. n = (n - 15 > 0) ? n - 15 : 0;
  2548. break;
  2549. }
  2550. case SB_LINEDOWN :
  2551. {
  2552. n = (n + 15 < g_qeglobals.d_texturewin.m_nTotalHeight) ? n + 15 : n;
  2553. break;
  2554. }
  2555. case SB_PAGEUP :
  2556. {
  2557. n = (n - g_qeglobals.d_texturewin.height > 0) ? n - g_qeglobals.d_texturewin.height : 0;
  2558. break;
  2559. }
  2560. case SB_PAGEDOWN :
  2561. {
  2562. n = (n + g_qeglobals.d_texturewin.height < g_qeglobals.d_texturewin.m_nTotalHeight) ? n + g_qeglobals.d_texturewin.height : n;
  2563. break;
  2564. }
  2565. case SB_THUMBPOSITION :
  2566. {
  2567. n = nPos;
  2568. break;
  2569. }
  2570. case SB_THUMBTRACK :
  2571. {
  2572. n = nPos;
  2573. break;
  2574. }
  2575. }
  2576. SetScrollPos(SB_VERT, n);
  2577. g_qeglobals.d_texturewin.originy = -((int)n);
  2578. Invalidate();
  2579. UpdateWindow();
  2580. //Sys_UpdateWindows(W_TEXTURE);
  2581. }
  2582. /*
  2583. and are the caps new caps? anything done with older stuff will be fubar'd.. which brings up the point if you ever naturalize a cap, you cannot force it back to cap texturing.. i will add that too
  2584. */
  2585. void CTexWnd::OnTexturesFlush()
  2586. {
  2587. // TODO: Add your command handler code here
  2588. }
  2589. void LoadShaders()
  2590. {
  2591. char dirstring[1024];
  2592. char *path;
  2593. //struct _finddata_t fileinfo;
  2594. //int handle;
  2595. path = ValueForKey (g_qeglobals.d_project_entity, "basepath");
  2596. sprintf (dirstring, "%s/scripts/shaderlist.txt", path);
  2597. char *pBuff = NULL;
  2598. int nLen = LoadFile(dirstring, reinterpret_cast<void**>(&pBuff));
  2599. if (nLen == -1)
  2600. {
  2601. nLen = PakLoadAnyFile(dirstring, reinterpret_cast<void**>(&pBuff));
  2602. }
  2603. if (nLen > 0)
  2604. {
  2605. CStringList lst;
  2606. StartTokenParsing(pBuff);
  2607. nLen = 0;
  2608. while (GetToken(true))
  2609. {
  2610. // each token should be a shader filename
  2611. sprintf(dirstring, "%s/scripts/%s.shader", path, token);
  2612. lst.AddTail(dirstring);
  2613. nLen++;
  2614. }
  2615. POSITION pos = lst.GetHeadPosition();
  2616. while (pos != NULL)
  2617. {
  2618. LoadShader(lst.GetAt(pos).GetBuffer(0), NULL);
  2619. lst.GetNext(pos);
  2620. }
  2621. free(pBuff);
  2622. }
  2623. else
  2624. {
  2625. Sys_Printf("Unable to load shaderlist.txt, shaders not loaded!");
  2626. }
  2627. /*
  2628. handle = _findfirst (dirstring, &fileinfo);
  2629. if (handle != -1)
  2630. {
  2631. do
  2632. {
  2633. if ((fileinfo.attrib & _A_SUBDIR))
  2634. continue;
  2635. sprintf(dirstring, "%s/scripts/%s", path, fileinfo.name);
  2636. LoadShader(dirstring, NULL);
  2637. } while (_findnext( handle, &fileinfo ) != -1);
  2638. _findclose (handle);
  2639. }
  2640. */
  2641. }
  2642. void FreeShaders()
  2643. {
  2644. int nSize = g_lstShaders.GetSize();
  2645. for (int i = 0; i < nSize; i++)
  2646. {
  2647. CShaderInfo *pInfo = reinterpret_cast<CShaderInfo*>(g_lstShaders.ElementAt(i));
  2648. delete pInfo;
  2649. }
  2650. g_lstShaders.RemoveAll();
  2651. }
  2652. void ReloadShaders()
  2653. {
  2654. FreeShaders();
  2655. LoadShaders();
  2656. qtexture_t* pTex = g_qeglobals.d_qtextures;
  2657. while (pTex != NULL)
  2658. {
  2659. SetNameShaderInfo(pTex, NULL, pTex->name);
  2660. pTex = pTex->next;
  2661. }
  2662. }
  2663. int WINAPI Texture_LoadSkin(char *pName, int *pnWidth, int *pnHeight)
  2664. {
  2665. byte *pic = NULL;
  2666. byte *pic32 = NULL;
  2667. int nTex = -1;
  2668. strlwr(pName);
  2669. QE_ConvertDOSToUnixName(pName, pName);
  2670. int nSize = g_lstSkinCache.GetSize();
  2671. for (int i = 0; i < nSize; i++)
  2672. {
  2673. SkinInfo *pInfo = reinterpret_cast<SkinInfo*>(g_lstSkinCache.GetAt(i));
  2674. if (pInfo)
  2675. {
  2676. if (stricmp(pName, pInfo->m_strName) == 0)
  2677. {
  2678. return pInfo->m_nTextureBind;
  2679. }
  2680. }
  2681. }
  2682. LoadImage( pName, &pic32, pnWidth, pnHeight);
  2683. if (pic32 != NULL)
  2684. {
  2685. nTex = texture_extension_number++;
  2686. if (g_PrefsDlg.m_bSGIOpenGL)
  2687. {
  2688. //if (!qwglMakeCurrent(g_qeglobals.d_hdcBase, g_qeglobals.d_hglrcBase))
  2689. if (!qwglMakeCurrent(s_hdcTexture, s_hglrcTexture))
  2690. Error ("wglMakeCurrent in LoadTexture failed");
  2691. }
  2692. qglBindTexture( GL_TEXTURE_2D, nTex);
  2693. SetTexParameters ();
  2694. int nCount = MAX_TEXTURE_QUALITY - g_PrefsDlg.m_nTextureQuality;
  2695. while (nCount-- > 0)
  2696. {
  2697. if (*pnWidth > 16 && *pnHeight > 16)
  2698. {
  2699. R_MipMap(pic32, *pnWidth, *pnHeight);
  2700. }
  2701. else
  2702. {
  2703. break;
  2704. }
  2705. }
  2706. if (g_PrefsDlg.m_bSGIOpenGL)
  2707. {
  2708. if (nomips)
  2709. {
  2710. qglTexImage2D(GL_TEXTURE_2D, 0, 3, *pnWidth, *pnHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic32);
  2711. }
  2712. else
  2713. qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, *pnWidth, *pnHeight,GL_RGBA, GL_UNSIGNED_BYTE, pic32);
  2714. }
  2715. else
  2716. {
  2717. if (nomips)
  2718. qglTexImage2D(GL_TEXTURE_2D, 0, 3, *pnWidth, *pnHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, pic32);
  2719. else
  2720. qgluBuild2DMipmaps(GL_TEXTURE_2D, 3, *pnWidth, *pnHeight,GL_RGBA, GL_UNSIGNED_BYTE, pic32);
  2721. }
  2722. free (pic32);
  2723. qglBindTexture( GL_TEXTURE_2D, 0 );
  2724. }
  2725. SkinInfo *pInfo = new SkinInfo(pName, nTex);
  2726. g_lstSkinCache.Add(pInfo);
  2727. return nTex;
  2728. }