simpleComponent.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 _SIMPLECOMPONENT_H_
  23. #define _SIMPLECOMPONENT_H_
  24. #ifndef _SIMCOMPONENT_H_
  25. #include "component/simComponent.h"
  26. #endif
  27. #ifndef _COMPONENTINTERFACE_H_
  28. #include "component/componentInterface.h"
  29. #endif
  30. /// This is a very simple interface. Interfaces provide ways for components to
  31. /// interact with each-other, and query each-other for functionality. It makes it
  32. /// possible for two components to be interdependent on one another, as well. An
  33. /// interface should make accessor calls to it's owner for functionality, and
  34. /// generally be as thin of a layer as possible.
  35. class SimpleComponentInterface : public ComponentInterface
  36. {
  37. public:
  38. bool isFortyTwo( const U32 test );
  39. };
  40. //////////////////////////////////////////////////////////////////////////
  41. /// The purpose of this component is to provide a minimalistic component that
  42. /// exposes a simple, cached interface
  43. class SimpleComponent : public SimComponent
  44. {
  45. typedef SimComponent Parent;
  46. protected:
  47. SimpleComponentInterface mSCInterface;
  48. public:
  49. // Components are still SimObjects, and need to be declared and implemented
  50. // with the standard macros
  51. DECLARE_CONOBJECT(SimpleComponent);
  52. //////////////////////////////////////////////////////////////////////////
  53. // SimComponent overloads.
  54. // This method is called on each component as it's parent is getting onAdd
  55. // called. The purpose of overloading this method is to expose cached interfaces
  56. // before onComponentRegister is called, so that other components can depend on the
  57. // interfaces you expose in order to register properly. This functionality
  58. // will be demonstrated in a more advanced example.
  59. virtual void registerInterfaces( SimComponent *owner )
  60. {
  61. // While it is not imperative that we pass this call to the Parent in this
  62. // example, if there existed a class-heirarchy of components, it would be
  63. // critical, so for good practice, call up to the Parent.
  64. Parent::registerInterfaces( owner );
  65. // Now we should go ahead and register our cached interface. What we are doing
  66. // is telling the component which contains this component (if it exists)
  67. // all of the interfaces that we expose. When this call is made, it will
  68. // recurse up the owner list.
  69. //
  70. // For example, there exists components A, B, and C.
  71. // A owns B, and B owns C.
  72. //
  73. // If C exposes a cached interface, it will expose it via registerCachedInterface
  74. // when registerInterfaces is recursively called. It will add it's interface to
  75. // it's cache list, and then pass the register call up to it's parent. The parent
  76. // will also cache the interface, and continue to pass the cache call up the
  77. // child->parent chain until there exists no parent.
  78. //
  79. // The result is that, if C exposes an interface 'foo', and A owns B, and
  80. // B owns C, an interface request for 'foo' given to component A will result
  81. // in 'foo' being returned, even though A does not expose 'foo'. This makes
  82. // it possible for a component to query it's owner for an interface, and
  83. // not care where that interface is exposed. It also allows for game code
  84. // to work with any SimComponent and query that component for any interface
  85. // it wants without knowing or caring exactly where it is coming from.
  86. //
  87. // registerCachedInterface returns a boolean value if it was successful.
  88. // Success results in the caching of this interface throughout the full
  89. // child->parent chain. An interface will be added to a cache list
  90. // successfully iff there exists no entry in that list that has matching
  91. // values for 'type', 'name' and 'owner'.
  92. owner->registerCachedInterface(
  93. // The first parameter is the 'type' of the interface, this is not to be
  94. // confused with any kind of existing console, or c++ type. It is simply
  95. // a string which is can be set to any value
  96. "example",
  97. // The next parameter is the 'name' of the interface. This is also a string
  98. // which can be set to any value
  99. "isfortytwo",
  100. // The owner of the interface. Note that the value being assigned here
  101. // is this instance of SimpleComponent, and not the 'owner' argument
  102. // of the function registerInterfaces that we are calling from.
  103. this,
  104. // And finally the interface; a pointer to an object with type ComponentInterface
  105. &mSCInterface );
  106. }
  107. //////////////////////////////////////////////////////////////////////////
  108. // Specific functionality
  109. /// This is the test method, it will return true if the number provided
  110. /// is forty two
  111. bool isFortyTwo( const U32 test ) const
  112. {
  113. return ( test == 42 );
  114. }
  115. };
  116. //////////////////////////////////////////////////////////////////////////
  117. // Interface implementation
  118. //
  119. // Since interfaces themselves implement very little functionality, it is a good
  120. // idea to inline them if at all possible. Interdependent components will be using
  121. // these interfaces constantly, and so putting as thin of a layer between the
  122. // functionality they expose, and the functionality the component implements is
  123. // a good design practice.
  124. inline bool SimpleComponentInterface::isFortyTwo( const U32 test )
  125. {
  126. // This code block will test for a valid owner in a debug build before
  127. // performing operations on it's owner. It is worth noting that the
  128. // ComponentInterface::isValid() method can be overridden to include
  129. // validation specific to your interface and/or component.
  130. AssertFatal( isValid(), "SimpleComponentInterface has not been registered properly by the component which exposes it." );
  131. // This is a sanity check. The owner of this interface should have the type
  132. // SimpleComponent, otherwise this won't work. (See further interface examples
  133. // for some ways around this)
  134. AssertFatal( dynamic_cast<SimpleComponent *>( getOwner() ) != NULL, "Owner of SimpleComponentInterface is not a SimpleComponent" );
  135. // Component interfaces rely on being registered to set their mOwner
  136. // field. This field is initialized to NULL, and then gets set by
  137. // SimComponent when the interface is registered.
  138. return static_cast<const SimpleComponent *>( getOwner() )->isFortyTwo( test );
  139. }
  140. #endif