runtimeClassRep.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _RUNTIME_CLASSREP_H_
  23. #define _RUNTIME_CLASSREP_H_
  24. #include "console/consoleObject.h"
  25. #include "console/consoleInternal.h"
  26. /// This class is to allow new types to be added, at run-time, to Torque.
  27. /// This is primarily for dynamic libraries, plugins etc.
  28. ///
  29. /// The idea is the same, one instance per type which is getting registered
  30. /// however it doesn't get added to the dictionary until it is told to
  31. /// add itself. It can be removed, as well, though no safe-execution
  32. /// assurances are made by this class. If an object type is removed
  33. /// behavior of existing console objects of that type is undefined.
  34. /// (aka bad stuff will probably happen but I don't know exactly what)
  35. template <class T>
  36. class RuntimeClassRep : public AbstractClassRep
  37. {
  38. protected:
  39. static bool smConRegistered; ///< This variable will be set to true if this class-rep is currently registered
  40. public:
  41. RuntimeClassRep( const char *name, const char* conTypeName, S32* conTypeIdPtr, S32 netClassGroupMask, S32 netClassType, S32 netEventDir, AbstractClassRep *parent )
  42. : AbstractClassRep( conTypeIdPtr, conTypeName )
  43. {
  44. // name is a static compiler string so no need to worry about copying or deleting
  45. mClassName = name;
  46. mTypeInfo = _MAPTYPE< T >();
  47. // Clean up mClassId
  48. for( U32 i = 0; i < NetClassGroupsCount; i++ )
  49. mClassId[i] = -1;
  50. // Set properties for this ACR
  51. mClassType = netClassType;
  52. mClassGroupMask = netClassGroupMask;
  53. mNetEventDir = netEventDir;
  54. parentClass = parent;
  55. };
  56. /// Perform class specific initialization tasks.
  57. ///
  58. /// Link namespaces, call initPersistFields() and consoleInit().
  59. void init() const
  60. {
  61. // Get handle to our parent class, if any, and ourselves (we are our parent's child).
  62. AbstractClassRep *parent = T::getParentStaticClassRep();
  63. AbstractClassRep *child = T::getStaticClassRep ();
  64. // If we got reps, then link those namespaces! (To get proper inheritance.)
  65. if( parent && child )
  66. Con::classLinkNamespaces( parent->getNameSpace(), child->getNameSpace() );
  67. // Finally, do any class specific initialization...
  68. T::initPersistFields();
  69. T::consoleInit();
  70. }
  71. /// Wrap constructor.
  72. ConsoleObject *create() const { return new T; }
  73. //-----------------------------------------------------------------------------
  74. /// Register this class with the Torque console
  75. void consoleRegister()
  76. {
  77. AssertFatal( !smConRegistered, "Calling consoleRegister, but this type is already linked into the class list" );
  78. if( !smConRegistered )
  79. registerClassRep( this );
  80. // Now initialize the namespace
  81. mNamespace = Con::lookupNamespace( StringTable->insert( getClassName() ) );
  82. mNamespace->mClassRep = this;
  83. // Perform field initialization
  84. sg_tempFieldList.setSize(0);
  85. init();
  86. // So if we have things in it, copy it over...
  87. if ( sg_tempFieldList.size() != 0 )
  88. mFieldList = sg_tempFieldList;
  89. // And of course delete it every round.
  90. sg_tempFieldList.clear();
  91. smConRegistered = true;
  92. }
  93. /// Unregister this class with the Torque console
  94. void consoleUnRegister()
  95. {
  96. AssertFatal( smConRegistered, "Calling consoleUnRegister, but this type is not linked into the class list" );
  97. if( !smConRegistered )
  98. return;
  99. removeClassRep( this );
  100. smConRegistered = false;
  101. }
  102. /// Returns true if this class type is registered with the console system
  103. static const bool isRegistered() { return smConRegistered; }
  104. /// @name Console Type Interface
  105. /// @{
  106. virtual void setData( void* dptr, S32 argc, const char** argv, const EnumTable* tbl, BitSet32 flag )
  107. {
  108. if( argc == 1 )
  109. {
  110. T** obj = ( T** ) dptr;
  111. *obj = dynamic_cast< T* >( T::__findObject( argv[ 0 ] ) );
  112. }
  113. else
  114. Con::errorf( "Cannot set multiple args to a single ConsoleObject*.");
  115. }
  116. virtual const char* getData( void* dptr, const EnumTable* tbl, BitSet32 flag )
  117. {
  118. T** obj = ( T** ) dptr;
  119. return Con::getReturnBuffer( T::__getObjectId( *obj ) );
  120. }
  121. virtual const char* getTypeClassName() { return mClassName; }
  122. virtual const bool isDatablock() { return T::__smIsDatablock; };
  123. /// @}
  124. };
  125. template<class T> bool RuntimeClassRep<T>::smConRegistered = false;
  126. //-----------------------------------------------------------------------------
  127. #define DECLARE_RUNTIME_CONOBJECT(className) \
  128. DECLARE_CLASS( className, Parent ); \
  129. static S32 _sTypeId; \
  130. static RuntimeClassRep<className> dynRTClassRep; \
  131. static AbstractClassRep* getParentStaticClassRep(); \
  132. static AbstractClassRep* getStaticClassRep(); \
  133. virtual AbstractClassRep* getClassRep() const
  134. #define IMPLEMENT_RUNTIME_CONOBJECT(className) \
  135. IMPLEMENT_CLASS( className, NULL ) \
  136. END_IMPLEMENT_CLASS; \
  137. S32 className::_sTypeId; \
  138. AbstractClassRep* className::getClassRep() const { return &className::dynRTClassRep; } \
  139. AbstractClassRep* className::getStaticClassRep() { return &dynRTClassRep; } \
  140. AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } \
  141. RuntimeClassRep<className> className::dynRTClassRep(#className, "Type" #className, &_sTypeId, 0, -1, 0, className::getParentStaticClassRep())
  142. #endif