2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
24 #include "entity_entitymodel.h"
33 static void Entity_FreeEpairs( entity_t *e );
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 );
39 static void Entity_OnKeyValueChanged( entity_t *e, const char* key, const char* value );
42 entity_t *Entity_Alloc(){
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 );
50 e->next = e->prev = NULL;
51 e->brushes.onext = e->brushes.oprev = &e->brushes;
54 e->model.pRender = NULL;
55 e->model.pSelect = NULL;
56 e->model.pEdit = NULL;
61 void Entity_Free( entity_t *e ){
62 while ( e->brushes.onext != &e->brushes )
63 Brush_Free( e->brushes.onext, true );
66 e->next->prev = e->prev;
67 e->prev->next = e->next;
70 Entity_FreeEpairs( e );
72 if ( e->model.pRender ) {
73 e->model.pRender->DecRef();
74 e->model.pRender = NULL;
76 if ( e->model.pSelect ) {
77 e->model.pSelect->DecRef();
78 e->model.pSelect = NULL;
80 if ( e->model.pEdit ) {
81 e->model.pEdit->DecRef();
82 e->model.pEdit = NULL;
88 // construct from entity
89 entity_t *Entity_Clone( entity_t *e ){
94 n->eclass = e->eclass;
96 for ( ep = e->epairs ; ep ; ep = ep->next )
97 SetKeyValue( n, ep->key, ep->value );
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 );
113 const char *ValueForKey( epair_t *&e, const char *key ){
115 for ( ep = e ; ep ; ep = ep->next )
117 if ( !strcmp( ep->key, key ) ) {
124 const char *ValueForKey( entity_t *ent, const char *key ){
125 return ValueForKey( ent->epairs, key );
128 void SetKeyValue( epair_t *&e, const char *key, const char *value ){
130 for ( ep = e ; ep ; ep = ep->next )
132 if ( !strcmp( ep->key, key ) ) {
134 ep->value = (char*)malloc( strlen( value ) + 1 );
135 strcpy( ep->value, value );
139 ep = (epair_t*)malloc( sizeof( *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 );
149 void SetKeyValue( entity_t *ent, const char *key, const char *value ){
151 Sys_FPrintf( SYS_ERR, "ERROR: SetKeyValue: NULL entity \n" );
155 if ( !key || !key[0] ) {
156 Sys_FPrintf( SYS_ERR, "ERROR: SetKeyValue: NULL or zero-length key\n" );
160 SetKeyValue( ent->epairs, key, value );
162 \todo TODO broadcast this through a clean messaging API ;-)
164 Entity_OnKeyValueChanged( ent, key, value );
167 void DeleteKey( epair_t *&e, const char *key ){
174 if ( !strcmp( next->key, key ) ) {
185 void DeleteKey( entity_t *ent, const char *key ){
186 DeleteKey( ent->epairs, key );
187 Entity_OnKeyValueChanged( ent, key, "" );
190 float FloatForKey( entity_t *ent, const char *key ){
193 k = ValueForKey( ent, key );
194 return (float) atof( k );
197 int IntForKey( entity_t *ent, const char *key ){
200 k = ValueForKey( ent, key );
204 void GetVectorForKey( entity_t *ent, const char *key, vec3_t vec ){
207 k = ValueForKey( ent, key );
208 sscanf( k, "%f %f %f", &vec[0], &vec[1], &vec[2] );
215 Frees the entity epairs.
218 void Entity_FreeEpairs( entity_t *e ){
221 for ( ep = e->epairs; ep; ep = next )
231 void Entity_AddToList( entity_t *e, entity_t *elist ){
232 if ( e->next || e->prev ) {
233 Error( "Entity_AddToList: already linked" );
235 //e->next = elist->next;
236 //elist->next->prev = e;
240 e->prev = elist->prev;
241 elist->prev->next = e;
245 void Entity_RemoveFromList( entity_t *e ){
246 if ( !e->next || !e->prev ) {
247 Error( "Entity_RemoveFromList: not linked" );
249 e->next->prev = e->prev;
250 e->prev->next = e->next;
251 e->next = e->prev = NULL;
254 void Entity_LinkBrush( entity_t *e, brush_t *b ){
255 if ( b->oprev || b->onext ) {
256 Error( "Entity_LinkBrush: Already linked" );
260 // b->onext = e->brushes.onext;
261 // b->oprev = &e->brushes;
262 // e->brushes.onext->oprev = b;
263 // e->brushes.onext = b;
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.
269 b->onext = &e->brushes;
270 b->oprev = e->brushes.oprev;
271 e->brushes.oprev->onext = b;
272 e->brushes.oprev = b;
275 void Entity_UnlinkBrush( brush_t *b ){
276 if ( !b->onext || !b->oprev ) {
277 Error( "Entity_UnlinkBrush: Not currently linked" );
279 b->onext->oprev = b->oprev;
280 b->oprev->onext = b->onext;
281 b->onext = b->oprev = NULL;
286 int Entity_MemorySize( entity_t *e ){
290 for ( ep = e->epairs; ep; ep = ep->next )
292 size += strlen( ep->key );
293 size += strlen( ep->value );
294 size += sizeof( epair_t );
296 size += sizeof( entity_t );
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 );
310 epair_t** Entity_GetKeyValList( entity_t *e ){
314 void Entity_SetKeyValList( entity_t *e, epair_t* ep ){
316 Sys_Printf( "Warning : pe->epairs != NULL in Entity_SetKeyValList, will not set\n" );
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 );
329 this is meant to raise messages instead of calling the IEdit directly
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 );
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 );
344 else if ( Entity_IsLight( e ) ) {
345 Light_OnKeyValueChanged( e, key, value );
347 else if ( e->model.pEdit ) {
348 e->model.pEdit->OnKeyValueChanged( e, key, value );
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 );