2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
30 Base class for all C++ objects. Provides fast run-time type checking and run-time
31 instancing of objects.
35 #include "../../idlib/precompiled.h"
38 #include "../Game_local.h"
43 /***********************************************************************
47 ***********************************************************************/
49 // this is the head of a singly linked list of all the idTypes
50 static idTypeInfo *typelist = NULL;
51 static idHierarchy<idTypeInfo> classHierarchy;
52 static int eventCallbackMemory = 0;
56 idTypeInfo::idClassType()
58 Constructor for class. Should only be called from CLASS_DECLARATION macro.
59 Handles linking class definition into class hierarchy. This should only happen
60 at startup as idTypeInfos are statically defined. Since static variables can be
61 initialized in any order, the constructor must handle the case that subclasses
62 are initialized before superclasses.
65 idTypeInfo::idTypeInfo( const char *classname, const char *superclass, idEventFunc<idClass> *eventCallbacks, idClass *( *CreateInstance )( void ),
66 void ( idClass::*Spawn )( void ), void ( idClass::*Save )( idSaveGame *savefile ) const, void ( idClass::*Restore )( idRestoreGame *savefile ) ) {
71 this->classname = classname;
72 this->superclass = superclass;
73 this->eventCallbacks = eventCallbacks;
74 this->eventMap = NULL;
77 this->Restore = Restore;
78 this->CreateInstance = CreateInstance;
79 this->super = idClass::GetClass( superclass );
80 this->freeEventMap = false;
84 // Check if any subclasses were initialized before their superclass
85 for( type = typelist; type != NULL; type = type->next ) {
86 if ( ( type->super == NULL ) && !idStr::Cmp( type->superclass, this->classname ) &&
87 idStr::Cmp( type->classname, "idClass" ) ) {
93 for ( insert = &typelist; *insert; insert = &(*insert)->next ) {
94 assert( idStr::Cmp( classname, (*insert)->classname ) );
95 if ( idStr::Cmp( classname, (*insert)->classname ) < 0 ) {
109 idTypeInfo::~idTypeInfo
112 idTypeInfo::~idTypeInfo() {
120 Initializes the event callback table for the class. Creates a
121 table for fast lookups of event functions. Should only be called once.
124 void idTypeInfo::Init( void ) {
126 idEventFunc<idClass> *def;
133 // we've already been initialized by a subclass
137 // make sure our superclass is initialized first
138 if ( super && !super->eventMap ) {
142 // add to our node hierarchy
144 node.ParentTo( super->node );
146 node.ParentTo( classHierarchy );
148 node.SetOwner( this );
150 // keep track of the number of children below each class
151 for( c = super; c != NULL; c = c->super ) {
155 // if we're not adding any new event callbacks, we can just use our superclass's table
156 if ( ( !eventCallbacks || !eventCallbacks->event ) && super ) {
157 eventMap = super->eventMap;
161 // set a flag so we know to delete the eventMap table
164 // Allocate our new table. It has to have as many entries as there
165 // are events. NOTE: could save some space by keeping track of the maximum
166 // event that the class responds to and doing range checking.
167 num = idEventDef::NumEventCommands();
168 eventMap = new eventCallback_t[ num ];
169 memset( eventMap, 0, sizeof( eventCallback_t ) * num );
170 eventCallbackMemory += sizeof( eventCallback_t ) * num;
172 // allocate temporary memory for flags so that the subclass's event callbacks
173 // override the superclass's event callback
174 set = new bool[ num ];
175 memset( set, 0, sizeof( bool ) * num );
177 // go through the inheritence order and copies the event callback function into
178 // a list indexed by the event number. This allows fast lookups of
180 for( c = this; c != NULL; c = c->super ) {
181 def = c->eventCallbacks;
186 // go through each entry until we hit the NULL terminator
187 for( i = 0; def[ i ].event != NULL; i++ ) {
188 ev = def[ i ].event->GetEventNum();
194 eventMap[ ev ] = def[ i ].function;
205 Should only be called when DLL or EXE is being shutdown.
206 Although it cleans up any allocated memory, it doesn't bother to remove itself
207 from the class list since the program is shutting down.
210 void idTypeInfo::Shutdown() {
211 // free up the memory used for event lookups
213 if ( freeEventMap ) {
223 /***********************************************************************
227 ***********************************************************************/
229 const idEventDef EV_Remove( "<immediateremove>", NULL );
230 const idEventDef EV_SafeRemove( "remove", NULL );
232 ABSTRACT_DECLARATION( NULL, idClass )
233 EVENT( EV_Remove, idClass::Event_Remove )
234 EVENT( EV_SafeRemove, idClass::Event_SafeRemove )
237 // alphabetical order
238 idList<idTypeInfo *> idClass::types;
240 idList<idTypeInfo *> idClass::typenums;
242 bool idClass::initialized = false;
243 int idClass::typeNumBits = 0;
244 int idClass::memused = 0;
245 int idClass::numobjects = 0;
252 void idClass::CallSpawn( void ) {
256 CallSpawnFunc( type );
261 idClass::CallSpawnFunc
264 classSpawnFunc_t idClass::CallSpawnFunc( idTypeInfo *cls ) {
265 classSpawnFunc_t func;
268 func = CallSpawnFunc( cls->super );
269 if ( func == cls->Spawn ) {
270 // don't call the same function twice in a row.
271 // this can happen when subclasses don't have their own spawn function.
276 ( this->*cls->Spawn )();
283 idClass::FindUninitializedMemory
286 void idClass::FindUninitializedMemory( void ) {
287 #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
288 unsigned long *ptr = ( ( unsigned long * )this ) - 1;
290 assert( ( size & 3 ) == 0 );
292 for ( int i = 0; i < size; i++ ) {
293 if ( ptr[i] == 0xcdcdcdcd ) {
294 const char *varName = GetTypeVariableName( GetClassname(), i << 2 );
295 gameLocal.Warning( "type '%s' has uninitialized variable %s (offset %d)", GetClassname(), varName, i << 2 );
306 void idClass::Spawn( void ) {
313 Destructor for object. Cancels any events that depend on this object.
316 idClass::~idClass() {
317 idEvent::CancelEvents( this );
322 idClass::DisplayInfo_f
325 void idClass::DisplayInfo_f( const idCmdArgs &args ) {
326 gameLocal.Printf( "Class memory status: %i bytes allocated in %i objects\n", memused, numobjects );
331 idClass::ListClasses_f
334 void idClass::ListClasses_f( const idCmdArgs &args ) {
338 gameLocal.Printf( "%-24s %-24s %-6s %-6s\n", "Classname", "Superclass", "Type", "Subclasses" );
339 gameLocal.Printf( "----------------------------------------------------------------------\n" );
341 for( i = 0; i < types.Num(); i++ ) {
343 gameLocal.Printf( "%-24s %-24s %6d %6d\n", type->classname, type->superclass, type->typeNum, type->lastChild - type->typeNum );
346 gameLocal.Printf( "...%d classes", types.Num() );
351 idClass::CreateInstance
354 idClass *idClass::CreateInstance( const char *name ) {
355 const idTypeInfo *type;
358 type = idClass::GetClass( name );
363 obj = type->CreateInstance();
371 Should be called after all idTypeInfos are initialized, so must be called
372 manually upon game code initialization. Tells all the idTypeInfos to initialize
373 their event callback table for the associated class. This should only be called
374 once during the execution of the program or DLL.
377 void idClass::Init( void ) {
381 gameLocal.Printf( "Initializing class hierarchy\n" );
384 gameLocal.Printf( "...already initialized\n" );
388 // init the event callback tables for all the classes
389 for( c = typelist; c != NULL; c = c->next ) {
393 // number the types according to the class hierarchy so we can quickly determine if a class
394 // is a subclass of another
396 for( c = classHierarchy.GetNext(); c != NULL; c = c->node.GetNext(), num++ ) {
401 // number of bits needed to send types over network
402 typeNumBits = idMath::BitsForInteger( num );
404 // create a list of the types so we can do quick lookups
405 // one list in alphabetical order, one in typenum order
406 types.SetGranularity( 1 );
408 typenums.SetGranularity( 1 );
409 typenums.SetNum( num );
411 for( c = typelist; c != NULL; c = c->next, num++ ) {
413 typenums[ c->typeNum ] = c;
418 gameLocal.Printf( "...%i classes, %i bytes for event callbacks\n", types.Num(), eventCallbackMemory );
426 void idClass::Shutdown( void ) {
429 for( c = typelist; c != NULL; c = c->next ) {
443 #ifdef ID_DEBUG_MEMORY
447 void * idClass::operator new( size_t s ) {
451 p = (int *)Mem_Alloc( s );
456 #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
457 unsigned long *ptr = (unsigned long *)p;
459 assert( ( size & 3 ) == 0 );
461 for ( int i = 1; i < size; i++ ) {
469 void * idClass::operator new( size_t s, int, int, char *, int ) {
473 p = (int *)Mem_Alloc( s );
478 #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
479 unsigned long *ptr = (unsigned long *)p;
481 assert( ( size & 3 ) == 0 );
483 for ( int i = 1; i < size; i++ ) {
491 #ifdef ID_DEBUG_MEMORY
492 #define new ID_DEBUG_NEW
500 void idClass::operator delete( void *ptr ) {
504 p = ( ( int * )ptr ) - 1;
511 void idClass::operator delete( void *ptr, int, int, char *, int ) {
515 p = ( ( int * )ptr ) - 1;
526 Returns the idTypeInfo for the name of the class passed in. This is a static function
527 so it must be called as idClass::GetClass( classname )
530 idTypeInfo *idClass::GetClass( const char *name ) {
537 if ( !initialized ) {
538 // idClass::Init hasn't been called yet, so do a slow lookup
539 for( c = typelist; c != NULL; c = c->next ) {
540 if ( !idStr::Cmp( c->classname, name ) ) {
545 // do a binary search through the list of types
547 max = types.Num() - 1;
548 while( min <= max ) {
549 mid = ( min + max ) / 2;
551 order = idStr::Cmp( c->classname, name );
554 } else if ( order > 0 ) {
570 idTypeInfo *idClass::GetType( const int typeNum ) {
573 if ( !initialized ) {
574 for( c = typelist; c != NULL; c = c->next ) {
575 if ( c->typeNum == typeNum ) {
579 } else if ( ( typeNum >= 0 ) && ( typeNum < types.Num() ) ) {
580 return typenums[ typeNum ];
588 idClass::GetClassname
590 Returns the text classname of the object.
593 const char *idClass::GetClassname( void ) const {
597 return type->classname;
602 idClass::GetSuperclass
604 Returns the text classname of the superclass.
607 const char *idClass::GetSuperclass( void ) const {
611 return cls->superclass;
616 idClass::CancelEvents
619 void idClass::CancelEvents( const idEventDef *ev ) {
620 idEvent::CancelEvents( this, ev );
625 idClass::PostEventArgs
628 bool idClass::PostEventArgs( const idEventDef *ev, int time, int numargs, ... ) {
635 if ( !idEvent::initialized ) {
640 if ( !c->eventMap[ ev->GetEventNum() ] ) {
641 // we don't respond to this event, so ignore it
645 // we service events on the client to avoid any bad code filling up the event pool
646 // we don't want them processed usually, unless when the map is (re)loading.
647 // we allow threads to run fine, though.
648 if ( gameLocal.isClient && ( gameLocal.GameState() != GAMESTATE_STARTUP ) && !IsType( idThread::Type ) ) {
652 va_start( args, numargs );
653 event = idEvent::Alloc( ev, numargs, args );
656 event->Schedule( this, c, time );
666 bool idClass::PostEventMS( const idEventDef *ev, int time ) {
667 return PostEventArgs( ev, time, 0 );
675 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1 ) {
676 return PostEventArgs( ev, time, 1, &arg1 );
684 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2 ) {
685 return PostEventArgs( ev, time, 2, &arg1, &arg2 );
693 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
694 return PostEventArgs( ev, time, 3, &arg1, &arg2, &arg3 );
702 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
703 return PostEventArgs( ev, time, 4, &arg1, &arg2, &arg3, &arg4 );
711 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
712 return PostEventArgs( ev, time, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
720 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
721 return PostEventArgs( ev, time, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
729 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
730 return PostEventArgs( ev, time, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
738 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
739 return PostEventArgs( ev, time, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
744 idClass::PostEventSec
747 bool idClass::PostEventSec( const idEventDef *ev, float time ) {
748 return PostEventArgs( ev, SEC2MS( time ), 0 );
753 idClass::PostEventSec
756 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1 ) {
757 return PostEventArgs( ev, SEC2MS( time ), 1, &arg1 );
762 idClass::PostEventSec
765 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2 ) {
766 return PostEventArgs( ev, SEC2MS( time ), 2, &arg1, &arg2 );
771 idClass::PostEventSec
774 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
775 return PostEventArgs( ev, SEC2MS( time ), 3, &arg1, &arg2, &arg3 );
780 idClass::PostEventSec
783 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
784 return PostEventArgs( ev, SEC2MS( time ), 4, &arg1, &arg2, &arg3, &arg4 );
789 idClass::PostEventSec
792 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
793 return PostEventArgs( ev, SEC2MS( time ), 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
798 idClass::PostEventSec
801 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
802 return PostEventArgs( ev, SEC2MS( time ), 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
807 idClass::PostEventSec
810 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
811 return PostEventArgs( ev, SEC2MS( time ), 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
816 idClass::PostEventSec
819 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
820 return PostEventArgs( ev, SEC2MS( time ), 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
825 idClass::ProcessEventArgs
828 bool idClass::ProcessEventArgs( const idEventDef *ev, int numargs, ... ) {
831 int data[ D_EVENT_MAXARGS ];
835 assert( idEvent::initialized );
838 num = ev->GetEventNum();
839 if ( !c->eventMap[ num ] ) {
840 // we don't respond to this event, so ignore it
844 va_start( args, numargs );
845 idEvent::CopyArgs( ev, numargs, args, data );
848 ProcessEventArgPtr( ev, data );
855 idClass::ProcessEvent
858 bool idClass::ProcessEvent( const idEventDef *ev ) {
859 return ProcessEventArgs( ev, 0 );
864 idClass::ProcessEvent
867 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1 ) {
868 return ProcessEventArgs( ev, 1, &arg1 );
873 idClass::ProcessEvent
876 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2 ) {
877 return ProcessEventArgs( ev, 2, &arg1, &arg2 );
882 idClass::ProcessEvent
885 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
886 return ProcessEventArgs( ev, 3, &arg1, &arg2, &arg3 );
891 idClass::ProcessEvent
894 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
895 return ProcessEventArgs( ev, 4, &arg1, &arg2, &arg3, &arg4 );
900 idClass::ProcessEvent
903 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
904 return ProcessEventArgs( ev, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
909 idClass::ProcessEvent
912 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
913 return ProcessEventArgs( ev, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
918 idClass::ProcessEvent
921 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
922 return ProcessEventArgs( ev, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
927 idClass::ProcessEvent
930 bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
931 return ProcessEventArgs( ev, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
936 idClass::ProcessEventArgPtr
939 bool idClass::ProcessEventArgPtr( const idEventDef *ev, int *data ) {
942 eventCallback_t callback;
945 assert( idEvent::initialized );
950 if ( IsType( idEntity::Type ) ) {
951 idEntity *ent = (idEntity*)this;
952 ts.PushState( ent->timeGroup );
956 if ( g_debugTriggers.GetBool() && ( ev == &EV_Activate ) && IsType( idEntity::Type ) ) {
957 const idEntity *ent = *reinterpret_cast<idEntity **>( data );
958 gameLocal.Printf( "%d: '%s' activated by '%s'\n", gameLocal.framenum, static_cast<idEntity *>( this )->GetName(), ent ? ent->GetName() : "NULL" );
962 num = ev->GetEventNum();
963 if ( !c->eventMap[ num ] ) {
964 // we don't respond to this event, so ignore it
968 callback = c->eventMap[ num ];
973 on ppc architecture, floats are passed in a seperate set of registers
974 the function prototypes must have matching float declaration
976 http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html
979 switch( ev->GetFormatspecIndex() ) {
980 case 1 << D_EVENT_MAXARGS :
981 ( this->*callback )();
984 // generated file - see CREATE_EVENT_CODE
985 #include "Callbacks.cpp"
988 gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
994 assert( D_EVENT_MAXARGS == 8 );
996 switch( ev->GetNumArgs() ) {
998 ( this->*callback )();
1002 typedef void ( idClass::*eventCallback_1_t )( const int );
1003 ( this->*( eventCallback_1_t )callback )( data[ 0 ] );
1007 typedef void ( idClass::*eventCallback_2_t )( const int, const int );
1008 ( this->*( eventCallback_2_t )callback )( data[ 0 ], data[ 1 ] );
1012 typedef void ( idClass::*eventCallback_3_t )( const int, const int, const int );
1013 ( this->*( eventCallback_3_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ] );
1017 typedef void ( idClass::*eventCallback_4_t )( const int, const int, const int, const int );
1018 ( this->*( eventCallback_4_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ] );
1022 typedef void ( idClass::*eventCallback_5_t )( const int, const int, const int, const int, const int );
1023 ( this->*( eventCallback_5_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ] );
1027 typedef void ( idClass::*eventCallback_6_t )( const int, const int, const int, const int, const int, const int );
1028 ( this->*( eventCallback_6_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
1032 typedef void ( idClass::*eventCallback_7_t )( const int, const int, const int, const int, const int, const int, const int );
1033 ( this->*( eventCallback_7_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ] );
1037 typedef void ( idClass::*eventCallback_8_t )( const int, const int, const int, const int, const int, const int, const int, const int );
1038 ( this->*( eventCallback_8_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ] );
1042 gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
1053 idClass::Event_Remove
1056 void idClass::Event_Remove( void ) {
1062 idClass::Event_SafeRemove
1065 void idClass::Event_SafeRemove( void ) {
1066 // Forces the remove to be done at a safe time
1067 PostEventMS( &EV_Remove, 0 );