123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- 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.
- ===========================================================================
- */
- /*
- Base class for all C++ objects. Provides fast run-time type checking and run-time
- instancing of objects.
- */
- #pragma hdrstop
- #include "../../idlib/precompiled.h"
- #include "../Game_local.h"
- #include "TypeInfo.h"
- /***********************************************************************
- idTypeInfo
- ***********************************************************************/
- // this is the head of a singly linked list of all the idTypes
- static idTypeInfo *typelist = NULL;
- static idHierarchy<idTypeInfo> classHierarchy;
- static int eventCallbackMemory = 0;
- /*
- ================
- idTypeInfo::idClassType()
- Constructor for class. Should only be called from CLASS_DECLARATION macro.
- Handles linking class definition into class hierarchy. This should only happen
- at startup as idTypeInfos are statically defined. Since static variables can be
- initialized in any order, the constructor must handle the case that subclasses
- are initialized before superclasses.
- ================
- */
- idTypeInfo::idTypeInfo( const char *classname, const char *superclass, idEventFunc<idClass> *eventCallbacks, idClass *( *CreateInstance )(),
- void ( idClass::*Spawn )(), void ( idClass::*Save )( idSaveGame *savefile ) const, void ( idClass::*Restore )( idRestoreGame *savefile ) ) {
- idTypeInfo *type;
- idTypeInfo **insert;
- this->classname = classname;
- this->superclass = superclass;
- this->eventCallbacks = eventCallbacks;
- this->eventMap = NULL;
- this->Spawn = Spawn;
- this->Save = Save;
- this->Restore = Restore;
- this->CreateInstance = CreateInstance;
- this->super = idClass::GetClass( superclass );
- this->freeEventMap = false;
- typeNum = 0;
- lastChild = 0;
- // Check if any subclasses were initialized before their superclass
- for( type = typelist; type != NULL; type = type->next ) {
- if ( ( type->super == NULL ) && !idStr::Cmp( type->superclass, this->classname ) &&
- idStr::Cmp( type->classname, "idClass" ) ) {
- type->super = this;
- }
- }
- // Insert sorted
- for ( insert = &typelist; *insert; insert = &(*insert)->next ) {
- assert( idStr::Cmp( classname, (*insert)->classname ) );
- if ( idStr::Cmp( classname, (*insert)->classname ) < 0 ) {
- next = *insert;
- *insert = this;
- break;
- }
- }
- if ( !*insert ) {
- *insert = this;
- next = NULL;
- }
- }
- /*
- ================
- idTypeInfo::~idTypeInfo
- ================
- */
- idTypeInfo::~idTypeInfo() {
- Shutdown();
- }
- /*
- ================
- idTypeInfo::Init
- Initializes the event callback table for the class. Creates a
- table for fast lookups of event functions. Should only be called once.
- ================
- */
- void idTypeInfo::Init() {
- idTypeInfo *c;
- idEventFunc<idClass> *def;
- int ev;
- int i;
- bool *set;
- int num;
- if ( eventMap ) {
- // we've already been initialized by a subclass
- return;
- }
- // make sure our superclass is initialized first
- if ( super && !super->eventMap ) {
- super->Init();
- }
- // add to our node hierarchy
- if ( super ) {
- node.ParentTo( super->node );
- } else {
- node.ParentTo( classHierarchy );
- }
- node.SetOwner( this );
- // keep track of the number of children below each class
- for( c = super; c != NULL; c = c->super ) {
- c->lastChild++;
- }
- // if we're not adding any new event callbacks, we can just use our superclass's table
- if ( ( !eventCallbacks || !eventCallbacks->event ) && super ) {
- eventMap = super->eventMap;
- return;
- }
- // set a flag so we know to delete the eventMap table
- freeEventMap = true;
- // Allocate our new table. It has to have as many entries as there
- // are events. NOTE: could save some space by keeping track of the maximum
- // event that the class responds to and doing range checking.
- num = idEventDef::NumEventCommands();
- eventMap = new (TAG_SYSTEM) eventCallback_t[ num ];
- memset( eventMap, 0, sizeof( eventCallback_t ) * num );
- eventCallbackMemory += sizeof( eventCallback_t ) * num;
- // allocate temporary memory for flags so that the subclass's event callbacks
- // override the superclass's event callback
- set = new (TAG_SYSTEM) bool[ num ];
- memset( set, 0, sizeof( bool ) * num );
- // go through the inheritence order and copies the event callback function into
- // a list indexed by the event number. This allows fast lookups of
- // event functions.
- for( c = this; c != NULL; c = c->super ) {
- def = c->eventCallbacks;
- if ( !def ) {
- continue;
- }
- // go through each entry until we hit the NULL terminator
- for( i = 0; def[ i ].event != NULL; i++ ) {
- ev = def[ i ].event->GetEventNum();
- if ( set[ ev ] ) {
- continue;
- }
- set[ ev ] = true;
- eventMap[ ev ] = def[ i ].function;
- }
- }
- delete[] set;
- }
- /*
- ================
- idTypeInfo::Shutdown
- Should only be called when DLL or EXE is being shutdown.
- Although it cleans up any allocated memory, it doesn't bother to remove itself
- from the class list since the program is shutting down.
- ================
- */
- void idTypeInfo::Shutdown() {
- // free up the memory used for event lookups
- if ( eventMap ) {
- if ( freeEventMap ) {
- delete[] eventMap;
- }
- eventMap = NULL;
- }
- typeNum = 0;
- lastChild = 0;
- }
- /***********************************************************************
- idClass
- ***********************************************************************/
- const idEventDef EV_Remove( "<immediateremove>", NULL );
- const idEventDef EV_SafeRemove( "remove", NULL );
- ABSTRACT_DECLARATION( NULL, idClass )
- EVENT( EV_Remove, idClass::Event_Remove )
- EVENT( EV_SafeRemove, idClass::Event_SafeRemove )
- END_CLASS
- // alphabetical order
- idList<idTypeInfo *, TAG_IDCLASS> idClass::types;
- // typenum order
- idList<idTypeInfo *, TAG_IDCLASS> idClass::typenums;
- bool idClass::initialized = false;
- int idClass::typeNumBits = 0;
- int idClass::memused = 0;
- int idClass::numobjects = 0;
- /*
- ================
- idClass::CallSpawn
- ================
- */
- void idClass::CallSpawn() {
- idTypeInfo *type;
- type = GetType();
- CallSpawnFunc( type );
- }
- /*
- ================
- idClass::CallSpawnFunc
- ================
- */
- classSpawnFunc_t idClass::CallSpawnFunc( idTypeInfo *cls ) {
- classSpawnFunc_t func;
- if ( cls->super ) {
- func = CallSpawnFunc( cls->super );
- if ( func == cls->Spawn ) {
- // don't call the same function twice in a row.
- // this can happen when subclasses don't have their own spawn function.
- return func;
- }
- }
- ( this->*cls->Spawn )();
- return cls->Spawn;
- }
- /*
- ================
- idClass::FindUninitializedMemory
- ================
- */
- void idClass::FindUninitializedMemory() {
- #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
- unsigned long *ptr = ( ( unsigned long * )this ) - 1;
- int size = *ptr;
- assert( ( size & 3 ) == 0 );
- size >>= 2;
- for ( int i = 0; i < size; i++ ) {
- if ( ptr[i] == 0xcdcdcdcd ) {
- const char *varName = GetTypeVariableName( GetClassname(), i << 2 );
- gameLocal.Warning( "type '%s' has uninitialized variable %s (offset %d)", GetClassname(), varName, i << 2 );
- }
- }
- #endif
- }
- /*
- ================
- idClass::Spawn
- ================
- */
- void idClass::Spawn() {
- }
- /*
- ================
- idClass::~idClass
- Destructor for object. Cancels any events that depend on this object.
- ================
- */
- idClass::~idClass() {
- idEvent::CancelEvents( this );
- }
- /*
- ================
- idClass::DisplayInfo_f
- ================
- */
- void idClass::DisplayInfo_f( const idCmdArgs &args ) {
- gameLocal.Printf( "Class memory status: %i bytes allocated in %i objects\n", memused, numobjects );
- }
- /*
- ================
- idClass::ListClasses_f
- ================
- */
- void idClass::ListClasses_f( const idCmdArgs &args ) {
- int i;
- idTypeInfo *type;
- gameLocal.Printf( "%-24s %-24s %-6s %-6s\n", "Classname", "Superclass", "Type", "Subclasses" );
- gameLocal.Printf( "----------------------------------------------------------------------\n" );
- for( i = 0; i < types.Num(); i++ ) {
- type = types[ i ];
- gameLocal.Printf( "%-24s %-24s %6d %6d\n", type->classname, type->superclass, type->typeNum, type->lastChild - type->typeNum );
- }
- gameLocal.Printf( "...%d classes", types.Num() );
- }
- /*
- ================
- idClass::CreateInstance
- ================
- */
- idClass *idClass::CreateInstance( const char *name ) {
- const idTypeInfo *type;
- idClass *obj;
- type = idClass::GetClass( name );
- if ( !type ) {
- return NULL;
- }
- obj = type->CreateInstance();
- return obj;
- }
- /*
- ================
- idClass::Init
- Should be called after all idTypeInfos are initialized, so must be called
- manually upon game code initialization. Tells all the idTypeInfos to initialize
- their event callback table for the associated class. This should only be called
- once during the execution of the program or DLL.
- ================
- */
- void idClass::Init() {
- idTypeInfo *c;
- int num;
- gameLocal.Printf( "Initializing class hierarchy\n" );
- if ( initialized ) {
- gameLocal.Printf( "...already initialized\n" );
- return;
- }
- // init the event callback tables for all the classes
- for( c = typelist; c != NULL; c = c->next ) {
- c->Init();
- }
- // number the types according to the class hierarchy so we can quickly determine if a class
- // is a subclass of another
- num = 0;
- for( c = classHierarchy.GetNext(); c != NULL; c = c->node.GetNext(), num++ ) {
- c->typeNum = num;
- c->lastChild += num;
- }
- // number of bits needed to send types over network
- typeNumBits = idMath::BitsForInteger( num );
- // create a list of the types so we can do quick lookups
- // one list in alphabetical order, one in typenum order
- types.SetGranularity( 1 );
- types.SetNum( num );
- typenums.SetGranularity( 1 );
- typenums.SetNum( num );
- num = 0;
- for( c = typelist; c != NULL; c = c->next, num++ ) {
- types[ num ] = c;
- typenums[ c->typeNum ] = c;
- }
- initialized = true;
- gameLocal.Printf( "...%i classes, %i bytes for event callbacks\n", types.Num(), eventCallbackMemory );
- }
- /*
- ================
- idClass::Shutdown
- ================
- */
- void idClass::Shutdown() {
- idTypeInfo *c;
- for( c = typelist; c != NULL; c = c->next ) {
- c->Shutdown();
- }
- types.Clear();
- typenums.Clear();
- initialized = false;
- }
- /*
- ================
- idClass::new
- ================
- */
- void * idClass::operator new( size_t s ) {
- int *p;
- s += sizeof( int );
- p = (int *)Mem_Alloc( s, TAG_IDCLASS );
- *p = s;
- memused += s;
- numobjects++;
- return p + 1;
- }
- /*
- ================
- idClass::delete
- ================
- */
- void idClass::operator delete( void *ptr ) {
- int *p;
- if ( ptr ) {
- p = ( ( int * )ptr ) - 1;
- memused -= *p;
- numobjects--;
- Mem_Free( p );
- }
- }
- /*
- ================
- idClass::GetClass
- Returns the idTypeInfo for the name of the class passed in. This is a static function
- so it must be called as idClass::GetClass( classname )
- ================
- */
- idTypeInfo *idClass::GetClass( const char *name ) {
- idTypeInfo *c;
- int order;
- int mid;
- int min;
- int max;
- if ( !initialized ) {
- // idClass::Init hasn't been called yet, so do a slow lookup
- for( c = typelist; c != NULL; c = c->next ) {
- if ( !idStr::Cmp( c->classname, name ) ) {
- return c;
- }
- }
- } else {
- // do a binary search through the list of types
- min = 0;
- max = types.Num() - 1;
- while( min <= max ) {
- mid = ( min + max ) / 2;
- c = types[ mid ];
- order = idStr::Cmp( c->classname, name );
- if ( !order ) {
- return c;
- } else if ( order > 0 ) {
- max = mid - 1;
- } else {
- min = mid + 1;
- }
- }
- }
- return NULL;
- }
- /*
- ================
- idClass::GetType
- ================
- */
- idTypeInfo *idClass::GetType( const int typeNum ) {
- idTypeInfo *c;
- if ( !initialized ) {
- for( c = typelist; c != NULL; c = c->next ) {
- if ( c->typeNum == typeNum ) {
- return c;
- }
- }
- } else if ( ( typeNum >= 0 ) && ( typeNum < types.Num() ) ) {
- return typenums[ typeNum ];
- }
- return NULL;
- }
- /*
- ================
- idClass::GetClassname
- Returns the text classname of the object.
- ================
- */
- const char *idClass::GetClassname() const {
- idTypeInfo *type;
- type = GetType();
- return type->classname;
- }
- /*
- ================
- idClass::GetSuperclass
- Returns the text classname of the superclass.
- ================
- */
- const char *idClass::GetSuperclass() const {
- idTypeInfo *cls;
- cls = GetType();
- return cls->superclass;
- }
- /*
- ================
- idClass::CancelEvents
- ================
- */
- void idClass::CancelEvents( const idEventDef *ev ) {
- idEvent::CancelEvents( this, ev );
- }
- /*
- ================
- idClass::PostEventArgs
- ================
- */
- bool idClass::PostEventArgs( const idEventDef *ev, int time, int numargs, ... ) {
- idTypeInfo *c;
- idEvent *event;
- va_list args;
-
- assert( ev );
-
- if ( !idEvent::initialized ) {
- return false;
- }
- c = GetType();
- if ( !c->eventMap[ ev->GetEventNum() ] ) {
- // we don't respond to this event, so ignore it
- return false;
- }
- bool isReplicated = true;
- // If this is an entity with skipReplication, we want to process the event normally even on clients.
- if ( IsType( idEntity::Type ) ) {
- idEntity * thisEnt = static_cast< idEntity * >( this );
- if ( thisEnt->fl.skipReplication ) {
- isReplicated = false;
- }
- }
- // we service events on the client to avoid any bad code filling up the event pool
- // we don't want them processed usually, unless when the map is (re)loading.
- // we allow threads to run fine, though.
- if ( common->IsClient() && isReplicated && ( gameLocal.GameState() != GAMESTATE_STARTUP ) && !IsType( idThread::Type ) ) {
- return true;
- }
- va_start( args, numargs );
- event = idEvent::Alloc( ev, numargs, args );
- va_end( args );
- event->Schedule( this, c, time );
- return true;
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time ) {
- return PostEventArgs( ev, time, 0 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1 ) {
- return PostEventArgs( ev, time, 1, &arg1 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2 ) {
- return PostEventArgs( ev, time, 2, &arg1, &arg2 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
- return PostEventArgs( ev, time, 3, &arg1, &arg2, &arg3 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
- return PostEventArgs( ev, time, 4, &arg1, &arg2, &arg3, &arg4 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
- return PostEventArgs( ev, time, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
- return PostEventArgs( ev, time, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
- return PostEventArgs( ev, time, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
- }
- /*
- ================
- idClass::PostEventMS
- ================
- */
- bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
- return PostEventArgs( ev, time, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time ) {
- return PostEventArgs( ev, SEC2MS( time ), 0 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1 ) {
- return PostEventArgs( ev, SEC2MS( time ), 1, &arg1 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2 ) {
- return PostEventArgs( ev, SEC2MS( time ), 2, &arg1, &arg2 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
- return PostEventArgs( ev, SEC2MS( time ), 3, &arg1, &arg2, &arg3 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
- return PostEventArgs( ev, SEC2MS( time ), 4, &arg1, &arg2, &arg3, &arg4 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
- return PostEventArgs( ev, SEC2MS( time ), 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
- return PostEventArgs( ev, SEC2MS( time ), 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
- return PostEventArgs( ev, SEC2MS( time ), 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
- }
- /*
- ================
- idClass::PostEventSec
- ================
- */
- bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
- return PostEventArgs( ev, SEC2MS( time ), 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
- }
- /*
- ================
- idClass::ProcessEventArgs
- ================
- */
- bool idClass::ProcessEventArgs( const idEventDef *ev, int numargs, ... ) {
- idTypeInfo *c;
- int num;
- int data[ D_EVENT_MAXARGS ];
- va_list args;
-
- assert( ev );
- assert( idEvent::initialized );
- c = GetType();
- num = ev->GetEventNum();
- if ( !c->eventMap[ num ] ) {
- // we don't respond to this event, so ignore it
- return false;
- }
- va_start( args, numargs );
- idEvent::CopyArgs( ev, numargs, args, data );
- va_end( args );
- ProcessEventArgPtr( ev, data );
- return true;
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev ) {
- return ProcessEventArgs( ev, 0 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1 ) {
- return ProcessEventArgs( ev, 1, &arg1 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2 ) {
- return ProcessEventArgs( ev, 2, &arg1, &arg2 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
- return ProcessEventArgs( ev, 3, &arg1, &arg2, &arg3 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
- return ProcessEventArgs( ev, 4, &arg1, &arg2, &arg3, &arg4 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
- return ProcessEventArgs( ev, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
- return ProcessEventArgs( ev, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
- return ProcessEventArgs( ev, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
- }
- /*
- ================
- idClass::ProcessEvent
- ================
- */
- bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
- return ProcessEventArgs( ev, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
- }
- /*
- ================
- idClass::ProcessEventArgPtr
- ================
- */
- bool idClass::ProcessEventArgPtr( const idEventDef *ev, int *data ) {
- idTypeInfo *c;
- int num;
- eventCallback_t callback;
- assert( ev );
- assert( idEvent::initialized );
- SetTimeState ts;
- if ( IsType( idEntity::Type ) ) {
- idEntity *ent = (idEntity*)this;
- ts.PushState( ent->timeGroup );
- }
- if ( g_debugTriggers.GetBool() && ( ev == &EV_Activate ) && IsType( idEntity::Type ) ) {
- const idEntity *ent = *reinterpret_cast<idEntity **>( data );
- gameLocal.Printf( "%d: '%s' activated by '%s'\n", gameLocal.framenum, static_cast<idEntity *>( this )->GetName(), ent ? ent->GetName() : "NULL" );
- }
- c = GetType();
- num = ev->GetEventNum();
- if ( !c->eventMap[ num ] ) {
- // we don't respond to this event, so ignore it
- return false;
- }
- callback = c->eventMap[ num ];
- #if !CPU_EASYARGS
- /*
- on ppc architecture, floats are passed in a seperate set of registers
- the function prototypes must have matching float declaration
- http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html
- */
- switch( ev->GetFormatspecIndex() ) {
- case 1 << D_EVENT_MAXARGS :
- ( this->*callback )();
- break;
- // generated file - see CREATE_EVENT_CODE
- #include "Callbacks.cpp"
- default:
- gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
- break;
- }
- #else
- assert( D_EVENT_MAXARGS == 8 );
- switch( ev->GetNumArgs() ) {
- case 0 :
- ( this->*callback )();
- break;
- case 1 :
- typedef void ( idClass::*eventCallback_1_t )( const int );
- ( this->*( eventCallback_1_t )callback )( data[ 0 ] );
- break;
- case 2 :
- typedef void ( idClass::*eventCallback_2_t )( const int, const int );
- ( this->*( eventCallback_2_t )callback )( data[ 0 ], data[ 1 ] );
- break;
- case 3 :
- typedef void ( idClass::*eventCallback_3_t )( const int, const int, const int );
- ( this->*( eventCallback_3_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ] );
- break;
- case 4 :
- typedef void ( idClass::*eventCallback_4_t )( const int, const int, const int, const int );
- ( this->*( eventCallback_4_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ] );
- break;
- case 5 :
- typedef void ( idClass::*eventCallback_5_t )( const int, const int, const int, const int, const int );
- ( this->*( eventCallback_5_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ] );
- break;
- case 6 :
- typedef void ( idClass::*eventCallback_6_t )( const int, const int, const int, const int, const int, const int );
- ( this->*( eventCallback_6_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
- break;
- case 7 :
- typedef void ( idClass::*eventCallback_7_t )( const int, const int, const int, const int, const int, const int, const int );
- ( this->*( eventCallback_7_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ] );
- break;
- case 8 :
- typedef void ( idClass::*eventCallback_8_t )( const int, const int, const int, const int, const int, const int, const int, const int );
- ( this->*( eventCallback_8_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ] );
- break;
- default:
- gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
- break;
- }
- #endif
- return true;
- }
- /*
- ================
- idClass::Event_Remove
- ================
- */
- void idClass::Event_Remove() {
- delete this;
- }
- /*
- ================
- idClass::Event_SafeRemove
- ================
- */
- void idClass::Event_SafeRemove() {
- // Forces the remove to be done at a safe time
- PostEventMS( &EV_Remove, 0 );
- }
|