ECLASS.CPP 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933
  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. #include "stdafx.h"
  19. #include "qe3.h"
  20. #include "io.h"
  21. #include "pakstuff.h"
  22. //#include "qertypes.h"
  23. eclass_t *eclass = NULL;
  24. eclass_t *eclass_bad = NULL;
  25. char eclass_directory[1024];
  26. // md3 cache for misc_models
  27. eclass_t *g_md3Cache = NULL;
  28. /*
  29. the classname, color triple, and bounding box are parsed out of comments
  30. A ? size means take the exact brush size.
  31. /*QUAKED <classname> (0 0 0) ?
  32. /*QUAKED <classname> (0 0 0) (-8 -8 -8) (8 8 8)
  33. Flag names can follow the size description:
  34. /*QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY
  35. */
  36. void CleanEntityList(eclass_t *&pList)
  37. {
  38. while (pList)
  39. {
  40. eclass_t* pTemp = pList->next;
  41. entitymodel *model = pList->model;
  42. while (model != NULL)
  43. {
  44. delete []model->pTriList;
  45. model = model->pNext;
  46. }
  47. if (pList->modelpath)
  48. free(pList->modelpath);
  49. if (pList->skinpath) // PGM
  50. free(pList->skinpath); // PGM
  51. free(pList->name);
  52. free(pList->comments);
  53. free(pList);
  54. pList = pTemp;
  55. }
  56. pList = NULL;
  57. }
  58. void CleanUpEntities()
  59. {
  60. CleanEntityList(eclass);
  61. CleanEntityList(g_md3Cache);
  62. /*
  63. while (eclass)
  64. {
  65. eclass_t* pTemp = eclass->next;
  66. delete []eclass->pTriList;
  67. if (eclass->modelpath)
  68. free(eclass->modelpath);
  69. if (eclass->skinpath) // PGM
  70. free(eclass->skinpath); // PGM
  71. free(eclass->name);
  72. free(eclass->comments);
  73. free(eclass);
  74. eclass = pTemp;
  75. }
  76. eclass = NULL;
  77. */
  78. if (eclass_bad)
  79. {
  80. free(eclass_bad->name);
  81. free(eclass_bad->comments);
  82. free(eclass_bad);
  83. eclass_bad = NULL;
  84. }
  85. }
  86. void ExtendBounds(vec3_t v, vec3_t &vMin, vec3_t &vMax)
  87. {
  88. for (int i = 0 ;i < 3 ;i++)
  89. {
  90. vec_t f = v[i];
  91. if (f < vMin[i])
  92. {
  93. vMin[i] = f;
  94. }
  95. if (f > vMax[i])
  96. {
  97. vMax[i] = f;
  98. }
  99. }
  100. }
  101. // FIXME: this code is a TOTAL clusterfuck
  102. //
  103. void LoadModel(const char *pLocation, eclass_t *e, vec3_t &vMin, vec3_t &vMax, entitymodel *&pModel, const char *pSkin)
  104. {
  105. // this assumes a path only and uses tris.md2
  106. // for the model and skin.pcx for the skin
  107. char cPath[1024];
  108. char cSkin[1024];
  109. char cFullLocation[1024];
  110. //struct _finddata_t fileinfo;
  111. vMin[0] = vMin[1] = vMin[2] = 99999;
  112. vMax[0] = vMax[1] = vMax[2] = -99999;
  113. bool bMD3 = false;
  114. bool bASE = false;
  115. strcpy( cFullLocation, pLocation );
  116. if (strstr(pLocation, ".md3"))
  117. {
  118. bMD3 = true;
  119. }
  120. else if (strstr(pLocation, ".md2") != NULL)
  121. {
  122. sprintf( cFullLocation, "%stris.md2", pLocation);
  123. }
  124. else if (strstr(pLocation, ".ase") != NULL)
  125. {
  126. bASE = true;
  127. }
  128. sprintf( cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cFullLocation);
  129. Sys_Printf("Loading model %s...", cPath);
  130. unsigned char* p = NULL;
  131. bool bOpen = (LoadFile(cPath, reinterpret_cast<void**>(&p)) > 0);
  132. if (!bOpen)
  133. {
  134. Sys_Printf(" failed. Trying PAK file...");
  135. // sprintf (cPath, "%stris.md2", pLocation);
  136. strcpy (cPath, cFullLocation);
  137. bOpen = (PakLoadAnyFile(cPath, reinterpret_cast<void**>(&p)) > 0);
  138. }
  139. if (bOpen)
  140. {
  141. Sys_Printf(" successful.\n");
  142. if (bASE)
  143. {
  144. /*
  145. free(p);
  146. CString strOut;
  147. ::GetTempPath(1024, strOut.GetBuffer(1024));
  148. strOut.ReleaseBuffer();
  149. AddSlash(strOut);
  150. strOut += "Temp.ase";
  151. CopyFile(cPath, strOut, false);
  152. CString strIn = strOut;
  153. FindReplace(strOut, ".ase", ".md3");
  154. strcpy(cPath, strIn);
  155. strcpy(cSkin, strOut);
  156. Q3Data_ProduceTempMD3(ValueForKey(g_qeglobals.d_project_entity, "basepath"), cPath, cSkin);
  157. CString strModel = cPath;
  158. if (LoadFile(strOut.GetBuffer(0), reinterpret_cast<void**>(&p)) == 0)
  159. {
  160. Sys_Printf(" Conversion from ASE failed.\n");
  161. return;
  162. }
  163. bMD3 = true;
  164. */
  165. }
  166. if (bMD3)
  167. {
  168. md3Header_t header;
  169. md3Surface_t *pSurface;
  170. header = *(md3Header_t *)p;
  171. if (pSkin != NULL)
  172. {
  173. strcpy(cSkin, pSkin);
  174. }
  175. else
  176. {
  177. cSkin[0] = '\0';
  178. }
  179. int n = header.numFrames;
  180. pSurface = (md3Surface_t *) (p + header.ofsSurfaces);
  181. for (int z = 0; z < header.numSurfaces; z++ )
  182. {
  183. int nTris = pSurface->numTriangles;
  184. //unsigned char* pTris = reinterpret_cast<unsigned char*>(pSurface);
  185. //pTris += pSurface->ofsTriangles;
  186. if (nTris > 0)
  187. {
  188. int nStart = 0;
  189. if (pModel->pTriList == NULL)
  190. {
  191. pModel->nModelPosition = 0;
  192. pModel->pTriList = new trimodel[nTris];
  193. pModel->nTriCount = nTris;
  194. }
  195. else
  196. {
  197. // already have one so we need to reallocate
  198. int nNewCount = pModel->nTriCount + nTris;
  199. trimodel* pNewModels = new trimodel[nNewCount];
  200. for (int i = 0; i < pModel->nTriCount; i++)
  201. {
  202. memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
  203. }
  204. nStart = pModel->nTriCount;
  205. pModel->nTriCount = nNewCount;
  206. //nTris = nNewCount;
  207. delete [] pModel->pTriList;
  208. pModel->pTriList = pNewModels;
  209. }
  210. md3Triangle_t *pTris = reinterpret_cast<md3Triangle_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsTriangles));
  211. md3XyzNormal_t *pXyz = reinterpret_cast<md3XyzNormal_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsXyzNormals));
  212. if (e->nFrame < pSurface->numFrames)
  213. {
  214. pXyz += (e->nFrame * pSurface->numVerts);
  215. }
  216. md3St_t *pST = reinterpret_cast<md3St_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsSt));
  217. for (int i = 0; i < nTris; i++)
  218. {
  219. for (int k = 0; k < 3; k ++)
  220. {
  221. for (int j = 0; j < 3; j++)
  222. {
  223. //e->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
  224. pModel->pTriList[nStart].v[k][j] = pXyz[pTris[i].indexes[k]].xyz[j] * MD3_XYZ_SCALE;
  225. }
  226. pModel->pTriList[nStart].st[k][0] = pST[pTris[i].indexes[k]].st[0];
  227. pModel->pTriList[nStart].st[k][1] = pST[pTris[i].indexes[k]].st[1];
  228. ExtendBounds (pModel->pTriList[nStart].v[k], vMin, vMax);
  229. }
  230. nStart++;
  231. }
  232. }
  233. md3Shader_t *pShader = reinterpret_cast<md3Shader_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsShaders));
  234. sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pShader->name);
  235. strlwr(cPath);
  236. pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
  237. if (pModel->nTextureBind == -1)
  238. {
  239. Sys_Printf("Model skin load failed on texture %s\n", cPath);
  240. }
  241. pSurface = (md3Surface_t *) ((( char * ) pSurface) + pSurface->ofsEnd);
  242. pModel->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
  243. pModel = pModel->pNext;
  244. }
  245. }
  246. else
  247. {
  248. dmdl_t model;
  249. daliasframe_t *f;
  250. unsigned char* pTris = p;
  251. dstvert_t *pST = NULL;
  252. int nTris = 0;
  253. // grab model params
  254. memcpy(&model, p, sizeof(dmdl_t));
  255. f = (daliasframe_t*)(p + model.ofs_frames);
  256. pTris += model.ofs_tris;
  257. pST = reinterpret_cast<dstvert_t*>(p + model.ofs_st);
  258. nTris = model.num_tris;
  259. if(pSkin)
  260. {
  261. strcpy (cSkin, pSkin);
  262. if ((cSkin[strlen(cSkin)-1] == '\\') || (cSkin[strlen(cSkin)-1] == '/'))
  263. strcat(cSkin, "skin.pcx\0");
  264. }
  265. else
  266. {
  267. strcpy(cSkin, (char *)(p + model.ofs_skins));
  268. }
  269. sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
  270. strlwr(cPath);
  271. pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
  272. if (pModel->nTextureBind == -1)
  273. {
  274. Sys_Printf("Model skin load failed on texture %s\n", cPath);
  275. }
  276. int nStart = 0;
  277. if (pModel->pTriList == NULL)
  278. {
  279. pModel->nModelPosition = 0;
  280. pModel->pTriList = new trimodel[nTris];
  281. pModel->nTriCount = nTris;
  282. }
  283. else
  284. {
  285. // already have one so we need to reallocate
  286. int nNewCount = pModel->nTriCount + nTris;
  287. trimodel* pNewModels = new trimodel[nNewCount];
  288. for (int i = 0; i < pModel->nTriCount; i++)
  289. {
  290. memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
  291. }
  292. nStart = pModel->nTriCount;
  293. pModel->nTriCount = nNewCount;
  294. nTris = nNewCount;
  295. delete [] pModel->pTriList;
  296. pModel->pTriList = pNewModels;
  297. }
  298. for (int i = nStart; i < nTris; i++)
  299. {
  300. dtriangle_t tri;
  301. memcpy(&tri, pTris, sizeof(dtriangle_t));
  302. for (int k = 0; k < 3; k ++)
  303. {
  304. for (int j = 0; j < 3; j++)
  305. {
  306. pModel->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
  307. }
  308. pModel->pTriList[i].st[k][0] = pST[tri.index_st[k]].s / pModel->nSkinWidth;
  309. pModel->pTriList[i].st[k][1] = pST[tri.index_st[k]].t / pModel->nSkinHeight;;
  310. ExtendBounds (pModel->pTriList[i].v[k], vMin, vMax);
  311. }
  312. pTris += sizeof(dtriangle_t);
  313. }
  314. }
  315. free(p);
  316. }
  317. else
  318. {
  319. Sys_Printf(" failed.\n");
  320. }
  321. #if 0
  322. if (pModel->pTriList != NULL && pModel->nTriCount > 0 && !bMD3)
  323. {
  324. if(fabs(vMin[2]) < ((vMax[2]-vMin[2]) / 10.0)) // > 90% above 0 point.
  325. pModel->nModelPosition = 1;
  326. // sprintf (cPath, "%s/%sskin.pcx", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pLocation);
  327. sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
  328. pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
  329. if (pModel->nTextureBind == -1)
  330. {
  331. // sprintf (cPath, "%sskin.pcx", pLocation);
  332. strcpy (cPath, cSkin);
  333. pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
  334. }
  335. }
  336. #endif
  337. }
  338. void setSpecialLoad(eclass_t *e, const char* pWhat, char*& p)
  339. {
  340. CString str = e->comments;
  341. int n = str.Find(pWhat);
  342. if (n >= 0)
  343. {
  344. char* pText = e->comments + n + strlen(pWhat);
  345. if (*pText == '\"')
  346. pText++;
  347. str = "";
  348. while (*pText != '\"' && *pText != '\0')
  349. {
  350. str += *pText;
  351. pText++;
  352. }
  353. if (str.GetLength() > 0)
  354. {
  355. p = strdup(str);
  356. //--LoadModel(str, e);
  357. }
  358. }
  359. }
  360. char *debugname;
  361. eclass_t *Eclass_InitFromText (char *text)
  362. {
  363. char *t;
  364. int len;
  365. int r, i;
  366. char parms[256], *p;
  367. eclass_t *e;
  368. char color[128];
  369. e = (eclass_t*)qmalloc(sizeof(*e));
  370. memset (e, 0, sizeof(*e));
  371. text += strlen("/*QUAKED ");
  372. // grab the name
  373. text = COM_Parse (text);
  374. e->name = (char*)qmalloc (strlen(com_token)+1);
  375. strcpy (e->name, com_token);
  376. debugname = e->name;
  377. // grab the color, reformat as texture name
  378. r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);
  379. if (r != 3)
  380. return e;
  381. sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);
  382. //strcpy (e->texdef.name, color);
  383. e->texdef.SetName(color);
  384. while (*text != ')')
  385. {
  386. if (!*text)
  387. return e;
  388. text++;
  389. }
  390. text++;
  391. // get the size
  392. text = COM_Parse (text);
  393. if (com_token[0] == '(')
  394. { // parse the size as two vectors
  395. e->fixedsize = true;
  396. r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],
  397. &e->maxs[0], &e->maxs[1], &e->maxs[2]);
  398. if (r != 6)
  399. return e;
  400. for (i=0 ; i<2 ; i++)
  401. {
  402. while (*text != ')')
  403. {
  404. if (!*text)
  405. return e;
  406. text++;
  407. }
  408. text++;
  409. }
  410. }
  411. else
  412. { // use the brushes
  413. }
  414. // get the flags
  415. // copy to the first /n
  416. p = parms;
  417. while (*text && *text != '\n')
  418. *p++ = *text++;
  419. *p = 0;
  420. text++;
  421. // any remaining words are parm flags
  422. p = parms;
  423. for (i=0 ; i<8 ; i++)
  424. {
  425. p = COM_Parse (p);
  426. if (!p)
  427. break;
  428. strcpy (e->flagnames[i], com_token);
  429. }
  430. // find the length until close comment
  431. for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)
  432. ;
  433. // copy the comment block out
  434. len = t-text;
  435. e->comments = (char*)qmalloc (len+1);
  436. memcpy (e->comments, text, len);
  437. #if 0
  438. for (i=0 ; i<len ; i++)
  439. if (text[i] == '\n')
  440. e->comments[i] = '\r';
  441. else
  442. e->comments[i] = text[i];
  443. #endif
  444. e->comments[len] = 0;
  445. setSpecialLoad(e, "model=", e->modelpath);
  446. setSpecialLoad(e, "skin=", e->skinpath);
  447. char *pFrame = NULL;
  448. setSpecialLoad(e, "frame=", pFrame);
  449. if (pFrame != NULL)
  450. {
  451. e->nFrame = atoi(pFrame);
  452. }
  453. if(!e->skinpath)
  454. setSpecialLoad(e, "texture=", e->skinpath);
  455. // setup show flags
  456. e->nShowFlags = 0;
  457. if (strcmpi(e->name, "light") == 0)
  458. {
  459. e->nShowFlags |= ECLASS_LIGHT;
  460. }
  461. if ( (strnicmp(e->name, "info_player", strlen("info_player")) == 0)
  462. ||(strnicmp(e->name, "path_corner", strlen("path_corner")) == 0)
  463. ||(strnicmp(e->name, "team_ctf", strlen("team_ctf")) == 0) )
  464. {
  465. e->nShowFlags |= ECLASS_ANGLE;
  466. }
  467. if (strcmpi(e->name, "path") == 0)
  468. {
  469. e->nShowFlags |= ECLASS_PATH;
  470. }
  471. if (strcmpi(e->name, "misc_model") == 0)
  472. {
  473. e->nShowFlags |= ECLASS_MISCMODEL;
  474. }
  475. return e;
  476. }
  477. qboolean Eclass_hasModel(eclass_t *e, vec3_t &vMin, vec3_t &vMax)
  478. {
  479. if (e->modelpath != NULL)
  480. {
  481. if (e->model == NULL)
  482. {
  483. e->model = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
  484. }
  485. char *pModelBuff = strdup(e->modelpath);
  486. char *pSkinBuff = NULL;
  487. if (e->skinpath)
  488. {
  489. pSkinBuff = strdup(e->skinpath);
  490. }
  491. CStringList Models;
  492. CStringList Skins;
  493. char* pToken = strtok(pModelBuff, ";\0");
  494. while (pToken != NULL)
  495. {
  496. Models.AddTail(pToken);
  497. pToken = strtok(NULL, ";\0");
  498. }
  499. if (pSkinBuff != NULL)
  500. {
  501. pToken = strtok(pSkinBuff, ";\0");
  502. while (pToken != NULL)
  503. {
  504. Skins.AddTail(pToken);
  505. pToken = strtok(NULL, ";\0");
  506. }
  507. }
  508. entitymodel *model = e->model;
  509. for (int i = 0; i < Models.GetCount(); i++)
  510. {
  511. char *pSkin = NULL;
  512. if (i < Skins.GetCount())
  513. {
  514. pSkin = Skins.GetAt(Skins.FindIndex(i)).GetBuffer(0);
  515. }
  516. LoadModel(Models.GetAt(Models.FindIndex(i)), e, vMin, vMax, model, pSkin);
  517. model->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
  518. model = model->pNext;
  519. }
  520. // at this poitn vMin and vMax contain the min max of the model
  521. // which needs to be centered at origin 0, 0, 0
  522. VectorSnap(vMin);
  523. VectorSnap(vMax);
  524. if (vMax[0] - vMin[0] < 2)
  525. {
  526. vMin[0] -= 1;
  527. vMax[0] += 1;
  528. }
  529. if (vMin[1] - vMax[1] < 2)
  530. {
  531. vMin[1] -= 1;
  532. vMax[1] += 1;
  533. }
  534. if (vMax[2] - vMin[2] < 2)
  535. {
  536. vMax[2] -= 1;
  537. vMax[2] += 1;
  538. }
  539. vec3_t vTemp;
  540. VectorAdd(vMin, vMax, vTemp);
  541. VectorScale(vTemp, 0.5, vTemp);
  542. model = e->model;
  543. while (model != NULL)
  544. {
  545. for (i = 0; i < model->nTriCount; i++)
  546. {
  547. for (int j = 0; j < 3; j++)
  548. {
  549. ;//VectorSubtract(model->pTriList[i].v[j], vTemp, model->pTriList[i].v[j]);
  550. }
  551. }
  552. model = model->pNext;
  553. }
  554. free(pModelBuff);
  555. free(e->modelpath);
  556. e->modelpath = NULL;
  557. if(e->skinpath)
  558. {
  559. free(e->skinpath);
  560. e->skinpath = NULL;
  561. free(pSkinBuff);
  562. }
  563. }
  564. return (e->model != NULL && e->model->nTriCount > 0);
  565. }
  566. void EClass_InsertSortedList(eclass_t *&pList, eclass_t *e)
  567. {
  568. eclass_t *s;
  569. if (!pList)
  570. {
  571. pList = e;
  572. return;
  573. }
  574. s = pList;
  575. if (stricmp (e->name, s->name) < 0)
  576. {
  577. e->next = s;
  578. pList = e;
  579. return;
  580. }
  581. do
  582. {
  583. if (!s->next || stricmp (e->name, s->next->name) < 0)
  584. {
  585. e->next = s->next;
  586. s->next = e;
  587. return;
  588. }
  589. s=s->next;
  590. } while (1);
  591. }
  592. /*
  593. =================
  594. Eclass_InsertAlphabetized
  595. =================
  596. */
  597. void Eclass_InsertAlphabetized (eclass_t *e)
  598. {
  599. #if 1
  600. EClass_InsertSortedList(eclass, e);
  601. #else
  602. eclass_t *s;
  603. if (!eclass)
  604. {
  605. eclass = e;
  606. return;
  607. }
  608. s = eclass;
  609. if (stricmp (e->name, s->name) < 0)
  610. {
  611. e->next = s;
  612. eclass = e;
  613. return;
  614. }
  615. do
  616. {
  617. if (!s->next || stricmp (e->name, s->next->name) < 0)
  618. {
  619. e->next = s->next;
  620. s->next = e;
  621. return;
  622. }
  623. s=s->next;
  624. } while (1);
  625. #endif
  626. }
  627. /*
  628. =================
  629. Eclass_ScanFile
  630. =================
  631. */
  632. qboolean parsing_single = false;
  633. qboolean eclass_found;
  634. eclass_t *eclass_e;
  635. //#ifdef BUILD_LIST
  636. extern bool g_bBuildList;
  637. CString strDefFile;
  638. //#endif
  639. void Eclass_ScanFile (char *filename)
  640. {
  641. int size;
  642. char *data;
  643. eclass_t *e;
  644. int i;
  645. char temp[1024];
  646. QE_ConvertDOSToUnixName( temp, filename );
  647. Sys_Printf ("ScanFile: %s\n", temp);
  648. // BUG
  649. size = LoadFile (filename, (void**)&data);
  650. eclass_found = false;
  651. for (i=0 ; i<size ; i++)
  652. if (!strncmp(data+i, "/*QUAKED",8))
  653. {
  654. //#ifdef BUILD_LIST
  655. if (g_bBuildList)
  656. {
  657. CString strDef = "";
  658. int j = i;
  659. while (1)
  660. {
  661. strDef += *(data+j);
  662. if (*(data+j) == '/' && *(data+j-1) == '*')
  663. break;
  664. j++;
  665. }
  666. strDef += "\r\n\r\n\r\n";
  667. strDefFile += strDef;
  668. }
  669. //#endif
  670. e = Eclass_InitFromText (data+i);
  671. if (e)
  672. Eclass_InsertAlphabetized (e);
  673. else
  674. printf ("Error parsing: %s in %s\n",debugname, filename);
  675. // single ?
  676. eclass_e = e;
  677. eclass_found = true;
  678. if ( parsing_single )
  679. break;
  680. }
  681. free (data);
  682. }
  683. void Eclass_InitForSourceDirectory (char *path)
  684. {
  685. struct _finddata_t fileinfo;
  686. int handle;
  687. char filename[1024];
  688. char filebase[1024];
  689. char temp[1024];
  690. char *s;
  691. QE_ConvertDOSToUnixName( temp, path );
  692. Sys_Printf ("Eclass_InitForSourceDirectory: %s\n", temp );
  693. strcpy (filebase, path);
  694. s = filebase + strlen(filebase)-1;
  695. while (*s != '\\' && *s != '/' && s!=filebase)
  696. s--;
  697. *s = 0;
  698. CleanUpEntities();
  699. eclass = NULL;
  700. //#ifdef BUILD_LIST
  701. if (g_bBuildList)
  702. strDefFile = "";
  703. //#endif
  704. handle = _findfirst (path, &fileinfo);
  705. if (handle != -1)
  706. {
  707. do
  708. {
  709. sprintf (filename, "%s\\%s", filebase, fileinfo.name);
  710. Eclass_ScanFile (filename);
  711. } while (_findnext( handle, &fileinfo ) != -1);
  712. _findclose (handle);
  713. }
  714. //#ifdef BUILD_LIST
  715. if (g_bBuildList)
  716. {
  717. CFile file;
  718. if (file.Open("c:\\entities.def", CFile::modeCreate | CFile::modeWrite))
  719. {
  720. file.Write(strDefFile.GetBuffer(0), strDefFile.GetLength());
  721. file.Close();
  722. }
  723. }
  724. //#endif
  725. eclass_bad = Eclass_InitFromText ("/*QUAKED UNKNOWN_CLASS (0 0.5 0) ?");
  726. }
  727. eclass_t *Eclass_ForName (char *name, qboolean has_brushes)
  728. {
  729. eclass_t *e;
  730. char init[1024];
  731. #ifdef _DEBUG
  732. // grouping stuff, not an eclass
  733. if (strcmp(name, "group_info")==0)
  734. Sys_Printf("WARNING: unexpected group_info entity in Eclass_ForName\n");
  735. #endif
  736. if (!name)
  737. return eclass_bad;
  738. for (e=eclass ; e ; e=e->next)
  739. if (!strcmp (name, e->name))
  740. return e;
  741. // create a new class for it
  742. if (has_brushes)
  743. {
  744. sprintf (init, "/*QUAKED %s (0 0.5 0) ?\nNot found in source.\n", name);
  745. e = Eclass_InitFromText (init);
  746. }
  747. else
  748. {
  749. sprintf (init, "/*QUAKED %s (0 0.5 0) (-8 -8 -8) (8 8 8)\nNot found in source.\n", name);
  750. e = Eclass_InitFromText (init);
  751. }
  752. Eclass_InsertAlphabetized (e);
  753. return e;
  754. }
  755. eclass_t* GetCachedModel(entity_t *pEntity, const char *pName, vec3_t &vMin, vec3_t &vMax)
  756. {
  757. eclass_t *e = NULL;
  758. if (pName == NULL || strlen(pName) == 0)
  759. {
  760. return NULL;
  761. }
  762. for (e = g_md3Cache; e ; e = e->next)
  763. {
  764. if (!strcmp (pName, e->name))
  765. {
  766. pEntity->md3Class = e;
  767. VectorCopy(e->mins, vMin);
  768. VectorCopy(e->maxs, vMax);
  769. return e;
  770. }
  771. }
  772. e = (eclass_t*)qmalloc(sizeof(*e));
  773. memset (e, 0, sizeof(*e));
  774. e->name = strdup(pName);
  775. e->modelpath = strdup(pName);
  776. e->skinpath = strdup(pName);
  777. char *p = strstr(e->skinpath, ".md3");
  778. if (p != NULL)
  779. {
  780. p++;
  781. strncpy(p, "tga", 3);
  782. }
  783. else
  784. {
  785. free(e->skinpath);
  786. e->skinpath = NULL;
  787. }
  788. e->color[0] = e->color[2] = 0.85;
  789. if (Eclass_hasModel(e, vMin, vMax))
  790. {
  791. EClass_InsertSortedList(g_md3Cache, e);
  792. VectorCopy(vMin, e->mins);
  793. VectorCopy(vMax, e->maxs);
  794. pEntity->md3Class = e;
  795. return e;
  796. }
  797. return NULL;
  798. }