2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
24 #include "entity_entitymodel.h"
\r
33 static void Entity_FreeEpairs(entity_t *e);
\r
35 static void SetKeyValue (epair_t *&e, const char *key, const char *value);
\r
36 static void DeleteKey (epair_t *&e, const char *key);
\r
37 static const char *ValueForKey ( epair_t *&e, const char *key);
\r
39 static void Entity_OnKeyValueChanged(entity_t *e, const char* key, const char* value);
\r
42 entity_t *Entity_Alloc()
\r
45 e = (entity_t*)malloc (sizeof(*e));
\r
46 e->entityId = g_entityId++;
\r
47 VectorSet(e->origin, 0, 0, 0);
\r
48 VectorSet(e->color, 1, 1, 1);
\r
51 e->next = e->prev = NULL;
\r
52 e->brushes.onext = e->brushes.oprev = &e->brushes;
\r
55 e->model.pRender = NULL;
\r
56 e->model.pSelect = NULL;
\r
57 e->model.pEdit = NULL;
\r
62 void Entity_Free (entity_t *e)
\r
64 while (e->brushes.onext != &e->brushes)
\r
65 Brush_Free( e->brushes.onext, true );
\r
69 e->next->prev = e->prev;
\r
70 e->prev->next = e->next;
\r
73 Entity_FreeEpairs(e);
\r
75 if (e->model.pRender)
\r
77 e->model.pRender->DecRef();
\r
78 e->model.pRender = NULL;
\r
80 if (e->model.pSelect)
\r
82 e->model.pSelect->DecRef();
\r
83 e->model.pSelect = NULL;
\r
87 e->model.pEdit->DecRef();
\r
88 e->model.pEdit = NULL;
\r
94 // construct from entity
\r
95 entity_t *Entity_Clone (entity_t *e)
\r
100 n = Entity_Alloc();
\r
101 n->eclass = e->eclass;
\r
103 for (ep = e->epairs ; ep ; ep=ep->next)
\r
104 SetKeyValue(n, ep->key, ep->value);
\r
106 // copy some misc stuff as well
\r
107 VectorCopy( e->origin, n->origin );
\r
108 // VectorCopy( e->vRotation, n->vRotation );
\r
109 // VectorCopy( e->vScale, n->vScale );
\r
111 // n->bDirty = true;
\r
120 const char *ValueForKey ( epair_t *&e, const char *key)
\r
123 for (ep=e ; ep ; ep=ep->next)
\r
125 if (!strcmp (ep->key, key) )
\r
133 const char *ValueForKey (entity_t *ent, const char *key)
\r
135 return ValueForKey(ent->epairs, key);
\r
138 void SetKeyValue (epair_t *&e, const char *key, const char *value)
\r
141 for (ep=e ; ep ; ep=ep->next)
\r
143 if (!strcmp (ep->key, key) )
\r
146 ep->value = (char*)malloc(strlen(value)+1);
\r
147 strcpy (ep->value, value);
\r
151 ep = (epair_t*)malloc (sizeof(*ep));
\r
154 ep->key = (char*)malloc(strlen(key)+1);
\r
155 strcpy (ep->key, key);
\r
156 ep->value = (char*)malloc(strlen(value)+1);
\r
157 strcpy (ep->value, value);
\r
161 void SetKeyValue (entity_t *ent, const char *key, const char *value)
\r
165 Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL entity \n");
\r
169 if (!key || !key[0])
\r
171 Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL or zero-length key\n");
\r
175 SetKeyValue(ent->epairs, key, value);
\r
177 \todo TODO broadcast this through a clean messaging API ;-)
\r
179 Entity_OnKeyValueChanged(ent, key, value);
\r
182 void DeleteKey (epair_t *&e, const char *key)
\r
184 epair_t **ep, *next;
\r
190 if ( !strcmp (next->key, key) )
\r
202 void DeleteKey (entity_t *ent, const char *key)
\r
204 DeleteKey(ent->epairs, key);
\r
205 Entity_OnKeyValueChanged(ent, key, "");
\r
208 float FloatForKey (entity_t *ent, const char *key)
\r
212 k = ValueForKey (ent, key);
\r
213 return (float) atof(k);
\r
216 int IntForKey (entity_t *ent, const char *key)
\r
220 k = ValueForKey (ent, key);
\r
224 void GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
\r
228 k = ValueForKey (ent, key);
\r
229 sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
\r
236 Frees the entity epairs.
\r
239 void Entity_FreeEpairs(entity_t *e)
\r
241 epair_t *ep, *next;
\r
243 for (ep = e->epairs; ep; ep = next)
\r
253 void Entity_AddToList(entity_t *e, entity_t *elist)
\r
255 if (e->next || e->prev)
\r
256 Error ("Entity_AddToList: already linked");
\r
257 //e->next = elist->next;
\r
258 //elist->next->prev = e;
\r
262 e->prev = elist->prev;
\r
263 elist->prev->next = e;
\r
267 void Entity_RemoveFromList (entity_t *e)
\r
269 if (!e->next || !e->prev)
\r
270 Error ("Entity_RemoveFromList: not linked");
\r
271 e->next->prev = e->prev;
\r
272 e->prev->next = e->next;
\r
273 e->next = e->prev = NULL;
\r
276 void Entity_LinkBrush (entity_t *e, brush_t *b)
\r
278 if (b->oprev || b->onext)
\r
279 Error ("Entity_LinkBrush: Already linked");
\r
282 // b->onext = e->brushes.onext;
\r
283 // b->oprev = &e->brushes;
\r
284 // e->brushes.onext->oprev = b;
\r
285 // e->brushes.onext = b;
\r
287 SPoG - changed to add brushes to end of list instead of start - so this can be used by map loader.
\r
288 This could concievably cause a problem if someone is traversing e->brushes while calling this function.
\r
291 b->onext = &e->brushes;
\r
292 b->oprev = e->brushes.oprev;
\r
293 e->brushes.oprev->onext = b;
\r
294 e->brushes.oprev = b;
\r
297 void Entity_UnlinkBrush (brush_t *b)
\r
299 if (!b->onext || !b->oprev)
\r
300 Error ("Entity_UnlinkBrush: Not currently linked");
\r
301 b->onext->oprev = b->oprev;
\r
302 b->oprev->onext = b->onext;
\r
303 b->onext = b->oprev = NULL;
\r
308 int Entity_MemorySize(entity_t *e)
\r
313 for (ep = e->epairs; ep; ep = ep->next)
\r
315 size += strlen(ep->key);
\r
316 size += strlen(ep->value);
\r
317 size += sizeof(epair_t);
\r
319 size += sizeof(entity_t);
\r
323 epair_t* Entity_AllocateEpair(const char *key, const char *value)
\r
325 epair_t *ep = (epair_t*)malloc (sizeof(*ep));
\r
326 ep->key = (char*)malloc(strlen(key)+1);
\r
327 strcpy (ep->key, key);
\r
328 ep->value = (char*)malloc(strlen(value)+1);
\r
329 strcpy (ep->value, value);
\r
334 epair_t** Entity_GetKeyValList(entity_t *e)
\r
339 void Entity_SetKeyValList(entity_t *e, epair_t* ep)
\r
342 Sys_Printf( "Warning : pe->epairs != NULL in Entity_SetKeyValList, will not set\n" );
\r
346 for (epair_t *pe_ep = e->epairs; pe_ep; pe_ep = pe_ep->next)
\r
347 Entity_OnKeyValueChanged(e, pe_ep->key, pe_ep->value);
\r
354 this is meant to raise messages instead of calling the IEdit directly
\r
356 static void Entity_OnKeyValueChanged(entity_t *e, const char *key, const char* value)
\r
358 if(strcmp(key,"classname") == 0)
\r
360 e->eclass = Eclass_ForName(value, false);
\r
361 Entity_UpdateClass(e, value);
\r
362 if(strcmp(value,"light") == 0)
\r
363 for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
\r
364 Light_OnKeyValueChanged(e, ep->key, ep->value);
\r
366 for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
\r
367 e->model.pEdit->OnKeyValueChanged(e, ep->key, ep->value);
\r
369 else if(Entity_IsLight(e))
\r
370 Light_OnKeyValueChanged(e, key, value);
\r
371 else if(e->model.pEdit)
\r
372 e->model.pEdit->OnKeyValueChanged(e, key, value);
\r
374 // update brush mins/maxs for legacy culling system
\r
375 if(e->model.pRender && e->brushes.onext != &e->brushes)
\r
376 Brush_Build( e->brushes.onext, true, true, false, true );
\r