Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

ECLASS.CPP

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 #include "stdafx.h"
00023 #include "qe3.h"
00024 #include "io.h"
00025 #include "pakstuff.h"
00026 //#include "qertypes.h"
00027 
00028 eclass_t    *eclass = NULL;
00029 eclass_t    *eclass_bad = NULL;
00030 char        eclass_directory[1024];
00031 
00032 // md3 cache for misc_models
00033 eclass_t *g_md3Cache = NULL;
00034 
00035 /*
00036 
00037 the classname, color triple, and bounding box are parsed out of comments
00038 A ? size means take the exact brush size.
00039 
00040 /*QUAKED <classname> (0 0 0) ?
00041 /*QUAKED <classname> (0 0 0) (-8 -8 -8) (8 8 8)
00042 
00043 Flag names can follow the size description:
00044 
00045 /*QUAKED func_door (0 .5 .8) ? START_OPEN STONE_SOUND DOOR_DONT_LINK GOLD_KEY SILVER_KEY
00046 
00047 */
00048 
00049 void CleanEntityList(eclass_t *&pList)
00050 {
00051   while (pList)
00052   {
00053     eclass_t* pTemp = pList->next;
00054 
00055     entitymodel *model = pList->model;
00056     while (model != NULL)
00057     {
00058       delete []model->pTriList;
00059       model = model->pNext;
00060     }
00061     
00062     if (pList->modelpath)
00063       free(pList->modelpath);
00064       if (pList->skinpath)          // PGM
00065           free(pList->skinpath);        // PGM
00066     
00067     free(pList->name);
00068     free(pList->comments);
00069     free(pList);
00070     pList = pTemp;
00071   }
00072 
00073   pList = NULL;
00074 
00075 }
00076 
00077 
00078 void CleanUpEntities()
00079 {
00080   CleanEntityList(eclass);
00081   CleanEntityList(g_md3Cache);
00082 /*
00083   while (eclass)
00084   {
00085     eclass_t* pTemp = eclass->next;
00086     delete []eclass->pTriList;
00087     
00088     if (eclass->modelpath)
00089       free(eclass->modelpath);
00090       if (eclass->skinpath)         // PGM
00091           free(eclass->skinpath);       // PGM
00092     
00093     free(eclass->name);
00094     free(eclass->comments);
00095     free(eclass);
00096     eclass = pTemp;
00097   }
00098 
00099   eclass = NULL;
00100 */
00101   if (eclass_bad)
00102   {
00103     free(eclass_bad->name);
00104     free(eclass_bad->comments);
00105     free(eclass_bad);
00106     eclass_bad = NULL;
00107   }
00108 }
00109 
00110 void ExtendBounds(vec3_t v, vec3_t &vMin, vec3_t &vMax)
00111 {
00112     for (int i = 0 ;i < 3 ;i++)
00113     {
00114         vec_t f = v[i];
00115         
00116     if (f < vMin[i])
00117     {
00118             vMin[i] = f;
00119     }
00120 
00121     if (f > vMax[i])
00122     {
00123             vMax[i] = f;
00124     }
00125     }
00126 }
00127 
00128 
00129 
00130 // FIXME: this code is a TOTAL clusterfuck
00131 //
00132 void LoadModel(const char *pLocation, eclass_t *e, vec3_t &vMin, vec3_t &vMax, entitymodel *&pModel, const char *pSkin)
00133 {
00134   // this assumes a path only and uses tris.md2
00135   // for the model and skin.pcx for the skin
00136   char cPath[1024];
00137   char cSkin[1024];
00138   char cFullLocation[1024];
00139     //struct _finddata_t fileinfo;
00140 
00141   vMin[0] = vMin[1] = vMin[2] = 99999;
00142   vMax[0] = vMax[1] = vMax[2] = -99999;
00143 
00144   bool bMD3 = false;
00145   bool bASE = false;
00146 
00147   strcpy( cFullLocation, pLocation );
00148 
00149   if (strstr(pLocation, ".md3"))
00150   {
00151     bMD3 = true;
00152   }
00153   else if (strstr(pLocation, ".md2") != NULL)
00154   {
00155       sprintf( cFullLocation, "%stris.md2", pLocation);
00156   }
00157   else if (strstr(pLocation, ".ase") != NULL)
00158   {
00159     bASE = true;
00160   }
00161 
00162   sprintf( cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cFullLocation);
00163 
00164   Sys_Printf("Loading model %s...", cPath);
00165   unsigned char* p = NULL;
00166   bool bOpen = (LoadFile(cPath, reinterpret_cast<void**>(&p)) > 0);
00167   if (!bOpen)
00168   {
00169     Sys_Printf(" failed. Trying PAK file...");
00170 //    sprintf (cPath, "%stris.md2", pLocation);
00171       strcpy (cPath, cFullLocation);
00172       bOpen = (PakLoadAnyFile(cPath, reinterpret_cast<void**>(&p)) > 0);
00173   }
00174 
00175   if (bOpen)
00176   {
00177     Sys_Printf(" successful.\n");
00178 
00179     if (bASE)
00180     {
00181 /*
00182       free(p);
00183       CString strOut;
00184       ::GetTempPath(1024, strOut.GetBuffer(1024));
00185       strOut.ReleaseBuffer();
00186       AddSlash(strOut);
00187       strOut += "Temp.ase";
00188       CopyFile(cPath, strOut, false);
00189       CString strIn = strOut;
00190       FindReplace(strOut, ".ase", ".md3");
00191       strcpy(cPath, strIn);
00192       strcpy(cSkin, strOut);
00193       Q3Data_ProduceTempMD3(ValueForKey(g_qeglobals.d_project_entity, "basepath"), cPath, cSkin);
00194       CString strModel = cPath;
00195       if (LoadFile(strOut.GetBuffer(0), reinterpret_cast<void**>(&p)) == 0)
00196       {
00197         Sys_Printf(" Conversion from ASE failed.\n");
00198         return;
00199       }
00200       bMD3 = true;
00201 */
00202     }
00203 
00204     if (bMD3)
00205     {
00206         md3Header_t header;
00207         md3Surface_t *pSurface;
00208         header = *(md3Header_t *)p;
00209       if (pSkin != NULL)
00210       {
00211         strcpy(cSkin, pSkin);
00212       }
00213         else
00214       {
00215             cSkin[0] = '\0';
00216       }
00217       int n = header.numFrames;
00218         pSurface = (md3Surface_t *) (p + header.ofsSurfaces);
00219         for (int z = 0; z < header.numSurfaces; z++ )
00220         {
00221         int nTris = pSurface->numTriangles;
00222         
00223         //unsigned char* pTris = reinterpret_cast<unsigned char*>(pSurface);
00224         //pTris += pSurface->ofsTriangles;
00225 
00226         if (nTris > 0)
00227         {
00228           int nStart = 0;
00229           if (pModel->pTriList == NULL)
00230           {
00231                 pModel->nModelPosition = 0;
00232             pModel->pTriList = new trimodel[nTris];
00233             pModel->nTriCount = nTris;
00234           }
00235           else
00236           {
00237             // already have one so we need to reallocate
00238             int nNewCount = pModel->nTriCount + nTris;
00239             trimodel* pNewModels = new trimodel[nNewCount];
00240             for (int i = 0; i < pModel->nTriCount; i++)
00241             {
00242               memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
00243             }
00244             nStart = pModel->nTriCount;
00245             pModel->nTriCount = nNewCount;
00246             //nTris = nNewCount;
00247             delete [] pModel->pTriList;
00248             pModel->pTriList = pNewModels;
00249           }
00250           
00251           md3Triangle_t *pTris = reinterpret_cast<md3Triangle_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsTriangles));
00252           md3XyzNormal_t *pXyz = reinterpret_cast<md3XyzNormal_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsXyzNormals));
00253           if (e->nFrame < pSurface->numFrames)
00254           {
00255             pXyz += (e->nFrame * pSurface->numVerts);
00256           }
00257 
00258           md3St_t *pST = reinterpret_cast<md3St_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsSt)); 
00259 
00260           for (int i = 0; i < nTris; i++)
00261           {
00262             for (int k = 0; k < 3; k ++)
00263             {
00264               for (int j = 0; j < 3; j++)
00265               {
00266                 //e->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
00267                 pModel->pTriList[nStart].v[k][j] = pXyz[pTris[i].indexes[k]].xyz[j] * MD3_XYZ_SCALE;
00268               }
00269                   pModel->pTriList[nStart].st[k][0] = pST[pTris[i].indexes[k]].st[0];
00270                   pModel->pTriList[nStart].st[k][1] = pST[pTris[i].indexes[k]].st[1];
00271                   ExtendBounds (pModel->pTriList[nStart].v[k], vMin, vMax);
00272                 }
00273             nStart++;
00274               }
00275 
00276         }
00277 
00278         md3Shader_t *pShader = reinterpret_cast<md3Shader_t*>((reinterpret_cast<unsigned char*>(pSurface) + pSurface->ofsShaders)); 
00279         sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pShader->name);
00280         strlwr(cPath);
00281           pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
00282         if (pModel->nTextureBind == -1)
00283         {
00284           Sys_Printf("Model skin load failed on texture %s\n", cPath);
00285         }
00286             pSurface = (md3Surface_t *) ((( char * ) pSurface) + pSurface->ofsEnd);
00287         pModel->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
00288         pModel = pModel->pNext;
00289       }
00290     }
00291     else
00292     {
00293 
00294       dmdl_t model;
00295       daliasframe_t *f;
00296       unsigned char* pTris = p;
00297       dstvert_t *pST = NULL;
00298       int nTris = 0;
00299 
00300       // grab model params
00301       memcpy(&model, p, sizeof(dmdl_t));
00302       f = (daliasframe_t*)(p + model.ofs_frames);
00303       pTris += model.ofs_tris;
00304       pST = reinterpret_cast<dstvert_t*>(p + model.ofs_st);
00305       nTris = model.num_tris;
00306 
00307         if(pSkin)
00308         {
00309             strcpy (cSkin, pSkin);
00310             if ((cSkin[strlen(cSkin)-1] == '\\') || (cSkin[strlen(cSkin)-1] == '/'))
00311                 strcat(cSkin, "skin.pcx\0");
00312         }
00313         else
00314       {
00315             strcpy(cSkin, (char *)(p + model.ofs_skins));
00316       }
00317 
00318       sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
00319       strlwr(cPath);
00320       pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
00321       if (pModel->nTextureBind == -1)
00322       {
00323         Sys_Printf("Model skin load failed on texture %s\n", cPath);
00324       }
00325       int nStart = 0;
00326       if (pModel->pTriList == NULL)
00327       {
00328             pModel->nModelPosition = 0;
00329         pModel->pTriList = new trimodel[nTris];
00330         pModel->nTriCount = nTris;
00331       }
00332       else
00333       {
00334         // already have one so we need to reallocate
00335         int nNewCount = pModel->nTriCount + nTris;
00336         trimodel* pNewModels = new trimodel[nNewCount];
00337         for (int i = 0; i < pModel->nTriCount; i++)
00338         {
00339           memcpy(&pNewModels[i], &pModel->pTriList[i], sizeof(trimodel));
00340         }
00341         nStart = pModel->nTriCount;
00342         pModel->nTriCount = nNewCount;
00343         nTris = nNewCount;
00344         delete [] pModel->pTriList;
00345         pModel->pTriList = pNewModels;
00346       }
00347       
00348       for (int i = nStart; i < nTris; i++)
00349       {
00350         dtriangle_t tri;
00351         memcpy(&tri, pTris, sizeof(dtriangle_t));
00352         for (int k = 0; k < 3; k ++)
00353         {
00354           for (int j = 0; j < 3; j++)
00355           {
00356             pModel->pTriList[i].v[k][j] = (f->verts[tri.index_xyz[k]].v[j] * f->scale[j] + f->translate[j]);
00357           }
00358 
00359           pModel->pTriList[i].st[k][0] = pST[tri.index_st[k]].s / pModel->nSkinWidth;
00360           pModel->pTriList[i].st[k][1] = pST[tri.index_st[k]].t / pModel->nSkinHeight;;
00361           ExtendBounds (pModel->pTriList[i].v[k], vMin, vMax);
00362             }
00363         pTris += sizeof(dtriangle_t);
00364           }
00365     }
00366     free(p);
00367   }
00368   else
00369   {
00370     Sys_Printf(" failed.\n");
00371   }
00372 
00373 #if 0
00374   if (pModel->pTriList != NULL && pModel->nTriCount > 0 && !bMD3)
00375   {
00376       if(fabs(vMin[2]) < ((vMax[2]-vMin[2]) / 10.0))    // > 90% above 0 point.
00377         pModel->nModelPosition = 1;
00378 //  sprintf (cPath, "%s/%sskin.pcx", ValueForKey(g_qeglobals.d_project_entity, "basepath"), pLocation);
00379     sprintf (cPath, "%s/%s", ValueForKey(g_qeglobals.d_project_entity, "basepath"), cSkin);
00380       pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
00381     if (pModel->nTextureBind == -1)
00382     {
00383 //      sprintf (cPath, "%sskin.pcx", pLocation);
00384           strcpy (cPath, cSkin);
00385       pModel->nTextureBind = Texture_LoadSkin(cPath, &pModel->nSkinWidth, &pModel->nSkinHeight);
00386     }
00387   }
00388 #endif
00389 
00390 }
00391 
00392 void setSpecialLoad(eclass_t *e, const char* pWhat, char*& p)
00393 {
00394   CString str = e->comments;
00395   int n = str.Find(pWhat);
00396   if (n >= 0)
00397   {
00398     char* pText = e->comments + n + strlen(pWhat);
00399     if (*pText == '\"')
00400       pText++;
00401 
00402     str = "";
00403     while (*pText != '\"' && *pText != '\0')
00404     {
00405       str += *pText;
00406       pText++;
00407     }
00408     if (str.GetLength() > 0)
00409     {         
00410       p = strdup(str);
00411       //--LoadModel(str, e);
00412     }
00413   }
00414 }
00415 
00416 char    *debugname;
00417 
00418 eclass_t *Eclass_InitFromText (char *text)
00419 {
00420     char    *t;
00421     int     len;
00422     int     r, i;
00423     char    parms[256], *p;
00424     eclass_t    *e;
00425     char    color[128];
00426 
00427     e = (eclass_t*)qmalloc(sizeof(*e));
00428     memset (e, 0, sizeof(*e));
00429     
00430     text += strlen("/*QUAKED ");
00431     
00432 // grab the name
00433     text = COM_Parse (text);
00434     e->name = (char*)qmalloc (strlen(com_token)+1);
00435     strcpy (e->name, com_token);
00436     debugname = e->name;
00437     
00438 // grab the color, reformat as texture name
00439     r = sscanf (text," (%f %f %f)", &e->color[0], &e->color[1], &e->color[2]);
00440     if (r != 3)
00441         return e;
00442     sprintf (color, "(%f %f %f)", e->color[0], e->color[1], e->color[2]);
00443     //strcpy (e->texdef.name, color);
00444     e->texdef.SetName(color);
00445 
00446     while (*text != ')')
00447     {
00448         if (!*text)
00449             return e;
00450         text++;
00451     }
00452     text++;
00453     
00454 // get the size 
00455     text = COM_Parse (text);
00456     if (com_token[0] == '(')
00457     {   // parse the size as two vectors
00458         e->fixedsize = true;
00459         r = sscanf (text,"%f %f %f) (%f %f %f)", &e->mins[0], &e->mins[1], &e->mins[2],
00460             &e->maxs[0], &e->maxs[1], &e->maxs[2]);
00461         if (r != 6)
00462             return e;
00463 
00464         for (i=0 ; i<2 ; i++)
00465         {
00466             while (*text != ')')
00467             {
00468                 if (!*text)
00469                     return e;
00470                 text++;
00471             }
00472             text++;
00473         }
00474     }
00475     else
00476     {   // use the brushes
00477     }
00478     
00479 // get the flags
00480     
00481 
00482 // copy to the first /n
00483     p = parms;
00484     while (*text && *text != '\n')
00485         *p++ = *text++;
00486     *p = 0;
00487     text++;
00488     
00489 // any remaining words are parm flags
00490     p = parms;
00491     for (i=0 ; i<8 ; i++)
00492     {
00493         p = COM_Parse (p);
00494         if (!p)
00495             break;
00496         strcpy (e->flagnames[i], com_token);
00497     } 
00498 
00499 // find the length until close comment
00500     for (t=text ; t[0] && !(t[0]=='*' && t[1]=='/') ; t++)
00501     ;
00502     
00503 // copy the comment block out
00504     len = t-text;
00505     e->comments = (char*)qmalloc (len+1);
00506     memcpy (e->comments, text, len);
00507 #if 0
00508     for (i=0 ; i<len ; i++)
00509         if (text[i] == '\n')
00510             e->comments[i] = '\r';
00511         else
00512             e->comments[i] = text[i];
00513 #endif
00514     e->comments[len] = 0;
00515     
00516   setSpecialLoad(e, "model=", e->modelpath);
00517   setSpecialLoad(e, "skin=", e->skinpath);
00518   char *pFrame = NULL;
00519   setSpecialLoad(e, "frame=", pFrame);
00520   if (pFrame != NULL)
00521   {
00522     e->nFrame = atoi(pFrame);
00523   }
00524 
00525   if(!e->skinpath)
00526       setSpecialLoad(e, "texture=", e->skinpath);
00527 
00528   // setup show flags
00529   e->nShowFlags = 0;
00530   if (strcmpi(e->name, "light") == 0)
00531   {
00532     e->nShowFlags |= ECLASS_LIGHT;
00533   }
00534 
00535   if (  (strnicmp(e->name, "info_player", strlen("info_player")) == 0)
00536       ||(strnicmp(e->name, "path_corner", strlen("path_corner")) == 0) 
00537       ||(strnicmp(e->name, "team_ctf", strlen("team_ctf")) == 0) )
00538   {
00539     e->nShowFlags |= ECLASS_ANGLE;
00540   }
00541   if (strcmpi(e->name, "path") == 0)
00542   {
00543     e->nShowFlags |= ECLASS_PATH;
00544   }
00545   if (strcmpi(e->name, "misc_model") == 0)
00546   {
00547     e->nShowFlags |= ECLASS_MISCMODEL;
00548   }
00549 
00550 
00551   return e;
00552 }
00553 
00554 qboolean Eclass_hasModel(eclass_t *e, vec3_t &vMin, vec3_t &vMax)
00555 {
00556   if (e->modelpath != NULL)
00557   {
00558     if (e->model == NULL)
00559     {
00560       e->model = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
00561     }
00562     char *pModelBuff = strdup(e->modelpath);
00563     char *pSkinBuff = NULL;
00564     if (e->skinpath)
00565     {
00566       pSkinBuff = strdup(e->skinpath);
00567     }
00568 
00569     CStringList Models;
00570     CStringList Skins;
00571     char* pToken = strtok(pModelBuff, ";\0");
00572     while (pToken != NULL)
00573     {
00574       Models.AddTail(pToken);
00575       pToken = strtok(NULL, ";\0");
00576     }
00577 
00578     if (pSkinBuff != NULL)
00579     {
00580       pToken = strtok(pSkinBuff, ";\0");
00581       while (pToken != NULL)
00582       {
00583         Skins.AddTail(pToken);
00584         pToken = strtok(NULL, ";\0");
00585       }
00586     }
00587 
00588     entitymodel *model = e->model;
00589     for (int i = 0; i < Models.GetCount(); i++)
00590     {
00591       char *pSkin = NULL;
00592       if (i < Skins.GetCount())
00593       {
00594         pSkin = Skins.GetAt(Skins.FindIndex(i)).GetBuffer(0);
00595       }
00596       LoadModel(Models.GetAt(Models.FindIndex(i)), e, vMin, vMax, model, pSkin);
00597       model->pNext = reinterpret_cast<entitymodel_t*>(qmalloc(sizeof(entitymodel_t)));
00598       model = model->pNext;
00599     }
00600 
00601     // at this poitn vMin and vMax contain the min max of the model
00602     // which needs to be centered at origin 0, 0, 0
00603 
00604     VectorSnap(vMin);
00605     VectorSnap(vMax);
00606 
00607     if (vMax[0] - vMin[0] < 2)
00608     {
00609       vMin[0] -= 1;
00610       vMax[0] += 1;
00611     }
00612 
00613     if (vMin[1] - vMax[1] < 2)
00614     {
00615       vMin[1] -= 1;
00616       vMax[1] += 1;
00617     }
00618 
00619     if (vMax[2] - vMin[2] < 2)
00620     {
00621       vMax[2] -= 1;
00622       vMax[2] += 1;
00623     }
00624 
00625     vec3_t vTemp;
00626     VectorAdd(vMin, vMax, vTemp);
00627     VectorScale(vTemp, 0.5, vTemp);
00628     model = e->model;
00629     while (model != NULL)
00630     {
00631       for (i = 0; i < model->nTriCount; i++)
00632       {
00633         for (int j = 0; j < 3; j++)
00634         {
00635           ;//VectorSubtract(model->pTriList[i].v[j], vTemp, model->pTriList[i].v[j]);
00636         }
00637       }
00638       model = model->pNext;
00639     }
00640 
00641     free(pModelBuff);
00642     free(e->modelpath);
00643     e->modelpath = NULL;
00644       
00645     if(e->skinpath)
00646       {
00647           free(e->skinpath);
00648           e->skinpath = NULL;
00649       free(pSkinBuff);
00650       }
00651 
00652   }
00653   return (e->model != NULL && e->model->nTriCount > 0);
00654 }
00655 
00656 
00657 void EClass_InsertSortedList(eclass_t *&pList, eclass_t *e)
00658 {
00659     eclass_t    *s;
00660     
00661     if (!pList)
00662     {
00663         pList = e;
00664         return;
00665     }
00666 
00667 
00668     s = pList;
00669     if (stricmp (e->name, s->name) < 0)
00670     {
00671         e->next = s;
00672         pList = e;
00673         return;
00674     }
00675 
00676     do
00677     {
00678         if (!s->next || stricmp (e->name, s->next->name) < 0)
00679         {
00680             e->next = s->next;
00681             s->next = e;
00682             return;
00683         }
00684         s=s->next;
00685     } while (1);
00686 }
00687 
00688 /*
00689 =================
00690 Eclass_InsertAlphabetized
00691 =================
00692 */
00693 void Eclass_InsertAlphabetized (eclass_t *e)
00694 {
00695 #if 1
00696   EClass_InsertSortedList(eclass, e);
00697 #else
00698     eclass_t    *s;
00699     
00700     if (!eclass)
00701     {
00702         eclass = e;
00703         return;
00704     }
00705 
00706 
00707     s = eclass;
00708     if (stricmp (e->name, s->name) < 0)
00709     {
00710         e->next = s;
00711         eclass = e;
00712         return;
00713     }
00714 
00715     do
00716     {
00717         if (!s->next || stricmp (e->name, s->next->name) < 0)
00718         {
00719             e->next = s->next;
00720             s->next = e;
00721             return;
00722         }
00723         s=s->next;
00724     } while (1);
00725 #endif
00726 }
00727 
00728 
00729 /*
00730 =================
00731 Eclass_ScanFile
00732 =================
00733 */
00734 
00735 qboolean parsing_single = false;
00736 qboolean eclass_found;
00737 eclass_t *eclass_e;
00738 //#ifdef BUILD_LIST
00739 extern bool g_bBuildList;
00740 CString strDefFile;
00741 //#endif
00742 void Eclass_ScanFile (char *filename)
00743 {
00744     int     size;
00745     char    *data;
00746     eclass_t    *e;
00747     int     i;
00748     char    temp[1024];
00749     
00750     QE_ConvertDOSToUnixName( temp, filename );
00751     
00752     Sys_Printf ("ScanFile: %s\n", temp);
00753     
00754     // BUG
00755     size = LoadFile (filename, (void**)&data);
00756     eclass_found = false;
00757     for (i=0 ; i<size ; i++)
00758         if (!strncmp(data+i, "/*QUAKED",8))
00759         {
00760             
00761             //#ifdef BUILD_LIST
00762             if (g_bBuildList)
00763             {
00764                 CString strDef = "";
00765                 int j = i;
00766                 while (1)
00767                 {
00768                     strDef += *(data+j);
00769                     if (*(data+j) == '/' && *(data+j-1) == '*')
00770                         break;
00771                     j++;
00772                 }
00773                 strDef += "\r\n\r\n\r\n";
00774                 strDefFile += strDef;
00775             }
00776             //#endif
00777             e = Eclass_InitFromText (data+i);
00778             if (e)
00779                 Eclass_InsertAlphabetized (e);
00780             else
00781                 printf ("Error parsing: %s in %s\n",debugname, filename);
00782 
00783             // single ?
00784             eclass_e = e;
00785             eclass_found = true;
00786             if ( parsing_single )
00787                 break;
00788         }
00789         
00790         free (data);        
00791 }
00792 
00793 
00794 
00795 void Eclass_InitForSourceDirectory (char *path)
00796 {
00797     struct _finddata_t fileinfo;
00798     int     handle;
00799     char    filename[1024];
00800     char    filebase[1024];
00801     char    temp[1024];
00802     char    *s;
00803 
00804     QE_ConvertDOSToUnixName( temp, path );
00805 
00806     Sys_Printf ("Eclass_InitForSourceDirectory: %s\n", temp );
00807 
00808     strcpy (filebase, path);
00809     s = filebase + strlen(filebase)-1;
00810     while (*s != '\\' && *s != '/' && s!=filebase)
00811         s--;
00812     *s = 0;
00813 
00814   CleanUpEntities();
00815     eclass = NULL;
00816 //#ifdef BUILD_LIST
00817   if (g_bBuildList)
00818     strDefFile = "";
00819 //#endif
00820     handle = _findfirst (path, &fileinfo);
00821     if (handle != -1)
00822     {
00823         do
00824         {
00825             sprintf (filename, "%s\\%s", filebase, fileinfo.name);
00826             Eclass_ScanFile (filename);
00827         } while (_findnext( handle, &fileinfo ) != -1);
00828 
00829         _findclose (handle);
00830     }
00831 
00832 //#ifdef BUILD_LIST
00833   if (g_bBuildList)
00834   {
00835     CFile file;
00836     if (file.Open("c:\\entities.def", CFile::modeCreate | CFile::modeWrite)) 
00837     {
00838       file.Write(strDefFile.GetBuffer(0), strDefFile.GetLength());
00839       file.Close();
00840     }
00841   }
00842 //#endif
00843 
00844     eclass_bad = Eclass_InitFromText ("/*QUAKED UNKNOWN_CLASS (0 0.5 0) ?");
00845 }
00846 
00847 eclass_t *Eclass_ForName (char *name, qboolean has_brushes)
00848 {
00849     eclass_t    *e;
00850     char        init[1024];
00851 
00852 #ifdef _DEBUG
00853   // grouping stuff, not an eclass
00854   if (strcmp(name, "group_info")==0)
00855     Sys_Printf("WARNING: unexpected group_info entity in Eclass_ForName\n");
00856 #endif
00857 
00858     if (!name)
00859         return eclass_bad;
00860 
00861     for (e=eclass ; e ; e=e->next)
00862         if (!strcmp (name, e->name))
00863             return e;
00864 
00865     // create a new class for it
00866     if (has_brushes)
00867     {
00868         sprintf (init, "/*QUAKED %s (0 0.5 0) ?\nNot found in source.\n", name);
00869         e = Eclass_InitFromText (init);
00870     }
00871     else
00872     {
00873         sprintf (init, "/*QUAKED %s (0 0.5 0) (-8 -8 -8) (8 8 8)\nNot found in source.\n", name);
00874         e = Eclass_InitFromText (init);
00875     }
00876 
00877     Eclass_InsertAlphabetized (e);
00878 
00879     return e;
00880 }
00881 
00882 
00883 eclass_t* GetCachedModel(entity_t *pEntity, const char *pName, vec3_t &vMin, vec3_t &vMax)
00884 {
00885 
00886     eclass_t *e = NULL;
00887   if (pName == NULL || strlen(pName) == 0)
00888   {
00889     return NULL;
00890   }
00891 
00892     for (e = g_md3Cache; e ; e = e->next)
00893   {
00894         if (!strcmp (pName, e->name))
00895     {
00896       pEntity->md3Class = e;
00897       VectorCopy(e->mins, vMin);
00898       VectorCopy(e->maxs, vMax);
00899             return e;
00900     }
00901   }
00902 
00903     e = (eclass_t*)qmalloc(sizeof(*e));
00904     memset (e, 0, sizeof(*e));
00905   e->name = strdup(pName);
00906   e->modelpath = strdup(pName);
00907   e->skinpath = strdup(pName);
00908   char *p = strstr(e->skinpath, ".md3");
00909   if (p != NULL)
00910   {
00911     p++;
00912     strncpy(p, "tga", 3);
00913   }
00914   else
00915   {
00916     free(e->skinpath);
00917     e->skinpath = NULL;
00918   }
00919 
00920   e->color[0] = e->color[2] = 0.85;
00921 
00922   if (Eclass_hasModel(e, vMin, vMax))
00923   {
00924     EClass_InsertSortedList(g_md3Cache, e);
00925     VectorCopy(vMin, e->mins);
00926     VectorCopy(vMax, e->maxs);
00927     pEntity->md3Class = e;
00928     return e;
00929   }
00930 
00931   return NULL;
00932 }

Generated on Thu Aug 25 12:38:28 2005 for Quake III Arena by  doxygen 1.3.9.1