2 BobToolz plugin for GtkRadiant
3 Copyright (C) 2001 Gordon Biggans
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // DEntity.cpp: implementation of the DEntity class.
22 //////////////////////////////////////////////////////////////////////
27 #pragma warning(disable : 4786)
32 #include "dialogs/dialogs-gtk.h"
36 const char* brushEntityList[] = {
56 //////////////////////////////////////////////////////////////////////
57 // Construction/Destruction
58 //////////////////////////////////////////////////////////////////////
60 DEntity::DEntity(char *classname, int ID)
62 SetClassname(classname);
74 //////////////////////////////////////////////////////////////////////
76 //////////////////////////////////////////////////////////////////////
78 void DEntity::ClearBrushes()
80 for(list<DBrush *>::const_iterator deadBrush=brushList.begin(); deadBrush!=brushList.end(); deadBrush++)
87 void DEntity::ClearPatches()
89 for(list<DPatch *>::const_iterator deadPatch=patchList.begin(); deadPatch!=patchList.end(); deadPatch++)
96 DPatch* DEntity::NewPatch()
98 DPatch* newPatch = new DPatch;
100 patchList.push_back(newPatch);
105 DBrush* DEntity::NewBrush(int ID)
107 DBrush* newBrush = new DBrush(ID);
109 brushList.push_back(newBrush);
114 char* getNextBracket(char* s)
127 bool DEntity::LoadFromPrt(char *filename)
130 strcpy(portals.fn, filename);
133 if(portals.node_count == 0)
140 for(unsigned int i = 0; i < portals.node_count; i++)
143 DBrush* brush = NewBrush();
145 for(unsigned int j = 0; j < portals.node[i].portal_count; j++)
147 for(unsigned int k = 0; k < portals.node[i].portal[j].point_count-2; k++)
149 vec3_t v1, v2, normal, n;
150 VectorSubtract(portals.node[i].portal[j].point[k+2].p, portals.node[i].portal[j].point[k+1].p, v1);
151 VectorSubtract(portals.node[i].portal[j].point[k].p, portals.node[i].portal[j].point[k+1].p, v2);
152 CrossProduct(v1, v2, n);
153 VectorNormalize(n, v2);
157 VectorCopy(v2, normal);
161 VectorSubtract(v2, normal, v1);
162 if(VectorLength(v1) > 0.01)
171 brush->AddFace(portals.node[i].portal[j].point[2].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[0].p, "textures/common/caulk", FALSE);
173 brush->AddFace(portals.node[i].portal[j].point[0].p, portals.node[i].portal[j].point[1].p, portals.node[i].portal[j].point[2].p, "textures/common/caulk", FALSE);
176 brush->BuildInRadiant(FALSE, NULL);
182 DPlane* DEntity::AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID)
184 DBrush* buildBrush = GetBrushForID(ID);
185 return buildBrush->AddFace(va, vb, vc, faceData);
186 // slow, dont use much
189 DBrush* DEntity::GetBrushForID(int ID)
191 DBrush* buildBrush = NULL;
193 for(list<DBrush *>::const_iterator chkBrush=brushList.begin(); chkBrush!=brushList.end(); chkBrush++)
195 if((*chkBrush)->m_nBrushID == ID)
197 buildBrush = (*chkBrush);
203 buildBrush = NewBrush(ID);
208 void DEntity::LoadSelectedBrushes()
213 int count = g_FuncTable.m_pfnAllocateSelectedBrushHandles();
215 for(int i = 0; i < count; i++) {
216 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetSelectedBrushHandle(i);
221 DBrush* loadBrush = NewBrush(i);
222 loadBrush->LoadFromBrush_t(brush, TRUE);
225 g_FuncTable.m_pfnReleaseSelectedBrushHandles();
228 void DEntity::LoadSelectedPatches()
233 int count = g_FuncTable.m_pfnAllocateSelectedPatchHandles();
235 for(int i = 0; i < count; i++)
237 //$ FIXME: m_pfnGetPatchHandle
238 patchMesh_t *pmesh = (patchMesh_t*)g_FuncTable.m_pfnGetPatchData(i);
240 DPatch* loadPatch = NewPatch();
241 loadPatch->LoadFromBrush_t(pmesh->pSymbiot);
244 g_FuncTable.m_pfnReleasePatchHandles();
247 bool* DEntity::BuildIntersectList()
249 int max = GetIDMax();
253 bool* pbIntList = new bool[max];
254 memset(pbIntList, 0, sizeof(bool)*(max));
256 for(list<DBrush *>::const_iterator pB1=brushList.begin(); pB1!=brushList.end(); pB1++)
258 list<DBrush *>::const_iterator pB2=pB1;
259 for(pB2++; pB2!=brushList.end(); pB2++)
261 if((*pB1)->IntersectsWith((*pB2)))
263 pbIntList[(*pB1)->m_nBrushID] = TRUE;
264 pbIntList[(*pB2)->m_nBrushID] = TRUE;
272 bool* DEntity::BuildDuplicateList()
274 int max = GetIDMax();
278 bool* pbDupList = new bool[max];
279 memset(pbDupList, 0, sizeof(bool)*(max));
281 for(list<DBrush *>::const_iterator pB1=brushList.begin(); pB1!=brushList.end(); pB1++)
283 list<DBrush *>::const_iterator pB2=pB1;
284 for(pB2++; pB2!=brushList.end(); pB2++)
288 pbDupList[(*pB1)->m_nBrushID] = TRUE;
289 pbDupList[(*pB2)->m_nBrushID] = TRUE;
297 void DEntity::SelectBrushes(bool *selectList)
299 if(selectList == NULL)
302 g_FuncTable.m_pfnDeselectAllBrushes();
304 g_FuncTable.m_pfnAllocateActiveBrushHandles();
306 for(std::list<DBrush *>::const_iterator pBrush=brushList.begin(); pBrush!=brushList.end(); pBrush++)
308 if(selectList[(*pBrush)->m_nBrushID])
309 g_FuncTable.m_pfnSelectBrush((*pBrush)->QER_brush);
311 g_FuncTable.m_pfnReleaseActiveBrushHandles();
314 bool DEntity::LoadFromEntity(int id, bool bLoadPatches) {
315 return LoadFromEntity((entity_t*)g_FuncTable.m_pfnGetEntityHandle(id), bLoadPatches);
318 bool DEntity::LoadFromEntity(entity_t* ent, bool bLoadPatches) {
325 epair_t* epl = *g_EntityTable.m_pfnGetEntityKeyValList(QER_Entity);
330 for(i = 0; brushEntityList[i]; i++)
332 if(!stricmp(brushEntityList[i], m_Classname))
342 int count = g_FuncTable.m_pfnAllocateEntityBrushHandles(QER_Entity);
344 for(i = 0; i < count; i++)
347 brush_t *brush = (brush_t*)g_FuncTable.m_pfnGetEntityBrushHandle(i);
350 DoMessageBox("GTKRadiant returned a NULL pointer, NOT a good sign", "WARNING!!!", MB_OK);
358 DPatch* loadPatch = NewPatch();
359 loadPatch->LoadFromBrush_t(brush);
364 DBrush* loadBrush = NewBrush(i);
365 loadBrush->LoadFromBrush_t(brush, TRUE);
369 g_FuncTable.m_pfnReleaseEntityBrushHandles();
374 void DEntity::RemoveNonCheckBrushes(list<Str>* exclusionList, bool useDetail)
376 list<DBrush *>::iterator chkBrush=brushList.begin();
378 while( chkBrush!=brushList.end() )
382 if((*chkBrush)->IsDetail())
385 chkBrush = brushList.erase(chkBrush);
390 list<Str>::iterator eTexture;
392 for( eTexture=exclusionList->begin(); eTexture!=exclusionList->end(); eTexture++ )
394 if((*chkBrush)->HasTexture((*eTexture).GetBuffer()))
397 chkBrush = brushList.erase(chkBrush);
402 if( eTexture == exclusionList->end() )
407 void DEntity::ResetChecks(list<Str>* exclusionList)
409 for(list<DBrush *>::const_iterator resetBrush=brushList.begin(); resetBrush!=brushList.end(); resetBrush++)
411 (*resetBrush)->ResetChecks(exclusionList);
415 int DEntity::FixBrushes(bool rebuild)
417 g_FuncTable.m_pfnAllocateActiveBrushHandles();
421 for(list<DBrush *>::const_iterator fixBrush=brushList.begin(); fixBrush!=brushList.end(); fixBrush++)
423 int count = (*fixBrush)->RemoveRedundantPlanes();
429 g_FuncTable.m_pfnDeleteBrushHandle((*fixBrush)->QER_brush);
431 (*fixBrush)->BuildInRadiant(FALSE, NULL);
436 g_FuncTable.m_pfnReleaseActiveBrushHandles();
441 void DEntity::BuildInRadiant(bool allowDestruction)
443 bool makeEntity = strcmp(m_Classname, "worldspawn") ? true : false;
447 entity_t* pE = (entity_t*)g_FuncTable.m_pfnCreateEntityHandle();
449 epair_t* pEpS = GetNextChainItem(NULL, "classname", m_Classname);
453 for(list<DEPair* >::const_iterator buildEPair=epairList.begin(); buildEPair!=epairList.end(); buildEPair++)
455 pEp = GetNextChainItem(pEp, (*buildEPair)->key, (*buildEPair)->value);
458 g_EntityTable.m_pfnSetEntityKeyValList(pE, pEpS);
460 g_FuncTable.m_pfnCommitEntityHandleToMap(pE);
462 for(list<DBrush *>::const_iterator buildBrush=brushList.begin(); buildBrush!=brushList.end(); buildBrush++)
463 (*buildBrush)->BuildInRadiant(allowDestruction, NULL, pE);
465 for(list<DPatch *>::const_iterator buildPatch=patchList.begin(); buildPatch!=patchList.end(); buildPatch++)
466 (*buildPatch)->BuildInRadiant(pE);
472 for(list<DBrush *>::const_iterator buildBrush=brushList.begin(); buildBrush!=brushList.end(); buildBrush++)
473 (*buildBrush)->BuildInRadiant(allowDestruction, NULL);
475 for(list<DPatch *>::const_iterator buildPatch=patchList.begin(); buildPatch!=patchList.end(); buildPatch++)
476 (*buildPatch)->BuildInRadiant();
482 int DEntity::GetIDMax( void ) {
484 for(list<DBrush *>::const_iterator cntBrush=brushList.begin(); cntBrush!=brushList.end(); cntBrush++) {
485 if((*cntBrush)->m_nBrushID > max)
486 max = (*cntBrush)->m_nBrushID;
491 void DEntity::SetClassname( char *classname ) {
492 m_Classname = classname;
495 void DEntity::SaveToFile(FILE *pFile)
497 fprintf(pFile, "{\n");
499 fprintf(pFile, "\"classname\" \"%s\"\n", (const char *)m_Classname);
501 for(list<DEPair *>::const_iterator ep=epairList.begin(); ep!=epairList.end(); ep++)
503 fprintf(pFile, "\"%s\" \"%s\"\n", (const char *)(*ep)->key, (const char *)(*ep)->value);
506 for(list<DBrush *>::const_iterator bp=brushList.begin(); bp!=brushList.end(); bp++)
508 (*bp)->SaveToFile(pFile);
511 fprintf(pFile, "}\n");
514 void DEntity::ClearEPairs()
516 for(list<DEPair *>::const_iterator deadEPair=epairList.begin(); deadEPair!=epairList.end(); deadEPair++)
523 void DEntity::AddEPair(const char *key, const char *value) {
525 newEPair = FindEPairByKey( key );
527 newEPair = new DEPair;
528 newEPair->Build(key, value);
529 epairList.push_back(newEPair);
531 newEPair->Build(key, value);
535 void DEntity::LoadEPairList(epair_t *epl)
540 if(!strcmp(ep->key, "classname"))
541 SetClassname(ep->value);
543 AddEPair(ep->key, ep->value);
549 bool DEntity::ResetTextures(const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName,
550 int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild)
552 g_FuncTable.m_pfnDeselectAllBrushes();
554 g_FuncTable.m_pfnAllocateActiveBrushHandles();
558 for(list<DBrush *>::const_iterator resetBrush=brushList.begin(); resetBrush!=brushList.end(); resetBrush++)
560 bool tmp = (*resetBrush)->ResetTextures(textureName, fScale, fShift, rotation, newTextureName,
561 bResetTextureName, bResetScale, bResetShift, bResetRotation);
569 entity_t *pE = (*resetBrush)->QER_brush->owner;
570 g_FuncTable.m_pfnDeleteBrushHandle((*resetBrush)->QER_brush);
571 (*resetBrush)->BuildInRadiant(FALSE, NULL, pE->entityId == 0 ? NULL : pE);
573 if( pE->entityId == 0 ? NULL : pE )
580 if(bResetTextureName)
582 for(list<DPatch *>::const_iterator resetPatch=patchList.begin(); resetPatch!=patchList.end(); resetPatch++)
584 bool tmp = (*resetPatch)->ResetTextures(textureName, newTextureName);
592 entity_t *pE = (*resetPatch)->QER_brush->owner;
593 g_FuncTable.m_pfnDeleteBrushHandle((*resetPatch)->QER_brush);
594 (*resetPatch)->BuildInRadiant(pE->entityId == 0 ? NULL : pE);
600 g_FuncTable.m_pfnReleaseActiveBrushHandles();
605 DEPair* DEntity::FindEPairByKey(const char* keyname)
607 for(list<DEPair *>::const_iterator ep=epairList.begin(); ep!=epairList.end(); ep++)
609 char* c = (*ep)->key;
610 if(!strcmp(c, keyname))
616 void DEntity::RemoveFromRadiant()
618 g_EntityTable.m_pfnEntity_Free( (entity_t*)QER_Entity );
623 void DEntity::SpawnString(const char* key, const char* defaultstring, const char** out)
625 DEPair* pEP = FindEPairByKey(key);
629 *out = defaultstring;
633 void DEntity::SpawnInt(const char* key, const char* defaultstring, int* out)
635 DEPair* pEP = FindEPairByKey(key);
637 *out = atoi(pEP->value);
639 *out = atoi(defaultstring);
643 void DEntity::SpawnFloat(const char* key, const char* defaultstring, float* out)
645 DEPair* pEP = FindEPairByKey(key);
647 *out = static_cast< float >( atof( pEP->value ) );
649 *out = static_cast< float >( atof(defaultstring) );
653 void DEntity::SpawnVector(const char* key, const char* defaultstring, vec_t* out)
655 DEPair* pEP = FindEPairByKey(key);
657 sscanf(pEP->value, "%f %f %f", &out[0], &out[1], &out[2]);
659 sscanf(defaultstring, "%f %f %f", &out[0], &out[1], &out[2]);
663 int DEntity::GetBrushCount( void ) {
664 return brushList.size();
667 DBrush* DEntity::FindBrushByPointer( brush_t* brush ) {
668 for(list<DBrush *>::const_iterator listBrush = brushList.begin(); listBrush != brushList.end(); listBrush++) {
669 DBrush* pBrush = (*listBrush);
670 if(pBrush->QER_brush == brush) {