componentInterface.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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 _COMPONENTINTERFACE_H_
  23. #define _COMPONENTINTERFACE_H_
  24. #ifndef _TVECTOR_H_
  25. #include "core/util/tVector.h"
  26. #endif
  27. #ifndef _SIMOBJECT_H_
  28. #include "console/simObject.h"
  29. #endif
  30. #include "core/util/safeDelete.h"
  31. class SimComponent;
  32. // CodeReview [patw, 2, 13, 2007] The issue I have not addressed in this class is
  33. // interface locking. I think that we want to do this, for sure, but I also want
  34. // to keep it as light-weight as possible. For the most part, there should only
  35. // ever be one thing doing something with a component at one time, but I can see
  36. // many situations where this wouldn't be the case. When we decide to address
  37. // the issues of locking, I believe it should be done here, at the ComponentInterface
  38. // level. I would like lock functionality to be as centralized as possible, and
  39. // so this is the place for it. The functionality is critical for safe useage of
  40. // the ComponentProperty class, so implementation here would also be ideal.
  41. // CodeReview [patw, 2, 14, 2007] This really should be a ref-counted object
  42. class ComponentInterface
  43. {
  44. friend class SimComponent;
  45. private:
  46. SimObjectPtr<SimComponent> mOwner; ///< SimComponent will directly modify this value
  47. public:
  48. /// Default constructor
  49. ComponentInterface() : mOwner(NULL) {};
  50. /// Destructor
  51. virtual ~ComponentInterface()
  52. {
  53. mOwner = NULL;
  54. }
  55. /// This will return true if the interface is valid
  56. virtual bool isValid() const
  57. {
  58. return mOwner != NULL;
  59. }
  60. /// Get the owner of this interface
  61. SimComponent *getOwner() { return mOwner; }
  62. const SimComponent *getOwner() const { return mOwner; }
  63. };
  64. typedef VectorPtr<ComponentInterface *> ComponentInterfaceList;
  65. typedef VectorPtr<ComponentInterface *>::iterator ComponentInterfaceListIterator;
  66. // These two asserts I found myself wanting a lot when doing interface methods
  67. #ifdef TORQUE_ENABLE_ASSERTS
  68. # define VALID_INTERFACE_ASSERT(OwningClassType) \
  69. AssertFatal( isValid(), "Interface validity check failed." ); \
  70. AssertFatal( dynamic_cast<const OwningClassType *>( getOwner() ) != NULL, avar( "Owner is not an instance of %s", #OwningClassType ) )
  71. #else
  72. # define VALID_INTERFACE_ASSERT(OwningClassType)
  73. #endif
  74. /// This class is designed to wrap an existing class or type easily to allow
  75. /// a SimComponent to expose a property with custom processing code in an efficient
  76. /// and safe way. Specialized templates could be written which include validation
  77. /// on sets, and processing on gets.
  78. ///
  79. /// This class has a lot of "blow your leg off" potential, if you have bad aim.
  80. /// I think that a lot of very intuitive functionality can be gained from using
  81. /// this properly, however when implementing a specialized template, be mindful
  82. /// of what you are doing, and
  83. // CodeReview [patw, 2, 13, 2007] I am very interested in making this as thin as
  84. // possible. I really like the possibilities that it exposes as far as exposing
  85. // "properties" to other components. I want it to be performant, however, so
  86. // if anyone has notes on this, mark up the source, e-mail me, whatever.
  87. template<class T>
  88. class ComponentProperty : public ComponentInterface
  89. {
  90. typedef ComponentInterface Parent;
  91. protected:
  92. T *mValuePtr;
  93. // ComponentInterface Overrides
  94. public:
  95. // Override this to add a check for valid memory.
  96. virtual bool isValid() const
  97. {
  98. return ( mValuePtr != NULL ) && Parent::isValid();
  99. }
  100. // Operator overloads
  101. public:
  102. /// Dereferencing a value interface will allow get to do any processing and
  103. /// return the reference to that
  104. const T &operator*()
  105. {
  106. return get();
  107. }
  108. /// Assignment operator will invoke set.
  109. const T &operator=( const T &lval )
  110. {
  111. return set( lval );
  112. }
  113. // Constructors/Destructors, specialize these if needed
  114. public:
  115. /// Default Constructor.
  116. ComponentProperty() : mValuePtr( NULL )
  117. {
  118. mValuePtr = new T;
  119. }
  120. /// Copy constructor
  121. ComponentProperty( const T &copy )
  122. {
  123. ComponentProperty();
  124. // CodeReview [patw, 2, 13, 2007] So, the reasoning here is that I want to
  125. // use the functionality that a specialized template implements in the set
  126. // method. See the notes on the set method implementation.
  127. set( copy );
  128. }
  129. /// Destructor, destroy memory
  130. virtual ~ComponentProperty()
  131. {
  132. SAFE_DELETE( mValuePtr );
  133. }
  134. // This is the ComponentProperty interface that specializations of the class
  135. // will be interested in.
  136. public:
  137. /// Get the value associated with this interface. Processing code can be done
  138. /// here for specialized implementations.
  139. virtual const T &get() // 'const' is intentionally not used as a modifier here
  140. {
  141. return *mValuePtr;
  142. }
  143. /// Set the value associated with this interface. Validation/processing code
  144. /// can be done here. The copy-constructor uses the set method to do it's copy
  145. /// so be mindful of that, or specialize the copy-constructor.
  146. virtual const T &set( const T &t )
  147. {
  148. // CodeReview [patw, 2, 13, 2007] So I am using the = operator here. Do you
  149. // guys think that this should be the default behavior? I am trying to keep
  150. // everything as object friendly as possible, so I figured I'd use this.
  151. *mValuePtr = t;
  152. return *mValuePtr;
  153. }
  154. };
  155. /// This class is just designed to isolate the functionality of querying for, and
  156. /// managing interfaces.
  157. class ComponentInterfaceCache
  158. {
  159. // CodeReview [patw, 2, 14, 2007] When we move this whole system to Juggernaught
  160. // we may want to consider making safe pointers for ComponentInterfaces. Not
  161. // sure why I put this note here.
  162. private:
  163. struct _InterfaceEntry
  164. {
  165. ComponentInterface *iface;
  166. StringTableEntry type;
  167. StringTableEntry name;
  168. const SimComponent *owner;
  169. };
  170. Vector<_InterfaceEntry> mInterfaceList;
  171. typedef Vector<_InterfaceEntry>::const_iterator _InterfaceEntryItr;
  172. public:
  173. /// Add an interface to the cache. This function will return true if the interface
  174. /// is added successfully. An interface will not be added successfully if an entry
  175. /// in the list with the same values for 'type' and 'name' is present in the list.
  176. ///
  177. /// @param type Type of the interface being added. If NULL is passed, it will match any type string queried.
  178. /// @param name Name of interface being added. If NULL is passed, it will match any name string queried.
  179. /// @param owner The owner of the ComponentInterface being cached
  180. /// @param cinterface The ComponentInterface being cached
  181. virtual bool add( const char *type, const char *name, const SimComponent *owner, ComponentInterface *cinterface );
  182. /// Clear the interface cache. This does not perform any operations on the contents
  183. /// of the list.
  184. virtual void clear();
  185. /// Query the list for all of the interfaces it stores references to that match
  186. /// the 'type' and 'name' parameters. The results of the query will be appended
  187. /// to the list specified. Pattern matching is done using core/findMatch.h; for
  188. /// more information on matching, see that code/header pair. Passing NULL for
  189. /// one of these fields will match all values for that field. The return value
  190. /// for the method will be the number of interfaces which match the query.
  191. ///
  192. /// @param list The list that this method will append search results on to. It is possible to pass NULL here and just receive the return value.
  193. /// @param type An expression which the 'type' field on an added object must match to be included in results
  194. /// @param name An expression which the 'name' field on an added object must match to be included in results
  195. /// @param owner Limit results to components owned/not-owned by this SimComponent (see next param)
  196. /// @param notOwner If set to true, this will enumerate only interfaces NOT owned by 'owner'
  197. virtual U32 enumerate( ComponentInterfaceList *list, const char *type = NULL, const char *name = NULL, const SimComponent *owner = NULL, bool notOwner = false ) const;
  198. };
  199. #endif