1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402 |
- /*
- ===========================================================================
- Doom 3 GPL Source Code
- Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
- Doom 3 Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #include "../../idlib/precompiled.h"
- #pragma hdrstop
- #include "qe3.h"
- #include "../../renderer/tr_local.h"
- #include "../../renderer/model_local.h" // for idRenderModelMD5
- int g_entityId = 1;
- #define CURVE_TAG "curve_"
- extern void Brush_Resize(brush_t *b, idVec3 vMin, idVec3 vMax);
- int GetNumKeys(entity_t *ent)
- {
- // int iCount = 0;
- // for (epair_t* ep=ent->epairs ; ep ; ep=ep->next)
- // {
- // iCount++;
- // }
- int iCount = ent->epairs.GetNumKeyVals();
- return iCount;
- }
- const char *GetKeyString(entity_t *ent, int iIndex)
- {
- // for (epair_t* ep=ent->epairs ; ep ; ep=ep->next)
- // {
- // if (!iIndex--)
- // return ep->key;
- // }
- //
- // assert(0);
- // return NULL;
-
- if ( iIndex < GetNumKeys(ent) )
- {
- return ent->epairs.GetKeyVal(iIndex)->GetKey().c_str();
- }
- assert(0);
- return NULL;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- const char *ValueForKey(entity_t *ent, const char *key) {
- return ent->epairs.GetString(key);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void TrackMD3Angles(entity_t *e, const char *key, const char *value) {
- if ( idStr::Icmp(key, "angle") != 0 ) {
- return;
- }
- if ((e->eclass->fixedsize && e->eclass->nShowFlags & ECLASS_MISCMODEL) || EntityHasModel(e)) {
- float a = FloatForKey(e, "angle");
- float b = atof(value);
- if (a != b) {
- idVec3 vAngle;
- vAngle[0] = vAngle[1] = 0;
- vAngle[2] = -a;
- Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
- vAngle[2] = b;
- Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
- }
- }
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void SetKeyValue(entity_t *ent, const char *key, const char *value, bool trackAngles) {
- if (ent == NULL) {
- return;
- }
- if (!key || !key[0]) {
- return;
- }
- if (trackAngles) {
- TrackMD3Angles(ent, key, value);
- }
- ent->epairs.Set(key, value);
- GetVectorForKey(ent, "origin", ent->origin);
- // update sound in case this key was relevent
- Entity_UpdateSoundEmitter( ent );
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void SetKeyVec3(entity_t *ent, const char *key, idVec3 v) {
- if (ent == NULL) {
- return;
- }
- if (!key || !key[0]) {
- return;
- }
- idStr str;
- sprintf(str, "%g %g %g", v.x, v.y, v.z);
- ent->epairs.Set(key, str);
- GetVectorForKey(ent, "origin", ent->origin);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void SetKeyMat3(entity_t *ent, const char *key, idMat3 m) {
- if (ent == NULL) {
- return;
- }
- if (!key || !key[0]) {
- return;
- }
- idStr str;
-
- sprintf(str, "%g %g %g %g %g %g %g %g %g",m[0][0],m[0][1],m[0][2],m[1][0],m[1][1],m[1][2],m[2][0],m[2][1],m[2][2]);
-
- ent->epairs.Set(key, str);
- GetVectorForKey(ent, "origin", ent->origin);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void DeleteKey(entity_t *ent, const char *key) {
- ent->epairs.Delete(key);
- if (stricmp(key, "rotation") == 0) {
- ent->rotation.Identity();
- }
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- float FloatForKey(entity_t *ent, const char *key) {
- const char *k;
- k = ValueForKey(ent, key);
- if (k && *k) {
- return atof(k);
- }
- return 0.0;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- int IntForKey(entity_t *ent, const char *key) {
- const char *k;
- k = ValueForKey(ent, key);
- return atoi(k);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool GetVectorForKey(entity_t *ent, const char *key, idVec3 &vec) {
- const char *k;
- k = ValueForKey(ent, key);
- if (k && strlen(k) > 0) {
- sscanf(k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
- return true;
- }
- else {
- vec[0] = vec[1] = vec[2] = 0;
- }
- return false;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool GetVector4ForKey(entity_t *ent, const char *key, idVec4 &vec) {
- const char *k;
- k = ValueForKey(ent, key);
- if (k && strlen(k) > 0) {
- sscanf(k, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
- return true;
- }
- else {
- vec[0] = vec[1] = vec[2] = vec[3] = 0;
- }
- return false;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool GetFloatForKey(entity_t *ent, const char *key, float *f) {
- const char *k;
- k = ValueForKey(ent, key);
- if (k && strlen(k) > 0) {
- *f = atof(k);
- return true;
- }
- *f = 0;
- return false;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool GetMatrixForKey(entity_t *ent, const char *key, idMat3 &mat) {
- const char *k;
- k = ValueForKey(ent, key);
- if (k && strlen(k) > 0) {
- sscanf
- (
- k,
- "%f %f %f %f %f %f %f %f %f ",
- &mat[0][0],
- &mat[0][1],
- &mat[0][2],
- &mat[1][0],
- &mat[1][1],
- &mat[1][2],
- &mat[2][0],
- &mat[2][1],
- &mat[2][2]
- );
- return true;
- }
- else {
- mat.Identity();
- }
- return false;
- }
- /*
- =======================================================================================================================
- Entity_FreeEpairs Frees the entity epairs.
- =======================================================================================================================
- */
- void Entity_FreeEpairs(entity_t *e) {
- e->epairs.Clear();
- }
- /*
- =======================================================================================================================
- Entity_AddToList
- =======================================================================================================================
- */
- void Entity_AddToList(entity_t *e, entity_t *list) {
- if (e->next || e->prev) {
- Error("Entity_AddToList: allready linked");
- }
- e->next = list->next;
- list->next->prev = e;
- list->next = e;
- e->prev = list;
- }
- /*
- =======================================================================================================================
- Entity_RemoveFromList
- =======================================================================================================================
- */
- void Entity_RemoveFromList(entity_t *e) {
- if ( !e->next || !e->prev ) {
- Error("Entity_RemoveFromList: not linked");
- }
- e->next->prev = e->prev;
- e->prev->next = e->next;
- e->next = e->prev = NULL;
- }
- /*
- =======================================================================================================================
- Entity_Free Frees the entity and any brushes is has. The entity is removed from the global entities list.
- =======================================================================================================================
- */
- void Entity_Free( entity_t *e ) {
- while ( e->brushes.onext != &e->brushes ) {
- Brush_Free(e->brushes.onext);
- }
- if ( e->next ) {
- e->next->prev = e->prev;
- e->prev->next = e->next;
- }
- Entity_FreeEpairs( e );
- delete e;
- }
- /*
- =======================================================================================================================
- Entity_MemorySize
- =======================================================================================================================
- */
- int Entity_MemorySize( entity_t *e )
- {
- brush_t *b;
- int size;
- size = sizeof( entity_t ) + e->epairs.Size();
- for( b = e->brushes.onext; b != &e->brushes; b = b->onext )
- {
- size += Brush_MemorySize( b );
- }
- return( size );
- }
- /*
- =======================================================================================================================
- ParseEpair
- =======================================================================================================================
- */
- struct EpairFixup {
- const char *name;
- int type;
- };
- const EpairFixup FloatFixups[] = {
- { "origin", 1 },
- { "rotation", 2 },
- { "_color", 1 },
- { "falloff", 0 },
- { "light", 0 },
- { "light_target", 1 },
- { "light_up", 1 },
- { "light_right", 1 },
- { "light_start", 1 },
- { "light_center", 1 },
- { "light_end", 1 },
- { "light_radius", 1 },
- { "light_origin", 1 }
- };
- const int FixupCount = sizeof(FloatFixups) / sizeof(EpairFixup);
- void FixFloats(idDict *dict) {
- int count = dict->GetNumKeyVals();
- for (int i = 0; i < count; i++) {
- const idKeyValue *kv = dict->GetKeyVal(i);
- for (int j = 0; j < FixupCount; j++) {
- if (kv->GetKey().Icmp(FloatFixups[j].name) == 0) {
- idStr val;
- if (FloatFixups[j].type == 1) {
- idVec3 v;
- sscanf(kv->GetValue().c_str(), "%f %f %f", &v.x, &v.y, &v.z);
- sprintf(val, "%g %g %g", v.x, v.y, v.z);
- } else if (FloatFixups[j].type == 2) {
- idMat3 mat;
- sscanf(kv->GetValue().c_str(), "%f %f %f %f %f %f %f %f %f ",&mat[0][0],&mat[0][1],&mat[0][2],&mat[1][0],&mat[1][1],&mat[1][2],&mat[2][0],&mat[2][1],&mat[2][2]);
- sprintf(val, "%g %g %g %g %g %g %g %g %g",mat[0][0],mat[0][1],mat[0][2],mat[1][0],mat[1][1],mat[1][2],mat[2][0],mat[2][1],mat[2][2]);
- } else {
- float f = atof(kv->GetValue().c_str());
- sprintf(val, "%g", f);
- }
- dict->Set(kv->GetKey(), val);
- break;
- }
- }
- }
- }
- void ParseEpair(idDict *dict) {
- idStr key = token;
- GetToken(false);
- idStr val = token;
-
- if (key.Length() > 0) {
- dict->Set(key, val);
- }
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool EntityHasModel(entity_t *ent) {
- if (ent) {
- const char *model = ValueForKey(ent, "model");
- const char *name = ValueForKey(ent, "name");
- if (model && *model) {
- if ( idStr::Icmp(model, name) ) {
- return true;
- }
- }
- }
- return false;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- entity_t *Entity_New() {
- entity_t *ent = new entity_t;
-
- ent->prev = ent->next = NULL;
- ent->brushes.prev = ent->brushes.next = NULL;
- ent->brushes.oprev = ent->brushes.onext = NULL;
- ent->brushes.owner = NULL;
- ent->undoId = 0;
- ent->redoId = 0;
- ent->entityId = g_entityId++;
- ent->origin.Zero();
- ent->eclass = NULL;
- ent->md3Class = NULL;
- ent->lightOrigin.Zero();
- ent->lightRotation.Identity();
- ent->trackLightOrigin = false;
- ent->rotation.Identity();
- ent->lightDef = -1;
- ent->modelDef = -1;
- ent->soundEmitter = NULL;
- ent->curve = NULL;
- return ent;
- }
- void Entity_UpdateCurveData( entity_t *ent ) {
-
- if ( ent == NULL || ent->curve == NULL ) {
- return;
- }
- const idKeyValue *kv = ent->epairs.MatchPrefix( CURVE_TAG );
- if ( kv == NULL ) {
- if ( ent->curve ) {
- delete ent->curve;
- ent->curve = NULL;
- if ( g_qeglobals.d_select_mode == sel_editpoint ) {
- g_qeglobals.d_select_mode = sel_brush;
- }
- }
- return;
- }
- int c = ent->curve->GetNumValues();
- idStr str = va( "%i ( ", c );
- idVec3 v;
- for ( int i = 0; i < c; i++ ) {
- v = ent->curve->GetValue( i );
- str += " ";
- str += v.ToString();
- str += " ";
- }
- str += " )";
- ent->epairs.Set( kv->GetKey(), str );
- }
- idCurve<idVec3> *Entity_MakeCurve( entity_t *ent ) {
- const idKeyValue *kv = ent->epairs.MatchPrefix( CURVE_TAG );
- if ( kv ) {
- idStr str = kv->GetKey().Right( kv->GetKey().Length() - strlen( CURVE_TAG ) );
- if ( str.Icmp( "CatmullRomSpline" ) == 0 ) {
- return new idCurve_CatmullRomSpline<idVec3>();
- } else if ( str.Icmp( "Nurbs" ) == 0 ) {
- return new idCurve_NURBS<idVec3>();
- }
- }
- return NULL;
- }
- void Entity_SetCurveData( entity_t *ent ) {
- ent->curve = Entity_MakeCurve( ent );
- const idKeyValue *kv = ent->epairs.MatchPrefix( CURVE_TAG );
- if ( kv && ent->curve ) {
- idLexer lex;
- lex.LoadMemory( kv->GetValue(), kv->GetValue().Length(), "_curve" );
- int numPoints = lex.ParseInt();
- if ( numPoints > 0 ) {
- float *fp = new float[numPoints * 3];
- lex.Parse1DMatrix( numPoints * 3, fp );
- int time = 0;
- for ( int i = 0; i < numPoints * 3; i += 3 ) {
- idVec3 v;
- v.x = fp[i];
- v.y = fp[i+1];
- v.z = fp[i+2];
- ent->curve->AddValue( time, v );
- time += 100;
- }
- delete []fp;
- }
- }
- }
- entity_t *Entity_PostParse(entity_t *ent, brush_t *pList) {
- bool has_brushes;
- eclass_t *e;
- brush_t *b;
- idVec3 mins, maxs, zero;
- idBounds bo;
- zero.Zero();
- Entity_SetCurveData( ent );
- if (ent->brushes.onext == &ent->brushes) {
- has_brushes = false;
- }
- else {
- has_brushes = true;
- }
- bool needsOrigin = !GetVectorForKey(ent, "origin", ent->origin);
- const char *pModel = ValueForKey(ent, "model");
- const char *cp = ValueForKey(ent, "classname");
- if (strlen(cp)) {
- e = Eclass_ForName(cp, has_brushes);
- } else {
- const char *cp2 = ValueForKey(ent, "name");
- if (strlen(cp2)) {
- char buff[1024];
- strcpy(buff, cp2);
- int len = strlen(buff);
- while ((isdigit(buff[len-1]) || buff[len-1] == '_') && len > 0) {
- buff[len-1] = '\0';
- len--;
- }
- e = Eclass_ForName(buff, has_brushes);
- SetKeyValue(ent, "classname", buff, false);
- } else {
- e = Eclass_ForName("", has_brushes);
- }
- }
- idStr str;
-
- if (e->defArgs.GetString("model", "", str) && e->entityModel == NULL) {
- e->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &e->defArgs );
- }
-
- ent->eclass = e;
- bool hasModel = EntityHasModel(ent);
- if (hasModel) {
- ent->eclass->defArgs.GetString("model", "", str);
- if (str.Length()) {
- hasModel = false;
- ent->epairs.Delete("model");
- }
- }
- if (e->nShowFlags & ECLASS_WORLDSPAWN) {
- ent->origin.Zero();
- needsOrigin = false;
- ent->epairs.Delete( "model" );
- } else if (e->nShowFlags & ECLASS_LIGHT) {
- if (GetVectorForKey(ent, "light_origin", ent->lightOrigin)) {
- GetMatrixForKey(ent, "light_rotation", ent->lightRotation);
- ent->trackLightOrigin = true;
- } else if (hasModel) {
- SetKeyValue(ent, "light_origin", ValueForKey(ent, "origin"));
- ent->lightOrigin = ent->origin;
- if (GetMatrixForKey(ent, "rotation", ent->lightRotation)) {
- SetKeyValue(ent, "light_rotation", ValueForKey(ent, "rotation"));
- }
- ent->trackLightOrigin = true;
- }
- } else if ( e->nShowFlags & ECLASS_ENV ) {
- // need to create an origin from the bones here
- idVec3 org;
- idAngles ang;
- bo.Clear();
- bool hasBody = false;
- const idKeyValue *arg = ent->epairs.MatchPrefix( "body ", NULL );
- while ( arg ) {
- sscanf( arg->GetValue(), "%f %f %f %f %f %f", &org.x, &org.y, &org.z, &ang.pitch, &ang.yaw, &ang.roll );
- bo.AddPoint( org );
- arg = ent->epairs.MatchPrefix( "body ", arg );
- hasBody = true;
- }
- if (hasBody) {
- ent->origin = bo.GetCenter();
- }
- }
- if (e->fixedsize || hasModel) { // fixed size entity
- if (ent->brushes.onext != &ent->brushes) {
- for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
- b->entityModel = true;
- }
- }
- if (hasModel) {
- // model entity
- idRenderModel *modelHandle = renderModelManager->FindModel( pModel );
- if ( dynamic_cast<idRenderModelPrt*>( modelHandle ) || dynamic_cast<idRenderModelLiquid*>( modelHandle ) ) {
- bo.Zero();
- bo.ExpandSelf( 12.0f );
- } else {
- bo = modelHandle->Bounds( NULL );
- }
- VectorCopy(bo[0], mins);
- VectorCopy(bo[1], maxs);
- for (int i = 0; i < 3; i++) {
- if (mins[i] == maxs[i]) {
- mins[i]--;
- maxs[i]++;
- }
- }
- VectorAdd(mins, ent->origin, mins);
- VectorAdd(maxs, ent->origin, maxs);
- b = Brush_Create(mins, maxs, &e->texdef);
- b->modelHandle = modelHandle;
- float yaw = 0;
- bool convertAngles = GetFloatForKey(ent, "angle", &yaw);
- extern void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild);
- extern void Brush_Rotate(brush_t *b, idVec3 rot, idVec3 origin, bool bBuild);
-
- if (convertAngles) {
- idVec3 rot(0, 0, yaw);
- Brush_Rotate(b, rot, ent->origin, false);
- }
- if (GetMatrixForKey(ent, "rotation", ent->rotation)) {
- idBounds bo2;
- bo2.FromTransformedBounds(bo, ent->origin, ent->rotation);
- b->owner = ent;
- Brush_Resize(b, bo2[0], bo2[1]);
- }
- Entity_LinkBrush(ent, b);
- }
- if (!hasModel || (ent->eclass->nShowFlags & ECLASS_LIGHT && hasModel)) {
- // create a custom brush
- if (ent->trackLightOrigin) {
- mins = e->mins + ent->lightOrigin;
- maxs = e->maxs + ent->lightOrigin;
- } else {
- mins = e->mins + ent->origin;
- maxs = e->maxs + ent->origin;
- }
- b = Brush_Create(mins, maxs, &e->texdef);
- GetMatrixForKey(ent, "rotation", ent->rotation);
- Entity_LinkBrush(ent, b);
- b->trackLightOrigin = ent->trackLightOrigin;
- if ( e->texdef.name == NULL ) {
- brushprimit_texdef_t bp;
- texdef_t td;
- td.SetName( ent->eclass->defMaterial );
- Brush_SetTexture( b, &td, &bp, false );
- }
- }
- } else { // brush entity
- if (ent->brushes.next == &ent->brushes) {
- printf("Warning: Brush entity with no brushes\n");
- }
- if (!needsOrigin) {
- idStr cn = ValueForKey(ent, "classname");
- idStr name = ValueForKey(ent, "name");
- idStr model = ValueForKey(ent, "model");
- if (cn.Icmp("func_static") == 0) {
- if (name.Icmp(model) == 0) {
- needsOrigin = true;
- }
- }
- }
- if (needsOrigin) {
- idVec3 mins, maxs, mid;
- int i;
- char text[32];
- mins[0] = mins[1] = mins[2] = 999999;
- maxs[0] = maxs[1] = maxs[2] = -999999;
- // add in the origin
- for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
- Brush_Build(b, true, false, false);
- for (i = 0; i < 3; i++) {
- if (b->mins[i] < mins[i]) {
- mins[i] = b->mins[i];
- }
- if (b->maxs[i] > maxs[i]) {
- maxs[i] = b->maxs[i];
- }
- }
- }
- for (i = 0; i < 3; i++) {
- ent->origin[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
- }
- sprintf(text, "%i %i %i", (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]);
- SetKeyValue(ent, "origin", text);
- }
- if (!(e->nShowFlags & ECLASS_WORLDSPAWN)) {
- if (e->defArgs.FindKey("model") == NULL && (pModel == NULL || (pModel && strlen(pModel) == 0))) {
- SetKeyValue(ent, "model", ValueForKey(ent, "name"));
- }
- }
- else {
- DeleteKey(ent, "origin");
- }
- }
- // add all the brushes to the main list
- if (pList) {
- for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
- b->next = pList->next;
- pList->next->prev = b;
- b->prev = pList;
- pList->next = b;
- }
- }
- FixFloats(&ent->epairs);
- return ent;
- }
- /*
- =======================================================================================================================
- Entity_Parse If onlypairs is set, the classname info will not be looked up, and the entity will not be added to the
- global list. Used for parsing the project.
- =======================================================================================================================
- */
- entity_t *Entity_Parse(bool onlypairs, brush_t *pList) {
- entity_t *ent;
- if (!GetToken(true)) {
- return NULL;
- }
- if (strcmp(token, "{")) {
- Error("ParseEntity: { not found");
- }
- ent = Entity_New();
- ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
- ent->origin.Zero();
- int n = 0;
- do {
- if (!GetToken(true)) {
- Warning("ParseEntity: EOF without closing brace");
- return NULL;
- }
- if (!strcmp(token, "}")) {
- break;
- }
- if (!strcmp(token, "{")) {
- GetVectorForKey(ent, "origin", ent->origin);
- brush_t *b = Brush_Parse(ent->origin);
- if (b != NULL) {
- b->owner = ent;
- // add to the end of the entity chain
- b->onext = &ent->brushes;
- b->oprev = ent->brushes.oprev;
- ent->brushes.oprev->onext = b;
- ent->brushes.oprev = b;
- }
- else {
- break;
- }
- }
- else {
- ParseEpair(&ent->epairs);
- }
- } while (1);
- if (onlypairs) {
- return ent;
- }
- return Entity_PostParse(ent, pList);
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void VectorMidpoint(idVec3 va, idVec3 vb, idVec3 &out) {
- for (int i = 0; i < 3; i++) {
- out[i] = va[i] + ((vb[i] - va[i]) / 2);
- }
- }
- /*
- =======================================================================================================================
- Entity_Write
- =======================================================================================================================
- */
- void Entity_Write(entity_t *e, FILE *f, bool use_region) {
- brush_t *b;
- idVec3 origin;
- char text[128];
- int count;
- // if none of the entities brushes are in the region, don't write the entity at all
- if (use_region) {
- // in region mode, save the camera position as playerstart
- if (!strcmp(ValueForKey(e, "classname"), "info_player_start")) {
- fprintf(f, "{\n");
- fprintf(f, "\"classname\" \"info_player_start\"\n");
- fprintf
- (
- f,
- "\"origin\" \"%i %i %i\"\n",
- (int)g_pParentWnd->GetCamera()->Camera().origin[0],
- (int)g_pParentWnd->GetCamera()->Camera().origin[1],
- (int)g_pParentWnd->GetCamera()->Camera().origin[2]
- );
- fprintf(f, "\"angle\" \"%i\"\n", (int)g_pParentWnd->GetCamera()->Camera().angles[YAW]);
- fprintf(f, "}\n");
- return;
- }
- for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
- if (!Map_IsBrushFiltered(b)) {
- break; // got one
- }
- }
- if (b == &e->brushes) {
- return; // nothing visible
- }
- }
- if (e->eclass->nShowFlags & ECLASS_PLUGINENTITY) {
- // NOTE: the whole brush placement / origin stuff is a mess
- VectorCopy(e->origin, origin);
- sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
- SetKeyValue(e, "origin", text);
- }
- // if fixedsize, calculate a new origin based on the current brush position
- else if (e->eclass->fixedsize || EntityHasModel(e)) {
- if (!GetVectorForKey(e, "origin", origin)) {
- VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin);
- sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
- SetKeyValue(e, "origin", text);
- }
- }
- fprintf(f, "{\n");
- count = e->epairs.GetNumKeyVals();
- for (int j = 0; j < count; j++) {
- fprintf(f, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str());
- }
- if (!EntityHasModel(e)) {
- count = 0;
- for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
- if (e->eclass->fixedsize && !b->entityModel) {
- continue;
- }
- if (!use_region || !Map_IsBrushFiltered(b)) {
- fprintf(f, "// brush %i\n", count);
- count++;
- Brush_Write( b, f, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) );
- }
- }
- }
- fprintf(f, "}\n");
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- bool IsBrushSelected(brush_t *bSel) {
- for (brush_t * b = selected_brushes.next; b != NULL && b != &selected_brushes; b = b->next) {
- if (b == bSel) {
- return true;
- }
- }
- return false;
- }
- //
- // =======================================================================================================================
- // Entity_WriteSelected
- // =======================================================================================================================
- //
- void Entity_WriteSelected(entity_t *e, FILE *f) {
- brush_t *b;
- idVec3 origin;
- char text[128];
- int count;
- for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
- if (IsBrushSelected(b)) {
- break; // got one
- }
- }
- if (b == &e->brushes) {
- return; // nothing selected
- }
- // if fixedsize, calculate a new origin based on the current brush position
- if (e->eclass->fixedsize || EntityHasModel(e)) {
- if (!GetVectorForKey(e, "origin", origin)) {
- VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin);
- sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
- SetKeyValue(e, "origin", text);
- }
- }
- fprintf(f, "{\n");
-
- count = e->epairs.GetNumKeyVals();
- for (int j = 0; j < count; j++) {
- fprintf(f, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str());
- }
- if (!EntityHasModel(e)) {
- count = 0;
- for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
- if (e->eclass->fixedsize && !b->entityModel) {
- continue;
- }
- if (IsBrushSelected(b)) {
- fprintf(f, "// brush %i\n", count);
- count++;
- Brush_Write( b, f, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) );
- }
- }
- }
- fprintf(f, "}\n");
- }
- //
- // =======================================================================================================================
- // Entity_WriteSelected to a CMemFile
- // =======================================================================================================================
- //
- void Entity_WriteSelected(entity_t *e, CMemFile *pMemFile) {
- brush_t *b;
- idVec3 origin;
- char text[128];
- int count;
- for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
- if (IsBrushSelected(b)) {
- break; // got one
- }
- }
- if (b == &e->brushes) {
- return; // nothing selected
- }
- // if fixedsize, calculate a new origin based on the current brush position
- if (e->eclass->fixedsize || EntityHasModel(e)) {
- if (!GetVectorForKey(e, "origin", origin)) {
- VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin);
- sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
- SetKeyValue(e, "origin", text);
- }
- }
- MemFile_fprintf(pMemFile, "{\n");
- count = e->epairs.GetNumKeyVals();
- for (int j = 0; j < count; j++) {
- MemFile_fprintf(pMemFile, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str());
- }
- if (!EntityHasModel(e)) {
- count = 0;
- for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
- if (e->eclass->fixedsize && !b->entityModel) {
- continue;
- }
- if (IsBrushSelected(b)) {
- MemFile_fprintf(pMemFile, "// brush %i\n", count);
- count++;
- Brush_Write( b, pMemFile, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) );
- }
- }
- }
- MemFile_fprintf(pMemFile, "}\n");
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void Entity_SetName(entity_t *e, const char *name) {
- CString oldName = ValueForKey(e, "name");
- CString oldModel = ValueForKey(e, "model");
- SetKeyValue(e, "name", name);
- if (oldName == oldModel) {
- SetKeyValue(e, "model", name);
- }
- }
- extern bool Entity_NameIsUnique(const char *name);
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- void Entity_Name(entity_t *e, bool force) {
- const char *name = ValueForKey(e, "name");
- if (!force && name && name[0]) {
- return;
- }
- if (name && name[0] && Entity_NameIsUnique(name)) {
- return;
- }
- bool setModel = false;
- if (name[0]) {
- const char *model = ValueForKey(e, "model");
- if (model[0]) {
- if ( idStr::Icmp(model, name) == 0 ) {
- setModel = true;
- }
- }
- }
- const char *eclass = ValueForKey(e, "classname");
- if (eclass && eclass[0]) {
- idStr str = cvarSystem->GetCVarString( "radiant_nameprefix" );
- int id = Map_GetUniqueEntityID(str, eclass);
- if (str.Length()) {
- SetKeyValue(e, "name", va("%s_%s_%i", str.c_str(), eclass, id));
- } else {
- SetKeyValue(e, "name", va("%s_%i", eclass, id));
- }
- if (setModel) {
- if (str.Length()) {
- SetKeyValue(e, "model", va("%s_%s_%i", str.c_str(), eclass, id));
- } else {
- SetKeyValue(e, "model", va("%s_%i", eclass, id));
- }
- }
- }
- }
- /*
- =======================================================================================================================
- Entity_Create Creates a new entity out of the selected_brushes list. If the entity class is fixed size, the brushes
- are only used to find a midpoint. Otherwise, the brushes have their ownership transfered to the new entity.
- =======================================================================================================================
- */
- entity_t *Entity_Create(eclass_t *c, bool forceFixed) {
- entity_t *e;
- brush_t *b;
- idVec3 mins, maxs, origin;
- char text[32];
- texdef_t td;
- brushprimit_texdef_t bp;
- // check to make sure the brushes are ok
- for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
- if (b->owner != world_entity) {
- Sys_Status("Entity NOT created, brushes not all from world\n");
- Sys_Beep();
- return NULL;
- }
- }
- idStr str;
- if (c->defArgs.GetString("model", "", str) && c->entityModel == NULL) {
- c->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &c->defArgs );
- }
- // create it
- e = Entity_New();
- e->brushes.onext = e->brushes.oprev = &e->brushes;
- e->eclass = c;
- e->epairs.Copy(c->args);
- SetKeyValue(e, "classname", c->name);
- Entity_Name(e, false);
- // add the entity to the entity list
- Entity_AddToList(e, &entities);
- if (c->fixedsize) {
- //
- // just use the selection for positioning b = selected_brushes.next; for (i=0 ;
- // i<3 ; i++) { e->origin[i] = b->mins[i] - c->mins[i]; }
- //
- Select_GetMid(e->origin);
- VectorCopy(e->origin, origin);
- // create a custom brush
- VectorAdd(c->mins, e->origin, mins);
- VectorAdd(c->maxs, e->origin, maxs);
- b = Brush_Create(mins, maxs, &c->texdef);
- Entity_LinkBrush(e, b);
- if (c->defMaterial.Length()) {
- td.SetName(c->defMaterial);
- Brush_SetTexture(b, &td, &bp, false);
- }
- // delete the current selection
- Select_Delete();
- // select the new brush
- b->next = b->prev = &selected_brushes;
- selected_brushes.next = selected_brushes.prev = b;
- Brush_Build(b);
- }
- else {
- Select_GetMid(origin);
- // change the selected brushes over to the new entity
- for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
- Entity_UnlinkBrush(b);
- Entity_LinkBrush(e, b);
- Brush_Build(b); // so the key brush gets a name
- if (c->defMaterial.Length()) {
- td.SetName(c->defMaterial);
- Brush_SetTexture(b, &td, &bp, false);
- }
- }
- //for (int i = 0; i < 3; i++) {
- // origin[i] = vMin[i] + vMax[i] * 0.5;
- //}
- if (!forceFixed) {
- SetKeyValue(e, "model", ValueForKey(e, "name"));
- }
- }
- sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
- SetKeyValue(e, "origin", text);
- VectorCopy(origin, e->origin);
- Sys_UpdateWindows(W_ALL);
- return e;
- }
- void Brush_MakeDirty(brush_t *b) {
- for (face_t *f = b->brush_faces; f; f = f->next) {
- f->dirty = true;
- }
- }
- /*
- =======================================================================================================================
- Entity_LinkBrush
- =======================================================================================================================
- */
- void Entity_LinkBrush(entity_t *e, brush_t *b) {
- if (b->oprev || b->onext) {
- Error("Entity_LinkBrush: Allready linked");
- }
- Brush_MakeDirty(b);
- b->owner = e;
- b->onext = e->brushes.onext;
- b->oprev = &e->brushes;
- e->brushes.onext->oprev = b;
- e->brushes.onext = b;
- }
- /*
- =======================================================================================================================
- Entity_UnlinkBrush
- =======================================================================================================================
- */
- void Entity_UnlinkBrush(brush_t *b) {
- // if (!b->owner || !b->onext || !b->oprev)
- if (!b->onext || !b->oprev) {
- Error("Entity_UnlinkBrush: Not currently linked");
- }
- b->onext->oprev = b->oprev;
- b->oprev->onext = b->onext;
- b->onext = b->oprev = NULL;
- b->owner = NULL;
- }
- /*
- =======================================================================================================================
- Entity_Clone
- =======================================================================================================================
- */
- entity_t *Entity_Clone(entity_t *e) {
- entity_t *n;
- n = Entity_New();
- n->brushes.onext = n->brushes.oprev = &n->brushes;
- n->eclass = e->eclass;
- n->rotation = e->rotation;
- n->origin = e->origin;
- // add the entity to the entity list
- Entity_AddToList(n, &entities);
- n->epairs = e->epairs;
- return n;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- int GetUniqueTargetId(int iHint) {
- int iMin, iMax, i;
- BOOL fFound;
- entity_t *pe;
- fFound = FALSE;
- pe = entities.next;
- iMin = 0;
- iMax = 0;
- for (; pe != NULL && pe != &entities; pe = pe->next) {
- i = IntForKey(pe, "target");
- if (i) {
- iMin = Min(i, iMin);
- iMax = Max(i, iMax);
- if (i == iHint) {
- fFound = TRUE;
- }
- }
- }
- if (fFound) {
- return iMax + 1;
- }
- else {
- return iHint;
- }
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- entity_t *FindEntity(const char *pszKey, const char *pszValue) {
- entity_t *pe;
- pe = entities.next;
- for (; pe != NULL && pe != &entities; pe = pe->next) {
- if (!strcmp(ValueForKey(pe, pszKey), pszValue)) {
- return pe;
- }
- }
- return NULL;
- }
- /*
- =======================================================================================================================
- =======================================================================================================================
- */
- entity_t *FindEntityInt(const char *pszKey, int iValue) {
- entity_t *pe;
- pe = entities.next;
- for (; pe != NULL && pe != &entities; pe = pe->next) {
- if (IntForKey(pe, pszKey) == iValue) {
- return pe;
- }
- }
- return NULL;
- }
- /*
- ====================
- Entity_UpdateSoundEmitter
- Deletes the soundEmitter if the entity should not emit a sound due
- to it not having one, being filtered away, or the sound mode being turned off.
- Creates or updates the soundEmitter if needed
- ====================
- */
- void Entity_UpdateSoundEmitter( entity_t *ent ) {
- bool playing = false;
- // if an entity doesn't have any brushes at all, don't do anything
- // if the brush isn't displayed (filtered or culled), don't do anything
- if ( g_pParentWnd->GetCamera()->GetSoundMode()
- && ent->brushes.onext != &ent->brushes && !FilterBrush(ent->brushes.onext) ) {
- // check for sounds
- const char *v = ValueForKey( ent, "s_shader" );
- if ( v[0] ) {
- refSound_t sound;
- gameEdit->ParseSpawnArgsToRefSound( &ent->epairs, &sound );
- if ( !sound.waitfortrigger ) { // waitfortrigger will not start playing immediately
- if ( !ent->soundEmitter ) {
- ent->soundEmitter = g_qeglobals.sw->AllocSoundEmitter();
- }
- playing = true;
- ent->soundEmitter->UpdateEmitter( ent->origin, 0, &sound.parms );
- // always play on a single channel, so updates always override
- ent->soundEmitter->StartSound( sound.shader, SCHANNEL_ONE );
- }
- }
- }
- // delete the soundEmitter if not used
- if ( !playing && ent->soundEmitter ) {
- ent->soundEmitter->Free( true );
- ent->soundEmitter = NULL;
- }
- }
|