doom3-gpl
Doom 3 GPL source release
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Class.cpp
Go to the documentation of this file.
1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
8 
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.
13 
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.
18 
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/>.
21 
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.
23 
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.
25 
26 ===========================================================================
27 */
28 /*
29 
30 Base class for all C++ objects. Provides fast run-time type checking and run-time
31 instancing of objects.
32 
33 */
34 
35 #include "../../idlib/precompiled.h"
36 #pragma hdrstop
37 
38 #include "../Game_local.h"
39 
40 #include "TypeInfo.h"
41 
42 
43 /***********************************************************************
44 
45  idTypeInfo
46 
47 ***********************************************************************/
48 
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;
53 
54 /*
55 ================
56 idTypeInfo::idClassType()
57 
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.
63 ================
64 */
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 ) ) {
67 
69  idTypeInfo **insert;
70 
71  this->classname = classname;
72  this->superclass = superclass;
73  this->eventCallbacks = eventCallbacks;
74  this->eventMap = NULL;
75  this->Spawn = Spawn;
76  this->Save = Save;
77  this->Restore = Restore;
79  this->super = idClass::GetClass( superclass );
80  this->freeEventMap = false;
81  typeNum = 0;
82  lastChild = 0;
83 
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" ) ) {
88  type->super = this;
89  }
90  }
91 
92  // Insert sorted
93  for ( insert = &typelist; *insert; insert = &(*insert)->next ) {
94  assert( idStr::Cmp( classname, (*insert)->classname ) );
95  if ( idStr::Cmp( classname, (*insert)->classname ) < 0 ) {
96  next = *insert;
97  *insert = this;
98  break;
99  }
100  }
101  if ( !*insert ) {
102  *insert = this;
103  next = NULL;
104  }
105 }
106 
107 /*
108 ================
109 idTypeInfo::~idTypeInfo
110 ================
111 */
113  Shutdown();
114 }
115 
116 /*
117 ================
118 idTypeInfo::Init
119 
120 Initializes the event callback table for the class. Creates a
121 table for fast lookups of event functions. Should only be called once.
122 ================
123 */
124 void idTypeInfo::Init( void ) {
125  idTypeInfo *c;
127  int ev;
128  int i;
129  bool *set;
130  int num;
131 
132  if ( eventMap ) {
133  // we've already been initialized by a subclass
134  return;
135  }
136 
137  // make sure our superclass is initialized first
138  if ( super && !super->eventMap ) {
139  super->Init();
140  }
141 
142  // add to our node hierarchy
143  if ( super ) {
144  node.ParentTo( super->node );
145  } else {
146  node.ParentTo( classHierarchy );
147  }
148  node.SetOwner( this );
149 
150  // keep track of the number of children below each class
151  for( c = super; c != NULL; c = c->super ) {
152  c->lastChild++;
153  }
154 
155  // if we're not adding any new event callbacks, we can just use our superclass's table
156  if ( ( !eventCallbacks || !eventCallbacks->event ) && super ) {
158  return;
159  }
160 
161  // set a flag so we know to delete the eventMap table
162  freeEventMap = true;
163 
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.
168  eventMap = new eventCallback_t[ num ];
169  memset( eventMap, 0, sizeof( eventCallback_t ) * num );
170  eventCallbackMemory += sizeof( eventCallback_t ) * num;
171 
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 );
176 
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
179  // event functions.
180  for( c = this; c != NULL; c = c->super ) {
181  def = c->eventCallbacks;
182  if ( !def ) {
183  continue;
184  }
185 
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();
189 
190  if ( set[ ev ] ) {
191  continue;
192  }
193  set[ ev ] = true;
194  eventMap[ ev ] = def[ i ].function;
195  }
196  }
197 
198  delete[] set;
199 }
200 
201 /*
202 ================
203 idTypeInfo::Shutdown
204 
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.
208 ================
209 */
211  // free up the memory used for event lookups
212  if ( eventMap ) {
213  if ( freeEventMap ) {
214  delete[] eventMap;
215  }
216  eventMap = NULL;
217  }
218  typeNum = 0;
219  lastChild = 0;
220 }
221 
222 
223 /***********************************************************************
224 
225  idClass
226 
227 ***********************************************************************/
228 
229 const idEventDef EV_Remove( "<immediateremove>", NULL );
230 const idEventDef EV_SafeRemove( "remove", NULL );
231 
233  EVENT( EV_Remove, idClass::Event_Remove )
234  EVENT( EV_SafeRemove, idClass::Event_SafeRemove )
235 END_CLASS
236 
237 // alphabetical order
238 idList<idTypeInfo *> idClass::types;
239 // typenum order
240 idList<idTypeInfo *> idClass::typenums;
241 
242 bool idClass::initialized = false;
243 int idClass::typeNumBits = 0;
244 int idClass::memused = 0;
245 int idClass::numobjects = 0;
246 
247 /*
248 ================
249 idClass::CallSpawn
250 ================
251 */
252 void idClass::CallSpawn( void ) {
253  idTypeInfo *type;
254 
255  type = GetType();
256  CallSpawnFunc( type );
257 }
258 
259 /*
260 ================
261 idClass::CallSpawnFunc
262 ================
263 */
265  classSpawnFunc_t func;
266 
267  if ( cls->super ) {
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.
272  return func;
273  }
274  }
275 
276  ( this->*cls->Spawn )();
277 
278  return cls->Spawn;
279 }
280 
281 /*
282 ================
283 idClass::FindUninitializedMemory
284 ================
285 */
287 #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
288  unsigned long *ptr = ( ( unsigned long * )this ) - 1;
289  int size = *ptr;
290  assert( ( size & 3 ) == 0 );
291  size >>= 2;
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 );
296  }
297  }
298 #endif
299 }
300 
301 /*
302 ================
303 idClass::Spawn
304 ================
305 */
306 void idClass::Spawn( void ) {
307 }
308 
309 /*
310 ================
311 idClass::~idClass
312 
313 Destructor for object. Cancels any events that depend on this object.
314 ================
315 */
317  idEvent::CancelEvents( this );
318 }
319 
320 /*
321 ================
322 idClass::DisplayInfo_f
323 ================
324 */
325 void idClass::DisplayInfo_f( const idCmdArgs &args ) {
326  gameLocal.Printf( "Class memory status: %i bytes allocated in %i objects\n", memused, numobjects );
327 }
328 
329 /*
330 ================
331 idClass::ListClasses_f
332 ================
333 */
334 void idClass::ListClasses_f( const idCmdArgs &args ) {
335  int i;
336  idTypeInfo *type;
337 
338  gameLocal.Printf( "%-24s %-24s %-6s %-6s\n", "Classname", "Superclass", "Type", "Subclasses" );
339  gameLocal.Printf( "----------------------------------------------------------------------\n" );
340 
341  for( i = 0; i < types.Num(); i++ ) {
342  type = types[ i ];
343  gameLocal.Printf( "%-24s %-24s %6d %6d\n", type->classname, type->superclass, type->typeNum, type->lastChild - type->typeNum );
344  }
345 
346  gameLocal.Printf( "...%d classes", types.Num() );
347 }
348 
349 /*
350 ================
351 idClass::CreateInstance
352 ================
353 */
355  const idTypeInfo *type;
356  idClass *obj;
357 
358  type = idClass::GetClass( name );
359  if ( !type ) {
360  return NULL;
361  }
362 
363  obj = type->CreateInstance();
364  return obj;
365 }
366 
367 /*
368 ================
369 idClass::Init
370 
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.
375 ================
376 */
377 void idClass::Init( void ) {
378  idTypeInfo *c;
379  int num;
380 
381  gameLocal.Printf( "Initializing class hierarchy\n" );
382 
383  if ( initialized ) {
384  gameLocal.Printf( "...already initialized\n" );
385  return;
386  }
387 
388  // init the event callback tables for all the classes
389  for( c = typelist; c != NULL; c = c->next ) {
390  c->Init();
391  }
392 
393  // number the types according to the class hierarchy so we can quickly determine if a class
394  // is a subclass of another
395  num = 0;
396  for( c = classHierarchy.GetNext(); c != NULL; c = c->node.GetNext(), num++ ) {
397  c->typeNum = num;
398  c->lastChild += num;
399  }
400 
401  // number of bits needed to send types over network
403 
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 );
407  types.SetNum( num );
409  typenums.SetNum( num );
410  num = 0;
411  for( c = typelist; c != NULL; c = c->next, num++ ) {
412  types[ num ] = c;
413  typenums[ c->typeNum ] = c;
414  }
415 
416  initialized = true;
417 
418  gameLocal.Printf( "...%i classes, %i bytes for event callbacks\n", types.Num(), eventCallbackMemory );
419 }
420 
421 /*
422 ================
423 idClass::Shutdown
424 ================
425 */
426 void idClass::Shutdown( void ) {
427  idTypeInfo *c;
428 
429  for( c = typelist; c != NULL; c = c->next ) {
430  c->Shutdown();
431  }
432  types.Clear();
433  typenums.Clear();
434 
435  initialized = false;
436 }
437 
438 /*
439 ================
440 idClass::new
441 ================
442 */
443 #ifdef ID_DEBUG_MEMORY
444 #undef new
445 #endif
446 
447 void * idClass::operator new( size_t s ) {
448  int *p;
449 
450  s += sizeof( int );
451  p = (int *)Mem_Alloc( s );
452  *p = s;
453  memused += s;
454  numobjects++;
455 
456 #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
457  unsigned long *ptr = (unsigned long *)p;
458  int size = s;
459  assert( ( size & 3 ) == 0 );
460  size >>= 3;
461  for ( int i = 1; i < size; i++ ) {
462  ptr[i] = 0xcdcdcdcd;
463  }
464 #endif
465 
466  return p + 1;
467 }
468 
469 void * idClass::operator new( size_t s, int, int, char *, int ) {
470  int *p;
471 
472  s += sizeof( int );
473  p = (int *)Mem_Alloc( s );
474  *p = s;
475  memused += s;
476  numobjects++;
477 
478 #ifdef ID_DEBUG_UNINITIALIZED_MEMORY
479  unsigned long *ptr = (unsigned long *)p;
480  int size = s;
481  assert( ( size & 3 ) == 0 );
482  size >>= 3;
483  for ( int i = 1; i < size; i++ ) {
484  ptr[i] = 0xcdcdcdcd;
485  }
486 #endif
487 
488  return p + 1;
489 }
490 
491 #ifdef ID_DEBUG_MEMORY
492 #define new ID_DEBUG_NEW
493 #endif
494 
495 /*
496 ================
497 idClass::delete
498 ================
499 */
500 void idClass::operator delete( void *ptr ) {
501  int *p;
502 
503  if ( ptr ) {
504  p = ( ( int * )ptr ) - 1;
505  memused -= *p;
506  numobjects--;
507  Mem_Free( p );
508  }
509 }
510 
511 void idClass::operator delete( void *ptr, int, int, char *, int ) {
512  int *p;
513 
514  if ( ptr ) {
515  p = ( ( int * )ptr ) - 1;
516  memused -= *p;
517  numobjects--;
518  Mem_Free( p );
519  }
520 }
521 
522 /*
523 ================
524 idClass::GetClass
525 
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 )
528 ================
529 */
531  idTypeInfo *c;
532  int order;
533  int mid;
534  int min;
535  int max;
536 
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 ) ) {
541  return c;
542  }
543  }
544  } else {
545  // do a binary search through the list of types
546  min = 0;
547  max = types.Num() - 1;
548  while( min <= max ) {
549  mid = ( min + max ) / 2;
550  c = types[ mid ];
551  order = idStr::Cmp( c->classname, name );
552  if ( !order ) {
553  return c;
554  } else if ( order > 0 ) {
555  max = mid - 1;
556  } else {
557  min = mid + 1;
558  }
559  }
560  }
561 
562  return NULL;
563 }
564 
565 /*
566 ================
567 idClass::GetType
568 ================
569 */
570 idTypeInfo *idClass::GetType( const int typeNum ) {
571  idTypeInfo *c;
572 
573  if ( !initialized ) {
574  for( c = typelist; c != NULL; c = c->next ) {
575  if ( c->typeNum == typeNum ) {
576  return c;
577  }
578  }
579  } else if ( ( typeNum >= 0 ) && ( typeNum < types.Num() ) ) {
580  return typenums[ typeNum ];
581  }
582 
583  return NULL;
584 }
585 
586 /*
587 ================
588 idClass::GetClassname
589 
590 Returns the text classname of the object.
591 ================
592 */
593 const char *idClass::GetClassname( void ) const {
594  idTypeInfo *type;
595 
596  type = GetType();
597  return type->classname;
598 }
599 
600 /*
601 ================
602 idClass::GetSuperclass
603 
604 Returns the text classname of the superclass.
605 ================
606 */
607 const char *idClass::GetSuperclass( void ) const {
608  idTypeInfo *cls;
609 
610  cls = GetType();
611  return cls->superclass;
612 }
613 
614 /*
615 ================
616 idClass::CancelEvents
617 ================
618 */
620  idEvent::CancelEvents( this, ev );
621 }
622 
623 /*
624 ================
625 idClass::PostEventArgs
626 ================
627 */
628 bool idClass::PostEventArgs( const idEventDef *ev, int time, int numargs, ... ) {
629  idTypeInfo *c;
630  idEvent *event;
631  va_list args;
632 
633  assert( ev );
634 
635  if ( !idEvent::initialized ) {
636  return false;
637  }
638 
639  c = GetType();
640  if ( !c->eventMap[ ev->GetEventNum() ] ) {
641  // we don't respond to this event, so ignore it
642  return false;
643  }
644 
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 ) ) {
649  return true;
650  }
651 
652  va_start( args, numargs );
653  event = idEvent::Alloc( ev, numargs, args );
654  va_end( args );
655 
656  event->Schedule( this, c, time );
657 
658  return true;
659 }
660 
661 /*
662 ================
663 idClass::PostEventMS
664 ================
665 */
666 bool idClass::PostEventMS( const idEventDef *ev, int time ) {
667  return PostEventArgs( ev, time, 0 );
668 }
669 
670 /*
671 ================
672 idClass::PostEventMS
673 ================
674 */
675 bool idClass::PostEventMS( const idEventDef *ev, int time, idEventArg arg1 ) {
676  return PostEventArgs( ev, time, 1, &arg1 );
677 }
678 
679 /*
680 ================
681 idClass::PostEventMS
682 ================
683 */
685  return PostEventArgs( ev, time, 2, &arg1, &arg2 );
686 }
687 
688 /*
689 ================
690 idClass::PostEventMS
691 ================
692 */
694  return PostEventArgs( ev, time, 3, &arg1, &arg2, &arg3 );
695 }
696 
697 /*
698 ================
699 idClass::PostEventMS
700 ================
701 */
703  return PostEventArgs( ev, time, 4, &arg1, &arg2, &arg3, &arg4 );
704 }
705 
706 /*
707 ================
708 idClass::PostEventMS
709 ================
710 */
712  return PostEventArgs( ev, time, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
713 }
714 
715 /*
716 ================
717 idClass::PostEventMS
718 ================
719 */
721  return PostEventArgs( ev, time, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
722 }
723 
724 /*
725 ================
726 idClass::PostEventMS
727 ================
728 */
730  return PostEventArgs( ev, time, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
731 }
732 
733 /*
734 ================
735 idClass::PostEventMS
736 ================
737 */
739  return PostEventArgs( ev, time, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
740 }
741 
742 /*
743 ================
744 idClass::PostEventSec
745 ================
746 */
747 bool idClass::PostEventSec( const idEventDef *ev, float time ) {
748  return PostEventArgs( ev, SEC2MS( time ), 0 );
749 }
750 
751 /*
752 ================
753 idClass::PostEventSec
754 ================
755 */
756 bool idClass::PostEventSec( const idEventDef *ev, float time, idEventArg arg1 ) {
757  return PostEventArgs( ev, SEC2MS( time ), 1, &arg1 );
758 }
759 
760 /*
761 ================
762 idClass::PostEventSec
763 ================
764 */
766  return PostEventArgs( ev, SEC2MS( time ), 2, &arg1, &arg2 );
767 }
768 
769 /*
770 ================
771 idClass::PostEventSec
772 ================
773 */
775  return PostEventArgs( ev, SEC2MS( time ), 3, &arg1, &arg2, &arg3 );
776 }
777 
778 /*
779 ================
780 idClass::PostEventSec
781 ================
782 */
784  return PostEventArgs( ev, SEC2MS( time ), 4, &arg1, &arg2, &arg3, &arg4 );
785 }
786 
787 /*
788 ================
789 idClass::PostEventSec
790 ================
791 */
793  return PostEventArgs( ev, SEC2MS( time ), 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
794 }
795 
796 /*
797 ================
798 idClass::PostEventSec
799 ================
800 */
802  return PostEventArgs( ev, SEC2MS( time ), 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
803 }
804 
805 /*
806 ================
807 idClass::PostEventSec
808 ================
809 */
811  return PostEventArgs( ev, SEC2MS( time ), 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
812 }
813 
814 /*
815 ================
816 idClass::PostEventSec
817 ================
818 */
820  return PostEventArgs( ev, SEC2MS( time ), 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
821 }
822 
823 /*
824 ================
825 idClass::ProcessEventArgs
826 ================
827 */
828 bool idClass::ProcessEventArgs( const idEventDef *ev, int numargs, ... ) {
829  idTypeInfo *c;
830  int num;
831  int data[ D_EVENT_MAXARGS ];
832  va_list args;
833 
834  assert( ev );
836 
837  c = GetType();
838  num = ev->GetEventNum();
839  if ( !c->eventMap[ num ] ) {
840  // we don't respond to this event, so ignore it
841  return false;
842  }
843 
844  va_start( args, numargs );
845  idEvent::CopyArgs( ev, numargs, args, data );
846  va_end( args );
847 
848  ProcessEventArgPtr( ev, data );
849 
850  return true;
851 }
852 
853 /*
854 ================
855 idClass::ProcessEvent
856 ================
857 */
859  return ProcessEventArgs( ev, 0 );
860 }
861 
862 /*
863 ================
864 idClass::ProcessEvent
865 ================
866 */
868  return ProcessEventArgs( ev, 1, &arg1 );
869 }
870 
871 /*
872 ================
873 idClass::ProcessEvent
874 ================
875 */
877  return ProcessEventArgs( ev, 2, &arg1, &arg2 );
878 }
879 
880 /*
881 ================
882 idClass::ProcessEvent
883 ================
884 */
886  return ProcessEventArgs( ev, 3, &arg1, &arg2, &arg3 );
887 }
888 
889 /*
890 ================
891 idClass::ProcessEvent
892 ================
893 */
895  return ProcessEventArgs( ev, 4, &arg1, &arg2, &arg3, &arg4 );
896 }
897 
898 /*
899 ================
900 idClass::ProcessEvent
901 ================
902 */
904  return ProcessEventArgs( ev, 5, &arg1, &arg2, &arg3, &arg4, &arg5 );
905 }
906 
907 /*
908 ================
909 idClass::ProcessEvent
910 ================
911 */
913  return ProcessEventArgs( ev, 6, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6 );
914 }
915 
916 /*
917 ================
918 idClass::ProcessEvent
919 ================
920 */
922  return ProcessEventArgs( ev, 7, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7 );
923 }
924 
925 /*
926 ================
927 idClass::ProcessEvent
928 ================
929 */
931  return ProcessEventArgs( ev, 8, &arg1, &arg2, &arg3, &arg4, &arg5, &arg6, &arg7, &arg8 );
932 }
933 
934 /*
935 ================
936 idClass::ProcessEventArgPtr
937 ================
938 */
939 bool idClass::ProcessEventArgPtr( const idEventDef *ev, int *data ) {
940  idTypeInfo *c;
941  int num;
943 
944  assert( ev );
946 
947 #ifdef _D3XP
948  SetTimeState ts;
949 
950  if ( IsType( idEntity::Type ) ) {
951  idEntity *ent = (idEntity*)this;
952  ts.PushState( ent->timeGroup );
953  }
954 #endif
955 
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" );
959  }
960 
961  c = GetType();
962  num = ev->GetEventNum();
963  if ( !c->eventMap[ num ] ) {
964  // we don't respond to this event, so ignore it
965  return false;
966  }
967 
968  callback = c->eventMap[ num ];
969 
970 #if !CPU_EASYARGS
971 
972 /*
973 on ppc architecture, floats are passed in a seperate set of registers
974 the function prototypes must have matching float declaration
975 
976 http://developer.apple.com/documentation/DeveloperTools/Conceptual/MachORuntime/2rt_powerpc_abi/chapter_9_section_5.html
977 */
978 
979  switch( ev->GetFormatspecIndex() ) {
980  case 1 << D_EVENT_MAXARGS :
981  ( this->*callback )();
982  break;
983 
984 // generated file - see CREATE_EVENT_CODE
985 #include "Callbacks.cpp"
986 
987  default:
988  gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
989  break;
990  }
991 
992 #else
993 
994  assert( D_EVENT_MAXARGS == 8 );
995 
996  switch( ev->GetNumArgs() ) {
997  case 0 :
998  ( this->*callback )();
999  break;
1000 
1001  case 1 :
1002  typedef void ( idClass::*eventCallback_1_t )( const int );
1003  ( this->*( eventCallback_1_t )callback )( data[ 0 ] );
1004  break;
1005 
1006  case 2 :
1007  typedef void ( idClass::*eventCallback_2_t )( const int, const int );
1008  ( this->*( eventCallback_2_t )callback )( data[ 0 ], data[ 1 ] );
1009  break;
1010 
1011  case 3 :
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 ] );
1014  break;
1015 
1016  case 4 :
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 ] );
1019  break;
1020 
1021  case 5 :
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 ] );
1024  break;
1025 
1026  case 6 :
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 ] );
1029  break;
1030 
1031  case 7 :
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 ] );
1034  break;
1035 
1036  case 8 :
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 ] );
1039  break;
1040 
1041  default:
1042  gameLocal.Warning( "Invalid formatspec on event '%s'", ev->GetName() );
1043  break;
1044  }
1045 
1046 #endif
1047 
1048  return true;
1049 }
1050 
1051 /*
1052 ================
1053 idClass::Event_Remove
1054 ================
1055 */
1057  delete this;
1058 }
1059 
1060 /*
1061 ================
1062 idClass::Event_SafeRemove
1063 ================
1064 */
1066  // Forces the remove to be done at a safe time
1067  PostEventMS( &EV_Remove, 0 );
1068 }
idHierarchy< idTypeInfo > node
Definition: Class.h:288
static void DisplayInfo_f(const idCmdArgs &args)
Definition: Class.cpp:325
idEventFunc< idClass > * eventCallbacks
Definition: Class.h:280
idTypeInfo * next
Definition: Class.h:283
#define min(a, b)
bool PostEventSec(const idEventDef *ev, float time)
Definition: Class.cpp:747
assert(prefInfo.fullscreenBtn)
int Cmp(const char *text) const
Definition: Str.h:652
static idTypeInfo * GetType(int num)
Definition: Class.cpp:570
void Printf(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:699
static void ListClasses_f(const idCmdArgs &args)
Definition: Class.cpp:334
void SetNum(int newnum, bool resize=true)
Definition: List.h:289
void FindUninitializedMemory(void)
Definition: Class.cpp:286
const idEventDef EV_Activate("activate","e")
void(idClass::* classSpawnFunc_t)(void)
Definition: Class.h:169
bool IsType(const idTypeInfo &c) const
Definition: Class.h:337
const idEventDef * event
Definition: Class.h:48
case const int
Definition: Callbacks.cpp:52
static idClass * CreateInstance(const char *name)
Definition: Class.cpp:354
bool ProcessEvent(const idEventDef *ev)
Definition: Class.cpp:858
static idList< idTypeInfo * > typenums
Definition: Class.h:259
void SetGranularity(int newgranularity)
Definition: List.h:305
prefInfo callback
bool isClient
Definition: Game_local.h:327
static int memused
Definition: Class.h:261
void SetOwner(type *object)
Definition: Hierarchy.h:114
idTypeInfo * super
Definition: Class.h:282
GLuint GLuint GLsizei GLenum type
Definition: glext.h:2845
GLdouble s
Definition: glext.h:2935
const char * GetClassname(void) const
Definition: Class.cpp:593
void ParentTo(idHierarchy &node)
Definition: Hierarchy.h:141
GLhandleARB obj
Definition: glext.h:3602
const idEventDef EV_SafeRemove("remove", NULL)
idTypeInfo(const char *classname, const char *superclass, idEventFunc< idClass > *eventCallbacks, idClass *(*CreateInstance)(void), void(idClass::*Spawn)(void), void(idClass::*Save)(idSaveGame *savefile) const, void(idClass::*Restore)(idRestoreGame *savefile))
Definition: Class.cpp:65
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:5286
void Init(void)
Definition: Class.cpp:124
int i
Definition: process.py:33
GLuint GLuint num
Definition: glext.h:5390
~idTypeInfo()
Definition: Class.cpp:112
static int NumEventCommands(void)
Definition: Event.cpp:174
const char * superclass
Definition: Class.h:274
Definition: Class.h:174
#define EVENT(event, function)
Definition: Class.h:53
#define ABSTRACT_DECLARATION(nameofsuperclass, nameofclass)
Definition: Class.h:156
void(idClass::* Restore)(idRestoreGame *savefile)
Definition: Class.h:278
classSpawnFunc_t CallSpawnFunc(idTypeInfo *cls)
Definition: Class.cpp:264
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:5285
void void void Warning(const char *fmt,...) const id_attribute((format(printf
Definition: Game_local.cpp:735
void Event_Remove(void)
Definition: Class.cpp:1056
void(idClass::* Save)(idSaveGame *savefile) const
Definition: Class.h:277
int typeNum
Definition: Class.h:285
const char * GetSuperclass(void) const
Definition: Class.cpp:607
idCVar g_debugTriggers("g_debugTriggers","0", CVAR_GAME|CVAR_BOOL,"")
eventCallback_t * eventMap
Definition: Class.h:281
bool ProcessEventArgs(const idEventDef *ev, int numargs,...)
Definition: Class.cpp:828
const char * GetName(void) const
Definition: Event.h:144
GLdouble GLdouble GLint GLint order
Definition: qgl.h:339
const GLubyte * c
Definition: glext.h:4677
const char * GetTypeVariableName(const char *typeName, int offset)
Definition: TypeInfo.cpp:92
void(idClass::* Spawn)(void)
Definition: Class.h:276
static int numobjects
Definition: Class.h:262
static idList< idTypeInfo * > types
Definition: Class.h:258
GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg3
Definition: glext.h:5287
Definition: Event.h:88
#define NULL
Definition: Lib.h:88
static void Shutdown(void)
Definition: Class.cpp:426
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:2853
bool initialized
Definition: maya_main.cpp:38
void Spawn(void)
Definition: Class.cpp:306
static idTypeInfo * GetClass(const char *name)
Definition: Class.cpp:530
void CancelEvents(const idEventDef *ev)
Definition: Class.cpp:619
void Event_SafeRemove(void)
Definition: Class.cpp:1065
#define D_EVENT_MAXARGS
Definition: Event.h:36
void Mem_Free(void *ptr)
Definition: Heap.cpp:1087
int GetEventNum(void) const
Definition: Event.h:208
type * GetNext(void) const
Definition: Hierarchy.h:310
void(idClass::* eventCallback_t)(void)
Definition: Class.h:44
gameState_t GameState(void) const
static bool initialized
Definition: Event.h:102
idGameLocal gameLocal
Definition: Game_local.cpp:64
#define END_CLASS
Definition: Class.h:54
unsigned int GetFormatspecIndex(void) const
Definition: Event.h:162
static int BitsForInteger(int i)
Definition: Math.h:727
int GetNumArgs(void) const
Definition: Event.h:180
int lastChild
Definition: Class.h:286
static void Init(void)
Definition: Class.cpp:377
#define SEC2MS(t)
Definition: Math.h:59
static bool initialized
Definition: Class.h:257
bool GetBool(void) const
Definition: CVarSystem.h:142
bool PostEventArgs(const idEventDef *ev, int time, int numargs,...)
Definition: Class.cpp:628
int Num(void) const
Definition: List.h:265
virtual ~idClass()
Definition: Class.cpp:316
const GLcharARB * name
Definition: glext.h:3629
GLsizeiptr size
Definition: glext.h:3112
const char * GetName(void) const
Definition: Entity.cpp:875
bool ProcessEventArgPtr(const idEventDef *ev, int *data)
Definition: Class.cpp:939
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
static int typeNumBits
Definition: Class.h:260
const idEventDef EV_Remove("<immediateremove>", NULL)
void * Mem_Alloc(const int size)
Definition: Heap.cpp:1067
eventCallback_t function
Definition: Class.h:49
void Shutdown(void)
Definition: Class.cpp:210
static void CopyArgs(const idEventDef *evdef, int numargs, va_list args, int data[D_EVENT_MAXARGS])
Definition: Event.cpp:337
const char * classname
Definition: Class.h:273
static idEvent * Alloc(const idEventDef *evdef, int numargs, va_list args)
Definition: Event.cpp:241
bool PostEventMS(const idEventDef *ev, int time)
Definition: Class.cpp:666
#define max(x, y)
Definition: os.h:70
static void CancelEvents(const idClass *obj, const idEventDef *evdef=NULL)
Definition: Event.cpp:437
GLfloat GLfloat p
Definition: glext.h:4674
Definition: List.h:84
bool freeEventMap
Definition: Class.h:284
idClass *(* CreateInstance)(void)
Definition: Class.h:275
void Clear(void)
Definition: List.h:184