simComponent.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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 _SIMCOMPONENT_H_
  23. #define _SIMCOMPONENT_H_
  24. #ifndef _TVECTOR_H_
  25. #include "core/util/tVector.h"
  26. #endif
  27. #ifndef _STRINGTABLE_H_
  28. #include "core/stringTable.h"
  29. #endif
  30. #ifndef _NETOBJECT_H_
  31. #include "sim/netObject.h"
  32. #endif
  33. #ifndef _COMPONENTINTERFACE_H_
  34. #include "component/componentInterface.h"
  35. #endif
  36. #ifndef _PLATFORM_THREADS_MUTEX_H_
  37. #include "platform/threads/mutex.h"
  38. #endif
  39. #ifndef _STRINGFUNCTIONS_H_
  40. #include "core/strings/stringFunctions.h"
  41. #endif
  42. // Forward refs
  43. class Stream;
  44. class ComponentInterface;
  45. class ComponentInterfaceCache;
  46. class SimComponent : public NetObject
  47. {
  48. typedef NetObject Parent;
  49. private:
  50. VectorPtr<SimComponent *> mComponentList; ///< The Component List
  51. void *mMutex; ///< Component List Mutex
  52. SimObjectPtr<SimComponent> mOwner; ///< The component which owns this one.
  53. /// This is called internally to instruct the component to iterate over it's
  54. // list of components and recursively call _registerInterfaces on their lists
  55. // of components.
  56. void _registerInterfaces( SimComponent *owner );
  57. bool _registerComponents( SimComponent *owner );
  58. void _unregisterComponents();
  59. protected:
  60. ComponentInterfaceCache mInterfaceCache; ///< Stores the interfaces exposed by this component.
  61. bool mEnabled;
  62. bool mTemplate;
  63. // Non-const getOwner for derived classes
  64. SimComponent *_getOwner() { return mOwner; }
  65. /// Returns a const reference to private mComponentList
  66. typedef VectorPtr<SimComponent *>::iterator SimComponentIterator;
  67. VectorPtr<SimComponent *> &lockComponentList()
  68. {
  69. Mutex::lockMutex( mMutex );
  70. return mComponentList;
  71. };
  72. void unlockComponentList()
  73. {
  74. Mutex::unlockMutex( mMutex );
  75. }
  76. /// onComponentRegister is called on each component by it's owner. If a component
  77. /// has no owner, onComponentRegister will not be called on it. The purpose
  78. /// of onComponentRegister is to allow a component to check for any external
  79. /// interfaces, or other dependencies which it needs to function. If any component
  80. /// in a component hierarchy returns false from it's onComponentRegister call
  81. /// the entire hierarchy is invalid, and SimObject::onAdd will fail on the
  82. /// top-level component. To put it another way, if a component contains other
  83. /// components, it will be registered successfully with Sim iff each subcomponent
  84. /// returns true from onComponentRegister. If a component does not contain
  85. /// other components, it will not receive an onComponentRegister call.
  86. ///
  87. /// Overloads of this method must pass the call along to their parent, as is
  88. /// shown in the example below.
  89. ///
  90. /// @code
  91. /// bool FooComponent::onComponentRegister( SimComponent *owner )
  92. /// {
  93. /// if( !Parent::onComponentRegister( owner ) )
  94. /// return false;
  95. /// ...
  96. /// }
  97. /// @endcode
  98. virtual bool onComponentRegister( SimComponent *owner )
  99. {
  100. mOwner = owner;
  101. return true;
  102. }
  103. /// onUnregister is called when the owner is unregistering. Your object should
  104. /// do cleanup here, as well as pass a call up the chain to the parent.
  105. virtual void onComponentUnRegister()
  106. {
  107. mOwner = NULL;
  108. }
  109. /// registerInterfaces is called on each component as it's owner is registering
  110. /// it's interfaces. This is called before onComponentRegister, and should be used to
  111. /// register all interfaces exposed by your component, as well as all callbacks
  112. /// needed by your component.
  113. virtual void registerInterfaces( SimComponent *owner )
  114. {
  115. }
  116. public:
  117. DECLARE_CONOBJECT(SimComponent);
  118. /// Constructor
  119. /// Add this component
  120. SimComponent();
  121. /// Destructor
  122. /// Remove this component and destroy child references
  123. virtual ~SimComponent();
  124. public:
  125. virtual bool onAdd();
  126. virtual void onRemove();
  127. static void initPersistFields();
  128. virtual bool processArguments(S32 argc, const char **argv);
  129. bool isEnabled() const { return mEnabled; }
  130. void setEnabled( bool value ) { mEnabled = value; }
  131. /// Will return true if this object contains components.
  132. bool hasComponents() const { return ( mComponentList.size() > 0 ); };
  133. /// The component which owns this object
  134. const SimComponent *getOwner() const { return mOwner; };
  135. // Component Information
  136. inline virtual StringTableEntry getComponentName() { return StringTable->insert( getClassName() ); };
  137. /// Protected 'Component' Field setter that will add a component to the list.
  138. static bool addComponentFromField(void* obj, const char* data);
  139. /// Add Component to this one
  140. virtual bool addComponent( SimComponent *component );
  141. /// Remove Component from this one
  142. virtual bool removeComponent( SimComponent *component );
  143. /// Clear Child components of this one
  144. virtual bool clearComponents() { mComponentList.clear(); return true; };
  145. virtual bool onComponentAdd(SimComponent *target);
  146. virtual void onComponentRemove(SimComponent *target);
  147. S32 getComponentCount() { return mComponentList.size(); }
  148. SimComponent *getComponent(S32 idx) { return mComponentList[idx]; }
  149. SimComponentIterator find(SimComponentIterator first, SimComponentIterator last, SimComponent *value)
  150. {
  151. return ::find(first, last, value);
  152. }
  153. static bool setIsTemplate( void *object, const char *index, const char *data )
  154. { static_cast<SimComponent*>(object)->setIsTemplate( dAtob( data ) ); return false; };
  155. virtual void setIsTemplate( const bool pTemplate ) { mTemplate = pTemplate; }
  156. bool getIsTemplate() const { return mTemplate; }
  157. virtual void write(Stream &stream, U32 tabStop, U32 flags = 0);
  158. virtual bool writeField(StringTableEntry fieldname, const char* value);
  159. /// getInterfaces allows the caller to enumerate the interfaces exposed by
  160. /// this component. This method can be overwritten to expose interfaces
  161. /// which are not cached on the object, before passing the call to the Parent.
  162. /// This can be used delay interface creation until it is queried for, instead
  163. /// of creating it on initialization, and caching it. Returns false if no results
  164. /// were found
  165. ///
  166. /// @param list The list that this method will append search results on to.
  167. /// @param type An expression which the 'type' field on an added object must match to be included in results
  168. /// @param name An expression which the 'name' field on an added object must match to be included in results
  169. /// @param owner Limit results to components owned/not-owned by this SimComponent (see next param)
  170. /// @param notOwner If set to true, this will enumerate only interfaces NOT owned by 'owner'
  171. virtual bool getInterfaces( ComponentInterfaceList *list, const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false ); // const omission intentional
  172. /// These two methods allow for easy query of component interfaces if you know
  173. /// exactly what you are looking for, and don't mind being passed back the first
  174. /// matching result.
  175. ComponentInterface *getInterface( const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false );
  176. template <class T>
  177. T *getInterface( const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false );
  178. /// Add an interface to the cache. This function will return true if the interface
  179. /// is added successfully. An interface will not be added successfully if an entry
  180. /// in this components cache with the same values for 'type' and 'name' is present.
  181. ///
  182. /// @param type Type of the interface being added. If NULL is passed, it will match any type string queried.
  183. /// @param name Name of interface being added. If NULL is passed, it will match any name string queried.
  184. /// @param interfaceOwner The component which owns the interface being cached
  185. /// @param cinterface The ComponentInterface being cached
  186. bool registerCachedInterface( const char *type, const char *name, SimComponent *interfaceOwner, ComponentInterface *cinterface );
  187. };
  188. //////////////////////////////////////////////////////////////////////////
  189. template <class T>
  190. T *SimComponent::getInterface( const char *type /* = NULL */, const char *name /* = NULL */,
  191. const SimComponent *owner /* = NULL */, bool notOwner /* = false */ )
  192. {
  193. ComponentInterfaceList iLst;
  194. if( getInterfaces( &iLst, type, name, owner, notOwner ) )
  195. {
  196. ComponentInterfaceListIterator itr = iLst.begin();
  197. while( dynamic_cast<T *>( *itr ) == NULL )
  198. itr++;
  199. if( itr != iLst.end() )
  200. return static_cast<T *>( *itr );
  201. }
  202. return NULL;
  203. }
  204. #endif // _SIMCOMPONENT_H_