more eol-style
[xonotic/netradiant.git] / plugins / entity / entity.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 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.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 #include "plugin.h"
23 #include "entity.h"
24 #include "entity_entitymodel.h"
25 #include "light.h"
26
27 int g_entityId = 1;
28
29
30
31 // internal
32
33 static void Entity_FreeEpairs(entity_t *e);
34
35 static void SetKeyValue (epair_t *&e, const char *key, const char *value);
36 static void  DeleteKey (epair_t *&e, const char *key);
37 static const char *ValueForKey ( epair_t *&e, const char *key);
38
39 static void Entity_OnKeyValueChanged(entity_t *e, const char* key, const char* value);
40
41 // constructor
42 entity_t *Entity_Alloc()
43 {
44   entity_t *e;
45         e = (entity_t*)malloc (sizeof(*e));
46         e->entityId = g_entityId++;
47   VectorSet(e->origin, 0, 0, 0);
48   VectorSet(e->color, 1, 1, 1);
49   e->redoId = 0;
50   e->undoId = 0;
51   e->next = e->prev = NULL;
52         e->brushes.onext = e->brushes.oprev = &e->brushes;
53   e->epairs = NULL;
54   e->eclass = NULL;
55   e->model.pRender = NULL;
56   e->model.pSelect = NULL;
57   e->model.pEdit = NULL;
58   return e;
59 }
60
61 // destructor
62 void Entity_Free (entity_t *e)
63 {
64         while (e->brushes.onext != &e->brushes)
65                 Brush_Free( e->brushes.onext, true );
66
67         if (e->next)
68         {
69                 e->next->prev = e->prev;
70                 e->prev->next = e->next;
71         }
72
73         Entity_FreeEpairs(e);
74
75   if (e->model.pRender)
76   {
77     e->model.pRender->DecRef();
78     e->model.pRender = NULL;
79   }
80   if (e->model.pSelect)
81   {
82     e->model.pSelect->DecRef();
83     e->model.pSelect = NULL;
84   }
85   if (e->model.pEdit)
86   {
87     e->model.pEdit->DecRef();
88     e->model.pEdit = NULL;
89   }
90
91         free (e);
92 }
93
94 // construct from entity
95 entity_t        *Entity_Clone (entity_t *e)
96 {
97         entity_t        *n;
98         epair_t         *ep;
99
100         n = Entity_Alloc();
101         n->eclass = e->eclass;
102
103         for (ep = e->epairs ; ep ; ep=ep->next)
104     SetKeyValue(n, ep->key, ep->value);
105
106         // copy some misc stuff as well
107         VectorCopy( e->origin, n->origin );
108 //      VectorCopy( e->vRotation, n->vRotation );
109 //      VectorCopy( e->vScale, n->vScale );
110
111 //  n->bDirty = true;
112
113         return n;
114 }
115
116
117
118
119
120 const char *ValueForKey ( epair_t *&e, const char *key)
121 {
122   epair_t *ep;
123   for (ep=e ; ep ; ep=ep->next)
124   {
125                 if (!strcmp (ep->key, key) )
126     {
127       return ep->value;
128     }
129   }
130   return "";
131 }
132
133 const char *ValueForKey (entity_t *ent, const char *key)
134 {
135   return ValueForKey(ent->epairs, key);
136 }
137
138 void    SetKeyValue (epair_t *&e, const char *key, const char *value)
139 {
140         epair_t *ep;
141   for (ep=e ; ep ; ep=ep->next)
142   {
143                 if (!strcmp (ep->key, key) )
144                 {
145                         free (ep->value);
146                         ep->value = (char*)malloc(strlen(value)+1);
147                         strcpy (ep->value, value);
148                         return;
149                 }
150   }
151         ep = (epair_t*)malloc (sizeof(*ep));
152         ep->next = e;
153         e = ep;
154         ep->key = (char*)malloc(strlen(key)+1);
155         strcpy (ep->key, key);
156         ep->value = (char*)malloc(strlen(value)+1);
157         strcpy (ep->value, value);
158
159 }
160
161 void SetKeyValue (entity_t *ent, const char *key, const char *value)
162 {
163         if (ent == NULL)
164   {
165     Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL entity \n");
166                 return;
167   }
168
169         if (!key || !key[0])
170   {
171     Sys_FPrintf(SYS_ERR, "ERROR: SetKeyValue: NULL or zero-length key\n");
172                 return;
173   }
174
175   SetKeyValue(ent->epairs, key, value);
176   /*!
177   \todo TODO broadcast this through a clean messaging API ;-)
178   */
179   Entity_OnKeyValueChanged(ent, key, value);
180 }
181
182 void    DeleteKey (epair_t *&e, const char *key)
183 {
184         epair_t **ep, *next;
185         
186         ep = &e;
187         while (*ep)
188         {
189                 next = *ep;
190                 if ( !strcmp (next->key, key) )
191                 {
192                         *ep = next->next;
193                         free(next->key);
194                         free(next->value);
195                         free(next);
196                         return;
197                 }
198                 ep = &next->next;
199         }
200 }
201
202 void    DeleteKey (entity_t *ent, const char *key)
203 {
204   DeleteKey(ent->epairs, key);
205   Entity_OnKeyValueChanged(ent, key, "");
206 }
207
208 float   FloatForKey (entity_t *ent, const char *key)
209 {
210         const char      *k;
211         
212         k = ValueForKey (ent, key);
213         return (float) atof(k);
214 }
215
216 int IntForKey (entity_t *ent, const char *key)
217 {
218         const char      *k;
219         
220         k = ValueForKey (ent, key);
221         return atoi(k);
222 }
223
224 void    GetVectorForKey (entity_t *ent, const char *key, vec3_t vec)
225 {
226         const char      *k;
227         
228         k = ValueForKey (ent, key);
229         sscanf (k, "%f %f %f", &vec[0], &vec[1], &vec[2]);
230 }
231
232 /*
233 ===============
234 Entity_FreeEpairs
235
236 Frees the entity epairs.
237 ===============
238 */
239 void Entity_FreeEpairs(entity_t *e)
240 {
241         epair_t *ep, *next;
242
243         for (ep = e->epairs; ep; ep = next)
244         {
245                 next = ep->next;
246                 free (ep->key);
247                 free (ep->value);
248                 free (ep);
249         }
250         e->epairs = NULL;
251 }
252
253 void Entity_AddToList(entity_t *e, entity_t *elist)
254 {
255         if (e->next || e->prev)
256                 Error ("Entity_AddToList: already linked");
257         //e->next = elist->next;
258         //elist->next->prev = e;
259         //elist->next = e;
260         //e->prev = elist;
261         e->next = elist;
262         e->prev = elist->prev;
263         elist->prev->next = e;
264         elist->prev = e;
265 }
266
267 void Entity_RemoveFromList (entity_t *e)
268 {
269         if (!e->next || !e->prev)
270                 Error ("Entity_RemoveFromList: not linked");
271         e->next->prev = e->prev;
272         e->prev->next = e->next;
273         e->next = e->prev = NULL;
274 }
275
276 void Entity_LinkBrush (entity_t *e, brush_t *b)
277 {
278         if (b->oprev || b->onext)
279                 Error ("Entity_LinkBrush: Already linked");
280         b->owner = e;
281
282 //      b->onext = e->brushes.onext;
283 //      b->oprev = &e->brushes;
284 //      e->brushes.onext->oprev = b;
285 //      e->brushes.onext = b;
286   /*
287   SPoG - changed to add brushes to end of list instead of start - so this can be used by map loader.
288   This could concievably cause a problem if someone is traversing e->brushes while calling this function.
289   So don't.
290   */
291   b->onext = &e->brushes;
292         b->oprev = e->brushes.oprev;
293         e->brushes.oprev->onext = b;
294         e->brushes.oprev = b;
295 }
296
297 void Entity_UnlinkBrush (brush_t *b)
298 {
299         if (!b->onext || !b->oprev)
300                 Error ("Entity_UnlinkBrush: Not currently linked");
301         b->onext->oprev = b->oprev;
302         b->oprev->onext = b->onext;
303         b->onext = b->oprev = NULL;
304         b->owner = NULL;
305 }
306
307 // for undo
308 int Entity_MemorySize(entity_t *e)
309 {
310         epair_t *ep;
311         int size = 0;
312
313         for (ep = e->epairs; ep; ep = ep->next)
314         {
315     size += strlen(ep->key);
316     size += strlen(ep->value);
317     size += sizeof(epair_t);
318         }
319   size += sizeof(entity_t);
320         return size;
321 }
322
323 epair_t* Entity_AllocateEpair(const char *key, const char *value)
324 {
325   epair_t *ep = (epair_t*)malloc (sizeof(*ep));
326   ep->key = (char*)malloc(strlen(key)+1);
327   strcpy (ep->key, key);
328   ep->value = (char*)malloc(strlen(value)+1);
329   strcpy (ep->value, value);
330   ep->next = NULL;
331   return ep;
332 }
333
334 epair_t** Entity_GetKeyValList(entity_t *e)
335 {
336   return &e->epairs;
337 }
338
339 void Entity_SetKeyValList(entity_t *e, epair_t* ep)
340 {
341   if( e->epairs )
342     Sys_Printf( "Warning : pe->epairs != NULL in Entity_SetKeyValList, will not set\n" );
343   else {
344     e->epairs = ep;
345
346     for (epair_t *pe_ep = e->epairs; pe_ep; pe_ep = pe_ep->next)
347       Entity_OnKeyValueChanged(e, pe_ep->key, pe_ep->value);
348   }
349 }
350
351
352 /*!
353 \todo FIXME TTimo
354 this is meant to raise messages instead of calling the IEdit directly
355 */
356 static void Entity_OnKeyValueChanged(entity_t *e, const char *key, const char* value)
357 {
358   if(strcmp(key,"classname") == 0)
359   {
360     e->eclass = Eclass_ForName(value, false);
361     Entity_UpdateClass(e, value);
362     if(strcmp(value,"light") == 0)
363       for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
364         Light_OnKeyValueChanged(e, ep->key, ep->value);
365     if(e->model.pEdit)
366       for(epair_t* ep = e->epairs; ep != NULL; ep=ep->next)
367         e->model.pEdit->OnKeyValueChanged(e, ep->key, ep->value);
368   }
369   else if(Entity_IsLight(e))
370     Light_OnKeyValueChanged(e, key, value);
371   else if(e->model.pEdit)
372     e->model.pEdit->OnKeyValueChanged(e, key, value);
373
374   // update brush mins/maxs for legacy culling system
375   if(e->model.pRender && e->brushes.onext != &e->brushes)
376     Brush_Build( e->brushes.onext, true, true, false, true );
377 }