]> git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/entity/entity.cpp
uncrustify! now the code is only ugly on the *inside*
[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         entity_t *e;
44         e = (entity_t*)malloc( sizeof( *e ) );
45         e->entityId = g_entityId++;
46         VectorSet( e->origin, 0, 0, 0 );
47         VectorSet( e->color, 1, 1, 1 );
48         e->redoId = 0;
49         e->undoId = 0;
50         e->next = e->prev = NULL;
51         e->brushes.onext = e->brushes.oprev = &e->brushes;
52         e->epairs = NULL;
53         e->eclass = NULL;
54         e->model.pRender = NULL;
55         e->model.pSelect = NULL;
56         e->model.pEdit = NULL;
57         return e;
58 }
59
60 // destructor
61 void Entity_Free( entity_t *e ){
62         while ( e->brushes.onext != &e->brushes )
63                 Brush_Free( e->brushes.onext, true );
64
65         if ( e->next ) {
66                 e->next->prev = e->prev;
67                 e->prev->next = e->next;
68         }
69
70         Entity_FreeEpairs( e );
71
72         if ( e->model.pRender ) {
73                 e->model.pRender->DecRef();
74                 e->model.pRender = NULL;
75         }
76         if ( e->model.pSelect ) {
77                 e->model.pSelect->DecRef();
78                 e->model.pSelect = NULL;
79         }
80         if ( e->model.pEdit ) {
81                 e->model.pEdit->DecRef();
82                 e->model.pEdit = NULL;
83         }
84
85         free( e );
86 }
87
88 // construct from entity
89 entity_t    *Entity_Clone( entity_t *e ){
90         entity_t    *n;
91         epair_t     *ep;
92
93         n = Entity_Alloc();
94         n->eclass = e->eclass;
95
96         for ( ep = e->epairs ; ep ; ep = ep->next )
97                 SetKeyValue( n, ep->key, ep->value );
98
99         // copy some misc stuff as well
100         VectorCopy( e->origin, n->origin );
101 //      VectorCopy( e->vRotation, n->vRotation );
102 //      VectorCopy( e->vScale, n->vScale );
103
104 //  n->bDirty = true;
105
106         return n;
107 }
108
109
110
111
112
113 const char *ValueForKey( epair_t *&e, const char *key ){
114         epair_t *ep;
115         for ( ep = e ; ep ; ep = ep->next )
116         {
117                 if ( !strcmp( ep->key, key ) ) {
118                         return ep->value;
119                 }
120         }
121         return "";
122 }
123
124 const char *ValueForKey( entity_t *ent, const char *key ){
125         return ValueForKey( ent->epairs, key );
126 }
127
128 void    SetKeyValue( epair_t *&e, const char *key, const char *value ){
129         epair_t *ep;
130         for ( ep = e ; ep ; ep = ep->next )
131         {
132                 if ( !strcmp( ep->key, key ) ) {
133                         free( ep->value );
134                         ep->value = (char*)malloc( strlen( value ) + 1 );
135                         strcpy( ep->value, value );
136                         return;
137                 }
138         }
139         ep = (epair_t*)malloc( sizeof( *ep ) );
140         ep->next = e;
141         e = ep;
142         ep->key = (char*)malloc( strlen( key ) + 1 );
143         strcpy( ep->key, key );
144         ep->value = (char*)malloc( strlen( value ) + 1 );
145         strcpy( ep->value, value );
146
147 }
148
149 void SetKeyValue( entity_t *ent, const char *key, const char *value ){
150         if ( ent == NULL ) {
151                 Sys_FPrintf( SYS_ERR, "ERROR: SetKeyValue: NULL entity \n" );
152                 return;
153         }
154
155         if ( !key || !key[0] ) {
156                 Sys_FPrintf( SYS_ERR, "ERROR: SetKeyValue: NULL or zero-length key\n" );
157                 return;
158         }
159
160         SetKeyValue( ent->epairs, key, value );
161         /*!
162            \todo TODO broadcast this through a clean messaging API ;-)
163          */
164         Entity_OnKeyValueChanged( ent, key, value );
165 }
166
167 void    DeleteKey( epair_t *&e, const char *key ){
168         epair_t **ep, *next;
169
170         ep = &e;
171         while ( *ep )
172         {
173                 next = *ep;
174                 if ( !strcmp( next->key, key ) ) {
175                         *ep = next->next;
176                         free( next->key );
177                         free( next->value );
178                         free( next );
179                         return;
180                 }
181                 ep = &next->next;
182         }
183 }
184
185 void    DeleteKey( entity_t *ent, const char *key ){
186         DeleteKey( ent->epairs, key );
187         Entity_OnKeyValueChanged( ent, key, "" );
188 }
189
190 float   FloatForKey( entity_t *ent, const char *key ){
191         const char  *k;
192
193         k = ValueForKey( ent, key );
194         return (float) atof( k );
195 }
196
197 int IntForKey( entity_t *ent, const char *key ){
198         const char  *k;
199
200         k = ValueForKey( ent, key );
201         return atoi( k );
202 }
203
204 void    GetVectorForKey( entity_t *ent, const char *key, vec3_t vec ){
205         const char  *k;
206
207         k = ValueForKey( ent, key );
208         sscanf( k, "%f %f %f", &vec[0], &vec[1], &vec[2] );
209 }
210
211 /*
212    ===============
213    Entity_FreeEpairs
214
215    Frees the entity epairs.
216    ===============
217  */
218 void Entity_FreeEpairs( entity_t *e ){
219         epair_t *ep, *next;
220
221         for ( ep = e->epairs; ep; ep = next )
222         {
223                 next = ep->next;
224                 free( ep->key );
225                 free( ep->value );
226                 free( ep );
227         }
228         e->epairs = NULL;
229 }
230
231 void Entity_AddToList( entity_t *e, entity_t *elist ){
232         if ( e->next || e->prev ) {
233                 Error( "Entity_AddToList: already linked" );
234         }
235         //e->next = elist->next;
236         //elist->next->prev = e;
237         //elist->next = e;
238         //e->prev = elist;
239         e->next = elist;
240         e->prev = elist->prev;
241         elist->prev->next = e;
242         elist->prev = e;
243 }
244
245 void Entity_RemoveFromList( entity_t *e ){
246         if ( !e->next || !e->prev ) {
247                 Error( "Entity_RemoveFromList: not linked" );
248         }
249         e->next->prev = e->prev;
250         e->prev->next = e->next;
251         e->next = e->prev = NULL;
252 }
253
254 void Entity_LinkBrush( entity_t *e, brush_t *b ){
255         if ( b->oprev || b->onext ) {
256                 Error( "Entity_LinkBrush: Already linked" );
257         }
258         b->owner = e;
259
260 //      b->onext = e->brushes.onext;
261 //      b->oprev = &e->brushes;
262 //      e->brushes.onext->oprev = b;
263 //      e->brushes.onext = b;
264         /*
265         SPoG - changed to add brushes to end of list instead of start - so this can be used by map loader.
266         This could concievably cause a problem if someone is traversing e->brushes while calling this function.
267         So don't.
268          */
269         b->onext = &e->brushes;
270         b->oprev = e->brushes.oprev;
271         e->brushes.oprev->onext = b;
272         e->brushes.oprev = b;
273 }
274
275 void Entity_UnlinkBrush( brush_t *b ){
276         if ( !b->onext || !b->oprev ) {
277                 Error( "Entity_UnlinkBrush: Not currently linked" );
278         }
279         b->onext->oprev = b->oprev;
280         b->oprev->onext = b->onext;
281         b->onext = b->oprev = NULL;
282         b->owner = NULL;
283 }
284
285 // for undo
286 int Entity_MemorySize( entity_t *e ){
287         epair_t *ep;
288         int size = 0;
289
290         for ( ep = e->epairs; ep; ep = ep->next )
291         {
292                 size += strlen( ep->key );
293                 size += strlen( ep->value );
294                 size += sizeof( epair_t );
295         }
296         size += sizeof( entity_t );
297         return size;
298 }
299
300 epair_t* Entity_AllocateEpair( const char *key, const char *value ){
301         epair_t *ep = (epair_t*)malloc( sizeof( *ep ) );
302         ep->key = (char*)malloc( strlen( key ) + 1 );
303         strcpy( ep->key, key );
304         ep->value = (char*)malloc( strlen( value ) + 1 );
305         strcpy( ep->value, value );
306         ep->next = NULL;
307         return ep;
308 }
309
310 epair_t** Entity_GetKeyValList( entity_t *e ){
311         return &e->epairs;
312 }
313
314 void Entity_SetKeyValList( entity_t *e, epair_t* ep ){
315         if ( e->epairs ) {
316                 Sys_Printf( "Warning : pe->epairs != NULL in Entity_SetKeyValList, will not set\n" );
317         }
318         else {
319                 e->epairs = ep;
320
321                 for ( epair_t *pe_ep = e->epairs; pe_ep; pe_ep = pe_ep->next )
322                         Entity_OnKeyValueChanged( e, pe_ep->key, pe_ep->value );
323         }
324 }
325
326
327 /*!
328    \todo FIXME TTimo
329    this is meant to raise messages instead of calling the IEdit directly
330  */
331 static void Entity_OnKeyValueChanged( entity_t *e, const char *key, const char* value ){
332         if ( strcmp( key,"classname" ) == 0 ) {
333                 e->eclass = Eclass_ForName( value, false );
334                 Entity_UpdateClass( e, value );
335                 if ( strcmp( value,"light" ) == 0 ) {
336                         for ( epair_t* ep = e->epairs; ep != NULL; ep = ep->next )
337                                 Light_OnKeyValueChanged( e, ep->key, ep->value );
338                 }
339                 if ( e->model.pEdit ) {
340                         for ( epair_t* ep = e->epairs; ep != NULL; ep = ep->next )
341                                 e->model.pEdit->OnKeyValueChanged( e, ep->key, ep->value );
342                 }
343         }
344         else if ( Entity_IsLight( e ) ) {
345                 Light_OnKeyValueChanged( e, key, value );
346         }
347         else if ( e->model.pEdit ) {
348                 e->model.pEdit->OnKeyValueChanged( e, key, value );
349         }
350
351         // update brush mins/maxs for legacy culling system
352         if ( e->model.pRender && e->brushes.onext != &e->brushes ) {
353                 Brush_Build( e->brushes.onext, true, true, false, true );
354         }
355 }