]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/radiant/EditorEntity.cpp
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / tools / radiant / EditorEntity.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21
22 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.
23
24 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.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "qe3.h"
33 #include "../../renderer/tr_local.h"
34 #include "../../renderer/model_local.h" // for idRenderModelMD5
35 int g_entityId = 1;
36
37 #define CURVE_TAG "curve_"
38
39 extern void Brush_Resize(brush_t *b, idVec3 vMin, idVec3 vMax);
40
41 int     GetNumKeys(entity_t *ent)
42 {
43 //      int iCount = 0;
44 //      for (epair_t* ep=ent->epairs ; ep ; ep=ep->next)
45 //      {
46 //              iCount++;
47 //      }
48
49         int iCount = ent->epairs.GetNumKeyVals();
50         return iCount;
51 }
52
53 const char *GetKeyString(entity_t *ent, int iIndex)
54 {
55 //      for (epair_t* ep=ent->epairs ; ep ; ep=ep->next)
56 //      {
57 //              if (!iIndex--)
58 //                      return ep->key;
59 //      }
60 //
61 //      assert(0);
62 //      return NULL;
63         
64         if ( iIndex < GetNumKeys(ent) )
65         {
66                 return ent->epairs.GetKeyVal(iIndex)->GetKey().c_str();
67         }
68
69         assert(0);
70         return NULL;
71 }
72
73
74 /*
75  =======================================================================================================================
76  =======================================================================================================================
77  */
78 const char *ValueForKey(entity_t *ent, const char *key) {
79         return ent->epairs.GetString(key);
80 }
81
82 /*
83  =======================================================================================================================
84  =======================================================================================================================
85  */
86 void TrackMD3Angles(entity_t *e, const char *key, const char *value) {
87         if ( idStr::Icmp(key, "angle") != 0 ) {
88                 return;
89         }
90
91         if ((e->eclass->fixedsize && e->eclass->nShowFlags & ECLASS_MISCMODEL) || EntityHasModel(e)) {
92                 float   a = FloatForKey(e, "angle");
93                 float   b = atof(value);
94                 if (a != b) {
95                         idVec3  vAngle;
96                         vAngle[0] = vAngle[1] = 0;
97                         vAngle[2] = -a;
98                         Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
99                         vAngle[2] = b;
100                         Brush_Rotate(e->brushes.onext, vAngle, e->origin, true);
101                 }
102         }
103 }
104
105 /*
106  =======================================================================================================================
107  =======================================================================================================================
108  */
109 void SetKeyValue(entity_t *ent, const char *key, const char *value, bool trackAngles) {
110         if (ent == NULL) {
111                 return;
112         }
113
114         if (!key || !key[0]) {
115                 return;
116         }
117
118         if (trackAngles) {
119                 TrackMD3Angles(ent, key, value);
120         }
121
122         ent->epairs.Set(key, value);
123         GetVectorForKey(ent, "origin", ent->origin);
124
125         // update sound in case this key was relevent
126         Entity_UpdateSoundEmitter( ent );
127 }
128
129 /*
130  =======================================================================================================================
131  =======================================================================================================================
132  */
133 void SetKeyVec3(entity_t *ent, const char *key, idVec3 v) {
134         if (ent == NULL) {
135                 return;
136         }
137
138         if (!key || !key[0]) {
139                 return;
140         }
141
142         idStr str;
143         sprintf(str, "%g %g %g", v.x, v.y, v.z);
144         ent->epairs.Set(key, str);
145         GetVectorForKey(ent, "origin", ent->origin);
146 }
147
148 /*
149  =======================================================================================================================
150  =======================================================================================================================
151  */
152 void SetKeyMat3(entity_t *ent, const char *key, idMat3 m) {
153         if (ent == NULL) {
154                 return;
155         }
156
157         if (!key || !key[0]) {
158                 return;
159         }
160
161         idStr str;
162         
163         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]);
164         
165         ent->epairs.Set(key, str);
166         GetVectorForKey(ent, "origin", ent->origin);
167 }
168
169
170
171 /*
172  =======================================================================================================================
173  =======================================================================================================================
174  */
175 void DeleteKey(entity_t *ent, const char *key) {
176         ent->epairs.Delete(key);
177         if (stricmp(key, "rotation") == 0) {
178                 ent->rotation.Identity();
179         }
180 }
181
182 /*
183  =======================================================================================================================
184  =======================================================================================================================
185  */
186 float FloatForKey(entity_t *ent, const char *key) {
187         const char      *k;
188
189         k = ValueForKey(ent, key);
190         if (k && *k) {
191                 return atof(k);
192         }
193
194         return 0.0;
195 }
196
197 /*
198  =======================================================================================================================
199  =======================================================================================================================
200  */
201 int IntForKey(entity_t *ent, const char *key) {
202         const char      *k;
203
204         k = ValueForKey(ent, key);
205         return atoi(k);
206 }
207
208 /*
209  =======================================================================================================================
210  =======================================================================================================================
211  */
212 bool GetVectorForKey(entity_t *ent, const char *key, idVec3 &vec) {
213         const char      *k;
214         k = ValueForKey(ent, key);
215         if (k && strlen(k) > 0) {
216                 sscanf(k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
217                 return true;
218         }
219         else {
220                 vec[0] = vec[1] = vec[2] = 0;
221         }
222
223         return false;
224 }
225
226 /*
227  =======================================================================================================================
228  =======================================================================================================================
229  */
230 bool GetVector4ForKey(entity_t *ent, const char *key, idVec4 &vec) {
231         const char      *k;
232         k = ValueForKey(ent, key);
233         if (k && strlen(k) > 0) {
234                 sscanf(k, "%f %f %f %f", &vec[0], &vec[1], &vec[2], &vec[3]);
235                 return true;
236         }
237         else {
238                 vec[0] = vec[1] = vec[2] = vec[3] = 0;
239         }
240
241         return false;
242 }
243
244 /*
245  =======================================================================================================================
246  =======================================================================================================================
247  */
248 bool GetFloatForKey(entity_t *ent, const char *key, float *f) {
249         const char      *k;
250         k = ValueForKey(ent, key);
251         if (k && strlen(k) > 0) {
252                 *f = atof(k);
253                 return true;
254         }
255
256         *f = 0;
257         return false;
258 }
259
260 /*
261  =======================================================================================================================
262  =======================================================================================================================
263  */
264 bool GetMatrixForKey(entity_t *ent, const char *key, idMat3 &mat) {
265         const char      *k;
266         k = ValueForKey(ent, key);
267         if (k && strlen(k) > 0) {
268                 sscanf
269                 (
270                         k,
271                         "%f %f %f %f %f %f %f %f %f ",
272                         &mat[0][0],
273                         &mat[0][1],
274                         &mat[0][2],
275                         &mat[1][0],
276                         &mat[1][1],
277                         &mat[1][2],
278                         &mat[2][0],
279                         &mat[2][1],
280                         &mat[2][2]
281                 );
282                 return true;
283         }
284         else {
285                 mat.Identity();
286         }
287
288         return false;
289 }
290
291 /*
292  =======================================================================================================================
293     Entity_FreeEpairs Frees the entity epairs.
294  =======================================================================================================================
295  */
296 void Entity_FreeEpairs(entity_t *e) {
297         e->epairs.Clear();
298 }
299
300 /*
301  =======================================================================================================================
302     Entity_AddToList
303  =======================================================================================================================
304  */
305 void Entity_AddToList(entity_t *e, entity_t *list) {
306         if (e->next || e->prev) {
307                 Error("Entity_AddToList: allready linked");
308         }
309
310         e->next = list->next;
311         list->next->prev = e;
312         list->next = e;
313         e->prev = list;
314 }
315
316 /*
317  =======================================================================================================================
318     Entity_RemoveFromList
319  =======================================================================================================================
320  */
321 void Entity_RemoveFromList(entity_t *e) {
322         if ( !e->next || !e->prev ) {
323                 Error("Entity_RemoveFromList: not linked");
324         }
325
326         e->next->prev = e->prev;
327         e->prev->next = e->next;
328         e->next = e->prev = NULL;
329 }
330
331 /*
332  =======================================================================================================================
333     Entity_Free Frees the entity and any brushes is has. The entity is removed from the global entities list.
334  =======================================================================================================================
335  */
336 void Entity_Free( entity_t *e ) {
337
338         while ( e->brushes.onext != &e->brushes ) {
339                 Brush_Free(e->brushes.onext);
340         }
341
342         if ( e->next ) {
343                 e->next->prev = e->prev;
344                 e->prev->next = e->next;
345         }
346
347         Entity_FreeEpairs( e );
348
349         delete e;
350 }
351
352 /*
353  =======================================================================================================================
354     Entity_MemorySize
355  =======================================================================================================================
356  */
357
358 int Entity_MemorySize( entity_t *e ) 
359 {
360         brush_t         *b;
361         int                     size;
362
363         size = sizeof( entity_t ) + e->epairs.Size();
364         for( b = e->brushes.onext; b != &e->brushes; b = b->onext )
365         {
366                 size += Brush_MemorySize( b );
367 }
368         return( size );
369 }
370
371 /*
372  =======================================================================================================================
373     ParseEpair
374  =======================================================================================================================
375  */
376
377 struct EpairFixup {
378         const char *name;
379         int type;
380 };
381
382
383 const EpairFixup FloatFixups[] = {
384         { "origin", 1 },
385         { "rotation", 2 },
386         { "_color", 1 },
387         { "falloff", 0 },
388         { "light", 0 },
389         { "light_target", 1 },
390         { "light_up", 1 },
391         { "light_right", 1 },
392         { "light_start", 1 },
393         { "light_center", 1 },
394         { "light_end", 1 },
395         { "light_radius", 1 },
396         { "light_origin", 1 }
397 };
398
399 const int FixupCount = sizeof(FloatFixups) / sizeof(EpairFixup);
400
401 void FixFloats(idDict *dict) {
402         int count = dict->GetNumKeyVals();
403         for (int i = 0; i < count; i++) {
404                 const idKeyValue *kv = dict->GetKeyVal(i);
405                 for (int j = 0; j < FixupCount; j++) {
406                         if (kv->GetKey().Icmp(FloatFixups[j].name) == 0) {
407                                 idStr val;
408                                 if (FloatFixups[j].type == 1) {
409                                         idVec3 v;
410                                         sscanf(kv->GetValue().c_str(), "%f %f %f", &v.x, &v.y, &v.z);
411                                         sprintf(val, "%g %g %g", v.x, v.y, v.z);
412                                 } else if (FloatFixups[j].type == 2) {
413                                         idMat3 mat;
414                                         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]);
415                                         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]);
416                                 } else {
417                                         float f = atof(kv->GetValue().c_str());
418                                         sprintf(val, "%g", f);
419                                 }
420                                 dict->Set(kv->GetKey(), val);
421                                 break;
422                         }
423                 }
424         }
425 }
426
427 void ParseEpair(idDict *dict) {
428         idStr key = token;
429         GetToken(false);
430         idStr val = token;
431         
432         if (key.Length() > 0) {
433                 dict->Set(key, val);
434         }
435 }
436
437 /*
438  =======================================================================================================================
439  =======================================================================================================================
440  */
441 bool EntityHasModel(entity_t *ent) {
442         if (ent) {
443                 const char      *model = ValueForKey(ent, "model");
444                 const char      *name = ValueForKey(ent, "name");
445                 if (model && *model) {
446                         if ( idStr::Icmp(model, name) ) {
447                                 return true;
448                         }
449                 }
450         }
451
452         return false;
453 }
454
455 /*
456  =======================================================================================================================
457  =======================================================================================================================
458  */
459 entity_t *Entity_New() {
460         entity_t *ent = new entity_t;
461         
462         ent->prev = ent->next = NULL;
463         ent->brushes.prev = ent->brushes.next = NULL;
464         ent->brushes.oprev = ent->brushes.onext = NULL;
465         ent->brushes.owner = NULL;
466         ent->undoId = 0;
467         ent->redoId = 0;
468         ent->entityId = g_entityId++;
469         ent->origin.Zero();
470         ent->eclass = NULL;
471         ent->md3Class = NULL;
472         ent->lightOrigin.Zero();
473         ent->lightRotation.Identity();
474         ent->trackLightOrigin = false;
475         ent->rotation.Identity();
476         ent->lightDef = -1;
477         ent->modelDef = -1;
478         ent->soundEmitter = NULL;
479         ent->curve = NULL;
480         return ent;
481 }
482
483 void Entity_UpdateCurveData( entity_t *ent ) {
484         
485         if ( ent == NULL || ent->curve == NULL ) {
486                 return;
487         }
488
489         const idKeyValue *kv = ent->epairs.MatchPrefix( CURVE_TAG );
490         if ( kv == NULL ) { 
491                 if ( ent->curve ) {
492                         delete ent->curve;
493                         ent->curve = NULL;
494                         if ( g_qeglobals.d_select_mode == sel_editpoint ) {
495                                 g_qeglobals.d_select_mode = sel_brush;
496                         }
497                 }
498                 return;
499         }
500
501         int c = ent->curve->GetNumValues();
502         idStr str = va( "%i ( ", c );
503         idVec3 v;
504         for ( int i = 0; i < c; i++ ) {
505                 v = ent->curve->GetValue( i );
506                 str += " ";
507                 str += v.ToString();
508                 str += " ";
509         }
510         str += " )";
511
512         ent->epairs.Set( kv->GetKey(), str );
513
514 }
515
516 idCurve<idVec3> *Entity_MakeCurve( entity_t *ent ) {
517         const idKeyValue *kv = ent->epairs.MatchPrefix( CURVE_TAG );
518         if ( kv ) {
519                 idStr str = kv->GetKey().Right( kv->GetKey().Length() - strlen( CURVE_TAG ) );
520                 if ( str.Icmp( "CatmullRomSpline" ) == 0 ) {
521                         return new idCurve_CatmullRomSpline<idVec3>();
522                 } else if ( str.Icmp( "Nurbs" ) == 0 ) {
523                         return new idCurve_NURBS<idVec3>();
524                 }
525         }
526         return NULL;
527 }
528
529 void Entity_SetCurveData( entity_t *ent ) {
530
531         ent->curve = Entity_MakeCurve( ent );
532         const idKeyValue *kv = ent->epairs.MatchPrefix( CURVE_TAG );
533         if ( kv && ent->curve ) {
534                 idLexer lex;
535                 lex.LoadMemory( kv->GetValue(), kv->GetValue().Length(), "_curve" );
536                 int numPoints = lex.ParseInt();
537                 if ( numPoints > 0 ) {
538                         float *fp = new float[numPoints * 3];
539                         lex.Parse1DMatrix( numPoints * 3, fp );
540                         int time = 0;
541                         for ( int i = 0; i < numPoints * 3; i += 3 ) {
542                                 idVec3 v;
543                                 v.x = fp[i];
544                                 v.y = fp[i+1];
545                                 v.z = fp[i+2];
546                                 ent->curve->AddValue( time, v );
547                                 time += 100;
548                         }
549                         delete []fp;
550                 }
551         }
552
553 }
554
555 entity_t *Entity_PostParse(entity_t *ent, brush_t *pList) {
556         bool            has_brushes;
557         eclass_t        *e;
558         brush_t         *b;
559         idVec3          mins, maxs, zero;
560         idBounds bo;
561
562         zero.Zero();
563
564         Entity_SetCurveData( ent );
565
566         if (ent->brushes.onext == &ent->brushes) {
567                 has_brushes = false;
568         }
569         else {
570                 has_brushes = true;
571         }
572
573         bool needsOrigin = !GetVectorForKey(ent, "origin", ent->origin);
574         const char      *pModel = ValueForKey(ent, "model");
575
576         const char *cp = ValueForKey(ent, "classname");
577
578         if (strlen(cp)) {
579                 e = Eclass_ForName(cp, has_brushes);
580         } else {
581                 const char *cp2 = ValueForKey(ent, "name");
582                 if (strlen(cp2)) {
583                         char buff[1024];
584                         strcpy(buff, cp2);
585                         int len = strlen(buff);
586                         while ((isdigit(buff[len-1]) || buff[len-1] == '_') && len > 0) {
587                                 buff[len-1] = '\0';
588                                 len--;
589                         }
590                         e = Eclass_ForName(buff, has_brushes);
591                         SetKeyValue(ent, "classname", buff, false);
592                 } else {
593                         e = Eclass_ForName("", has_brushes);
594                 }
595         }
596
597         idStr str;
598         
599         if (e->defArgs.GetString("model", "", str) && e->entityModel == NULL) {
600                 e->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &e->defArgs );
601         }
602         
603         ent->eclass = e;
604
605         bool hasModel = EntityHasModel(ent);
606
607         if (hasModel) {
608                 ent->eclass->defArgs.GetString("model", "", str);
609                 if (str.Length()) {
610                         hasModel = false;
611                         ent->epairs.Delete("model");
612                 }
613         }
614
615         if (e->nShowFlags & ECLASS_WORLDSPAWN) {
616                 ent->origin.Zero();
617                 needsOrigin = false;
618                 ent->epairs.Delete( "model" );
619         } else if (e->nShowFlags & ECLASS_LIGHT) {
620                 if (GetVectorForKey(ent, "light_origin", ent->lightOrigin)) {
621                         GetMatrixForKey(ent, "light_rotation", ent->lightRotation);
622                         ent->trackLightOrigin = true;
623                 } else if (hasModel) {
624                         SetKeyValue(ent, "light_origin", ValueForKey(ent, "origin"));
625                         ent->lightOrigin = ent->origin;
626                         if (GetMatrixForKey(ent, "rotation", ent->lightRotation)) {
627                                 SetKeyValue(ent, "light_rotation", ValueForKey(ent, "rotation"));
628                         }
629                         ent->trackLightOrigin = true;
630                 }
631         } else if ( e->nShowFlags & ECLASS_ENV ) {
632                 // need to create an origin from the bones here
633                 idVec3 org;
634                 idAngles ang;
635                 bo.Clear();
636                 bool hasBody = false;
637                 const idKeyValue *arg = ent->epairs.MatchPrefix( "body ", NULL );
638                 while ( arg ) {
639                         sscanf( arg->GetValue(), "%f %f %f %f %f %f", &org.x, &org.y, &org.z, &ang.pitch, &ang.yaw, &ang.roll );
640                         bo.AddPoint( org );
641                         arg = ent->epairs.MatchPrefix( "body ", arg );
642                         hasBody = true;
643                 }
644                 if (hasBody) {
645                         ent->origin = bo.GetCenter();
646                 }
647         }
648
649         if (e->fixedsize || hasModel) {                 // fixed size entity
650                 if (ent->brushes.onext != &ent->brushes) {
651                         for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
652                                 b->entityModel = true;
653                         }
654                 }
655
656                 if (hasModel) {
657                         // model entity
658                         idRenderModel *modelHandle = renderModelManager->FindModel( pModel );
659
660                         if ( dynamic_cast<idRenderModelPrt*>( modelHandle ) || dynamic_cast<idRenderModelLiquid*>( modelHandle ) ) {
661                                 bo.Zero();
662                                 bo.ExpandSelf( 12.0f );
663                         } else {
664                                 bo = modelHandle->Bounds( NULL );
665                         }
666
667                         VectorCopy(bo[0], mins);
668                         VectorCopy(bo[1], maxs);
669                         for (int i = 0; i < 3; i++) {
670                                 if (mins[i] == maxs[i]) {
671                                         mins[i]--;
672                                         maxs[i]++;
673                                 }
674                         }
675                         VectorAdd(mins, ent->origin, mins);
676                         VectorAdd(maxs, ent->origin, maxs);
677                         b = Brush_Create(mins, maxs, &e->texdef);
678                         b->modelHandle = modelHandle;
679
680                         float           yaw = 0;
681                         bool            convertAngles = GetFloatForKey(ent, "angle", &yaw);
682                         extern void Brush_Rotate(brush_t *b, idMat3 matrix, idVec3 origin, bool bBuild);
683                         extern void Brush_Rotate(brush_t *b, idVec3 rot, idVec3 origin, bool bBuild);
684                         
685                         if (convertAngles) {
686                                 idVec3  rot(0, 0, yaw);
687                                 Brush_Rotate(b, rot, ent->origin, false);
688                         }
689
690                         if (GetMatrixForKey(ent, "rotation", ent->rotation)) {
691                                 idBounds bo2;
692                                 bo2.FromTransformedBounds(bo, ent->origin, ent->rotation);
693                                 b->owner = ent;
694                                 Brush_Resize(b, bo2[0], bo2[1]);
695                         }
696                         Entity_LinkBrush(ent, b);
697                 }
698
699                 if (!hasModel || (ent->eclass->nShowFlags & ECLASS_LIGHT && hasModel)) {
700                         // create a custom brush
701                         if (ent->trackLightOrigin) {
702                                 mins = e->mins + ent->lightOrigin;
703                                 maxs = e->maxs + ent->lightOrigin;
704                         } else {
705                                 mins = e->mins + ent->origin;
706                                 maxs = e->maxs + ent->origin;
707                         }
708
709                         b = Brush_Create(mins, maxs, &e->texdef);
710                         GetMatrixForKey(ent, "rotation", ent->rotation);
711                         Entity_LinkBrush(ent, b);
712                         b->trackLightOrigin = ent->trackLightOrigin;
713                         if ( e->texdef.name == NULL ) {
714                                 brushprimit_texdef_t bp;
715                                 texdef_t td;
716                                 td.SetName( ent->eclass->defMaterial );
717                                 Brush_SetTexture( b, &td, &bp, false );
718                         }
719                 }
720         } else {        // brush entity
721                 if (ent->brushes.next == &ent->brushes) {
722                         printf("Warning: Brush entity with no brushes\n");
723                 }
724
725                 if (!needsOrigin) {
726                         idStr cn = ValueForKey(ent, "classname");
727                         idStr name = ValueForKey(ent, "name");
728                         idStr model = ValueForKey(ent, "model");
729                         if (cn.Icmp("func_static") == 0) {
730                                 if (name.Icmp(model) == 0) {
731                                         needsOrigin = true;
732                                 }
733                         }
734                 }
735
736                 if (needsOrigin) {
737                         idVec3  mins, maxs, mid;
738                         int             i;
739                         char    text[32];
740                         mins[0] = mins[1] = mins[2] = 999999;
741                         maxs[0] = maxs[1] = maxs[2] = -999999;
742
743                         // add in the origin
744                         for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
745                                 Brush_Build(b, true, false, false);
746                                 for (i = 0; i < 3; i++) {
747                                         if (b->mins[i] < mins[i]) {
748                                                 mins[i] = b->mins[i];
749                                         }
750
751                                         if (b->maxs[i] > maxs[i]) {
752                                                 maxs[i] = b->maxs[i];
753                                         }
754                                 }
755                         }
756
757                         for (i = 0; i < 3; i++) {
758                                 ent->origin[i] = (mins[i] + ((maxs[i] - mins[i]) / 2));
759                         }
760
761                         sprintf(text, "%i %i %i", (int)ent->origin[0], (int)ent->origin[1], (int)ent->origin[2]);
762                         SetKeyValue(ent, "origin", text);
763                 }
764
765                 if (!(e->nShowFlags & ECLASS_WORLDSPAWN)) {
766                         if (e->defArgs.FindKey("model") == NULL && (pModel == NULL || (pModel && strlen(pModel) == 0))) {
767                                 SetKeyValue(ent, "model", ValueForKey(ent, "name"));
768                         }
769                 }
770                 else {
771                         DeleteKey(ent, "origin");
772                 }
773         }
774
775         // add all the brushes to the main list
776         if (pList) {
777                 for (b = ent->brushes.onext; b != &ent->brushes; b = b->onext) {
778                         b->next = pList->next;
779                         pList->next->prev = b;
780                         b->prev = pList;
781                         pList->next = b;
782                 }
783         }
784
785         FixFloats(&ent->epairs);
786
787         return ent;
788
789 }
790
791 /*
792  =======================================================================================================================
793     Entity_Parse If onlypairs is set, the classname info will not be looked up, and the entity will not be added to the
794     global list. Used for parsing the project.
795  =======================================================================================================================
796  */
797 entity_t *Entity_Parse(bool onlypairs, brush_t *pList) {
798         entity_t        *ent;
799
800         if (!GetToken(true)) {
801                 return NULL;
802         }
803
804         if (strcmp(token, "{")) {
805                 Error("ParseEntity: { not found");
806         }
807
808         ent = Entity_New();
809         ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
810         ent->origin.Zero();
811
812         int n = 0;
813         do {
814                 if (!GetToken(true)) {
815                         Warning("ParseEntity: EOF without closing brace");
816                         return NULL;
817                 }
818
819                 if (!strcmp(token, "}")) {
820                         break;
821                 }
822
823                 if (!strcmp(token, "{")) {
824                         GetVectorForKey(ent, "origin", ent->origin);
825                         brush_t *b = Brush_Parse(ent->origin);
826                         if (b != NULL) {
827                                 b->owner = ent;
828
829                                 // add to the end of the entity chain
830                                 b->onext = &ent->brushes;
831                                 b->oprev = ent->brushes.oprev;
832                                 ent->brushes.oprev->onext = b;
833                                 ent->brushes.oprev = b;
834                         }
835                         else {
836                                 break;
837                         }
838                 }
839                 else {
840                         ParseEpair(&ent->epairs);
841                 }
842         } while (1);
843
844         if (onlypairs) {
845                 return ent;
846         }
847
848         return Entity_PostParse(ent, pList);
849 }
850
851 /*
852  =======================================================================================================================
853  =======================================================================================================================
854  */
855 void VectorMidpoint(idVec3 va, idVec3 vb, idVec3 &out) {
856         for (int i = 0; i < 3; i++) {
857                 out[i] = va[i] + ((vb[i] - va[i]) / 2);
858         }
859 }
860
861 /*
862  =======================================================================================================================
863     Entity_Write
864  =======================================================================================================================
865  */
866 void Entity_Write(entity_t *e, FILE *f, bool use_region) {
867         brush_t *b;
868         idVec3  origin;
869         char    text[128];
870         int             count;
871
872         // if none of the entities brushes are in the region, don't write the entity at all
873         if (use_region) {
874                 // in region mode, save the camera position as playerstart
875                 if (!strcmp(ValueForKey(e, "classname"), "info_player_start")) {
876                         fprintf(f, "{\n");
877                         fprintf(f, "\"classname\" \"info_player_start\"\n");
878                         fprintf
879                         (
880                                 f,
881                                 "\"origin\" \"%i %i %i\"\n",
882                                 (int)g_pParentWnd->GetCamera()->Camera().origin[0],
883                                 (int)g_pParentWnd->GetCamera()->Camera().origin[1],
884                                 (int)g_pParentWnd->GetCamera()->Camera().origin[2]
885                         );
886                         fprintf(f, "\"angle\" \"%i\"\n", (int)g_pParentWnd->GetCamera()->Camera().angles[YAW]);
887                         fprintf(f, "}\n");
888                         return;
889                 }
890
891                 for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
892                         if (!Map_IsBrushFiltered(b)) {
893                                 break;  // got one
894                         }
895                 }
896
897                 if (b == &e->brushes) {
898                         return;         // nothing visible
899                 }
900         }
901
902         if (e->eclass->nShowFlags & ECLASS_PLUGINENTITY) {
903                 // NOTE: the whole brush placement / origin stuff is a mess
904                 VectorCopy(e->origin, origin);
905                 sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
906                 SetKeyValue(e, "origin", text);
907         }
908
909         // if fixedsize, calculate a new origin based on the current brush position
910         else if (e->eclass->fixedsize || EntityHasModel(e)) {
911                 if (!GetVectorForKey(e, "origin", origin)) {
912                         VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin);
913                         sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
914                         SetKeyValue(e, "origin", text);
915                 }
916         }
917
918         fprintf(f, "{\n");
919
920         count = e->epairs.GetNumKeyVals();
921         for (int j = 0; j < count; j++) {
922                 fprintf(f, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str());
923         }
924
925         if (!EntityHasModel(e)) {
926                 count = 0;
927                 for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
928                         if (e->eclass->fixedsize && !b->entityModel) {
929                                 continue;
930                         }
931                         if (!use_region || !Map_IsBrushFiltered(b)) {
932                                 fprintf(f, "// brush %i\n", count);
933                                 count++;
934                                 Brush_Write( b, f, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) );
935                         }
936                 }
937         }
938
939         fprintf(f, "}\n");
940 }
941
942 /*
943  =======================================================================================================================
944  =======================================================================================================================
945  */
946 bool IsBrushSelected(brush_t *bSel) {
947         for (brush_t * b = selected_brushes.next; b != NULL && b != &selected_brushes; b = b->next) {
948                 if (b == bSel) {
949                         return true;
950                 }
951         }
952
953         return false;
954 }
955
956 //
957 // =======================================================================================================================
958 //    Entity_WriteSelected
959 // =======================================================================================================================
960 //
961 void Entity_WriteSelected(entity_t *e, FILE *f) {
962         brush_t *b;
963         idVec3  origin;
964         char    text[128];
965         int             count;
966
967         for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
968                 if (IsBrushSelected(b)) {
969                         break;  // got one
970                 }
971         }
972
973         if (b == &e->brushes) {
974                 return;         // nothing selected
975         }
976
977         // if fixedsize, calculate a new origin based on the current brush position
978         if (e->eclass->fixedsize || EntityHasModel(e)) {
979                 if (!GetVectorForKey(e, "origin", origin)) {
980                         VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin);
981                         sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
982                         SetKeyValue(e, "origin", text);
983                 }
984         }
985
986         fprintf(f, "{\n");
987         
988         count = e->epairs.GetNumKeyVals();
989         for (int j = 0; j < count; j++) {
990                 fprintf(f, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str());
991         }
992
993         if (!EntityHasModel(e)) {
994                 count = 0;
995                 for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
996                         if (e->eclass->fixedsize && !b->entityModel) {
997                                 continue;
998                         }
999                         if (IsBrushSelected(b)) {
1000                                 fprintf(f, "// brush %i\n", count);
1001                                 count++;
1002                                 Brush_Write( b, f, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) );
1003                         }
1004                 }
1005         }
1006
1007         fprintf(f, "}\n");
1008 }
1009
1010 //
1011 // =======================================================================================================================
1012 //    Entity_WriteSelected to a CMemFile
1013 // =======================================================================================================================
1014 //
1015 void Entity_WriteSelected(entity_t *e, CMemFile *pMemFile) {
1016         brush_t *b;
1017         idVec3  origin;
1018         char    text[128];
1019         int             count;
1020
1021         for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
1022                 if (IsBrushSelected(b)) {
1023                         break;  // got one
1024                 }
1025         }
1026
1027         if (b == &e->brushes) {
1028                 return;         // nothing selected
1029         }
1030
1031         // if fixedsize, calculate a new origin based on the current brush position
1032         if (e->eclass->fixedsize || EntityHasModel(e)) {
1033                 if (!GetVectorForKey(e, "origin", origin)) {
1034                         VectorSubtract(e->brushes.onext->mins, e->eclass->mins, origin);
1035                         sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
1036                         SetKeyValue(e, "origin", text);
1037                 }
1038         }
1039
1040         MemFile_fprintf(pMemFile, "{\n");
1041
1042         count = e->epairs.GetNumKeyVals();
1043         for (int j = 0; j < count; j++) {
1044                 MemFile_fprintf(pMemFile, "\"%s\" \"%s\"\n", e->epairs.GetKeyVal(j)->GetKey().c_str(), e->epairs.GetKeyVal(j)->GetValue().c_str());
1045         }
1046
1047         if (!EntityHasModel(e)) {
1048                 count = 0;
1049                 for (b = e->brushes.onext; b != &e->brushes; b = b->onext) {
1050                         if (e->eclass->fixedsize && !b->entityModel) {
1051                                 continue;
1052                         }
1053                         if (IsBrushSelected(b)) {
1054                                 MemFile_fprintf(pMemFile, "// brush %i\n", count);
1055                                 count++;
1056                                 Brush_Write( b, pMemFile, e->origin, ( g_PrefsDlg.m_bNewMapFormat != FALSE ) );
1057                         }
1058                 }
1059         }
1060
1061         MemFile_fprintf(pMemFile, "}\n");
1062 }
1063
1064 /*
1065  =======================================================================================================================
1066  =======================================================================================================================
1067  */
1068 void Entity_SetName(entity_t *e, const char *name) {
1069         CString oldName = ValueForKey(e, "name");
1070         CString oldModel = ValueForKey(e, "model");
1071         SetKeyValue(e, "name", name);
1072         if (oldName == oldModel) {
1073                 SetKeyValue(e, "model", name);
1074         }
1075 }
1076
1077 extern bool Entity_NameIsUnique(const char *name);
1078
1079 /*
1080  =======================================================================================================================
1081  =======================================================================================================================
1082  */
1083 void Entity_Name(entity_t *e, bool force) {
1084         const char      *name = ValueForKey(e, "name");
1085
1086         if (!force && name && name[0]) {
1087                 return;
1088         }
1089
1090         if (name && name[0] && Entity_NameIsUnique(name)) {
1091                 return;
1092         }
1093
1094         bool    setModel = false;
1095         if (name[0]) {
1096                 const char      *model = ValueForKey(e, "model");
1097                 if (model[0]) {
1098                         if ( idStr::Icmp(model, name) == 0 ) {
1099                                 setModel = true;
1100                         }
1101                 }
1102         }
1103
1104         const char *eclass = ValueForKey(e, "classname");
1105         if (eclass && eclass[0]) {
1106                 idStr str = cvarSystem->GetCVarString( "radiant_nameprefix" );
1107                 int id = Map_GetUniqueEntityID(str, eclass);
1108                 if (str.Length()) {
1109                         SetKeyValue(e, "name", va("%s_%s_%i", str.c_str(), eclass, id));
1110                 } else {
1111                         SetKeyValue(e, "name", va("%s_%i", eclass, id));
1112                 }
1113                 if (setModel) {
1114                         if (str.Length()) {
1115                                 SetKeyValue(e, "model", va("%s_%s_%i", str.c_str(), eclass, id));
1116                         } else {
1117                                 SetKeyValue(e, "model", va("%s_%i",  eclass, id));
1118                         }
1119                 }
1120         }
1121 }
1122
1123 /*
1124  =======================================================================================================================
1125     Entity_Create Creates a new entity out of the selected_brushes list. If the entity class is fixed size, the brushes
1126     are only used to find a midpoint. Otherwise, the brushes have their ownership transfered to the new entity.
1127  =======================================================================================================================
1128  */
1129 entity_t *Entity_Create(eclass_t *c, bool forceFixed) {
1130         entity_t        *e;
1131         brush_t         *b;
1132         idVec3          mins, maxs, origin;
1133         char            text[32];
1134         texdef_t td;
1135         brushprimit_texdef_t bp;
1136
1137         // check to make sure the brushes are ok
1138         for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1139                 if (b->owner != world_entity) {
1140                         Sys_Status("Entity NOT created, brushes not all from world\n");
1141                         Sys_Beep();
1142                         return NULL;
1143                 }
1144         }
1145
1146         idStr str;
1147         if (c->defArgs.GetString("model", "", str) && c->entityModel == NULL) {
1148                 c->entityModel = gameEdit->ANIM_GetModelFromEntityDef( &c->defArgs );
1149         }
1150
1151         // create it
1152         e = Entity_New();
1153         e->brushes.onext = e->brushes.oprev = &e->brushes;
1154         e->eclass = c;
1155         e->epairs.Copy(c->args);
1156         SetKeyValue(e, "classname", c->name);
1157         Entity_Name(e, false);
1158
1159         // add the entity to the entity list
1160         Entity_AddToList(e, &entities);
1161
1162         if (c->fixedsize) {
1163                 //
1164                 // just use the selection for positioning b = selected_brushes.next; for (i=0 ;
1165                 // i<3 ; i++) { e->origin[i] = b->mins[i] - c->mins[i]; }
1166                 //
1167                 Select_GetMid(e->origin);
1168                 VectorCopy(e->origin, origin);
1169
1170                 // create a custom brush
1171                 VectorAdd(c->mins, e->origin, mins);
1172                 VectorAdd(c->maxs, e->origin, maxs);
1173
1174                 b = Brush_Create(mins, maxs, &c->texdef);
1175
1176                 Entity_LinkBrush(e, b);
1177
1178                 if (c->defMaterial.Length()) {
1179                         td.SetName(c->defMaterial);
1180                         Brush_SetTexture(b, &td, &bp, false);
1181                 }
1182
1183
1184                 // delete the current selection
1185                 Select_Delete();
1186
1187                 // select the new brush
1188                 b->next = b->prev = &selected_brushes;
1189                 selected_brushes.next = selected_brushes.prev = b;
1190
1191                 Brush_Build(b);
1192         }
1193         else {
1194
1195                 Select_GetMid(origin);
1196
1197                 // change the selected brushes over to the new entity
1198                 for (b = selected_brushes.next; b != &selected_brushes; b = b->next) {
1199                         Entity_UnlinkBrush(b);
1200                         Entity_LinkBrush(e, b);
1201                         Brush_Build(b); // so the key brush gets a name
1202                         if (c->defMaterial.Length()) {
1203                                 td.SetName(c->defMaterial);
1204                                 Brush_SetTexture(b, &td, &bp, false);
1205                         }
1206
1207                 }
1208
1209                 //for (int i = 0; i < 3; i++) {
1210                 //      origin[i] = vMin[i] + vMax[i] * 0.5;
1211                 //}
1212
1213                 if (!forceFixed) {
1214                         SetKeyValue(e, "model", ValueForKey(e, "name"));
1215                 }
1216         }
1217
1218         sprintf(text, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
1219         SetKeyValue(e, "origin", text);
1220         VectorCopy(origin, e->origin);
1221
1222         Sys_UpdateWindows(W_ALL);
1223         return e;
1224 }
1225
1226 void Brush_MakeDirty(brush_t *b) {
1227         for (face_t *f = b->brush_faces; f; f = f->next) {
1228                 f->dirty = true;
1229         }
1230 }
1231 /*
1232  =======================================================================================================================
1233     Entity_LinkBrush
1234  =======================================================================================================================
1235  */
1236 void Entity_LinkBrush(entity_t *e, brush_t *b) {
1237         if (b->oprev || b->onext) {
1238                 Error("Entity_LinkBrush: Allready linked");
1239         }
1240
1241         Brush_MakeDirty(b);
1242
1243         b->owner = e;
1244
1245         b->onext = e->brushes.onext;
1246         b->oprev = &e->brushes;
1247         e->brushes.onext->oprev = b;
1248         e->brushes.onext = b;
1249 }
1250
1251 /*
1252  =======================================================================================================================
1253     Entity_UnlinkBrush
1254  =======================================================================================================================
1255  */
1256 void Entity_UnlinkBrush(brush_t *b) {
1257         // if (!b->owner || !b->onext || !b->oprev)
1258         if (!b->onext || !b->oprev) {
1259                 Error("Entity_UnlinkBrush: Not currently linked");
1260         }
1261
1262         b->onext->oprev = b->oprev;
1263         b->oprev->onext = b->onext;
1264         b->onext = b->oprev = NULL;
1265         b->owner = NULL;
1266 }
1267
1268 /*
1269  =======================================================================================================================
1270     Entity_Clone
1271  =======================================================================================================================
1272  */
1273 entity_t *Entity_Clone(entity_t *e) {
1274         entity_t        *n;
1275
1276         n = Entity_New();
1277         n->brushes.onext = n->brushes.oprev = &n->brushes;
1278         n->eclass = e->eclass;
1279         n->rotation = e->rotation;
1280         n->origin = e->origin;
1281
1282         // add the entity to the entity list
1283         Entity_AddToList(n, &entities);
1284
1285         n->epairs  = e->epairs;
1286
1287         return n;
1288 }
1289
1290 /*
1291  =======================================================================================================================
1292  =======================================================================================================================
1293  */
1294 int GetUniqueTargetId(int iHint) {
1295         int                     iMin, iMax, i;
1296         BOOL            fFound;
1297         entity_t        *pe;
1298
1299         fFound = FALSE;
1300         pe = entities.next;
1301         iMin = 0;
1302         iMax = 0;
1303
1304         for (; pe != NULL && pe != &entities; pe = pe->next) {
1305                 i = IntForKey(pe, "target");
1306                 if (i) {
1307                         iMin = Min(i, iMin);
1308                         iMax = Max(i, iMax);
1309                         if (i == iHint) {
1310                                 fFound = TRUE;
1311                         }
1312                 }
1313         }
1314
1315         if (fFound) {
1316                 return iMax + 1;
1317         }
1318         else {
1319                 return iHint;
1320         }
1321 }
1322
1323 /*
1324  =======================================================================================================================
1325  =======================================================================================================================
1326  */
1327 entity_t *FindEntity(const char *pszKey, const char *pszValue) {
1328         entity_t        *pe;
1329
1330         pe = entities.next;
1331
1332         for (; pe != NULL && pe != &entities; pe = pe->next) {
1333                 if (!strcmp(ValueForKey(pe, pszKey), pszValue)) {
1334                         return pe;
1335                 }
1336         }
1337
1338         return NULL;
1339 }
1340
1341 /*
1342  =======================================================================================================================
1343  =======================================================================================================================
1344  */
1345 entity_t *FindEntityInt(const char *pszKey, int iValue) {
1346         entity_t        *pe;
1347
1348         pe = entities.next;
1349
1350         for (; pe != NULL && pe != &entities; pe = pe->next) {
1351                 if (IntForKey(pe, pszKey) == iValue) {
1352                         return pe;
1353                 }
1354         }
1355
1356         return NULL;
1357 }
1358
1359 /*
1360 ====================
1361 Entity_UpdateSoundEmitter
1362
1363 Deletes the soundEmitter if the entity should not emit a sound due
1364 to it not having one, being filtered away, or the sound mode being turned off.
1365
1366 Creates or updates the soundEmitter if needed
1367 ====================
1368 */
1369 void Entity_UpdateSoundEmitter( entity_t *ent ) {
1370         bool    playing = false;
1371
1372         // if an entity doesn't have any brushes at all, don't do anything
1373         // if the brush isn't displayed (filtered or culled), don't do anything
1374         if ( g_pParentWnd->GetCamera()->GetSoundMode() 
1375                 && ent->brushes.onext != &ent->brushes && !FilterBrush(ent->brushes.onext) ) {
1376                 // check for sounds
1377                 const char *v = ValueForKey( ent, "s_shader" );
1378                 if ( v[0] ) {
1379                         refSound_t      sound;
1380
1381                         gameEdit->ParseSpawnArgsToRefSound( &ent->epairs, &sound );
1382                         if ( !sound.waitfortrigger ) {  // waitfortrigger will not start playing immediately
1383                                 if ( !ent->soundEmitter ) {
1384                                         ent->soundEmitter = g_qeglobals.sw->AllocSoundEmitter();
1385                                 }
1386                                 playing = true;
1387                                 ent->soundEmitter->UpdateEmitter( ent->origin, 0, &sound.parms );
1388                                 // always play on a single channel, so updates always override
1389                                 ent->soundEmitter->StartSound( sound.shader, SCHANNEL_ONE );
1390                         }
1391                 }
1392         }
1393
1394         // delete the soundEmitter if not used
1395         if ( !playing && ent->soundEmitter ) {
1396                 ent->soundEmitter->Free( true );
1397                 ent->soundEmitter = NULL;
1398         }
1399
1400 }
1401