2 ===========================================================================
3 Copyright (C) 1997-2006 Id Software, Inc.
5 This file is part of Quake 2 Tools source code.
7 Quake 2 Tools source code is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 2 of the License,
10 or (at your option) any later version.
12 Quake 2 Tools source code is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Quake 2 Tools source code; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 ===========================================================================
25 char *ValueForKey (entity_t *ent, char *key)
29 for (ep=ent->epairs ; ep ; ep=ep->next)
30 if (!strcmp (ep->key, key) )
35 void SetKeyValue (entity_t *ent, char *key, char *value)
45 for (ep=ent->epairs ; ep ; ep=ep->next)
46 if (!strcmp (ep->key, key) )
49 ep->value = qmalloc(strlen(value)+1);
50 strcpy (ep->value, value);
53 ep = qmalloc (sizeof(*ep));
54 ep->next = ent->epairs;
56 ep->key = qmalloc(strlen(key)+1);
57 strcpy (ep->key, key);
58 ep->value = qmalloc(strlen(value)+1);
59 strcpy (ep->value, value);
62 void DeleteKey (entity_t *ent, char *key)
70 if ( !strcmp (next->key, key) )
82 float FloatForKey (entity_t *ent, char *key)
86 k = ValueForKey (ent, key);
90 int IntForKey (entity_t *ent, char *key)
94 k = ValueForKey (ent, key);
98 void GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
102 k = ValueForKey (ent, key);
103 sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
111 Frees the entity and any brushes is has.
112 The entity is removed from the global entities list.
115 void Entity_Free (entity_t *e)
119 while (e->brushes.onext != &e->brushes)
120 Brush_Free (e->brushes.onext);
124 e->next->prev = e->prev;
125 e->prev->next = e->next;
128 for (ep = e->epairs ; ep ; ep=next)
141 epair_t *ParseEpair (void)
145 e = qmalloc (sizeof(*e));
147 e->key = qmalloc(strlen(token)+1);
148 strcpy (e->key, token);
151 e->value = qmalloc(strlen(token)+1);
152 strcpy (e->value, token);
161 If onlypairs is set, the classname info will not
162 be looked up, and the entity will not be added
163 to the global list. Used for parsing the project.
166 entity_t *Entity_Parse (qboolean onlypairs)
173 qboolean has_brushes;
175 if (!GetToken (true))
178 if (strcmp (token, "{") )
179 Error ("ParseEntity: { not found");
181 ent = qmalloc (sizeof(*ent));
182 ent->brushes.onext = ent->brushes.oprev = &ent->brushes;
186 if (!GetToken (true))
187 Error ("ParseEntity: EOF without closing brace");
188 if (!strcmp (token, "}") )
190 if (!strcmp (token, "{") )
195 // add to the end of the entity chain
196 b->onext = &ent->brushes;
197 b->oprev = ent->brushes.oprev;
198 ent->brushes.oprev->onext = b;
199 ent->brushes.oprev = b;
204 ep->next = ent->epairs;
212 if (ent->brushes.onext == &ent->brushes)
217 GetVectorForKey (ent, "origin", ent->origin);
219 e = Eclass_ForName (ValueForKey (ent, "classname"), has_brushes);
222 { // fixed size entity
223 if (ent->brushes.onext != &ent->brushes)
225 printf ("Warning: Fixed size entity with brushes\n");
227 while (ent->brushes.onext != &ent->brushes)
228 { // FIXME: this will free the entity and crash!
232 ent->brushes.next = ent->brushes.prev = &ent->brushes;
234 // create a custom brush
235 VectorAdd (e->mins, ent->origin, mins);
236 VectorAdd (e->maxs, ent->origin, maxs);
237 b = Brush_Create (mins, maxs, &e->texdef);
240 b->onext = ent->brushes.onext;
241 b->oprev = &ent->brushes;
242 ent->brushes.onext->oprev = b;
243 ent->brushes.onext = b;
247 if (ent->brushes.next == &ent->brushes)
248 printf ("Warning: Brush entity with no brushes\n");
251 // add all the brushes to the main list
252 for (b=ent->brushes.onext ; b != &ent->brushes ; b=b->onext)
254 b->next = active_brushes.next;
255 active_brushes.next->prev = b;
256 b->prev = &active_brushes;
257 active_brushes.next = b;
268 void Entity_Write (entity_t *e, FILE *f, qboolean use_region)
276 // if none of the entities brushes are in the region,
277 // don't write the entity at all
280 // in region mode, save the camera position as playerstart
281 if ( !strcmp(ValueForKey (e, "classname"), "info_player_start") )
284 fprintf (f, "\"classname\" \"info_player_start\"\n");
285 fprintf (f, "\"origin\" \"%i %i %i\"\n", (int)camera.origin[0],
286 (int)camera.origin[1], (int)camera.origin[2]);
287 fprintf (f, "\"angle\" \"%i\"\n", (int)camera.angles[YAW]);
292 for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
293 if (!Map_IsBrushFiltered(b))
296 if (b == &e->brushes)
297 return; // nothing visible
300 // if fixedsize, calculate a new origin based on the current
302 if (e->eclass->fixedsize)
304 VectorSubtract (e->brushes.onext->mins, e->eclass->mins, origin);
305 sprintf (text, "%i %i %i", (int)origin[0],
306 (int)origin[1], (int)origin[2]);
307 SetKeyValue (e, "origin", text);
311 for (ep = e->epairs ; ep ; ep=ep->next)
312 fprintf (f, "\"%s\" \"%s\"\n", ep->key, ep->value);
314 if (!e->eclass->fixedsize)
317 for (b=e->brushes.onext ; b != &e->brushes ; b=b->onext)
319 if (!use_region || !Map_IsBrushFiltered (b))
321 fprintf (f, "// brush %i\n", count);
336 Creates a new entity out of the selected_brushes list.
337 If the entity class is fixed size, the brushes are only
338 used to find a midpoint. Otherwise, the brushes have
339 their ownershi[ transfered to the new entity.
342 entity_t *Entity_Create (eclass_t *c)
349 // check to make sure the brushes are ok
351 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
352 if (b->owner != world_entity)
354 Sys_Printf ("Entity NOT created, brushes not all from world\n");
361 e = qmalloc(sizeof(*e));
362 e->brushes.onext = e->brushes.oprev = &e->brushes;
364 SetKeyValue (e, "classname", c->name);
366 // add the entity to the entity list
367 e->next = entities.next;
375 // just use the selection for positioning
377 b = selected_brushes.next;
378 for (i=0 ; i<3 ; i++)
379 e->origin[i] = b->mins[i] - c->mins[i];
381 // create a custom brush
382 VectorAdd (c->mins, e->origin, mins);
383 VectorAdd (c->maxs, e->origin, maxs);
384 b = Brush_Create (mins, maxs, &c->texdef);
386 Entity_LinkBrush (e, b);
388 // delete the current selection
391 // select the new brush
392 b->next = b->prev = &selected_brushes;
393 selected_brushes.next = selected_brushes.prev = b;
400 // change the selected brushes over to the new entity
402 for (b=selected_brushes.next ; b != &selected_brushes ; b=b->next)
404 Entity_UnlinkBrush (b);
405 Entity_LinkBrush (e, b);
406 Brush_Build( b ); // so the key brush gets a name
410 Sys_UpdateWindows (W_ALL);
420 void Entity_LinkBrush (entity_t *e, brush_t *b)
422 if (b->oprev || b->onext)
423 Error ("Entity_LinkBrush: Allready linked");
426 b->onext = e->brushes.onext;
427 b->oprev = &e->brushes;
428 e->brushes.onext->oprev = b;
429 e->brushes.onext = b;
437 void Entity_UnlinkBrush (brush_t *b)
439 if (!b->owner || !b->onext || !b->oprev)
440 Error ("Entity_UnlinkBrush: Not currently linked");
441 b->onext->oprev = b->oprev;
442 b->oprev->onext = b->onext;
443 b->onext = b->oprev = NULL;
454 entity_t *Entity_Clone (entity_t *e)
459 n = qmalloc(sizeof(*n));
460 n->brushes.onext = n->brushes.oprev = &n->brushes;
461 n->eclass = e->eclass;
463 // add the entity to the entity list
464 n->next = entities.next;
469 for (ep = e->epairs ; ep ; ep=ep->next)
471 np = qmalloc(sizeof(*np));
472 np->key = copystring(ep->key);
473 np->value = copystring(ep->value);
474 np->next = n->epairs;
480 int GetUniqueTargetId(int iHint)
491 for (; pe != NULL && pe != &entities ; pe = pe->next)
493 i = IntForKey(pe, "target");
509 entity_t *FindEntity(char *pszKey, char *pszValue)
515 for (; pe != NULL && pe != &entities ; pe = pe->next)
517 if (!strcmp(ValueForKey(pe, pszKey), pszValue))
524 entity_t *FindEntityInt(char *pszKey, int iValue)
530 for (; pe != NULL && pe != &entities ; pe = pe->next)
532 if (IntForKey(pe, pszKey) == iValue)