dynamicConsoleMethodComponent.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  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. #include "component/dynamicConsoleMethodComponent.h"
  23. #include "console/stringStack.h"
  24. extern StringStack STR;
  25. extern ConsoleValueStack CSTK;
  26. IMPLEMENT_CO_NETOBJECT_V1(DynamicConsoleMethodComponent);
  27. ConsoleDocClass( DynamicConsoleMethodComponent,
  28. "@brief Console object used for calling methods defined in script, from within other classes.\n\n"
  29. "Not intended for game development, for editors or internal use only.\n\n "
  30. "@internal");
  31. //-----------------------------------------------------------
  32. // Function name: SimComponent::handlesConsoleMethod
  33. // Summary:
  34. //-----------------------------------------------------------
  35. bool DynamicConsoleMethodComponent::handlesConsoleMethod( const char *fname, S32 *routingId )
  36. {
  37. // CodeReview: Host object is now given priority over components for method
  38. // redirection. [6/23/2007 Pat]
  39. // On this object?
  40. if( isMethod( fname ) )
  41. {
  42. *routingId = -1; // -1 denotes method on object
  43. #ifdef TORQUE_DEBUG
  44. // Inject Method.
  45. injectMethodCall( fname );
  46. #endif
  47. return true;
  48. }
  49. // on this objects components?
  50. S32 nI = 0;
  51. VectorPtr<SimComponent*> &componentList = lockComponentList();
  52. for( SimComponentIterator nItr = componentList.begin(); nItr != componentList.end(); nItr++, nI++ )
  53. {
  54. SimObject *pComponent = dynamic_cast<SimObject*>(*nItr);
  55. if( pComponent != NULL && pComponent->isMethod( fname ) )
  56. {
  57. *routingId = -2; // -2 denotes method on component
  58. unlockComponentList();
  59. #ifdef TORQUE_DEBUG
  60. // Inject Method.
  61. injectMethodCall( fname );
  62. #endif
  63. return true;
  64. }
  65. }
  66. unlockComponentList();
  67. return false;
  68. }
  69. const char *DynamicConsoleMethodComponent::callMethod( S32 argc, const char* methodName, ... )
  70. {
  71. const char *argv[128];
  72. methodName = StringTable->insert( methodName );
  73. argc++;
  74. va_list args;
  75. va_start(args, methodName);
  76. for(S32 i = 0; i < argc; i++)
  77. argv[i+2] = va_arg(args, const char *);
  78. va_end(args);
  79. // FIXME: the following seems a little excessive. I wonder why it's needed?
  80. argv[0] = methodName;
  81. argv[1] = methodName;
  82. argv[2] = methodName;
  83. StringStackConsoleWrapper argsw(argc, argv);
  84. return callMethodArgList( argsw.count() , argsw );
  85. }
  86. #ifdef TORQUE_DEBUG
  87. /// Inject Method Call.
  88. void DynamicConsoleMethodComponent::injectMethodCall( const char* method )
  89. {
  90. // Get Call Method.
  91. StringTableEntry callMethod = StringTable->insert( method );
  92. // Find Call Method Metric.
  93. callMethodMetricType::Iterator itr = mCallMethodMetrics.find( callMethod );
  94. // Did we find the method?
  95. if ( itr == mCallMethodMetrics.end() )
  96. {
  97. // No, so set the call count to initially be 1.
  98. itr = mCallMethodMetrics.insert( callMethod, 1 );
  99. }
  100. else
  101. {
  102. // Increment Call Count.
  103. itr->value++;
  104. }
  105. }
  106. #endif
  107. const char* DynamicConsoleMethodComponent::callMethodArgList( U32 argc, ConsoleValueRef argv[], bool callThis /* = true */ )
  108. {
  109. #ifdef TORQUE_DEBUG
  110. injectMethodCall( argv[0] );
  111. #endif
  112. return _callMethod( argc, argv, callThis );
  113. }
  114. // Call all components that implement methodName giving them a chance to operate
  115. // Components are called in reverse order of addition
  116. const char *DynamicConsoleMethodComponent::_callMethod( U32 argc, ConsoleValueRef argv[], bool callThis /* = true */ )
  117. {
  118. // Set Owner
  119. SimObject *pThis = dynamic_cast<SimObject *>( this );
  120. AssertFatal( pThis, "DynamicConsoleMethodComponent::callMethod : this should always exist!" );
  121. const char *cbName = StringTable->insert(argv[0]);
  122. if( getComponentCount() > 0 )
  123. {
  124. lockComponentList();
  125. for( S32 i = getComponentCount() - 1; i >= 0; i-- )
  126. //for( SimComponentIterator nItr = componentList.end(); nItr != componentList.begin(); nItr-- )
  127. {
  128. argv[0] = cbName;
  129. SimComponent *pComponent = dynamic_cast<SimComponent *>( getComponent( i ) );
  130. AssertFatal( pComponent, "DynamicConsoleMethodComponent::callMethod - NULL component in list!" );
  131. DynamicConsoleMethodComponent *pThisComponent = dynamic_cast<DynamicConsoleMethodComponent*>( pComponent );
  132. AssertFatal( pThisComponent, "DynamicConsoleMethodComponent::callMethod - Non DynamicConsoleMethodComponent component attempting to callback!");
  133. // Prevent stack corruption
  134. STR.pushFrame();
  135. CSTK.pushFrame();
  136. // --
  137. // Only call on first depth components
  138. // Should isMethod check these calls? [11/22/2006 justind]
  139. if(pComponent->isEnabled())
  140. Con::execute( pThisComponent, argc, argv );
  141. // Prevent stack corruption
  142. STR.popFrame();
  143. CSTK.popFrame();
  144. // --
  145. // Bail if this was the first element
  146. //if( nItr == componentList.begin() )
  147. // break;
  148. }
  149. unlockComponentList();
  150. }
  151. // Prevent stack corruption
  152. STR.pushFrame();
  153. CSTK.pushFrame();
  154. // --
  155. // Set Owner Field
  156. const char* result = "";
  157. if(callThis)
  158. result = Con::execute( pThis, argc, argv, true ); // true - exec method onThisOnly, not on DCMCs
  159. // Prevent stack corruption
  160. STR.popFrame();
  161. CSTK.popFrame();
  162. // --
  163. return result;
  164. }
  165. ConsoleMethod( DynamicConsoleMethodComponent, callMethod, void, 3, 64 , "(methodName, argi) Calls script defined method\n"
  166. "@param methodName The method's name as a string\n"
  167. "@param argi Any arguments to pass to the method\n"
  168. "@return No return value"
  169. "@note %obj.callMethod( %methodName, %arg1, %arg2, ... );\n")
  170. {
  171. object->callMethodArgList( argc - 1, argv + 2 );
  172. }
  173. //////////////////////////////////////////////////////////////////////////