Game Development Community

dev|Pro Game Development Curriculum

Easy way of calling methods on SimObject

by Fyodor -bank- Osokin · 05/06/2009 (1:06 pm) · 9 comments

After:
ConsoleMethod(SimObject, isMethod, bool, 3, 3, "obj.isMethod(string method name)")
{
   return object->isMethod( argv[2] );
}
Add:
ConsoleMethod(SimObject, call, const char *, 3, 0, "obj.call(funcName [,args ...])")
{
   argc -= 2; argv += 2;
   if(!object->isMethod(argv[0]))
   {
      Con::warnf(ConsoleLogEntry::Script, "%s: Unknown command.", argv[0]);
      Con::warnf(ConsoleLogEntry::General, "Object: %s(%d) [%s]",
            object->getName() ? object->getName() : "",
            object->getId(), object->getClassName() );
      return "";
   }
	const char *largv[128];
	for(S32 i = 0; i < argc; i++) largv[i+1] = argv[i];
	largv[0] = largv[1];
	argc++;
   return Con::execute(object, argc, argv);
}
From now you can call dynamic methods on objects without using "eval" to get a result:

Previously you may have used something like:
...
   if(%obj.isMethod(%myFuncName))
   {
      %ev = "%res = " @ %obj @ "." @ %myFuncName @"("@ %param1 @",\""@ %param2 @"\");";
      eval(%ev);
      echo(%res);
   }
And now:
...
   if(%obj.isMethod(%myFuncName))
   {
      %res = %obj.call(%myFuncName, %param1, %param2);
      echo(%res);
   }
I'm using this a lot, as I have lots of scripts where I need to call functions described as variables.

#1
05/06/2009 (1:48 pm)
handy.
if you're using it a lot, what do you think of writing a variant like "callNoWarn" which fails silently if the method doesn't exist ? that way you don't have to check for existence in torquescript.
#2
05/06/2009 (1:57 pm)
Easy workaround :)
if(!object->isMethod(argv[0]))
   {
#ifndef TORQUE_SHIPPING
      Con::warnf(ConsoleLogEntry::Script, "%s: Unknown command.", argv[0]);
      Con::warnf(ConsoleLogEntry::General, "Object: %s(%d) [%s]",
            object->getName() ? object->getName() : "",
            object->getId(), object->getClassName() );
#endif
      return "";
   }
So, the shipping build will not spam the console. Actually there are many ways to achieve that.
Actually, I would prefer adding something like this:
if(!object->isMethod(argv[0]))
   {
      if(mPrintWarnings)
      {
         Con::warnf(ConsoleLogEntry::Script, "%s: Unknown command.", argv[0]);
         Con::warnf(ConsoleLogEntry::General, "Object: %s(%d) [%s]",
               object->getName() ? object->getName() : "",
               object->getId(), object->getClassName() );
      }
      return "";
   }
Where mPrintWarnings can be linked as bool to SimObject persist.field, or even to global variable via Con::setIntVariable()
#3
05/06/2009 (2:02 pm)
i guess i assumed it was sometimes valid for the method not to exist,
since in that case your torquescript is failing silently, i think.

if it's valid for the method to not exist, then you don't want to print warnings in that case (even in a development build). if it's not valid for it not to exist, then why check in torquescript ?
#4
05/06/2009 (2:03 pm)
Orion, before "releasing" scripts to "live" (in my project), I always check if I have something "weird" in the console :)
And in my codebase I have it with getNamespaceList (if I'm not mistaken it was from your resource) together with getScopeName and some other additions.

Edit to reply to your post:
I never check it in scripts like in my example (isMethod), its just example :)
I call with that way only functions I know are existing.
#5
05/06/2009 (2:04 pm)
yay getNamespaceList !
#6
05/06/2009 (2:06 pm)
grrrr.. reminder to myself: always check for comments before posting your own reply lol :)
#7
05/06/2009 (4:32 pm)
But I liked the sometimes tricksome and cumbersome syntax of calling eval ;) Cool resource!
#8
05/07/2009 (7:05 am)
Huh? TGEA 1.7.1, SimObject.cpp, line 1116:

ConsoleMethod( SimObject, call, const char*, 2, 0, "( %args ) - Dynamically call a method on an object." )
{
   argv[1] = argv[2];
   return Con::execute( object, argc - 1, argv + 1 );
}

Which Torque version you're using? Call() has been there for a while, and applying the resource causes a compilation error because the method already exists. I believe it was added alongside isMethod() and others, which didn't existed in the past.
#9
05/07/2009 (7:55 am)
TGE152, hehe! :) And yeah its more simple than my.