Class.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. /*
  21. Base class for all C++ objects. Provides fast run-time type checking and run-time
  22. instancing of objects.
  23. */
  24. #include "../../idlib/precompiled.h"
  25. #pragma hdrstop
  26. #include "../Game_local.h"
  27. #include "TypeInfo.h"
  28. /***********************************************************************
  29. idTypeInfo
  30. ***********************************************************************/
  31. // this is the head of a singly linked list of all the idTypes
  32. static idTypeInfo *typelist = NULL;
  33. static idHierarchy<idTypeInfo> classHierarchy;
  34. static int eventCallbackMemory = 0;
  35. /*
  36. ================
  37. idTypeInfo::idClassType()
  38. Constructor for class. Should only be called from CLASS_DECLARATION macro.
  39. Handles linking class definition into class hierarchy. This should only happen
  40. at startup as idTypeInfos are statically defined. Since static variables can be
  41. initialized in any order, the constructor must handle the case that subclasses
  42. are initialized before superclasses.
  43. ================
  44. */
  45. idTypeInfo::idTypeInfo( const char *classname, const char *superclass, idEventFunc<idClass> *eventCallbacks, idClass *( *CreateInstance )( void ),
  46. void ( idClass::*Spawn )( void ), void ( idClass::*Save )( idSaveGame *savefile ) const, void ( idClass::*Restore )( idRestoreGame *savefile ) ) {
  47. idTypeInfo *type;
  48. idTypeInfo **insert;
  49. this->classname = classname;
  50. this->superclass = superclass;
  51. this->eventCallbacks = eventCallbacks;
  52. this->eventMap = NULL;
  53. this->Spawn = Spawn;
  54. this->Save = Save;
  55. this->Restore = Restore;
  56. this->CreateInstance = CreateInstance;
  57. this->super = idClass::GetClass( superclass );
  58. this->freeEventMap = false;
  59. typeNum = 0;
  60. lastChild = 0;
  61. // Check if any subclasses were initialized before their superclass
  62. for( type = typelist; type != NULL; type = type->next ) {
  63. if ( ( type->super == NULL ) && !idStr::Cmp( type->superclass, this->classname ) &&
  64. idStr::Cmp( type->classname, "idClass" ) ) {
  65. type->super = this;
  66. }
  67. }
  68. // Insert sorted
  69. for ( insert = &typelist; *insert; insert = &(*insert)->next ) {
  70. assert( idStr::Cmp( classname, (*insert)->classname ) );
  71. if ( idStr::Cmp( classname, (*insert)->classname ) < 0 ) {
  72. next = *insert;
  73. *insert = this;
  74. break;
  75. }
  76. }
  77. if ( !*insert ) {
  78. *insert = this;
  79. next = NULL;
  80. }
  81. }
  82. /*
  83. ================
  84. idTypeInfo::~idTypeInfo
  85. ================
  86. */
  87. idTypeInfo::~idTypeInfo() {
  88. Shutdown();
  89. }
  90. /*
  91. ================
  92. idTypeInfo::Init
  93. Initializes the event callback table for the class. Creates a
  94. table for fast lookups of event functions. Should only be called once.
  95. ================
  96. */
  97. void idTypeInfo::Init( void ) {
  98. idTypeInfo *c;
  99. idEventFunc<idClass> *def;
  100. int ev;
  101. int i;
  102. bool *set;
  103. int num;
  104. if ( eventMap ) {
  105. // we've already been initialized by a subclass
  106. return;
  107. }
  108. // make sure our superclass is initialized first
  109. if ( super && !super->eventMap ) {
  110. super->Init();
  111. }
  112. // add to our node hierarchy
  113. if ( super ) {
  114. node.ParentTo( super->node );
  115. } else {
  116. node.ParentTo( classHierarchy );
  117. }
  118. node.SetOwner( this );
  119. // keep track of the number of children below each class
  120. for( c = super; c != NULL; c = c->super ) {
  121. c->lastChild++;
  122. }
  123. // if we're not adding any new event callbacks, we can just use our superclass's table
  124. if ( ( !eventCallbacks || !eventCallbacks->event ) && super ) {
  125. eventMap = super->eventMap;
  126. return;
  127. }
  128. // set a flag so we know to delete the eventMap table
  129. freeEventMap = true;
  130. // Allocate our new table. It has to have as many entries as there
  131. // are events. NOTE: could save some space by keeping track of the maximum
  132. // event that the class responds to and doing range checking.
  133. num = idEventDef::NumEventCommands();
  134. eventMap = new eventCallback_t[ num ];
  135. memset( eventMap, 0, sizeof( eventCallback_t ) * num );
  136. eventCallbackMemory += sizeof( eventCallback_t ) * num;
  137. // allocate temporary memory for flags so that the subclass's event callbacks
  138. // override the superclass's event callback
  139. set = new bool[ num ];
  140. memset( set, 0, sizeof( bool ) * num );
  141. // go through the inheritence order and copies the event callback function into
  142. // a list indexed by the event number. This allows fast lookups of
  143. // event functions.
  144. for( c = this; c != NULL; c = c->super ) {
  145. def = c->eventCallbacks;
  146. if ( !def ) {
  147. continue;
  148. }
  149. // go through each entry until we hit the NULL terminator
  150. for( i = 0; def[ i ].event != NULL; i++ ) {
  151. ev = def[ i ].event->GetEventNum();
  152. if ( set[ ev ] ) {
  153. continue;
  154. }
  155. set[ ev ] = true;
  156. eventMap[ ev ] = def[ i ].function;
  157. }
  158. }
  159. delete[] set;
  160. }
  161. /*
  162. ================
  163. idTypeInfo::Shutdown
  164. Should only be called when DLL or EXE is being shutdown.
  165. Although it cleans up any allocated memory, it doesn't bother to remove itself
  166. from the class list since the program is shutting down.
  167. ================
  168. */
  169. void idTypeInfo::Shutdown() {
  170. // free up the memory used for event lookups
  171. if ( eventMap ) {
  172. if ( freeEventMap ) {
  173. delete[] eventMap;
  174. }
  175. eventMap = NULL;
  176. }
  177. typeNum = 0;
  178. lastChild = 0;
  179. }
  180. /***********************************************************************
  181. idClass
  182. ***********************************************************************/
  183. const idEventDef EV_Remove( "<immediateremove>", NULL );
  184. const idEventDef EV_SafeRemove( "remove", NULL );
  185. ABSTRACT_DECLARATION( NULL, idClass )
  186. EVENT( EV_Remove, idClass::Event_Remove )
  187. EVENT( EV_SafeRemove, idClass::Event_SafeRemove )
  188. END_CLASS
  189. // alphabetical order
  190. idList<idTypeInfo *> idClass::types;
  191. // typenum order
  192. idList<idTypeInfo *> idClass::typenums;
  193. bool idClass::initialized = false;
  194. int idClass::typeNumBits = 0;
  195. int idClass::memused = 0;
  196. int idClass::numobjects = 0;
  197. /*
  198. ================
  199. idClass::CallSpawn
  200. ================
  201. */
  202. void idClass::CallSpawn( void ) {
  203. idTypeInfo *type;
  204. type = GetType();
  205. CallSpawnFunc( type );
  206. }
  207. /*
  208. ================
  209. idClass::CallSpawnFunc
  210. ================
  211. */
  212. classSpawnFunc_t idClass::CallSpawnFunc( idTypeInfo *cls ) {
  213. classSpawnFunc_t func;
  214. if ( cls->super ) {
  215. func = CallSpawnFunc( cls->super );
  216. if ( func == cls->Spawn ) {
  217. // don't call the same function twice in a row.
  218. // this can happen when subclasses don't have their own spawn function.
  219. return func;
  220. }
  221. }
  222. ( this->*cls->Spawn )();
  223. return cls->Spawn;
  224. }
  225. /*
  226. ================
  227. idClass::FindUninitializedMemory
  228. ================
  229. */
  230. void idClass::FindUninitializedMemory( void ) {
  231. #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
  232. unsigned long *ptr = ( ( unsigned long * )this ) - 1;
  233. int size = *ptr;
  234. assert( ( size & 3 ) == 0 );
  235. size >>= 2;
  236. for ( int i = 0; i < size; i++ ) {
  237. if ( ptr[i] == 0xcdcdcdcd ) {
  238. const char *varName = GetTypeVariableName( GetClassname(), i << 2 );
  239. gameLocal.Warning( "type '%s' has uninitialized variable %s (offset %d)", GetClassname(), varName, i << 2 );
  240. }
  241. }
  242. #endif
  243. }
  244. /*
  245. ================
  246. idClass::Spawn
  247. ================
  248. */
  249. void idClass::Spawn( void ) {
  250. }
  251. /*
  252. ================
  253. idClass::~idClass
  254. Destructor for object. Cancels any events that depend on this object.
  255. ================
  256. */
  257. idClass::~idClass() {
  258. idEvent::CancelEvents( this );
  259. }
  260. /*
  261. ================
  262. idClass::DisplayInfo_f
  263. ================
  264. */
  265. void idClass::DisplayInfo_f( const idCmdArgs &args ) {
  266. gameLocal.Printf( "Class memory status: %i bytes allocated in %i objects\n", memused, numobjects );
  267. }
  268. /*
  269. ================
  270. idClass::ListClasses_f
  271. ================
  272. */
  273. void idClass::ListClasses_f( const idCmdArgs &args ) {
  274. int i;
  275. idTypeInfo *type;
  276. gameLocal.Printf( "%-24s %-24s %-6s %-6s\n", "Classname", "Superclass", "Type", "Subclasses" );
  277. gameLocal.Printf( "----------------------------------------------------------------------\n" );
  278. for( i = 0; i < types.Num(); i++ ) {
  279. type = types[ i ];
  280. gameLocal.Printf( "%-24s %-24s %6d %6d\n", type->classname, type->superclass, type->typeNum, type->lastChild - type->typeNum );
  281. }
  282. gameLocal.Printf( "...%d classes", types.Num() );
  283. }
  284. /*
  285. ================
  286. idClass::CreateInstance
  287. ================
  288. */
  289. idClass *idClass::CreateInstance( const char *name ) {
  290. const idTypeInfo *type;
  291. idClass *obj;
  292. type = idClass::GetClass( name );
  293. if ( !type ) {
  294. return NULL;
  295. }
  296. obj = type->CreateInstance();
  297. return obj;
  298. }
  299. /*
  300. ================
  301. idClass::Init
  302. Should be called after all idTypeInfos are initialized, so must be called
  303. manually upon game code initialization. Tells all the idTypeInfos to initialize
  304. their event callback table for the associated class. This should only be called
  305. once during the execution of the program or DLL.
  306. ================
  307. */
  308. void idClass::Init( void ) {
  309. idTypeInfo *c;
  310. int num;
  311. gameLocal.Printf( "Initializing class hierarchy\n" );
  312. if ( initialized ) {
  313. gameLocal.Printf( "...already initialized\n" );
  314. return;
  315. }
  316. // init the event callback tables for all the classes
  317. for( c = typelist; c != NULL; c = c->next ) {
  318. c->Init();
  319. }
  320. // number the types according to the class hierarchy so we can quickly determine if a class
  321. // is a subclass of another
  322. num = 0;
  323. for( c = classHierarchy.GetNext(); c != NULL; c = c->node.GetNext(), num++ ) {
  324. c->typeNum = num;
  325. c->lastChild += num;
  326. }
  327. // number of bits needed to send types over network
  328. typeNumBits = idMath::BitsForInteger( num );
  329. // create a list of the types so we can do quick lookups
  330. // one list in alphabetical order, one in typenum order
  331. types.SetGranularity( 1 );
  332. types.SetNum( num );
  333. typenums.SetGranularity( 1 );
  334. typenums.SetNum( num );
  335. num = 0;
  336. for( c = typelist; c != NULL; c = c->next, num++ ) {
  337. types[ num ] = c;
  338. typenums[ c->typeNum ] = c;
  339. }
  340. initialized = true;
  341. gameLocal.Printf( "...%i classes, %i bytes for event callbacks\n", types.Num(), eventCallbackMemory );
  342. }
  343. /*
  344. ================
  345. idClass::Shutdown
  346. ================
  347. */
  348. void idClass::Shutdown( void ) {
  349. idTypeInfo *c;
  350. for( c = typelist; c != NULL; c = c->next ) {
  351. c->Shutdown();
  352. }
  353. types.Clear();
  354. typenums.Clear();
  355. initialized = false;
  356. }
  357. /*
  358. ================
  359. idClass::new
  360. ================
  361. */
  362. #ifdef ID_DEBUG_MEMORY
  363. #undef new
  364. #endif
  365. void * idClass::operator new( size_t s ) {
  366. int *p;
  367. s += sizeof( int );
  368. p = (int *)Mem_Alloc( s );
  369. *p = s;
  370. memused += s;
  371. numobjects++;
  372. #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
  373. unsigned long *ptr = (unsigned long *)p;
  374. int size = s;
  375. assert( ( size & 3 ) == 0 );
  376. size >>= 3;
  377. for ( int i = 1; i < size; i++ ) {
  378. ptr[i] = 0xcdcdcdcd;
  379. }
  380. #endif
  381. return p + 1;
  382. }
  383. void * idClass::operator new( size_t s, int, int, char *, int ) {
  384. int *p;
  385. s += sizeof( int );
  386. p = (int *)Mem_Alloc( s );
  387. *p = s;
  388. memused += s;
  389. numobjects++;
  390. #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
  391. unsigned long *ptr = (unsigned long *)p;
  392. int size = s;
  393. assert( ( size & 3 ) == 0 );
  394. size >>= 3;
  395. for ( int i = 1; i < size; i++ ) {
  396. ptr[i] = 0xcdcdcdcd;
  397. }
  398. #endif
  399. return p + 1;
  400. }
  401. #ifdef ID_DEBUG_MEMORY
  402. #define new ID_DEBUG_NEW
  403. #endif
  404. /*
  405. ================
  406. idClass::delete
  407. ================
  408. */
  409. void idClass::operator delete( void *ptr ) {
  410. int *p;
  411. if ( ptr ) {
  412. p = ( ( int * )ptr ) - 1;
  413. memused -= *p;
  414. numobjects--;
  415. Mem_Free( p );
  416. }
  417. }
  418. void idClass::operator delete( void *ptr, int, int, char *, int ) {
  419. int *p;
  420. if ( ptr ) {
  421. p = ( ( int * )ptr ) - 1;
  422. memused -= *p;
  423. numobjects--;
  424. Mem_Free( p );
  425. }
  426. }
  427. /*
  428. ================
  429. idClass::GetClass
  430. Returns the idTypeInfo for the name of the class passed in. This is a static function
  431. so it must be called as idClass::GetClass( classname )
  432. ================
  433. */
  434. idTypeInfo *idClass::GetClass( const char *name ) {
  435. idTypeInfo *c;
  436. int order;
  437. int mid;
  438. int min;
  439. int max;
  440. if ( !initialized ) {
  441. // idClass::Init hasn't been called yet, so do a slow lookup
  442. for( c = typelist; c != NULL; c = c->next ) {
  443. if ( !idStr::Cmp( c->classname, name ) ) {
  444. return c;
  445. }
  446. }
  447. } else {
  448. // do a binary search through the list of types
  449. min = 0;
  450. max = types.Num() - 1;
  451. while( min <= max ) {
  452. mid = ( min + max ) / 2;
  453. c = types[ mid ];
  454. order = idStr::Cmp( c->classname, name );
  455. if ( !order ) {
  456. return c;
  457. } else if ( order > 0 ) {
  458. max = mid - 1;
  459. } else {
  460. min = mid + 1;
  461. }
  462. }
  463. }
  464. return NULL;
  465. }
  466. /*
  467. ================
  468. idClass::GetType
  469. ================
  470. */
  471. idTypeInfo *idClass::GetType( const int typeNum ) {
  472. idTypeInfo *c;
  473. if ( !initialized ) {
  474. for( c = typelist; c != NULL; c = c->next ) {
  475. if ( c->typeNum == typeNum ) {
  476. return c;
  477. }
  478. }
  479. } else if ( ( typeNum >= 0 ) && ( typeNum < types.Num() ) ) {
  480. return typenums[ typeNum ];
  481. }
  482. return NULL;
  483. }
  484. /*
  485. ================
  486. idClass::GetClassname
  487. Returns the text classname of the object.
  488. ================
  489. */
  490. const char *idClass::GetClassname( void ) const {
  491. idTypeInfo *type;
  492. type = GetType();
  493. return type->classname;
  494. }
  495. /*
  496. ================
  497. idClass::GetSuperclass
  498. Returns the text classname of the superclass.
  499. ================
  500. */
  501. const char *idClass::GetSuperclass( void ) const {
  502. idTypeInfo *cls;
  503. cls = GetType();
  504. return cls->superclass;
  505. }
  506. /*
  507. ================
  508. idClass::CancelEvents
  509. ================
  510. */
  511. void idClass::CancelEvents( const idEventDef *ev ) {
  512. idEvent::CancelEvents( this, ev );
  513. }
  514. /*
  515. ================
  516. idClass::PostEventArgs
  517. ================
  518. */
  519. bool idClass::PostEventArgs( const idEventDef *ev, int time, int numargs, ... ) {
  520. idTypeInfo *c;
  521. idEvent *event;
  522. va_list args;
  523. assert( ev );
  524. if ( !idEvent::initialized ) {
  525. return false;
  526. }
  527. c = GetType();
  528. if ( !c->eventMap[ ev->GetEventNum() ] ) {
  529. // we don't respond to this event, so ignore it
  530. return false;
  531. }
  532. // we service events on the client to avoid any bad code filling up the event pool
  533. // we don't want them processed usually, unless when the map is (re)loading.
  534. // we allow threads to run fine, though.
  535. if ( gameLocal.isClient && ( gameLocal.GameState() != GAMESTATE_STARTUP ) && !IsType( idThread::Type ) ) {
  536. return true;
  537. }
  538. va_start( args, numargs );
  539. event = idEvent::Alloc( ev, numargs, args );
  540. va_end( args );
  541. event->Schedule( this, c, time );
  542. return true;
  543. }
  544. /*
  545. ================
  546. idClass::PostEventMS
  547. ================
  548. */
  549. bool idClass::PostEventMS( const idEventDef *ev, int time ) {
  550. return PostEventArgs( ev, time, 0 );
  551. }
  552. /*
  553. ================
  554. idClass::PostEventMS
  555. ================
  556. */
  557. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1 ) {
  558. return PostEventArgs( ev, time, 1, &arg1 );
  559. }
  560. /*
  561. ================
  562. idClass::PostEventMS
  563. ================
  564. */
  565. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2 ) {
  566. return PostEventArgs( ev, time, 2, &arg1, &arg2 );
  567. }
  568. /*
  569. ================
  570. idClass::PostEventMS
  571. ================
  572. */
  573. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
  574. return PostEventArgs( ev, time, 3, &arg1, &arg2, &arg3 );
  575. }
  576. /*
  577. ================
  578. idClass::PostEventMS
  579. ================
  580. */
  581. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
  582. return PostEventArgs( ev, time, 4, &arg1, &arg2, &arg3, &arg4 );
  583. }
  584. /*
  585. ================
  586. idClass::PostEventMS
  587. ================
  588. */
  589. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
  590. return PostEventArgs( ev, time, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
  591. }
  592. /*
  593. ================
  594. idClass::PostEventMS
  595. ================
  596. */
  597. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
  598. return PostEventArgs( ev, time, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
  599. }
  600. /*
  601. ================
  602. idClass::PostEventMS
  603. ================
  604. */
  605. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
  606. return PostEventArgs( ev, time, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
  607. }
  608. /*
  609. ================
  610. idClass::PostEventMS
  611. ================
  612. */
  613. bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
  614. return PostEventArgs( ev, time, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
  615. }
  616. /*
  617. ================
  618. idClass::PostEventSec
  619. ================
  620. */
  621. bool idClass::PostEventSec( const idEventDef *ev, float time ) {
  622. return PostEventArgs( ev, SEC2MS( time ), 0 );
  623. }
  624. /*
  625. ================
  626. idClass::PostEventSec
  627. ================
  628. */
  629. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1 ) {
  630. return PostEventArgs( ev, SEC2MS( time ), 1, &arg1 );
  631. }
  632. /*
  633. ================
  634. idClass::PostEventSec
  635. ================
  636. */
  637. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2 ) {
  638. return PostEventArgs( ev, SEC2MS( time ), 2, &arg1, &arg2 );
  639. }
  640. /*
  641. ================
  642. idClass::PostEventSec
  643. ================
  644. */
  645. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
  646. return PostEventArgs( ev, SEC2MS( time ), 3, &arg1, &arg2, &arg3 );
  647. }
  648. /*
  649. ================
  650. idClass::PostEventSec
  651. ================
  652. */
  653. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
  654. return PostEventArgs( ev, SEC2MS( time ), 4, &arg1, &arg2, &arg3, &arg4 );
  655. }
  656. /*
  657. ================
  658. idClass::PostEventSec
  659. ================
  660. */
  661. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
  662. return PostEventArgs( ev, SEC2MS( time ), 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
  663. }
  664. /*
  665. ================
  666. idClass::PostEventSec
  667. ================
  668. */
  669. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
  670. return PostEventArgs( ev, SEC2MS( time ), 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
  671. }
  672. /*
  673. ================
  674. idClass::PostEventSec
  675. ================
  676. */
  677. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
  678. return PostEventArgs( ev, SEC2MS( time ), 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
  679. }
  680. /*
  681. ================
  682. idClass::PostEventSec
  683. ================
  684. */
  685. bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
  686. return PostEventArgs( ev, SEC2MS( time ), 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
  687. }
  688. /*
  689. ================
  690. idClass::ProcessEventArgs
  691. ================
  692. */
  693. bool idClass::ProcessEventArgs( const idEventDef *ev, int numargs, ... ) {
  694. idTypeInfo *c;
  695. int num;
  696. int data[ D_EVENT_MAXARGS ];
  697. va_list args;
  698. assert( ev );
  699. assert( idEvent::initialized );
  700. c = GetType();
  701. num = ev->GetEventNum();
  702. if ( !c->eventMap[ num ] ) {
  703. // we don't respond to this event, so ignore it
  704. return false;
  705. }
  706. va_start( args, numargs );
  707. idEvent::CopyArgs( ev, numargs, args, data );
  708. va_end( args );
  709. ProcessEventArgPtr( ev, data );
  710. return true;
  711. }
  712. /*
  713. ================
  714. idClass::ProcessEvent
  715. ================
  716. */
  717. bool idClass::ProcessEvent( const idEventDef *ev ) {
  718. return ProcessEventArgs( ev, 0 );
  719. }
  720. /*
  721. ================
  722. idClass::ProcessEvent
  723. ================
  724. */
  725. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1 ) {
  726. return ProcessEventArgs( ev, 1, &arg1 );
  727. }
  728. /*
  729. ================
  730. idClass::ProcessEvent
  731. ================
  732. */
  733. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2 ) {
  734. return ProcessEventArgs( ev, 2, &arg1, &arg2 );
  735. }
  736. /*
  737. ================
  738. idClass::ProcessEvent
  739. ================
  740. */
  741. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3 ) {
  742. return ProcessEventArgs( ev, 3, &arg1, &arg2, &arg3 );
  743. }
  744. /*
  745. ================
  746. idClass::ProcessEvent
  747. ================
  748. */
  749. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4 ) {
  750. return ProcessEventArgs( ev, 4, &arg1, &arg2, &arg3, &arg4 );
  751. }
  752. /*
  753. ================
  754. idClass::ProcessEvent
  755. ================
  756. */
  757. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5 ) {
  758. return ProcessEventArgs( ev, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
  759. }
  760. /*
  761. ================
  762. idClass::ProcessEvent
  763. ================
  764. */
  765. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6 ) {
  766. return ProcessEventArgs( ev, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
  767. }
  768. /*
  769. ================
  770. idClass::ProcessEvent
  771. ================
  772. */
  773. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7 ) {
  774. return ProcessEventArgs( ev, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
  775. }
  776. /*
  777. ================
  778. idClass::ProcessEvent
  779. ================
  780. */
  781. bool idClass::ProcessEvent( const idEventDef *ev, idEventArg arg1, idEventArg arg2, idEventArg arg3, idEventArg arg4, idEventArg arg5, idEventArg arg6, idEventArg arg7, idEventArg arg8 ) {
  782. return ProcessEventArgs( ev, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
  783. }
  784. /*
  785. ================
  786. idClass::ProcessEventArgPtr
  787. ================
  788. */
  789. bool idClass::ProcessEventArgPtr( const idEventDef *ev, int *data ) {
  790. idTypeInfo *c;
  791. int num;
  792. eventCallback_t callback;
  793. assert( ev );
  794. assert( idEvent::initialized );
  795. #ifdef _D3XP
  796. SetTimeState ts;
  797. if ( IsType( idEntity::Type ) ) {
  798. idEntity *ent = (idEntity*)this;
  799. ts.PushState( ent->timeGroup );
  800. }
  801. #endif
  802. if ( g_debugTriggers.GetBool() && ( ev == &EV_Activate ) && IsType( idEntity::Type ) ) {
  803. const idEntity *ent = *reinterpret_cast<idEntity **>( data );
  804. gameLocal.Printf( "%d: '%s' activated by '%s'\n", gameLocal.framenum, static_cast<idEntity *>( this )->GetName(), ent ? ent->GetName() : "NULL" );
  805. }
  806. c = GetType();
  807. num = ev->GetEventNum();
  808. if ( !c->eventMap[ num ] ) {
  809. // we don't respond to this event, so ignore it
  810. return false;
  811. }
  812. callback = c->eventMap[ num ];
  813. #if !CPU_EASYARGS
  814. /*
  815. on ppc architecture, floats are passed in a seperate set of registers
  816. the function prototypes must have matching float declaration
  817. http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html
  818. */
  819. switch( ev->GetFormatspecIndex() ) {
  820. case 1 << D_EVENT_MAXARGS :
  821. ( this->*callback )();
  822. break;
  823. // generated file - see CREATE_EVENT_CODE
  824. #include "Callbacks.cpp"
  825. default:
  826. gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
  827. break;
  828. }
  829. #else
  830. assert( D_EVENT_MAXARGS == 8 );
  831. switch( ev->GetNumArgs() ) {
  832. case 0 :
  833. ( this->*callback )();
  834. break;
  835. case 1 :
  836. typedef void ( idClass::*eventCallback_1_t )( const int );
  837. ( this->*( eventCallback_1_t )callback )( data[ 0 ] );
  838. break;
  839. case 2 :
  840. typedef void ( idClass::*eventCallback_2_t )( const int, const int );
  841. ( this->*( eventCallback_2_t )callback )( data[ 0 ], data[ 1 ] );
  842. break;
  843. case 3 :
  844. typedef void ( idClass::*eventCallback_3_t )( const int, const int, const int );
  845. ( this->*( eventCallback_3_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ] );
  846. break;
  847. case 4 :
  848. typedef void ( idClass::*eventCallback_4_t )( const int, const int, const int, const int );
  849. ( this->*( eventCallback_4_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ] );
  850. break;
  851. case 5 :
  852. typedef void ( idClass::*eventCallback_5_t )( const int, const int, const int, const int, const int );
  853. ( this->*( eventCallback_5_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ] );
  854. break;
  855. case 6 :
  856. typedef void ( idClass::*eventCallback_6_t )( const int, const int, const int, const int, const int, const int );
  857. ( this->*( eventCallback_6_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ] );
  858. break;
  859. case 7 :
  860. typedef void ( idClass::*eventCallback_7_t )( const int, const int, const int, const int, const int, const int, const int );
  861. ( this->*( eventCallback_7_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ] );
  862. break;
  863. case 8 :
  864. typedef void ( idClass::*eventCallback_8_t )( const int, const int, const int, const int, const int, const int, const int, const int );
  865. ( this->*( eventCallback_8_t )callback )( data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ] );
  866. break;
  867. default:
  868. gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
  869. break;
  870. }
  871. #endif
  872. return true;
  873. }
  874. /*
  875. ================
  876. idClass::Event_Remove
  877. ================
  878. */
  879. void idClass::Event_Remove( void ) {
  880. delete this;
  881. }
  882. /*
  883. ================
  884. idClass::Event_SafeRemove
  885. ================
  886. */
  887. void idClass::Event_SafeRemove( void ) {
  888. // Forces the remove to be done at a safe time
  889. PostEventMS( &EV_Remove, 0 );
  890. }