dynamicConsoleMethodComponent.cpp 6.3 KB

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