Explorar el Código

Merge remote-tracking branch 'jamesu/console_stack_fix2' into development

Conflicts:
	Engine/source/console/console.cpp
Daniel Buckmaster hace 10 años
padre
commit
6c92ab065e
Se han modificado 48 ficheros con 1340 adiciones y 334 borrados
  1. 11 3
      Engine/source/T3D/gameBase/gameConnection.cpp
  2. 2 1
      Engine/source/T3D/gameBase/gameConnectionEvents.cpp
  3. 2 2
      Engine/source/T3D/item.cpp
  4. 1 1
      Engine/source/T3D/item.h
  5. 2 2
      Engine/source/T3D/pathCamera.cpp
  6. 1 1
      Engine/source/T3D/pathCamera.h
  7. 2 2
      Engine/source/T3D/rigidShape.cpp
  8. 1 1
      Engine/source/T3D/rigidShape.h
  9. 2 1
      Engine/source/app/badWordFilter.cpp
  10. 1 1
      Engine/source/app/net/serverQuery.cpp
  11. 2 6
      Engine/source/console/arrayObject.cpp
  12. 2 2
      Engine/source/console/codeBlock.cpp
  13. 1 1
      Engine/source/console/codeBlock.h
  14. 45 43
      Engine/source/console/compiledEval.cpp
  15. 182 117
      Engine/source/console/console.cpp
  16. 90 58
      Engine/source/console/console.h
  17. 53 23
      Engine/source/console/consoleInternal.cpp
  18. 18 1
      Engine/source/console/consoleInternal.h
  19. 323 20
      Engine/source/console/engineAPI.h
  20. 3 3
      Engine/source/console/sim.h
  21. 17 5
      Engine/source/console/simEvents.cpp
  22. 9 3
      Engine/source/console/simEvents.h
  23. 2 1
      Engine/source/console/simObjectList.cpp
  24. 46 2
      Engine/source/console/stringStack.cpp
  25. 33 0
      Engine/source/console/stringStack.h
  26. 3 1
      Engine/source/console/telnetConsole.cpp
  27. 287 0
      Engine/source/console/test/consoleTest.cpp
  28. 150 0
      Engine/source/console/test/engineAPITest.cpp
  29. 1 1
      Engine/source/forest/editor/forestSelectionTool.cpp
  30. 1 1
      Engine/source/gui/controls/guiConsoleTextCtrl.cpp
  31. 6 6
      Engine/source/gui/controls/guiListBoxCtrl.cpp
  32. 3 3
      Engine/source/gui/controls/guiListBoxCtrl.h
  33. 2 2
      Engine/source/gui/controls/guiMLTextCtrl.cpp
  34. 1 1
      Engine/source/gui/controls/guiMLTextCtrl.h
  35. 4 4
      Engine/source/gui/controls/guiTextListCtrl.cpp
  36. 2 2
      Engine/source/gui/controls/guiTextListCtrl.h
  37. 7 7
      Engine/source/gui/editor/guiMenuBar.cpp
  38. 4 4
      Engine/source/gui/editor/guiMenuBar.h
  39. 2 0
      Engine/source/gui/editor/inspector/customField.cpp
  40. 1 1
      Engine/source/gui/editor/inspector/field.cpp
  41. 2 1
      Engine/source/lighting/common/sceneLighting.cpp
  42. 1 0
      Engine/source/platform/platformRedBook.cpp
  43. 1 0
      Engine/source/platformSDL/menus/popupMenuSDL.cpp
  44. 1 0
      Engine/source/platformWin32/menus/popupMenuWin32.cpp
  45. 2 0
      Engine/source/sfx/sfxModifier.cpp
  46. 1 0
      Engine/source/sfx/sfxParameter.cpp
  47. 1 0
      Engine/source/sim/netDownload.cpp
  48. 6 0
      Engine/source/util/undo.h

+ 11 - 3
Engine/source/T3D/gameBase/gameConnection.cpp

@@ -459,6 +459,14 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
       return false;
    }
    ConsoleValueRef connectArgv[MaxConnectArgs + 3];
+   ConsoleValue connectArgvValue[MaxConnectArgs + 3];
+
+   for(U32 i = 0; i < mConnectArgc+3; i++)
+   {
+	   connectArgv[i].value = &connectArgvValue[i];
+	   connectArgvValue[i].init();
+   }
+
    for(U32 i = 0; i < mConnectArgc; i++)
    {
       char argString[256];
@@ -466,11 +474,11 @@ bool GameConnection::readConnectRequest(BitStream *stream, const char **errorStr
       mConnectArgv[i] = dStrdup(argString);
       connectArgv[i + 3] = mConnectArgv[i];
    }
-   connectArgv[0] = "onConnectRequest";
-   connectArgv[1] = 0;
+   connectArgvValue[0].setStackStringValue("onConnectRequest");
+   connectArgvValue[1].setIntValue(0);
    char buffer[256];
    Net::addressToString(getNetAddress(), buffer);
-   connectArgv[2] = buffer;
+   connectArgvValue[2].setStackStringValue(buffer);
 
    // NOTE: Cannot convert over to IMPLEMENT_CALLBACK as it has variable args.
    const char *ret = Con::execute(this, mConnectArgc + 3, connectArgv);

+ 2 - 1
Engine/source/T3D/gameBase/gameConnectionEvents.cpp

@@ -32,6 +32,7 @@
 #include "app/game.h"
 #include "T3D/gameBase/gameConnection.h"
 #include "T3D/gameBase/gameConnectionEvents.h"
+#include "console/engineAPI.h"
 
 #define DebugChecksum 0xF00DBAAD
 
@@ -234,7 +235,7 @@ void SimDataBlockEvent::process(NetConnection *cptr)
    if(mProcess)
    {
       //call the console function to set the number of blocks to be sent
-      Con::executef("onDataBlockObjectReceived", Con::getIntArg(mIndex), Con::getIntArg(mTotal));
+      Con::executef("onDataBlockObjectReceived", mIndex, mTotal);
 
       String &errorBuffer = NetConnection::getErrorBuffer();
                      

+ 2 - 2
Engine/source/T3D/item.cpp

@@ -292,7 +292,7 @@ IMPLEMENT_CALLBACK( Item, onStickyCollision, void, ( const char* objID ),( objID
    "@see Item, ItemData\n"
 );
 
-IMPLEMENT_CALLBACK( Item, onEnterLiquid, void, ( const char* objID, const char* waterCoverage, const char* liquidType ),( objID, waterCoverage, liquidType ),
+IMPLEMENT_CALLBACK( Item, onEnterLiquid, void, ( const char* objID, F32 waterCoverage, const char* liquidType ),( objID, waterCoverage, liquidType ),
    "Informs an Item object that it has entered liquid, along with information about the liquid type.\n"
    "@param objID Object ID for this Item object.\n"
    "@param waterCoverage How much coverage of water this Item object has.\n"
@@ -1005,7 +1005,7 @@ void Item::updatePos(const U32 /*mask*/, const F32 dt)
       {
          if(!mInLiquid && mWaterCoverage != 0.0f)
          {
-			onEnterLiquid_callback( getIdString(), Con::getFloatArg(mWaterCoverage), mLiquidType.c_str() );
+			onEnterLiquid_callback( getIdString(), mWaterCoverage, mLiquidType.c_str() );
             mInLiquid = true;
          }
          else if(mInLiquid && mWaterCoverage == 0.0f)

+ 1 - 1
Engine/source/T3D/item.h

@@ -114,7 +114,7 @@ class Item: public ShapeBase
 
   protected:
 	DECLARE_CALLBACK( void, onStickyCollision, ( const char* objID ));
-	DECLARE_CALLBACK( void, onEnterLiquid, ( const char* objID, const char* waterCoverage, const char* liquidType ));
+	DECLARE_CALLBACK( void, onEnterLiquid, ( const char* objID, F32 waterCoverage, const char* liquidType ));
 	DECLARE_CALLBACK( void, onLeaveLiquid, ( const char* objID, const char* liquidType ));
 
   public:

+ 2 - 2
Engine/source/T3D/pathCamera.cpp

@@ -104,7 +104,7 @@ ConsoleDocClass( PathCamera,
    "@ingroup PathCameras\n"
 );
 
-IMPLEMENT_CALLBACK( PathCamera, onNode, void, (const char* node), (node),
+IMPLEMENT_CALLBACK( PathCamera, onNode, void, (S32 node), (node),
 					"A script callback that indicates the path camera has arrived at a specific node in its path.  Server side only.\n"
 					"@param Node Unique ID assigned to this node.\n");
 
@@ -408,7 +408,7 @@ void PathCamera::popFront()
 void PathCamera::onNode(S32 node)
 {
    if (!isGhost())
-		onNode_callback(Con::getIntArg(node));
+		onNode_callback(node);
    
 }
 

+ 1 - 1
Engine/source/T3D/pathCamera.h

@@ -93,7 +93,7 @@ private:
 public:
    DECLARE_CONOBJECT(PathCamera);
    
-   DECLARE_CALLBACK( void, onNode, (const char* node));
+   DECLARE_CALLBACK( void, onNode, (S32 node));
 
    PathCamera();
    ~PathCamera();

+ 2 - 2
Engine/source/T3D/rigidShape.cpp

@@ -153,7 +153,7 @@ ConsoleDocClass( RigidShape,
 );
 
 
-IMPLEMENT_CALLBACK( RigidShape, onEnterLiquid, void, ( const char* objId, const char* waterCoverage, const char* liquidType ),
+IMPLEMENT_CALLBACK( RigidShape, onEnterLiquid, void, ( const char* objId, F32 waterCoverage, const char* liquidType ),
 													 ( objId, waterCoverage, liquidType ),
    "@brief Called whenever this RigidShape object enters liquid.\n\n"
    "@param objId The ID of the rigidShape object.\n"
@@ -1088,7 +1088,7 @@ void RigidShape::updatePos(F32 dt)
       // Water script callbacks      
       if (!inLiquid && mWaterCoverage != 0.0f) 
       {
-         onEnterLiquid_callback(getIdString(), Con::getFloatArg(mWaterCoverage), mLiquidType.c_str() );
+         onEnterLiquid_callback(getIdString(), mWaterCoverage, mLiquidType.c_str() );
          inLiquid = true;
       }
       else if (inLiquid && mWaterCoverage == 0.0f) 

+ 1 - 1
Engine/source/T3D/rigidShape.h

@@ -296,7 +296,7 @@ public:
    void unpackUpdate(NetConnection *conn,           BitStream *stream);
 
    DECLARE_CONOBJECT(RigidShape);
-   DECLARE_CALLBACK( void, onEnterLiquid, ( const char* objId, const char* waterCoverage, const char* liquidType ));
+   DECLARE_CALLBACK( void, onEnterLiquid, ( const char* objId, F32 waterCoverage, const char* liquidType ));
    DECLARE_CALLBACK( void, onLeaveLiquid, ( const char* objId, const char* liquidType ));
 };
 

+ 2 - 1
Engine/source/app/badWordFilter.cpp

@@ -23,9 +23,10 @@
 #include "core/strings/stringFunctions.h"
 
 #include "console/consoleTypes.h"
+#include "console/simBase.h"
+#include "console/engineAPI.h"
 #include "app/badWordFilter.h"
 #include "core/module.h"
-#include "console/engineAPI.h"
 
 MODULE_BEGIN( BadWordFilter )
 

+ 1 - 1
Engine/source/app/net/serverQuery.cpp

@@ -1337,7 +1337,7 @@ static void processPingsAndQueries( U32 session, bool schedule )
       else
          dSprintf( msg, sizeof( msg ), "%d servers found.", foundCount );
 
-      Con::executef( "onServerQueryStatus", "done", msg, "1");
+      Con::executef( "onServerQueryStatus", "done", (const char*)msg, "1");
    }
 }
 

+ 2 - 6
Engine/source/console/arrayObject.cpp

@@ -103,9 +103,7 @@ S32 QSORT_CALLBACK ArrayObject::_keyFunctionCompare( const void* a, const void*
    ArrayObject::Element* ea = ( ArrayObject::Element* )( a );
    ArrayObject::Element* eb = ( ArrayObject::Element* )( b );
    
-   ConsoleValueRef argv[] = { smCompareFunction, ea->key, eb->key }; 
-   
-   S32 result = dAtoi( Con::execute( 3, argv ) );
+   S32 result = dAtoi( Con::executef( (const char*)smCompareFunction, ea->value, eb->key ) );
    S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 );
    return ( smDecreasing ? -res : res );
 }
@@ -115,9 +113,7 @@ S32 QSORT_CALLBACK ArrayObject::_valueFunctionCompare( const void* a, const void
    ArrayObject::Element* ea = ( ArrayObject::Element* )( a );
    ArrayObject::Element* eb = ( ArrayObject::Element* )( b );
    
-   ConsoleValueRef argv[] = { smCompareFunction, ea->value, eb->value }; 
-   
-   S32 result = dAtoi( Con::execute( 3, argv ) );
+   S32 result = dAtoi( Con::executef( (const char*)smCompareFunction, ea->value, eb->value ) );
    S32 res = result < 0 ? -1 : ( result > 0 ? 1 : 0 );
    return ( smDecreasing ? -res : res );
 }

+ 2 - 2
Engine/source/console/codeBlock.cpp

@@ -570,7 +570,7 @@ bool CodeBlock::compile(const char *codeFileName, StringTableEntry fileName, con
 
 }
 
-const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
+ConsoleValueRef CodeBlock::compileExec(StringTableEntry fileName, const char *inString, bool noCalls, S32 setFrame)
 {
 	AssertFatal(Con::isMainThread(), "Compiling code on a secondary thread");
 	
@@ -635,7 +635,7 @@ const char *CodeBlock::compileExec(StringTableEntry fileName, const char *inStri
    if(!gStatementList)
    {
       delete this;
-      return "";
+      return ConsoleValueRef();
    }
 
    resetTables();

+ 1 - 1
Engine/source/console/codeBlock.h

@@ -129,7 +129,7 @@ public:
    /// with, zero being the top of the stack. If the the index is
    /// -1 a new frame is created. If the index is out of range the
    /// top stack frame is used.
-   const char *compileExec(StringTableEntry fileName, const char *script, 
+   ConsoleValueRef compileExec(StringTableEntry fileName, const char *script, 
       bool noCalls, S32 setFrame = -1 );
 
    /// Executes the existing code in the CodeBlock. The return string is any 

+ 45 - 43
Engine/source/console/compiledEval.cpp

@@ -87,7 +87,7 @@ struct IterStackRecord
    struct StringPos
    {
       /// The raw string data on the string stack.
-      const char* mString;
+      StringStackPtr mString;
       
       /// Current parsing position.
       U32 mIndex;
@@ -195,18 +195,20 @@ namespace Con
       return STR.getArgBuffer(bufferSize);
    }
 
-   ConsoleValueRef getFloatArg(F64 arg)
+   char *getFloatArg(F64 arg)
    {
-      ConsoleValueRef ref = arg;
-      return ref;
+      char *ret = STR.getArgBuffer(32);
+      dSprintf(ret, 32, "%g", arg);
+      return ret;
    }
 
-   ConsoleValueRef getIntArg(S32 arg)
+   char *getIntArg(S32 arg)
    {
-      ConsoleValueRef ref = arg;
-      return ref;
+      char *ret = STR.getArgBuffer(32);
+      dSprintf(ret, 32, "%d", arg);
+      return ret;
    }
-   
+
    char *getStringArg( const char *arg )
    {
       U32 len = dStrlen( arg ) + 1;
@@ -286,6 +288,12 @@ inline void ExprEvalState::setStringVariable(const char *val)
    currentVariable->setStringValue(val);
 }
 
+inline void ExprEvalState::setStringStackPtrVariable(StringStackPtr str)
+{
+   AssertFatal(currentVariable != NULL, "Invalid evaluator state - trying to set null variable!");
+   currentVariable->setStringStackPtrValue(str);
+}
+
 inline void ExprEvalState::setCopyVariable()
 {
    if (copyVariable)
@@ -432,6 +440,8 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
    U32 consoleStackStart = CSTK.mStackPos;
 #endif
 
+   //Con::printf("CodeBlock::exec(%s,%u)", functionName ? functionName : "??", ip);
+
    static char traceBuffer[1024];
    S32 i;
    
@@ -441,7 +451,7 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
    F64 *curFloatTable;
    char *curStringTable;
    S32 curStringTableLen = 0; //clint to ensure we dont overwrite it
-   STR.clearFunctionOffset();
+   STR.clearFunctionOffset(); // ensures arg buffer offset is back to 0
    StringTableEntry thisFunctionName = NULL;
    bool popFrame = false;
    if(argv)
@@ -489,15 +499,25 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
 
          ConsoleValueRef ref = argv[i+1];
 
-         if (argv[i+1].isString())
-            gEvalState.setStringVariable(argv[i+1]);
-         else if (argv[i+1].isInt())
+         switch(argv[i+1].getType())
+         {
+         case ConsoleValue::TypeInternalInt:
             gEvalState.setIntVariable(argv[i+1]);
-         else if (argv[i+1].isFloat())
+            break;
+         case ConsoleValue::TypeInternalFloat:
             gEvalState.setFloatVariable(argv[i+1]);
-         else
+            break;
+         case ConsoleValue::TypeInternalStringStackPtr:
+            gEvalState.setStringStackPtrVariable(argv[i+1].getStringStackPtrValue());
+            break;
+         case ConsoleValue::TypeInternalStackString:
+         case ConsoleValue::TypeInternalString:
+         default:
             gEvalState.setStringVariable(argv[i+1]);
+            break;
+         }
       }
+
       ip = ip + (fnArgc * 2) + (2 + 6 + 1);
       curFloatTable = functionFloats;
       curStringTable = functionStrings;
@@ -533,17 +553,6 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
       }
    }
 
-   bool doResetValueStack = !gEvalState.mResetLocked;
-   gEvalState.mResetLocked = true;
-   
-   if (gEvalState.mShouldReset)
-   {
-      // Ensure all stacks are clean in case anything became unbalanced during the previous execution
-      STR.clearFrames();
-      CSTK.clearFrames();
-      gEvalState.mShouldReset = false;
-   }
-
    // Grab the state of the telenet debugger here once
    // so that the push and pop frames are always balanced.
    const bool telDebuggerOn = TelDebugger && TelDebugger->isConnected();
@@ -590,7 +599,7 @@ ConsoleValueRef CodeBlock::exec(U32 ip, const char *functionName, Namespace *thi
       Con::gCurrentRoot = this->modPath;
    }
    const char * val;
-   const char *retValue;
+   StringStackPtr retValue;
 
    // note: anything returned is pushed to CSTK and will be invalidated on the next exec()
    ConsoleValueRef returnValue;
@@ -1144,7 +1153,7 @@ breakContinue:
       		// We're falling thru here on purpose.
             
          case OP_RETURN:
-            retValue = STR.getStringValue();
+            retValue = STR.getStringValuePtr();
 
             if( iterDepth > 0 )
             {
@@ -1156,13 +1165,13 @@ breakContinue:
                }
 
                STR.rewind();
-               STR.setStringValue( retValue ); // Not nice but works.
-               retValue = STR.getStringValue();
+               STR.setStringValue( StringStackPtrRef(retValue).getPtr(&STR) ); // Not nice but works.
+               retValue = STR.getStringValuePtr();
             }
 
             // Previously the return value was on the stack and would be returned using STR.getStringValue().
             // Now though we need to wrap it in a ConsoleValueRef 
-            returnValue.value = CSTK.pushStackString(retValue);
+            returnValue.value = CSTK.pushStringStackPtr(retValue);
                
             goto execFinished;
 
@@ -1847,7 +1856,7 @@ breakContinue:
 
                // This will clear everything including returnValue
                CSTK.popFrame();
-               STR.clearFunctionOffset();
+               //STR.clearFunctionOffset();
             }
             else
             {
@@ -1999,7 +2008,7 @@ breakContinue:
             break;
          case OP_PUSH:
             STR.push();
-            CSTK.pushString(STR.getPreviousStringValue());
+            CSTK.pushStringStackPtr(STR.getPreviousStringValuePtr());
             break;
          case OP_PUSH_UINT:
             CSTK.pushUINT(intStack[_UINT]);
@@ -2080,7 +2089,7 @@ breakContinue:
             
             if( iter.mIsStringIter )
             {
-               iter.mData.mStr.mString = STR.getStringValue();
+               iter.mData.mStr.mString = STR.getStringValuePtr();
                iter.mData.mStr.mIndex = 0;
             }
             else
@@ -2118,7 +2127,7 @@ breakContinue:
             
             if( iter.mIsStringIter )
             {
-               const char* str = iter.mData.mStr.mString;
+               const char* str = StringStackPtrRef(iter.mData.mStr.mString).getPtr(&STR);
                               
                U32 startIndex = iter.mData.mStr.mIndex;
                U32 endIndex = startIndex;
@@ -2234,18 +2243,11 @@ execFinished:
       Con::gCurrentRoot = saveCodeBlock->modPath;
    }
 
-   // Mark the reset flag for the next run if we've finished execution
-   if (doResetValueStack)
-   {
-      gEvalState.mShouldReset = true;
-      gEvalState.mResetLocked = false;
-   }
-
    decRefCount();
 
 #ifdef TORQUE_DEBUG
-   AssertFatal(!(STR.mStartStackSize > stackStart), "String stack not popped enough in script exec");
-   AssertFatal(!(STR.mStartStackSize < stackStart), "String stack popped too much in script exec");
+   //AssertFatal(!(STR.mStartStackSize > stackStart), "String stack not popped enough in script exec");
+   //AssertFatal(!(STR.mStartStackSize < stackStart), "String stack popped too much in script exec");
 #endif
 
    return returnValue;

+ 182 - 117
Engine/source/console/console.cpp

@@ -1138,8 +1138,11 @@ void addCommand( const char *name,BoolCallback cb,const char *usage, S32 minArgs
    Namespace::global()->addCommand( StringTable->insert(name), cb, usage, minArgs, maxArgs, isToolOnly, header );
 }
 
-const char *evaluate(const char* string, bool echo, const char *fileName)
+ConsoleValueRef evaluate(const char* string, bool echo, const char *fileName)
 {
+   ConsoleStackFrameSaver stackSaver;
+   stackSaver.save();
+
    if (echo)
    {
       if (string[0] == '%')
@@ -1156,8 +1159,11 @@ const char *evaluate(const char* string, bool echo, const char *fileName)
 }
 
 //------------------------------------------------------------------------------
-const char *evaluatef(const char* string, ...)
+ConsoleValueRef evaluatef(const char* string, ...)
 {
+   ConsoleStackFrameSaver stackSaver;
+   stackSaver.save();
+
    char buffer[4096];
    va_list args;
    va_start(args, string);
@@ -1167,26 +1173,34 @@ const char *evaluatef(const char* string, ...)
    return newCodeBlock->compileExec(NULL, buffer, false, 0);
 }
 
-const char *execute(S32 argc, ConsoleValueRef argv[])
+//------------------------------------------------------------------------------
+
+// Internal execute for global function which does not save the stack
+ConsoleValueRef _internalExecute(S32 argc, ConsoleValueRef argv[])
+{
+   Namespace::Entry *ent;
+   StringTableEntry funcName = StringTable->insert(argv[0]);
+   ent = Namespace::global()->lookup(funcName);
+
+   if(!ent)
+   {
+      warnf(ConsoleLogEntry::Script, "%s: Unknown command.", (const char*)argv[0]);
+
+      STR.clearFunctionOffset();
+      return ConsoleValueRef();
+   }
+   return ent->execute(argc, argv, &gEvalState);
+}
+
+ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[])
 {
 #ifdef TORQUE_MULTITHREAD
    if(isMainThread())
    {
 #endif
-      Namespace::Entry *ent;
-      StringTableEntry funcName = StringTable->insert(argv[0]);
-      ent = Namespace::global()->lookup(funcName);
-
-      if(!ent)
-      {
-         warnf(ConsoleLogEntry::Script, "%s: Unknown command.", (const char*)argv[0]);
-
-         // Clean up arg buffers, if any.
-         STR.clearFunctionOffset();
-         CSTK.resetFrame();
-         return "";
-      }
-      return ent->execute(argc, argv, &gEvalState);
+      ConsoleStackFrameSaver stackSaver;
+      stackSaver.save();
+	   return _internalExecute(argc, argv);
 #ifdef TORQUE_MULTITHREAD
    }
    else
@@ -1200,17 +1214,24 @@ const char *execute(S32 argc, ConsoleValueRef argv[])
 #endif
 }
 
-const char *execute(S32 argc, const char *argv[])
+ConsoleValueRef execute(S32 argc, const char *argv[])
 {
+   ConsoleStackFrameSaver stackSaver;
+   stackSaver.save();
    StringStackConsoleWrapper args(argc, argv);
    return execute(args.count(), args);
 }
 
 //------------------------------------------------------------------------------
-const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly)
+
+// Internal execute for object method which does not save the stack
+ConsoleValueRef _internalExecute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly)
 {
    if(argc < 2)
-      return "";
+   {
+      STR.clearFunctionOffset();
+      return ConsoleValueRef();
+   }
 
    // [neo, 10/05/2007 - #3010]
    // Make sure we don't get recursive calls, respect the flag!   
@@ -1230,10 +1251,8 @@ const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool th
 
    if(object->getNamespace())
    {
-	  ConsoleValueRef internalArgv[StringStack::MaxArgs];
-
-	  U32 ident = object->getId();
-	  ConsoleValueRef oldIdent = argv[1];
+      U32 ident = object->getId();
+      ConsoleValueRef oldIdent = argv[1];
 
       StringTableEntry funcName = StringTable->insert(argv[0]);
       Namespace::Entry *ent = object->getNamespace()->lookup(funcName);
@@ -1242,10 +1261,8 @@ const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool th
       {
          //warnf(ConsoleLogEntry::Script, "%s: undefined for object '%s' - id %d", funcName, object->getName(), object->getId());
 
-         // Clean up arg buffers, if any.
          STR.clearFunctionOffset();
-         CSTK.resetFrame();
-         return "";
+         return ConsoleValueRef();
       }
 
       // Twiddle %this argument
@@ -1253,7 +1270,7 @@ const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool th
 
       SimObject *save = gEvalState.thisObject;
       gEvalState.thisObject = object;
-      const char *ret = ent->execute(argc, argv, &gEvalState);
+      ConsoleValueRef ret = ent->execute(argc, argv, &gEvalState);
       gEvalState.thisObject = save;
 
       // Twiddle it back
@@ -1261,17 +1278,52 @@ const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool th
 
       return ret;
    }
+
+   warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), (const char*)argv[0]);
+   STR.clearFunctionOffset();
+   return ConsoleValueRef();
+}
+
+
+ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly)
+{
+   if(argc < 2)
+   {
+      STR.clearFunctionOffset();
+      return ConsoleValueRef();
+   }
+
+   ConsoleStackFrameSaver stackSaver;
+   stackSaver.save();
+
+   if (object->getNamespace() || !thisCallOnly)
+   {
+      if (isMainThread())
+      {
+         return _internalExecute(object, argc, argv, thisCallOnly);
+      }
+      else
+      {
+         SimConsoleThreadExecCallback cb;
+         SimConsoleThreadExecEvent *evt = new SimConsoleThreadExecEvent(argc, argv, true, &cb);
+         Sim::postEvent(object, evt, Sim::getCurrentTime());
+      }
+   }
+
    warnf(ConsoleLogEntry::Script, "Con::execute - %d has no namespace: %s", object->getId(), (const char*)argv[0]);
-   return "";
+   STR.clearFunctionOffset();
+   return ConsoleValueRef();
 }
 
-const char *execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly)
+ConsoleValueRef execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly)
 {
+   ConsoleStackFrameSaver stackSaver;
+   stackSaver.save();
    StringStackConsoleWrapper args(argc, argv);
    return execute(object, args.count(), args, thisCallOnly);
 }
 
-inline const char*_executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValueRef *argv)
+inline ConsoleValueRef _executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValueRef *argv)
 {
    const U32 maxArg = 12;
    AssertWarn(checkArgc == argc, "Incorrect arg count passed to Con::executef(SimObject*)");
@@ -1279,42 +1331,14 @@ inline const char*_executef(SimObject *obj, S32 checkArgc, S32 argc, ConsoleValu
    return execute(obj, argc, argv);
 }
 
-#define A ConsoleValueRef
-#define OBJ SimObject* obj
-const char *executef(OBJ, A a)                                    { ConsoleValueRef params[] = {a,ConsoleValueRef()}; return _executef(obj, 2, 2, params); }
-const char *executef(OBJ, A a, A b)                               { ConsoleValueRef params[] = {a,ConsoleValueRef(),b}; return _executef(obj, 3, 3, params); }
-const char *executef(OBJ, A a, A b, A c)                          { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c}; return _executef(obj, 4, 4, params); }
-const char *executef(OBJ, A a, A b, A c, A d)                     { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d}; return _executef(obj, 5, 5, params); }
-const char *executef(OBJ, A a, A b, A c, A d, A e)                { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d,e}; return _executef(obj, 6, 6, params); }
-const char *executef(OBJ, A a, A b, A c, A d, A e, A f)           { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d,e,f}; return _executef(obj, 7, 7, params); }
-const char *executef(OBJ, A a, A b, A c, A d, A e, A f, A g)      { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d,e,f,g}; return _executef(obj, 8, 8, params); }
-const char *executef(OBJ, A a, A b, A c, A d, A e, A f, A g, A h) { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d,e,f,g,h}; return _executef(obj, 9, 9, params); }
-const char *executef(OBJ, A a, A b, A c, A d, A e, A f, A g, A h, A i) { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d,e,f,g,h,i}; return _executef(obj, 10, 10, params); }
-const char *executef(OBJ, A a, A b, A c, A d, A e, A f, A g, A h, A i, A j) { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d,e,f,g,h,i,j}; return _executef(obj, 11, 11, params); }
-const char *executef(OBJ, A a, A b, A c, A d, A e, A f, A g, A h, A i, A j, A k) { ConsoleValueRef params[] = {a,ConsoleValueRef(),b,c,d,e,f,g,h,i,j,k}; return _executef(obj, 12, 12, params); }
-
 //------------------------------------------------------------------------------
-inline const char*_executef(S32 checkArgc, S32 argc, ConsoleValueRef *argv)
+inline ConsoleValueRef _executef(S32 checkArgc, S32 argc, ConsoleValueRef *argv)
 {
    const U32 maxArg = 10;
    AssertFatal(checkArgc == argc, "Incorrect arg count passed to Con::executef()");
    AssertFatal(argc <= maxArg, "Too many args passed to Con::_executef(). Please update the function to handle more.");
    return execute(argc, argv);
 }
-   
-#define A ConsoleValueRef
-const char *executef(A a)                                    { ConsoleValueRef params[] = {a}; return _executef(1, 1, params); }
-const char *executef(A a, A b)                               { ConsoleValueRef params[] = {a,b}; return _executef(2, 2, params); }
-const char *executef(A a, A b, A c)                          { ConsoleValueRef params[] = {a,b,c}; return _executef(3, 3, params); }
-const char *executef(A a, A b, A c, A d)                     { ConsoleValueRef params[] = {a,b,c,d}; return _executef(4, 4, params); }
-const char *executef(A a, A b, A c, A d, A e)                { ConsoleValueRef params[] = {a,b,c,d,e}; return _executef(5, 5, params); }
-const char *executef(A a, A b, A c, A d, A e, A f)           { ConsoleValueRef params[] = {a,b,c,d,e,f}; return _executef(6, 6, params); }
-const char *executef(A a, A b, A c, A d, A e, A f, A g)      { ConsoleValueRef params[] = {a,b,c,d,e,f,g}; return _executef(7, 7, params); }
-const char *executef(A a, A b, A c, A d, A e, A f, A g, A h) { ConsoleValueRef params[] = {a,b,c,d,e,f,g,h}; return _executef(8, 8, params); }
-const char *executef(A a, A b, A c, A d, A e, A f, A g, A h, A i) { ConsoleValueRef params[] = {a,b,c,d,e,f,g,h,i}; return _executef(9, 9, params); }
-const char *executef(A a, A b, A c, A d, A e, A f, A g, A h, A i, A j) { ConsoleValueRef params[] = {a,b,c,d,e,f,g,h,i,j}; return _executef(10, 10, params); }
-#undef A
-
 
 //------------------------------------------------------------------------------
 bool isFunction(const char *fn)
@@ -1577,10 +1601,13 @@ DefineEngineFunction( logWarning, void, ( const char* message ),,
    Con::warnf( "%s", message );
 }
 
+//------------------------------------------------------------------------------
+
+extern ConsoleValueStack CSTK;
+
 ConsoleValueRef::ConsoleValueRef(const ConsoleValueRef &ref)
 {
-	value = ref.value;
-	stringStackValue = ref.stringStackValue;
+   value = ref.value;
 }
 
 ConsoleValueRef::ConsoleValueRef(const char *newValue) : value(NULL)
@@ -1613,6 +1640,49 @@ ConsoleValueRef::ConsoleValueRef(F64 newValue) : value(NULL)
    *this = newValue;
 }
 
+ConsoleValueRef& ConsoleValueRef::operator=(const ConsoleValueRef &newValue)
+{
+   value = newValue.value;
+   return *this;
+}
+
+ConsoleValueRef& ConsoleValueRef::operator=(const char *newValue)
+{
+   AssertFatal(value, "value should not be NULL");
+   value->setStringValue(newValue);
+   return *this;
+}
+
+ConsoleValueRef& ConsoleValueRef::operator=(S32 newValue)
+{
+   AssertFatal(value, "value should not be NULL");
+   value->setIntValue(newValue);
+   return *this;
+}
+
+ConsoleValueRef& ConsoleValueRef::operator=(U32 newValue)
+{
+   AssertFatal(value, "value should not be NULL");
+   value->setIntValue(newValue);
+   return *this;
+}
+
+ConsoleValueRef& ConsoleValueRef::operator=(F32 newValue)
+{
+   AssertFatal(value, "value should not be NULL");
+   value->setFloatValue(newValue);
+   return *this;
+}
+
+ConsoleValueRef& ConsoleValueRef::operator=(F64 newValue)
+{
+   AssertFatal(value, "value should not be NULL");
+   value->setFloatValue(newValue);
+   return *this;
+}
+
+//------------------------------------------------------------------------------
+
 StringStackWrapper::StringStackWrapper(int targc, ConsoleValueRef targv[])
 {
    argv = new const char*[targc];
@@ -1637,10 +1707,13 @@ StringStackWrapper::~StringStackWrapper()
 StringStackConsoleWrapper::StringStackConsoleWrapper(int targc, const char** targ)
 {
    argv = new ConsoleValueRef[targc];
+   argvValue = new ConsoleValue[targc];
    argc = targc;
 
    for (int i=0; i<targc; i++) {
-      argv[i] = ConsoleValueRef(targ[i]);
+      argvValue[i].init();
+      argv[i].value = &argvValue[i];
+      argvValue[i].setStackStringValue(targ[i]);
    }
 }
 
@@ -1651,8 +1724,11 @@ StringStackConsoleWrapper::~StringStackConsoleWrapper()
       argv[i] = 0;
    }
    delete[] argv;
+   delete[] argvValue;
 }
 
+//------------------------------------------------------------------------------
+
 S32 ConsoleValue::getSignedIntValue()
 {
    if(type <= TypeInternalString)
@@ -1681,6 +1757,8 @@ const char *ConsoleValue::getStringValue()
 {
    if(type == TypeInternalString || type == TypeInternalStackString)
       return sval;
+   else if (type == TypeInternalStringStackPtr)
+      return STR.mBuffer + (U32)sval;
    if(type == TypeInternalFloat)
       return Con::getData(TypeF32, &fval, 0);
    else if(type == TypeInternalInt)
@@ -1689,10 +1767,18 @@ const char *ConsoleValue::getStringValue()
       return Con::getData(type, dataPtr, 0, enumTable);
 }
 
+StringStackPtr ConsoleValue::getStringStackPtr()
+{
+   if (type == TypeInternalStringStackPtr)
+      return (U32)sval;
+   else
+      return (U32)-1;
+}
+
 bool ConsoleValue::getBoolValue()
 {
-   if(type == TypeInternalString || type == TypeInternalStackString)
-      return dAtob(sval);
+   if(type == TypeInternalString || type == TypeInternalStackString || type == TypeInternalStringStackPtr)
+      return dAtob(getStringValue());
    if(type == TypeInternalFloat)
       return fval > 0;
    else if(type == TypeInternalInt)
@@ -1716,7 +1802,7 @@ void ConsoleValue::setIntValue(U32 val)
       ival = val;
       if(sval != typeValueEmpty)
       {
-         if (type != TypeInternalStackString) dFree(sval);
+         if (type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
          sval = typeValueEmpty;
       }
       type = TypeInternalInt;
@@ -1741,7 +1827,7 @@ void ConsoleValue::setFloatValue(F32 val)
       ival = static_cast<U32>(val);
       if(sval != typeValueEmpty)
       {
-         if (type != TypeInternalStackString) dFree(sval);
+         if (type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
          sval = typeValueEmpty;
       }
       type = TypeInternalFloat;
@@ -1753,70 +1839,49 @@ void ConsoleValue::setFloatValue(F32 val)
    }
 }
 
+//------------------------------------------------------------------------------
 
-const char *ConsoleValueRef::getStringArgValue()
+ConsoleValueRef _BaseEngineConsoleCallbackHelper::_exec()
 {
-   if (value)
+   ConsoleValueRef returnValue;
+   if( mThis )
    {
-      if (stringStackValue == NULL)
-         stringStackValue = Con::getStringArg(value->getStringValue());
-      return stringStackValue;
+      // Cannot invoke callback until object has been registered
+      if (mThis->isProperlyAdded()) {
+         returnValue = Con::_internalExecute( mThis, mArgc, mArgv, false );
+      } else {
+         STR.clearFunctionOffset();
+         returnValue = ConsoleValueRef();
+      }
    }
    else
-   {
-      return "";
-   }
-}
-
-
-extern ConsoleValueStack CSTK;
-   
-ConsoleValueRef& ConsoleValueRef::operator=(const ConsoleValueRef &newValue)
-{
-   value = newValue.value;
-   stringStackValue = newValue.stringStackValue;
-   return *this;
-}
-
-ConsoleValueRef& ConsoleValueRef::operator=(const char *newValue)
-{
-   value = CSTK.pushStackString(newValue);
-   stringStackValue = NULL;
-   return *this;
-}
+      returnValue = Con::_internalExecute( mArgc, mArgv );
 
-ConsoleValueRef& ConsoleValueRef::operator=(S32 newValue)
-{
-   value = CSTK.pushFLT(newValue);
-   stringStackValue = NULL;
-   return *this;
+   mArgc = mInitialArgc; // reset args
+   return returnValue;
 }
 
-ConsoleValueRef& ConsoleValueRef::operator=(U32 newValue)
+ConsoleValueRef _BaseEngineConsoleCallbackHelper::_execLater(SimConsoleThreadExecEvent *evt)
 {
-   value = CSTK.pushUINT(newValue);
-   stringStackValue = NULL;
-   return *this;
+   mArgc = mInitialArgc; // reset args
+   Sim::postEvent((SimObject*)Sim::getRootGroup(), evt, Sim::getCurrentTime());
+   return evt->getCB().waitForResult();
 }
 
-ConsoleValueRef& ConsoleValueRef::operator=(F32 newValue)
-{
-   value = CSTK.pushFLT(newValue);
-   stringStackValue = NULL;
-   return *this;
-}
+//------------------------------------------------------------------------------
 
-ConsoleValueRef& ConsoleValueRef::operator=(F64 newValue)
+void ConsoleStackFrameSaver::save()
 {
-   value = CSTK.pushFLT(newValue);
-   stringStackValue = NULL;
-   return *this;
+   CSTK.pushFrame();
+   STR.pushFrame();
+   mSaved = true;
 }
 
-namespace Con
+void ConsoleStackFrameSaver::restore()
 {
-	void resetStackFrame()
-	{
-		CSTK.resetFrame();
-	}
+   if (mSaved)
+   {
+      CSTK.popFrame();
+      STR.popFrame();
+   }
 }

+ 90 - 58
Engine/source/console/console.h

@@ -44,6 +44,8 @@ struct ConsoleFunctionHeader;
 class EngineEnumTable;
 typedef EngineEnumTable EnumTable;
 
+typedef U32 StringStackPtr;
+
 template< typename T > S32 TYPEID();
 
 
@@ -121,8 +123,9 @@ public:
    
    enum
    {
-      TypeInternalInt = -4,
-      TypeInternalFloat = -3,
+      TypeInternalInt = -5,
+      TypeInternalFloat = -4,
+      TypeInternalStringStackPtr = -3,
       TypeInternalStackString = -2,
       TypeInternalString = -1,
    };
@@ -166,6 +169,7 @@ public:
    S32 getSignedIntValue();
    F32 getFloatValue();
    const char *getStringValue();
+   StringStackPtr getStringStackPtr();
    bool getBoolValue();
    
    void setIntValue(U32 val);
@@ -173,6 +177,7 @@ public:
    void setFloatValue(F32 val);
    void setStringValue(const char *value);
    void setStackStringValue(const char *value);
+   void setStringStackPtrValue(StringStackPtr ptr);
    void setBoolValue(bool val);
    
    void init()
@@ -181,12 +186,13 @@ public:
       fval = 0;
       sval = typeValueEmpty;
       bufferLen = 0;
+	  type = TypeInternalString;
    }
    
    void cleanup()
    {
       if (type <= TypeInternalString &&
-          sval != typeValueEmpty && type != TypeInternalStackString )
+          sval != typeValueEmpty && type != TypeInternalStackString && type != TypeInternalStringStackPtr)
          dFree(sval);
       sval = typeValueEmpty;
       type = ConsoleValue::TypeInternalString;
@@ -203,9 +209,8 @@ class ConsoleValueRef
 {
 public:
    ConsoleValue *value;
-   const char *stringStackValue;
 
-   ConsoleValueRef() : value(0), stringStackValue(0) { ; }
+   ConsoleValueRef() : value(0) { ; }
    ~ConsoleValueRef() { ; }
 
    ConsoleValueRef(const ConsoleValueRef &ref);
@@ -216,8 +221,10 @@ public:
    ConsoleValueRef(F32 value);
    ConsoleValueRef(F64 value);
 
+   static ConsoleValueRef fromValue(ConsoleValue *value) { ConsoleValueRef ref; ref.value = value; return ref; }
+
    const char *getStringValue() { return value ? value->getStringValue() : ""; }
-   const char *getStringArgValue();
+   StringStackPtr getStringStackPtrValue() { return value ? value->getStringStackPtr() : 0; }
 
    inline U32 getIntValue() { return value ? value->getIntValue() : 0; }
    inline S32 getSignedIntValue() { return value ? value->getSignedIntValue() : 0; }
@@ -229,10 +236,13 @@ public:
    inline operator U32() { return getIntValue(); }
    inline operator S32() { return getSignedIntValue(); }
    inline operator F32() { return getFloatValue(); }
-
-   inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStackString : true; }
+   inline operator bool() { return getBoolValue(); }
+   
+   inline bool isStringStackPtr() { return value ? value->type == ConsoleValue::TypeInternalStringStackPtr : false; }
+   inline bool isString() { return value ? value->type >= ConsoleValue::TypeInternalStringStackPtr : true; }
    inline bool isInt() { return value ? value->type == ConsoleValue::TypeInternalInt : false; }
    inline bool isFloat() { return value ? value->type == ConsoleValue::TypeInternalFloat : false; }
+   inline S32 getType() { return value ? value->type : -1; }
 
    // Note: operators replace value
    ConsoleValueRef& operator=(const ConsoleValueRef &other);
@@ -281,6 +291,7 @@ public:
 class StringStackConsoleWrapper
 {
 public:
+   ConsoleValue *argvValue;
    ConsoleValueRef *argv;
    int argc;
 
@@ -753,23 +764,9 @@ namespace Con
    /// char* argv[] = {"abs", "-9"};
    /// char* result = execute(2, argv);
    /// @endcode
-   const char *execute(S32 argc, const char* argv[]);
-   const char *execute(S32 argc, ConsoleValueRef argv[]);
-
-   /// @see execute(S32 argc, const char* argv[])
-   // Note: this can't be ConsoleValueRef& since the compiler will confuse it with SimObject*
-#define ARG ConsoleValueRef
-   const char *executef( ARG);
-   const char *executef( ARG, ARG);
-   const char *executef( ARG, ARG, ARG);
-   const char *executef( ARG, ARG, ARG, ARG);
-   const char *executef( ARG, ARG, ARG, ARG, ARG);
-   const char *executef( ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef( ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-#undef ARG
+   /// NOTE: this function restores the console stack on return.
+   ConsoleValueRef execute(S32 argc, const char* argv[]);
+   ConsoleValueRef execute(S32 argc, ConsoleValueRef argv[]);
 
    /// Call a Torque Script member function of a SimObject from C/C++ code.
    /// @param object    Object on which to execute the method call.
@@ -783,35 +780,23 @@ namespace Con
    /// char* argv[] = {"setMode", "", "2"};
    /// char* result = execute(mysimobject, 3, argv);
    /// @endcode
-   const char *execute(SimObject *object, S32 argc, const char *argv[], bool thisCallOnly = false);
-   const char *execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false);
-
-   /// @see execute(SimObject *, S32 argc, ConsoleValueRef argv[])
-#define ARG ConsoleValueRef
-   const char *executef(SimObject *, ARG);
-   const char *executef(SimObject *, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-   const char *executef(SimObject *, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG, ARG);
-#undef ARG
+   /// NOTE: this function restores the console stack on return.
+   ConsoleValueRef execute(SimObject *object, S32 argc, const char* argv[], bool thisCallOnly = false);
+   ConsoleValueRef execute(SimObject *object, S32 argc, ConsoleValueRef argv[], bool thisCallOnly = false);
 
    /// Evaluate an arbitrary chunk of code.
    ///
    /// @param  string   Buffer containing code to execute.
    /// @param  echo     Should we echo the string to the console?
    /// @param  fileName Indicate what file this code is coming from; used in error reporting and such.
-   const char *evaluate(const char* string, bool echo = false, const char *fileName = NULL);
+   /// NOTE: This function restores the console stack on return.
+   ConsoleValueRef evaluate(const char* string, bool echo = false, const char *fileName = NULL);
 
    /// Evaluate an arbitrary line of script.
    ///
    /// This wraps dVsprintf(), so you can substitute parameters into the code being executed.
-   const char *evaluatef(const char* string, ...);
+   /// NOTE: This function restores the console stack on return.
+   ConsoleValueRef evaluatef(const char* string, ...);
 
    /// @}
 
@@ -831,14 +816,12 @@ namespace Con
    char* getReturnBuffer( const StringBuilder& str );
 
    char* getArgBuffer(U32 bufferSize);
-   ConsoleValueRef getFloatArg(F64 arg);
-   ConsoleValueRef getIntArg  (S32 arg);
-   char* getStringArg( const char *arg );
+   char* getFloatArg(F64 arg);
+   char* getIntArg  (S32 arg);
+   char* getStringArg( const char* arg );
    char* getStringArg( const String& arg );
    /// @}
 
-   void resetStackFrame();
-
    /// @name Namespaces
    /// @{
 
@@ -872,21 +855,48 @@ namespace Con
    /// @name Dynamic Type System
    /// @{
 
-   ///
-/*   void registerType( const char *typeName, S32 type, S32 size, GetDataFunction gdf, SetDataFunction sdf, bool isDatablockType = false );
-   void registerType( const char* typeName, S32 type, S32 size, bool isDatablockType = false );
-   void registerTypeGet( S32 type, GetDataFunction gdf );
-   void registerTypeSet( S32 type, SetDataFunction sdf );
-
-   const char *getTypeName(S32 type);
-   bool isDatablockType( S32 type ); */
-
    void setData(S32 type, void *dptr, S32 index, S32 argc, const char **argv, const EnumTable *tbl = NULL, BitSet32 flag = 0);
    const char *getData(S32 type, void *dptr, S32 index, const EnumTable *tbl = NULL, BitSet32 flag = 0);
    const char *getFormattedData(S32 type, const char *data, const EnumTable *tbl = NULL, BitSet32 flag = 0);
+
    /// @}
 };
 
+struct _EngineConsoleCallbackHelper;
+template<typename P1> struct _EngineConsoleExecCallbackHelper;
+
+namespace Con
+{
+	/// @name Console Execution - executef
+	/// {
+	///
+	/// Implements a script function thunk which automatically converts parameters to relevant console types.
+	/// Can be used as follows:
+	/// - Con::executef("functionName", ...);
+	/// - Con::executef(mySimObject, "functionName", ...);
+	/// 
+	/// NOTE: if you get a rather cryptic template error coming through here, most likely you are trying to 
+	/// convert a parameter which EngineMarshallType does not have a specialization for.
+	/// Another problem can occur if you do not include "console/simBase.h" and "console/engineAPI.h" 
+	/// since _EngineConsoleExecCallbackHelper and SimConsoleThreadExecCallback are required.
+	///
+	/// @see _EngineConsoleExecCallbackHelper
+	///
+	template<typename A> ConsoleValueRef executef(A a) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(); }
+	template<typename A, typename B> ConsoleValueRef executef(A a, B b) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b); }
+	template<typename A, typename B, typename C> ConsoleValueRef executef(A a, B b, C c) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c); }
+	template<typename A, typename B, typename C, typename D> ConsoleValueRef executef(A a, B b, C c, D d) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d); }
+	template<typename A, typename B, typename C, typename D, typename E> ConsoleValueRef executef(A a, B b, C c, D d, E e) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e); }
+	template<typename A, typename B, typename C, typename D, typename E, typename F> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f); }
+	template<typename A, typename B, typename C, typename D, typename E, typename F, typename G> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g); }
+	template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h); }
+	template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i); }
+	template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j); }
+	template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j, k); }
+	template<typename A, typename B, typename C, typename D, typename E, typename F, typename G, typename H, typename I, typename J, typename K, typename L> ConsoleValueRef executef(A a, B b, C c, D d, E e, F f, G g, H h, I i, J j, K k, L l) { _EngineConsoleExecCallbackHelper<A> callback( a ); return callback.template call<ConsoleValueRef>(b, c, d, e, f, g, h, i, j, k, l); }
+	/// }
+};
+
 extern void expandEscape(char *dest, const char *src);
 extern bool collapseEscape(char *buf);
 extern U32 HashPointer(StringTableEntry ptr);
@@ -1103,6 +1113,28 @@ struct ConsoleDocFragment
 };
 
 
+/// Utility class to save and restore the current console stack frame
+///
+class ConsoleStackFrameSaver
+{
+public:
+
+	bool mSaved;
+
+	ConsoleStackFrameSaver() : mSaved(false)
+	{
+	}
+
+	~ConsoleStackFrameSaver()
+	{
+		restore();
+	}
+
+	void save();
+	void restore();
+};
+
+
 /// @name Global Console Definition Macros
 ///
 /// @note If TORQUE_DEBUG is defined, then we gather documentation information, and

+ 53 - 23
Engine/source/console/consoleInternal.cpp

@@ -512,7 +512,7 @@ void ConsoleValue::setStringValue(const char * value)
 */
 	   if (value == typeValueEmpty)
       {
-            if (sval && sval != typeValueEmpty && type != TypeInternalStackString) dFree(sval);
+            if (sval && sval != typeValueEmpty && type != TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
             sval = typeValueEmpty;
             bufferLen = 0;
             fval = 0.f;
@@ -541,7 +541,7 @@ void ConsoleValue::setStringValue(const char * value)
       // may as well pad to the next cache line
       U32 newLen = ((stringLen + 1) + 15) & ~15;
 	  
-      if(sval == typeValueEmpty || type == TypeInternalStackString)
+      if(sval == typeValueEmpty || type == TypeInternalStackString || type == TypeInternalStringStackPtr)
          sval = (char *) dMalloc(newLen);
       else if(newLen > bufferLen)
          sval = (char *) dRealloc(sval, newLen);
@@ -556,7 +556,7 @@ void ConsoleValue::setStringValue(const char * value)
 }
 
 
-void ConsoleValue::setStackStringValue(const char * value)
+void ConsoleValue::setStackStringValue(const char *value)
 {
    if (value == NULL) value = typeValueEmpty;
 
@@ -564,7 +564,7 @@ void ConsoleValue::setStackStringValue(const char * value)
    {
 	   if (value == typeValueEmpty)
       {
-         if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString) dFree(sval);
+         if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString && type != ConsoleValue::TypeInternalStringStackPtr) dFree(sval);
          sval = typeValueEmpty;
          bufferLen = 0;
          fval = 0.f;
@@ -586,13 +586,42 @@ void ConsoleValue::setStackStringValue(const char * value)
       }
 
       type = TypeInternalStackString;
-	  sval = (char*)value;
+      sval = (char*)value;
       bufferLen = stringLen;
    }
    else
       Con::setData(type, dataPtr, 0, 1, &value, enumTable);      
 }
 
+void ConsoleValue::setStringStackPtrValue(StringStackPtr ptrValue)
+{
+   if(type <= ConsoleValue::TypeInternalString)
+   {
+      const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
+	   if (sval && sval != typeValueEmpty && type != ConsoleValue::TypeInternalStackString && type != TypeInternalStringStackPtr) dFree(sval);
+
+      U32 stringLen = dStrlen(value);
+      if(stringLen < 256)
+      {
+         fval = dAtof(value);
+         ival = dAtoi(value);
+      }
+      else
+      {
+         fval = 0.f;
+         ival = 0;
+      }
+
+      type = TypeInternalStringStackPtr;
+      sval = (char*)(value - STR.mBuffer);
+      bufferLen = stringLen;
+   }
+   else
+   {
+      const char *value = StringStackPtrRef(ptrValue).getPtr(&STR);
+      Con::setData(type, dataPtr, 0, 1, &value, enumTable);      
+   }
+}
 
 S32 Dictionary::getIntVariable(StringTableEntry name, bool *entValid)
 {
@@ -651,7 +680,8 @@ Dictionary::Entry* Dictionary::addVariable(  const char *name,
    Entry *ent = add(StringTable->insert(name));
    
    if (  ent->value.type <= ConsoleValue::TypeInternalString &&
-         ent->value.sval != typeValueEmpty && ent->value.type != ConsoleValue::TypeInternalStackString )
+         ent->value.sval != typeValueEmpty && 
+         ent->value.type != ConsoleValue::TypeInternalStackString && ent->value.type != ConsoleValue::TypeInternalStringStackPtr )
       dFree(ent->value.sval);
 
    ent->value.type = type;
@@ -1338,14 +1368,20 @@ void Namespace::markGroup(const char* name, const char* usage)
 
 extern S32 executeBlock(StmtNode *block, ExprEvalState *state);
 
-const char *Namespace::Entry::execute(S32 argc, ConsoleValueRef *argv, ExprEvalState *state)
+ConsoleValueRef Namespace::Entry::execute(S32 argc, ConsoleValueRef *argv, ExprEvalState *state)
 {
+   STR.clearFunctionOffset();
+
    if(mType == ConsoleFunctionType)
    {
       if(mFunctionOffset)
+      {
          return mCode->exec(mFunctionOffset, argv[0], mNamespace, argc, argv, false, mPackage);
+      }
       else
-         return "";
+      {
+         return ConsoleValueRef();
+      }
    }
 
 #ifndef TORQUE_DEBUG
@@ -1354,7 +1390,7 @@ const char *Namespace::Entry::execute(S32 argc, ConsoleValueRef *argv, ExprEvalS
    if(mToolOnly && ! Con::isCurrentScriptToolScript())
    {
       Con::errorf(ConsoleLogEntry::Script, "%s::%s - attempting to call tools only function from outside of tools", mNamespace->mName, mFunctionName);
-      return "";
+      return ConsoleValueRef();
    }
 #endif
 
@@ -1362,32 +1398,26 @@ const char *Namespace::Entry::execute(S32 argc, ConsoleValueRef *argv, ExprEvalS
    {
       Con::warnf(ConsoleLogEntry::Script, "%s::%s - wrong number of arguments.", mNamespace->mName, mFunctionName);
       Con::warnf(ConsoleLogEntry::Script, "usage: %s", mUsage);
-      return "";
+      return ConsoleValueRef();
    }
 
    static char returnBuffer[32];
    switch(mType)
    {
       case StringCallbackType:
-         return cb.mStringCallbackFunc(state->thisObject, argc, argv);
+         return ConsoleValueRef::fromValue(CSTK.pushStackString(cb.mStringCallbackFunc(state->thisObject, argc, argv)));
       case IntCallbackType:
-         dSprintf(returnBuffer, sizeof(returnBuffer), "%d",
-            cb.mIntCallbackFunc(state->thisObject, argc, argv));
-         return returnBuffer;
+		 return ConsoleValueRef::fromValue(CSTK.pushUINT((U32)cb.mBoolCallbackFunc(state->thisObject, argc, argv)));
       case FloatCallbackType:
-         dSprintf(returnBuffer, sizeof(returnBuffer), "%g",
-            cb.mFloatCallbackFunc(state->thisObject, argc, argv));
-         return returnBuffer;
+		 return ConsoleValueRef::fromValue(CSTK.pushFLT((U32)cb.mBoolCallbackFunc(state->thisObject, argc, argv)));
       case VoidCallbackType:
          cb.mVoidCallbackFunc(state->thisObject, argc, argv);
-         return "";
+         return ConsoleValueRef();
       case BoolCallbackType:
-         dSprintf(returnBuffer, sizeof(returnBuffer), "%d",
-            (U32)cb.mBoolCallbackFunc(state->thisObject, argc, argv));
-         return returnBuffer;
+		 return ConsoleValueRef::fromValue(CSTK.pushUINT((U32)cb.mBoolCallbackFunc(state->thisObject, argc, argv)));
    }
-
-   return "";
+   
+   return ConsoleValueRef();
 }
 
 //-----------------------------------------------------------------------------

+ 18 - 1
Engine/source/console/consoleInternal.h

@@ -151,7 +151,7 @@ class Namespace
          void clear();
 
          ///
-         const char *execute( S32 argc, ConsoleValueRef* argv, ExprEvalState* state );
+         ConsoleValueRef execute( S32 argc, ConsoleValueRef* argv, ExprEvalState* state );
          
          /// Return a one-line documentation text string for the function.
          String getBriefDescription( String* outRemainingDocText = NULL ) const;
@@ -367,6 +367,22 @@ public:
             notify->trigger();
       }
 
+      void setStringStackPtrValue(StringStackPtr newValue)
+      {
+         if( mIsConstant )
+         {
+            Con::errorf( "Cannot assign value to constant '%s'.", name );
+            return;
+         }
+         
+         value.setStringStackPtrValue(newValue);
+         
+         
+         // Fire off the notification if we have one.
+         if ( notify )
+            notify->trigger();
+      }
+
       void setStringValue(const char *newValue)
       {
          if( mIsConstant )
@@ -495,6 +511,7 @@ public:
    void setIntVariable(S32 val);
    void setFloatVariable(F64 val);
    void setStringVariable(const char *str);
+   void setStringStackPtrVariable(StringStackPtr str);
    void setCopyVariable();
 
    void pushFrame(StringTableEntry frameName, Namespace *ns);

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 323 - 20
Engine/source/console/engineAPI.h


+ 3 - 3
Engine/source/console/sim.h

@@ -157,13 +157,13 @@ namespace Sim
    SimTime getTargetTime();
 
    /// a target time of 0 on an event means current event
-   U32 postEvent(SimObject*, SimEvent*, U32 targetTime);
+   U32 postEvent(SimObject*, SimEvent*, SimTime targetTime);
 
-   inline U32 postEvent(SimObjectId iD,SimEvent*evt, U32 targetTime)
+   inline U32 postEvent(SimObjectId iD,SimEvent*evt, SimTime targetTime)
    {
       return postEvent(findObject(iD), evt, targetTime);
    }
-   inline U32 postEvent(const char *objectName,SimEvent*evt, U32 targetTime)
+   inline U32 postEvent(const char *objectName,SimEvent*evt, SimTime targetTime)
    {
       return postEvent(findObject(objectName), evt, targetTime);
    }

+ 17 - 5
Engine/source/console/simEvents.cpp

@@ -39,7 +39,10 @@ SimConsoleEvent::SimConsoleEvent(S32 argc, ConsoleValueRef *argv, bool onObject)
       mArgv[i].value = new ConsoleValue();
       mArgv[i].value->type = ConsoleValue::TypeInternalString;
       mArgv[i].value->init();
-      mArgv[i].value->setStringValue((const char*)argv[i]);
+	  if (argv)
+	  {
+		mArgv[i].value->setStringValue((const char*)argv[i]);
+	  }
    }
 }
 
@@ -92,10 +95,19 @@ void SimConsoleEvent::process(SimObject* object)
    }
 }
 
+void SimConsoleEvent::populateArgs(ConsoleValueRef *argv)
+{
+   for (U32 i=0; i<mArgc; i++)
+   {
+      argv[i].value = mArgv[i].value;
+   }
+}
+
 //-----------------------------------------------------------------------------
 
-SimConsoleThreadExecCallback::SimConsoleThreadExecCallback() : retVal(NULL)
+SimConsoleThreadExecCallback::SimConsoleThreadExecCallback()
 {
+   retVal.value = NULL;
    sem = new Semaphore(0);
 }
 
@@ -104,13 +116,13 @@ SimConsoleThreadExecCallback::~SimConsoleThreadExecCallback()
    delete sem;
 }
 
-void SimConsoleThreadExecCallback::handleCallback(const char *ret)
+void SimConsoleThreadExecCallback::handleCallback(ConsoleValueRef ret)
 {
    retVal = ret;
    sem->release();
 }
 
-const char *SimConsoleThreadExecCallback::waitForResult()
+ConsoleValueRef SimConsoleThreadExecCallback::waitForResult()
 {
    if(sem->acquire(true))
    {
@@ -129,7 +141,7 @@ SimConsoleThreadExecEvent::SimConsoleThreadExecEvent(S32 argc, ConsoleValueRef *
 
 void SimConsoleThreadExecEvent::process(SimObject* object)
 {
-   const char *retVal;
+   ConsoleValueRef retVal;
    if(mOnObject)
       retVal = Con::execute(object, mArgc, mArgv);
    else

+ 9 - 3
Engine/source/console/simEvents.h

@@ -114,19 +114,24 @@ public:
 
    ~SimConsoleEvent();
    virtual void process(SimObject *object);
+
+   /// Creates a reference to our internal args list in argv
+   void populateArgs(ConsoleValueRef *argv);
 };
 
+
+// NOTE: SimConsoleThreadExecCallback & SimConsoleThreadExecEvent moved to engineAPI.h
 /// Used by Con::threadSafeExecute()
 struct SimConsoleThreadExecCallback
 {
    Semaphore   *sem;
-   const char  *retVal;
+   ConsoleValueRef retVal;
 
    SimConsoleThreadExecCallback();
    ~SimConsoleThreadExecCallback();
 
-   void handleCallback(const char *ret);
-   const char *waitForResult();
+   void handleCallback(ConsoleValueRef ret);
+   ConsoleValueRef waitForResult();
 };
 
 class SimConsoleThreadExecEvent : public SimConsoleEvent
@@ -136,6 +141,7 @@ class SimConsoleThreadExecEvent : public SimConsoleEvent
 public:
    SimConsoleThreadExecEvent(S32 argc, ConsoleValueRef *argv, bool onObject, SimConsoleThreadExecCallback *callback);
 
+   SimConsoleThreadExecCallback& getCB() { return *cb; }
    virtual void process(SimObject *object);
 };
 

+ 2 - 1
Engine/source/console/simObjectList.cpp

@@ -23,7 +23,8 @@
 #include "platform/platform.h"
 #include "console/simObjectList.h"
 
-#include "console/console.h"
+#include "console/simBase.h"
+#include "console/engineAPI.h"
 #include "console/sim.h"
 #include "console/simObject.h"
 

+ 46 - 2
Engine/source/console/stringStack.cpp

@@ -31,12 +31,11 @@ void ConsoleValueStack::getArgcArgv(StringTableEntry name, U32 *argc, ConsoleVal
    U32 argCount   = getMin(mStackPos - startStack, (U32)MaxArgs - 1);
 
    *in_argv = mArgv;
-   mArgv[0] = name;
+   mArgv[0].value = CSTK.pushStackString(name);
    
    for(U32 i = 0; i < argCount; i++) {
       ConsoleValueRef *ref = &mArgv[i+1];
       ref->value = &mStack[startStack + i];
-      ref->stringStackValue = NULL;
    }
    argCount++;
    
@@ -91,11 +90,43 @@ void ConsoleValueStack::pushValue(ConsoleValue &variable)
       mStack[mStackPos++].setIntValue((S32)variable.getIntValue());
    case ConsoleValue::TypeInternalFloat:
       mStack[mStackPos++].setFloatValue((F32)variable.getFloatValue());
+   case ConsoleValue::TypeInternalStringStackPtr:
+      mStack[mStackPos++].setStringStackPtrValue(variable.getStringStackPtr());
    default:
       mStack[mStackPos++].setStringValue(variable.getStringValue());
    }
 }
 
+ConsoleValue* ConsoleValueStack::reserveValues(U32 count)
+{
+   U32 startPos = mStackPos;
+   if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
+      AssertFatal(false, "Console Value Stack is empty");
+      return NULL;
+   }
+
+   //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
+   mStackPos += count;
+   return &mStack[startPos];
+}
+
+bool ConsoleValueStack::reserveValues(U32 count, ConsoleValueRef *outValues)
+{
+   U32 startPos = mStackPos;
+   if (startPos+count >= ConsoleValueStack::MaxStackDepth) {
+      AssertFatal(false, "Console Value Stack is empty");
+      return false;
+   }
+
+   //Con::printf("[%i]CSTK reserveValues %i", mStackPos, count);
+   for (U32 i=0; i<count; i++)
+   {
+	   outValues[i].value = &mStack[mStackPos+i];
+   }
+   mStackPos += count;
+   return true;
+}
+
 ConsoleValue *ConsoleValueStack::pushString(const char *value)
 {
    if (mStackPos == ConsoleValueStack::MaxStackDepth) {
@@ -122,6 +153,19 @@ ConsoleValue *ConsoleValueStack::pushStackString(const char *value)
    return &mStack[mStackPos-1];
 }
 
+ConsoleValue *ConsoleValueStack::pushStringStackPtr(StringStackPtr value)
+{
+   if (mStackPos == ConsoleValueStack::MaxStackDepth) {
+      AssertFatal(false, "Console Value Stack is empty");
+      return NULL;
+   }
+
+   //Con::printf("[%i]CSTK pushStringStackPtr %s", mStackPos, StringStackPtrRef(value).getPtr(&STR));
+
+   mStack[mStackPos++].setStringStackPtrValue(value);
+   return &mStack[mStackPos-1];
+}
+
 ConsoleValue *ConsoleValueStack::pushUINT(U32 value)
 {
    if (mStackPos == ConsoleValueStack::MaxStackDepth) {

+ 33 - 0
Engine/source/console/stringStack.h

@@ -35,8 +35,21 @@
 #include "console/console.h"
 #endif
 
+typedef U32 StringStackPtr;
+struct StringStack;
 
+/// Helper class which stores a relative pointer in the StringStack buffer
+class StringStackPtrRef
+{
+public:
+   StringStackPtrRef() : mOffset(0) {;}
+   StringStackPtrRef(StringStackPtr offset) : mOffset(offset) {;}
+
+   StringStackPtr mOffset;
 
+   /// Get pointer to string in stack stk
+   inline char *getPtr(StringStack *stk);
+};
 
 /// Core stack for interpreter operations.
 ///
@@ -127,6 +140,7 @@ struct StringStack
    /// Return a temporary buffer we can use to return data.
    char* getReturnBuffer(U32 size)
    {
+      AssertFatal(Con::isMainThread(), "Manipulating return buffer from a secondary thread!");
       validateArgBufferSize(size);
       return mArgBuffer;
    }
@@ -136,6 +150,7 @@ struct StringStack
    /// This updates the function offset.
    char *getArgBuffer(U32 size)
    {
+      AssertFatal(Con::isMainThread(), "Manipulating console arg buffer from a secondary thread!");
       validateBufferSize(mStart + mFunctionOffset + size);
       char *ret = mBuffer + mStart + mFunctionOffset;
       mFunctionOffset += size;
@@ -197,6 +212,16 @@ struct StringStack
       return mBuffer + mStartOffsets[mStartStackSize-1];
    }
 
+   inline StringStackPtr getStringValuePtr()
+   {
+      return (getStringValue() - mBuffer);
+   }
+
+   inline StringStackPtr getPreviousStringValuePtr()
+   {
+      return (getPreviousStringValue() - mBuffer);
+   }
+
    /// Advance the start stack, placing a zero length string on the top.
    ///
    /// @note You should use StringStack::push, not this, if you want to
@@ -314,10 +339,13 @@ public:
 
    void pushVar(ConsoleValue *variable);
    void pushValue(ConsoleValue &value);
+   ConsoleValue* reserveValues(U32 numValues);
+   bool reserveValues(U32 numValues, ConsoleValueRef *values);
    ConsoleValue* pop();
 
    ConsoleValue *pushString(const char *value);
    ConsoleValue *pushStackString(const char *value);
+   ConsoleValue *pushStringStackPtr(StringStackPtr ptr);
    ConsoleValue *pushUINT(U32 value);
    ConsoleValue *pushFLT(float value);
 
@@ -338,4 +366,9 @@ public:
    ConsoleValueRef mArgv[MaxArgs];
 };
 
+extern StringStack STR;
+extern ConsoleValueStack CSTK;
+
+inline char* StringStackPtrRef::getPtr(StringStack *stk) { return stk->mBuffer + mOffset; }
+
 #endif

+ 3 - 1
Engine/source/console/telnetConsole.cpp

@@ -21,9 +21,11 @@
 //-----------------------------------------------------------------------------
 
 #include "platform/platform.h"
-#include "console/telnetConsole.h"
 
+#include "console/simBase.h"
 #include "console/engineAPI.h"
+#include "console/telnetConsole.h"
+
 #include "core/strings/stringFunctions.h"
 #include "core/util/journal/process.h"
 #include "core/module.h"

+ 287 - 0
Engine/source/console/test/consoleTest.cpp

@@ -0,0 +1,287 @@
+#ifdef TORQUE_TESTS_ENABLED
+#include "testing/unitTesting.h"
+#include "platform/platform.h"
+#include "console/simBase.h"
+#include "console/consoleTypes.h"
+#include "console/simBase.h"
+#include "console/engineAPI.h"
+#include "math/mMath.h"
+#include "console/stringStack.h"
+
+TEST(Con, executef)
+{
+	char buffer[128];
+	Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testExecutef(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k){return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j SPC %k;}\r\nfunction TestConExec::testThisFunction(%this,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j){ return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j;}\r\nnew ScriptObject(TestConExec);\r\n", false, "test");
+	
+	SimObject *testObject = NULL;
+	Sim::findObject("TestConExec", testObject);
+
+	EXPECT_TRUE(testObject != NULL)
+		<< "TestConExec object should exist";
+
+	// Check basic calls with SimObject. We'll do this for every single possible call just to make sure.
+	const char *returnValue = NULL;
+	
+	returnValue = Con::executef(testObject, "testThisFunction");
+	EXPECT_TRUE(dStricmp(returnValue, "         ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a");
+	EXPECT_TRUE(dStricmp(returnValue, "a         ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b");
+	EXPECT_TRUE(dStricmp(returnValue, "a b        ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c       ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d      ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e     ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f    ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f", "g");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f g   ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f", "g", "h");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f g h  ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef(testObject, "testThisFunction", "a", "b", "c", "d", "e", "f", "g", "h", "i");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f g h i ") == 0) <<
+		"All values should be printed in the correct order";
+
+	// Now test without the object
+	
+	returnValue = Con::executef("testExecutef");
+	EXPECT_TRUE(dStricmp(returnValue, "          ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a");
+	EXPECT_TRUE(dStricmp(returnValue, "a          ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b");
+	EXPECT_TRUE(dStricmp(returnValue, "a b         ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c        ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c", "d");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d       ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c", "d", "e");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e      ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c", "d", "e", "f");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f     ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c", "d", "e", "f", "g");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f g    ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c", "d", "e", "f", "g", "h");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f g h   ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c", "d", "e", "f", "g", "h", "i");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f g h i  ") == 0) <<
+		"All values should be printed in the correct order";
+	
+	returnValue = Con::executef("testExecutef", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j");
+	EXPECT_TRUE(dStricmp(returnValue, "a b c d e f g h i j ") == 0) <<
+		"All values should be printed in the correct order";
+
+	// Test type conversions with and without SimObject...
+
+	// Integer
+	returnValue = Con::executef(testObject, "testThisFunction", 123);
+	EXPECT_TRUE(dStricmp(returnValue, "123         ") == 0) <<
+		"Integer should be converted";
+	returnValue = Con::executef("testExecutef", 123);
+	EXPECT_TRUE(dStricmp(returnValue, "123          ") == 0) <<
+		"Integer should be converted";
+
+	// Float
+	returnValue = Con::executef(testObject, "testThisFunction", (F32)123.4);
+	EXPECT_TRUE(dStricmp(returnValue, "123.4         ") == 0) <<
+		"Float should be converted";
+	returnValue = Con::executef("testExecutef", (F32)123.4);
+	EXPECT_TRUE(dStricmp(returnValue, "123.4          ") == 0) <<
+		"Float should be converted";
+
+	// SimObject
+	dSprintf(buffer, sizeof(buffer), "%i         ", testObject->getId());
+	returnValue = Con::executef(testObject, "testThisFunction", testObject);
+	EXPECT_TRUE(dStricmp(returnValue, buffer) == 0) <<
+		"SimObject should be converted";
+	dSprintf(buffer, sizeof(buffer), "%i          ", testObject->getId());
+	returnValue = Con::executef("testExecutef", testObject);
+	EXPECT_TRUE(dStricmp(returnValue, buffer) == 0) <<
+		"SimObject should be converted";
+
+	// Point3F
+	Point3F point(1,2,3);
+	returnValue = Con::executef(testObject, "testThisFunction", point);
+	EXPECT_TRUE(dStricmp(returnValue, "1 2 3         ") == 0) <<
+		"Point3F should be converted";
+	returnValue = Con::executef("testExecutef", point);
+	EXPECT_TRUE(dStricmp(returnValue, "1 2 3          ") == 0) <<
+		"Point3F should be converted";
+
+   // Finally test the function arg offset. This should be consistently 0 after each call
+   
+	EXPECT_TRUE(STR.mFunctionOffset == 0) <<
+		"Function offset should be 0";
+
+   const char *floatArg = Con::getFloatArg(1.23);
+	EXPECT_TRUE(STR.mFunctionOffset > 0) <<
+		"Function offset should not be 0";
+
+   Con::executef("testExecutef", floatArg);
+   
+	EXPECT_TRUE(STR.mFunctionOffset == 0) <<
+		"Function offset should be 0";
+
+   floatArg = Con::getFloatArg(1.23);
+	EXPECT_TRUE(STR.mFunctionOffset > 0) <<
+		"Function offset should not be 0";
+
+   Con::executef("testImaginaryFunction_", floatArg);
+   
+	EXPECT_TRUE(STR.mFunctionOffset == 0) <<
+		"Function offset should be 0";
+}
+
+TEST(Con, execute)
+{
+	Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testScriptExecuteFunction(%a,%b) {return %a SPC %b;}\nfunction TestConExec::testScriptExecuteFunction(%this, %a,%b) {return %a SPC %b;}new ScriptObject(TestConExec);\r\n", false, "testExecute");
+	
+	U32 startStackPos = CSTK.mStackPos;
+	U32 startStringStackPos = STR.mStart;
+	U32 startStackFrame = CSTK.mFrame;
+	
+	SimObject *testObject = NULL;
+	Sim::findObject("TestConExec", testObject);
+
+	EXPECT_TRUE(testObject != NULL)
+		<< "TestConExec object should exist";
+
+	// const char* versions of execute should maintain stack
+	const char *argv[] = {"testScriptExecuteFunction", "1", "2"};
+	const char *argvObject[] = {"testScriptExecuteFunction", "", "1", "2"};
+	const char *returnValue = Con::execute(3, argv);
+
+	EXPECT_TRUE(dStricmp(returnValue, "1 2") == 0) <<
+		"execute should return 1 2";
+	
+	EXPECT_TRUE(CSTK.mStackPos == startStackPos) <<
+		"execute should restore stack";
+
+	returnValue = Con::execute(testObject, 4, argvObject);
+
+	EXPECT_TRUE(dStricmp(returnValue, "1 2") == 0) <<
+		"execute should return 1 2";
+	
+	EXPECT_TRUE(CSTK.mStackPos == startStackPos) <<
+		"execute should restore stack";
+
+	// ConsoleValueRef versions of execute should not restore stack
+	CSTK.pushFrame();
+	STR.pushFrame();
+
+	ConsoleValue valueArg[4];
+	ConsoleValueRef refArg[4];
+	ConsoleValue valueArgObject[4];
+	ConsoleValueRef refArgObject[4];
+	for (U32 i=0; i<4; i++)
+	{
+		refArg[i].value = &valueArg[i];
+		refArgObject[i].value = &valueArgObject[i];
+		valueArgObject[i].init();
+		valueArg[i].init();
+	}
+
+	refArg[0] = "testScriptExecuteFunction";
+	refArg[1] = "1";
+	refArg[2] = "2";
+
+	refArgObject[0] = "testScriptExecuteFunction";
+	refArgObject[2] = "1";
+	refArgObject[3] = "2";
+
+	returnValue = Con::execute(3, refArg);
+
+	EXPECT_TRUE(dStricmp(returnValue, "1 2") == 0) <<
+		"execute should return 1 2";
+	
+	EXPECT_TRUE(CSTK.mStackPos == startStackPos) <<
+		"execute should restore stack";
+
+	CSTK.popFrame();
+	STR.popFrame();
+
+	CSTK.pushFrame();
+	STR.pushFrame();
+
+	returnValue = Con::execute(testObject, 4, refArgObject);
+
+	EXPECT_TRUE(dStricmp(returnValue, "1 2") == 0) <<
+		"execute should return 1 2";
+	
+	EXPECT_TRUE(CSTK.mStackPos == startStackPos) <<
+		"execute should restore stack";
+
+	CSTK.popFrame();
+	STR.popFrame();
+}
+
+static U32 gConsoleStackFrame = 0;
+
+ConsoleFunction(testConsoleStackFrame, S32, 1, 1, "")
+{
+	gConsoleStackFrame = CSTK.mFrame;
+	return (U32)Con::executef("testScriptEvalFunction"); // execute a sub function which manipulates the stack
+}
+
+TEST(Con, evaluate)
+{
+	U32 startStackPos = CSTK.mStackPos;
+	U32 startStringStackPos = STR.mStart;
+	S32 returnValue = Con::evaluate("function testScriptEvalFunction() {return \"1\"@\"2\"@\"3\";}\nreturn testConsoleStackFrame();", false, "testEvaluate");
+	U32 frame = CSTK.mFrame;
+
+	EXPECT_TRUE(returnValue == 123) <<
+		"Evaluate should return 123";
+
+	EXPECT_TRUE(gConsoleStackFrame == (frame+2)) <<
+		"Console stack frame inside function should be +2";
+
+	EXPECT_TRUE(CSTK.mFrame == frame) <<
+		"Console stack frame outside function should be the same as before";
+
+	EXPECT_TRUE(STR.mStart == startStringStackPos) <<
+		"Console string stack should not be changed";
+
+	EXPECT_TRUE(CSTK.mStackPos == startStackPos) <<
+		"Console stack should not be changed";
+
+}
+
+#endif

+ 150 - 0
Engine/source/console/test/engineAPITest.cpp

@@ -0,0 +1,150 @@
+#ifdef TORQUE_TESTS_ENABLED
+#include "testing/unitTesting.h"
+#include "platform/platform.h"
+#include "console/simBase.h"
+#include "console/consoleTypes.h"
+#include "console/simBase.h"
+#include "console/engineAPI.h"
+#include "math/mMath.h"
+
+
+TEST(EngineAPI, EngineMarshallData)
+{
+	// Reserve some values
+	ConsoleValue values[16];
+	ConsoleValueRef refValues[16];
+
+	for (U32 i=0; i<16; i++)
+	{
+		values[i].init();
+		refValues[i].value = &values[i];
+	}
+
+	// Basic string casting...
+	SimObject *foo = new SimObject();
+	foo->registerObject();
+
+	const char *value = EngineMarshallData(foo);
+	EXPECT_TRUE(dStricmp(value, foo->getIdString()) == 0) 
+		<< "SimObject should be casted to its ID";
+
+	U32 unsignedNumber = 123;
+	S32 signedNumber = -123;
+	value = EngineMarshallData(unsignedNumber);
+	EXPECT_TRUE(dStricmp(value, "123") == 0) 
+		<< "Integer should be converted to 123";
+	value = EngineMarshallData(signedNumber);
+	EXPECT_TRUE(dStricmp(value, "-123") == 0) 
+		<< "Integer should be converted to -123";
+
+	bool boolValue = true;
+	value = EngineMarshallData(boolValue);
+	EXPECT_TRUE(dStricmp(value, "1") == 0) 
+		<< "Bool should be converted to 1";
+
+	Point3F point(1,2,3);
+	value = EngineMarshallData(point);
+	EXPECT_TRUE(dStricmp(value, "1 2 3") == 0) 
+		<< "Point3F should be converted to 1 2 3";
+
+	F32 floatValue = 1.23f;
+	value = EngineMarshallData(floatValue);
+	EXPECT_TRUE(dStricmp(value, "1.23") == 0) 
+		<< "F32 should be converted to 1.23";
+
+	// Argv based casting
+	S32 argc = 0;
+	EngineMarshallData(foo, argc, refValues);
+	EngineMarshallData((const SimObject*)foo, argc, refValues);
+	EngineMarshallData(point, argc, refValues);
+	EngineMarshallData(unsignedNumber, argc, refValues);
+	EngineMarshallData(signedNumber, argc, refValues);
+	EngineMarshallData(boolValue, argc, refValues);
+	EngineMarshallData(floatValue, argc, refValues);
+
+	EXPECT_TRUE(argc == 7) 
+		<< "7 args should have been set";
+
+	EXPECT_TRUE(values[0].type == ConsoleValue::TypeInternalInt && values[0].getSignedIntValue() == foo->getId())
+		<< "1st arg should be foo's id";
+
+	EXPECT_TRUE(values[1].type == ConsoleValue::TypeInternalInt && values[1].getSignedIntValue() == foo->getId())
+		<< "2nd arg should be foo's id";
+
+	EXPECT_TRUE(values[2].type == ConsoleValue::TypeInternalString && dStricmp(values[2].getStringValue(), "1 2 3") == 0)
+		<< "3rd arg should be 1 2 3";
+
+	EXPECT_TRUE(values[3].type == ConsoleValue::TypeInternalFloat && values[3].getSignedIntValue() == 123)
+		<< "4th arg should be 123";
+
+	EXPECT_TRUE(values[4].type == ConsoleValue::TypeInternalFloat && values[4].getSignedIntValue() == -123)
+		<< "5th arg should be -123";
+
+	EXPECT_TRUE(values[5].type == ConsoleValue::TypeInternalFloat && values[5].getBoolValue() == true)
+		<< "6th arg should be -123";
+
+	EXPECT_TRUE(values[6].type == ConsoleValue::TypeInternalFloat && mRound(values[6].getFloatValue() * 100) == 123)
+		<< "7th arg should be 1.23";
+
+	foo->deleteObject();
+}
+
+TEST(EngineAPI, EngineUnMarshallData)
+{
+	SimObject *foo = new SimObject();
+	foo->registerObject();
+
+	SimObject *testFoo = EngineUnmarshallData<SimObject*>()(foo->getIdString());
+
+	EXPECT_TRUE(foo == testFoo)
+		<< "Unmarshalling foo's id should return foo";
+
+	testFoo = EngineUnmarshallData<SimObject*>()("ShouldNotExist_Really123");
+	EXPECT_TRUE(testFoo == NULL)
+		<< "Unmarshalling a bad object should return NULL";
+
+	foo->deleteObject();
+}
+
+TEST(EngineAPI, _EngineConsoleCallbackHelper)
+{
+	Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testExecutef(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k){return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j SPC %k;}\r\nfunction TestConExec::testThisFunction(%this,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j){ return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j;}\r\nnew ScriptObject(TestConExec);\r\n", false, "test");
+	
+	SimObject *testObject = NULL;
+	Sim::findObject("TestConExec", testObject);
+
+   _EngineConsoleCallbackHelper helper("testExecutef", NULL);
+   const char *returnValue = helper.call<const char*>("a", "b", "c");
+
+	EXPECT_TRUE(dStricmp(returnValue, "a b c        ") == 0) <<
+		"All values should be printed in the correct order";
+   
+   _EngineConsoleCallbackHelper objectHelper("testThisFunction", testObject);
+   returnValue = helper.call<const char*>("a", "b", "c");
+
+	EXPECT_TRUE(dStricmp(returnValue, "a b c        ") == 0) <<
+		"All values should be printed in the correct order";
+}
+
+// NOTE: this is also indirectly tested by the executef tests
+TEST(EngineAPI, _EngineConsoleExecCallbackHelper)
+{
+	Con::evaluate("if (isObject(TestConExec)) {\r\nTestConExec.delete();\r\n}\r\nfunction testExecutef(%a,%b,%c,%d,%e,%f,%g,%h,%i,%j,%k){return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j SPC %k;}\r\nfunction TestConExec::testThisFunction(%this,%a,%b,%c,%d,%e,%f,%g,%h,%i,%j){ return %a SPC %b SPC %c SPC %d SPC %e SPC %f SPC %g SPC %h SPC %i SPC %j;}\r\nnew ScriptObject(TestConExec);\r\n", false, "test");
+	
+	SimObject *testObject = NULL;
+	Sim::findObject("TestConExec", testObject);
+
+   _EngineConsoleExecCallbackHelper<const char*> helper("testExecutef");
+   const char *returnValue = helper.call<const char*>("a", "b", "c");
+
+	EXPECT_TRUE(dStricmp(returnValue, "a b c        ") == 0) <<
+		"All values should be printed in the correct order";
+   
+   _EngineConsoleExecCallbackHelper<SimObject*> objectHelper(testObject);
+   returnValue = objectHelper.call<const char*>("testThisFunction", "a", "b", "c");
+
+	EXPECT_TRUE(dStricmp(returnValue, "a b c       ") == 0) <<
+		"All values should be printed in the correct order";
+}
+
+#endif

+ 1 - 1
Engine/source/forest/editor/forestSelectionTool.cpp

@@ -517,7 +517,7 @@ bool ForestSelectionTool::updateGuiInfo()
 
    Con::executef( statusbar, "setInfo", text.c_str() );
 
-   Con::executef( statusbar, "setSelectionObjectsByCount", Con::getIntArg( mSelection.size() ) );
+   Con::executef( statusbar, "setSelectionObjectsByCount", mSelection.size() );
 
    return true;
 }

+ 1 - 1
Engine/source/gui/controls/guiConsoleTextCtrl.cpp

@@ -113,7 +113,7 @@ void GuiConsoleTextCtrl::onPreRender()
 {   
    if ( mConsoleExpression.isNotEmpty() )
    {
-      mResult = Con::evaluatef( "$guiConsoleTextCtrlTemp = %s;", mConsoleExpression.c_str() );
+      mResult = (const char*)Con::evaluatef( "$guiConsoleTextCtrlTemp = %s;", mConsoleExpression.c_str() );
       
       // Of the resulting string we will be printing,
       // Find the number of lines and length of each.      

+ 6 - 6
Engine/source/gui/controls/guiListBoxCtrl.cpp

@@ -71,7 +71,7 @@ IMPLEMENT_CALLBACK( GuiListBoxCtrl, onClearSelection, void, (),(),
    "@see GuiControl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiListBoxCtrl, onUnSelect, void, ( const char* index, const char* itemText),( index, itemText ),
+IMPLEMENT_CALLBACK( GuiListBoxCtrl, onUnSelect, void, ( S32 index, const char* itemText),( index, itemText ),
    "@brief Called whenever a selected item in the list has been unselected.\n\n"
    "@param index Index id of the item that was unselected\n"
    "@param itemText Text for the list entry at the index id that was unselected\n\n"
@@ -85,7 +85,7 @@ IMPLEMENT_CALLBACK( GuiListBoxCtrl, onUnSelect, void, ( const char* index, const
    "@see GuiControl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiListBoxCtrl, onSelect, void, ( const char* index , const char* itemText ),( index, itemText ),
+IMPLEMENT_CALLBACK( GuiListBoxCtrl, onSelect, void, ( S32 index , const char* itemText ),( index, itemText ),
    "@brief Called whenever an item in the list is selected.\n\n"
    "@param index Index id for the item in the list that was selected.\n"
    "@param itemText Text for the list item at the index that was selected.\n\n"
@@ -111,7 +111,7 @@ IMPLEMENT_CALLBACK( GuiListBoxCtrl, onDoubleClick, void, (),(),
    "@see GuiControl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiListBoxCtrl, onMouseUp, void, (const char* itemHit, const char* mouseClickCount),( itemHit,mouseClickCount),
+IMPLEMENT_CALLBACK( GuiListBoxCtrl, onMouseUp, void, ( S32 itemHit, S32 mouseClickCount ),( itemHit,mouseClickCount ),
    "@brief Called whenever the mouse has previously been clicked down (onMouseDown) and has now been raised on the control.\n"
    "If an item in the list was hit during the click cycle, then the index id of the clicked object along with how many clicks occured are passed\n"
    "into the callback.\n\n"
@@ -309,7 +309,7 @@ void GuiListBoxCtrl::removeSelection( LBItem *item, S32 index )
       {
          mSelectedItems.erase( &mSelectedItems[i] );
          item->isSelected = false;
-         onUnSelect_callback(Con::getIntArg(index), item->itemText);
+         onUnSelect_callback(index, item->itemText);
          return;
       }
    }
@@ -355,7 +355,7 @@ void GuiListBoxCtrl::addSelection( LBItem *item, S32 index )
    item->isSelected = true;
    mSelectedItems.push_front( item );
 
-   onSelect_callback(Con::getIntArg( index ), item->itemText);
+   onSelect_callback(index, item->itemText);
 }
 
 S32 GuiListBoxCtrl::getItemIndex( LBItem *item )
@@ -1224,7 +1224,7 @@ void GuiListBoxCtrl::onMouseUp( const GuiEvent& event )
 {
    S32 itemHit = -1;
    if( hitTest( event.mousePoint, itemHit ) )
-      onMouseUp_callback(Con::getIntArg( itemHit ), Con::getIntArg( event.mouseClickCount ) );
+      onMouseUp_callback( itemHit, event.mouseClickCount );
 
    // Execute console command
    execConsoleCallback();

+ 3 - 3
Engine/source/gui/controls/guiListBoxCtrl.h

@@ -57,10 +57,10 @@ public:
 
    DECLARE_CALLBACK( void, onMouseDragged, ());
    DECLARE_CALLBACK( void, onClearSelection, ());
-   DECLARE_CALLBACK( void, onUnSelect, ( const char* index, const char* itemText));
-   DECLARE_CALLBACK( void, onSelect, ( const char* index , const char* itemText ));
+   DECLARE_CALLBACK( void, onUnSelect, ( S32 index, const char* itemText));
+   DECLARE_CALLBACK( void, onSelect, ( S32 index , const char* itemText ));
    DECLARE_CALLBACK( void, onDoubleClick, ());
-   DECLARE_CALLBACK( void, onMouseUp, (const char* itemHit, const char* mouseClickCount));
+   DECLARE_CALLBACK( void, onMouseUp, ( S32 itemHit, S32 mouseClickCount ));
    DECLARE_CALLBACK( void, onDeleteKey, ());
    DECLARE_CALLBACK( bool, isObjectMirrored, ( const char* indexIdString ));
 

+ 2 - 2
Engine/source/gui/controls/guiMLTextCtrl.cpp

@@ -73,7 +73,7 @@ IMPLEMENT_CALLBACK( GuiMLTextCtrl, onURL, void, ( const char* url ),( url ),
    "@see GuiControl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiMLTextCtrl, onResize, void, ( const char* width, const char* maxY ),( width, maxY ),
+IMPLEMENT_CALLBACK( GuiMLTextCtrl, onResize, void, ( S32 width, S32 maxY ),( width, maxY ),
    "@brief Called whenever the control size changes.\n\n"
    "@param width The new width value for the control\n"
    "@param maxY The current maximum allowed Y value for the control\n\n"
@@ -2133,7 +2133,7 @@ textemit:
    processEmitAtoms();
    emitNewLine(mScanPos);
    setHeight( mMaxY );
-   onResize_callback(Con::getIntArg( getWidth() ), Con::getIntArg( mMaxY ) );
+   onResize_callback( getWidth(), mMaxY );
 	
    //make sure the cursor is still visible - this handles if we're a child of a scroll ctrl...
    ensureCursorOnScreen();

+ 1 - 1
Engine/source/gui/controls/guiMLTextCtrl.h

@@ -128,7 +128,7 @@ class GuiMLTextCtrl : public GuiControl
    ~GuiMLTextCtrl();
 
    DECLARE_CALLBACK( void, onURL, (const char* url));
-   DECLARE_CALLBACK( void, onResize, ( const char* width, const char* maxY ));
+   DECLARE_CALLBACK( void, onResize, ( S32 width, S32 maxY ));
 
    // Text retrieval functions
    U32 getNumChars() const;

+ 4 - 4
Engine/source/gui/controls/guiTextListCtrl.cpp

@@ -52,7 +52,7 @@ ConsoleDocClass( GuiTextListCtrl,
 );
 
 
-IMPLEMENT_CALLBACK( GuiTextListCtrl, onSelect, void, (const char* cellid, const char* text),( cellid , text ),
+IMPLEMENT_CALLBACK( GuiTextListCtrl, onSelect, void, (S32 cellid, const char* text),( cellid , text ),
    "@brief Called whenever an item in the list is selected.\n\n"
    "@param cellid The ID of the cell that was selected\n"
    "@param text The text in the selected cel\n\n"
@@ -66,7 +66,7 @@ IMPLEMENT_CALLBACK( GuiTextListCtrl, onSelect, void, (const char* cellid, const
    "@see GuiControl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiTextListCtrl, onDeleteKey, void, ( const char* id ),( id ),
+IMPLEMENT_CALLBACK( GuiTextListCtrl, onDeleteKey, void, ( S32 id ),( id ),
    "@brief Called when the delete key has been pressed.\n\n"
    "@param id Id of the selected item in the list\n"
    "@tsexample\n"
@@ -172,7 +172,7 @@ bool GuiTextListCtrl::cellSelected(Point2I cell)
 
 void GuiTextListCtrl::onCellSelected(Point2I cell)
 {
-   onSelect_callback(Con::getIntArg(mList[cell.y].id), mList[cell.y].text);
+   onSelect_callback(mList[cell.y].id, mList[cell.y].text);
    execConsoleCallback();
 }
 
@@ -497,7 +497,7 @@ bool GuiTextListCtrl::onKeyDown( const GuiEvent &event )
       break;
    case KEY_DELETE:
       if ( mSelectedCell.y >= 0 && mSelectedCell.y < mList.size() )
-      onDeleteKey_callback(Con::getIntArg( mList[mSelectedCell.y].id ) );
+      onDeleteKey_callback( mList[mSelectedCell.y].id );
       break;
    default:
    return( Parent::onKeyDown( event ) );

+ 2 - 2
Engine/source/gui/controls/guiTextListCtrl.h

@@ -67,8 +67,8 @@ class GuiTextListCtrl : public GuiArrayCtrl
    DECLARE_CATEGORY( "Gui Lists" );
    DECLARE_DESCRIPTION( "A control that displays text in tabular form." );
    
-   DECLARE_CALLBACK( void, onSelect, (const char* cellid, const char* text));
-   DECLARE_CALLBACK( void, onDeleteKey, ( const char* id ));
+   DECLARE_CALLBACK( void, onSelect, (S32 cellid, const char* text));
+   DECLARE_CALLBACK( void, onDeleteKey, ( S32 id ));
 
    static void initPersistFields();
 

+ 7 - 7
Engine/source/gui/editor/guiMenuBar.cpp

@@ -111,7 +111,7 @@ IMPLEMENT_CALLBACK( GuiMenuBar, onMouseInMenu, void, (bool isInMenu),( isInMenu
    "@see GuiTickCtrl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiMenuBar, onMenuSelect, void, ( const char* menuId, const char* menuText ),( menuId , menuText ),
+IMPLEMENT_CALLBACK( GuiMenuBar, onMenuSelect, void, ( S32 menuId, const char* menuText ),( menuId , menuText ),
    "@brief Called whenever a menu is selected.\n\n"
    "@param menuId Index id of the clicked menu\n"
    "@param menuText Text of the clicked menu\n\n"
@@ -125,7 +125,7 @@ IMPLEMENT_CALLBACK( GuiMenuBar, onMenuSelect, void, ( const char* menuId, const
    "@see GuiTickCtrl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiMenuBar, onMenuItemSelect, void, ( const char* menuId, const char* menuText, const char* menuItemId, const char* menuItemText ),
+IMPLEMENT_CALLBACK( GuiMenuBar, onMenuItemSelect, void, ( S32 menuId, const char* menuText, S32 menuItemId, const char* menuItemText ),
 												   ( menuId, menuText, menuItemId, menuItemText ),
    "@brief Called whenever an item in a menu is selected.\n\n"
    "@param menuId Index id of the menu which contains the selected menu item\n"
@@ -142,7 +142,7 @@ IMPLEMENT_CALLBACK( GuiMenuBar, onMenuItemSelect, void, ( const char* menuId, co
    "@see GuiTickCtrl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiMenuBar, onSubmenuSelect, void, ( const char* submenuId, const char* submenuText ),( submenuId, submenuText ),
+IMPLEMENT_CALLBACK( GuiMenuBar, onSubmenuSelect, void, ( S32 submenuId, const char* submenuText ),( submenuId, submenuText ),
    "@brief Called whenever a submenu is selected.\n\n"
    "@param submenuId Id of the selected submenu\n"
    "@param submenuText Text of the selected submenu\n\n"
@@ -1393,7 +1393,7 @@ void GuiMenuBar::acceleratorKeyPress(U32 index)
          if(item->acceleratorIndex == index)
          {
             // first, call the script callback for menu selection:
-            onMenuSelect_callback(Con::getIntArg(menu->id), menu->text);
+            onMenuSelect_callback(menu->id, menu->text);
 			
             if(item->visible)
                menuItemSelected(menu, item);
@@ -1575,7 +1575,7 @@ bool GuiSubmenuBackgroundCtrl::pointInControl(const Point2I& parentCoordPoint)
 void GuiMenuBar::menuItemSelected(GuiMenuBar::Menu *menu, GuiMenuBar::MenuItem *item)
 {
    if(item->enabled)
-      onMenuItemSelect_callback(Con::getIntArg(menu->id), menu->text, Con::getIntArg(item->id), item->text);
+      onMenuItemSelect_callback(menu->id, menu->text, item->id, item->text);
 }
 
 void GuiMenuBar::onSleep()
@@ -1668,7 +1668,7 @@ void GuiMenuBar::onAction()
       return;
 
    // first, call the script callback for menu selection:
-   onMenuSelect_callback(Con::getIntArg(mouseDownMenu->id), mouseDownMenu->text);
+   onMenuSelect_callback(mouseDownMenu->id, mouseDownMenu->text);
 
    MenuItem *visWalk = mouseDownMenu->firstMenuItem;
    while(visWalk)
@@ -1783,7 +1783,7 @@ void GuiMenuBar::onSubmenuAction(S32 selectionIndex, RectI bounds, Point2I cellS
       return;
 
    // first, call the script callback for menu selection:
-   onSubmenuSelect_callback(Con::getIntArg(mouseOverSubmenu->id), mouseOverSubmenu->text);
+   onSubmenuSelect_callback(mouseOverSubmenu->id, mouseOverSubmenu->text);
 
    MenuItem *visWalk = mouseOverSubmenu->submenu->firstMenuItem;
    while(visWalk)

+ 4 - 4
Engine/source/gui/editor/guiMenuBar.h

@@ -220,10 +220,10 @@ public:
    static void initPersistFields();
 
    DECLARE_CONOBJECT(GuiMenuBar);
-   DECLARE_CALLBACK( void, onMouseInMenu, (bool hasLeftMenu));
-   DECLARE_CALLBACK( void, onMenuSelect, (const char* menuId, const char* menuText));
-   DECLARE_CALLBACK( void, onMenuItemSelect, ( const char* menuId, const char* menuText, const char* menuItemId, const char* menuItemText  ));
-   DECLARE_CALLBACK( void, onSubmenuSelect, ( const char* submenuId, const char* submenuText));
+   DECLARE_CALLBACK( void, onMouseInMenu, ( bool hasLeftMenu ));
+   DECLARE_CALLBACK( void, onMenuSelect, ( S32 menuId, const char* menuText ));
+   DECLARE_CALLBACK( void, onMenuItemSelect, ( S32 menuId, const char* menuText, S32 menuItemId, const char* menuItemText  ));
+   DECLARE_CALLBACK( void, onSubmenuSelect, ( S32 submenuId, const char* submenuText ));
 };
 
 #endif

+ 2 - 0
Engine/source/gui/editor/inspector/customField.cpp

@@ -20,6 +20,8 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#include "console/simBase.h"
+#include "console/engineAPI.h"
 #include "gui/editor/inspector/customField.h"
 #include "gui/editor/guiInspector.h"
 

+ 1 - 1
Engine/source/gui/editor/inspector/field.cpp

@@ -269,7 +269,7 @@ void GuiInspectorField::setData( const char* data, bool callbacks )
          {
             char buffer[ 2048 ];
             expandEscape( buffer, newValue );
-            newValue = Con::evaluatef( "%%f = \"%s\"; return ( %s );", oldValue.c_str(), buffer );
+            newValue = (const char*)Con::evaluatef( "%%f = \"%s\"; return ( %s );", oldValue.c_str(), buffer );
          }
          else if(    type == TypeS32Vector
                   || type == TypeF32Vector

+ 2 - 1
Engine/source/lighting/common/sceneLighting.cpp

@@ -24,6 +24,7 @@
 #include "lighting/common/sceneLighting.h"
 
 #include "T3D/gameBase/gameConnection.h"
+#include "console/engineAPI.h"
 #include "console/consoleTypes.h"
 #include "scene/sceneManager.h"
 #include "lighting/common/shadowVolumeBSP.h"
@@ -605,7 +606,7 @@ void SceneLighting::completed(bool success)
    }
 
    if(gCompleteCallback && gCompleteCallback[0])
-      Con::executef(gCompleteCallback);
+      Con::executef((const char*)gCompleteCallback);
 
    dFree(gCompleteCallback);
    gCompleteCallback = NULL;

+ 1 - 0
Engine/source/platform/platformRedBook.cpp

@@ -22,6 +22,7 @@
 
 #include "core/strings/stringFunctions.h"
 #include "console/console.h"
+#include "console/simBase.h"
 #include "console/engineAPI.h"
 #include "platform/platformRedBook.h"
 

+ 1 - 0
Engine/source/platformSDL/menus/popupMenuSDL.cpp

@@ -35,6 +35,7 @@
 #include "gui/editor/guiMenuBar.h"
 
 #include "platformSDL/menus/PlatformSDLPopupMenuData.h"
+#include "console/engineAPI.h"
 
 //////////////////////////////////////////////////////////////////////////
 // Platform Menu Data

+ 1 - 0
Engine/source/platformWin32/menus/popupMenuWin32.cpp

@@ -24,6 +24,7 @@
 
 #include "platform/menus/popupMenu.h"
 #include "platformWin32/platformWin32.h"
+#include "console/engineAPI.h"
 #include "console/consoleTypes.h"
 #include "gui/core/guiCanvas.h"
 #include "windowManager/platformWindowMgr.h"

+ 2 - 0
Engine/source/sfx/sfxModifier.cpp

@@ -20,6 +20,8 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#include "console/simBase.h"
+#include "console/engineAPI.h"
 #include "sfx/sfxModifier.h"
 #include "sfx/sfxSource.h"
 

+ 1 - 0
Engine/source/sfx/sfxParameter.cpp

@@ -22,6 +22,7 @@
 
 #include "sfx/sfxParameter.h"
 #include "console/consoleTypes.h"
+#include "console/simBase.h"
 #include "console/engineAPI.h"
 #include "console/simSet.h"
 #include "math/mMathFn.h"

+ 1 - 0
Engine/source/sim/netDownload.cpp

@@ -23,6 +23,7 @@
 #include "platform/platform.h"
 #include "core/dnet.h"
 #include "console/simBase.h"
+#include "console/engineAPI.h"
 #include "sim/netConnection.h"
 #include "core/stream/bitStream.h"
 #include "core/stream/fileStream.h"

+ 6 - 0
Engine/source/util/undo.h

@@ -29,6 +29,12 @@
 #ifndef _TVECTOR_H_
 #include "core/util/tVector.h"
 #endif
+#ifndef _SIMBASE_H_
+#include "console/simBase.h"
+#endif
+#ifndef _ENGINEAPI_H_
+#include "console/engineAPI.h"
+#endif
 
 class UndoManager;
 

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio