Game Development Community

dev|Pro Game Development Curriculum

SimObject::dumpFields() and SimObject::dumpMethods()

by Orion Elenzil · 02/12/2008 (9:11 am) · 6 comments

Improvements to dump().
(note i originally submitted a much simpler version of this improvement which was just trivial; this version has some real utility)

This resource improves %obj.dump() and provides new methods %obj.dumpFields() and %obj.dumpMethods() and also a new function dumpMethods(className).

The result is that you can easily see two things:
First, the class inheritance of an object, and second, the method inheritance of an object.

warning as of 20080211, this resource can mislead you in the case where a child namespace implements a function which is also in a parent namespace: it will appear in the first namespace to implement it, and not in the children who also implement it. see discussion here.

The modifications are simple,
but familiarity with C++ and the Torque codebase is assumed.

the following is based on a TGE 1.3.5 codebase, but is probably applicable to TGE 1.X, TGB, TGEA, etc.

simBase.h
add this somewhere to the declaration of class SimObject:
public:
   void                dumpFields        ();
   void                dumpMethods       ();

simBase.cc
replace the whole ConsoleMethod(SimObject, dump, void, 2, 2, "obj.dump()") section of code w/ this:
void SimObject::dumpFields()
{
   const AbstractClassRep::FieldList &list = getFieldList();

   S32   bufSize        = 1024;
   char* expandedBuffer = new char[bufSize];

   Con::printf("Member Fields:");
   Vector<const AbstractClassRep::Field *> flist(__FILE__, __LINE__);

   for(U32 n = 0; n < list.size(); n++)
      flist.push_back(&list[n]);

   dQsort(flist.address(),flist.size(),sizeof(AbstractClassRep::Field *),compareFields);

   for(Vector<const AbstractClassRep::Field *>::iterator itr = flist.begin(); itr != flist.end(); itr++)
   {
      const AbstractClassRep::Field* f = *itr;
      if(f->type == AbstractClassRep::DepricatedFieldType ||
         f->type == AbstractClassRep::StartGroupFieldType ||
         f->type == AbstractClassRep::EndGroupFieldType     ) continue;

      for(U32 j = 0; S32(j) < f->elementCount; j++)
      {
         const char *val = (f->getDataFn)(this, Con::getData(f->type, (void *) (((const char *)this) + f->offset), j, f->table, f->flag));
         if(!val || !*val)
            continue;

         S32 worstCaseSize = dStrlen(val) * 4 + dStrlen(f->pFieldname) + 32;   // 32 is arbitrary, just for spaces and quotes and stuff.
         if (worstCaseSize > bufSize)
         {
            delete [] expandedBuffer;
            bufSize        = worstCaseSize;
            expandedBuffer = new char[bufSize];
         }

         if(f->elementCount == 1)
            dSprintf(expandedBuffer, bufSize, "  %s = \"", f->pFieldname);
         else
            dSprintf(expandedBuffer, bufSize, "  %s[%d] = \"", f->pFieldname, j);
         S32 bufUsed = dStrlen(expandedBuffer);
         expandEscape(expandedBuffer + bufUsed, val, sizeof(expandedBuffer) - bufUsed);
         Con::printf("%s\"", expandedBuffer);
      }
   }

   Con::printf("Tagged Fields:");
   if(getFieldDictionary())
      getFieldDictionary()->printFields(this);

   delete [] expandedBuffer;
}

void SimObject::dumpMethods()
{
   getNamespace()->dumpMethods();
}

ConsoleMethod(SimObject, dump, void, 2, 2, "obj.dump()")
{
   object->dumpFields ();
   object->dumpMethods();
}

ConsoleMethod(SimObject, dumpFields, void, 2, 2, "obj.dumpFields()")
{
   object->dumpFields ();
}

ConsoleMethod(SimObject, dumpMethods, void, 2, 2, "obj.dumpMethods()")
{
   object->dumpMethods();
}


consoleInternal.h
right after the line static void dump();
add:
void dumpMethods();

consoleInternal.cc
right after the method void Namespace::dump()
add:
void Namespace::dumpMethods()
{
   if (this == NULL)    // i <3 madness!
      return;

   mParent->dumpMethods();

   Vector<Namespace::Entry *> vec(__FILE__, __LINE__);
   getEntryList(&vec);

   bool isNative;
   S32  count = 0;
   for (Vector<Namespace::Entry *>::iterator j = vec.begin(); j != vec.end(); j++)
   {
      if (mParent == NULL)
         isNative = true;
      else
         isNative = (mParent->lookup((*j)->mFunctionName) == NULL);

      count += isNative ? 1 : 0;
   }

   const char* formatString;
   if (mPackage != NULL)
      formatString = "%3d Methods from %s in package %s:";
   else
      formatString = "%3d Methods from %s:";
   Con::printf(formatString, count, mName, mPackage);

   for (Vector<Namespace::Entry *>::iterator j = vec.begin(); j != vec.end(); j++)
   {
      if (mParent == NULL)
         isNative = true;
      else
         isNative = (mParent->lookup((*j)->mFunctionName) == NULL);

      if (isNative)
      {
#ifdef    TORQUE_DEBUG
         formatString = "  %-40s() %3s - %s";
#else  // TORQUE_DEBUG
         formatString = "  %-40s() %3s";
#endif // TORQUE_DEBUG
         Con::printf(formatString, (*j)->mFunctionName, (*j)->mType == Entry::ScriptFunctionType ? "scr" : "eng", (*j)->mUsage ? (*j)->mUsage : "");
      }
   }
}

at the bottom of the file (just after ConsoleFunctionGroupEnd( Packages );),
add:
ConsoleFunctionGroupBegin( Namespaces, "Functions relating to Namespaces.");

ConsoleFunction(dumpMethods, void, 2, 2, "dumpMethods(nameSpace)")
{
   Namespace* ns = Namespace::find(StringTable->insert(argv[1]));
   if (ns == NULL)
   {
      Con::errorf("dumpMethods(\"%s\") - unknown namespace.", argv[1]);
      return;
   }

   ns->dumpMethods();
}

ConsoleFunctionGroupEnd( Namespaces );


example output:
==>dumpMethods(aiplayer);
 33 Methods from SimObject:
  addToAVPlayerNameList                   () - 
  allowInstanceMethods                    () - obj.allowInstanceMethods()
  etc..
 10 Methods from NetObject:
  clearScopeToClient                      () - clearScopeToClient(%client)Undo the effects of a scopeToClient() call.
  getGhostID                              () - 
  etc..
 33 Methods from SceneObject:
  getDCObject                             () - 
  getForwardVector                        () - Returns a vector indicating the direction this object is facing.
  etc..
  2 Methods from GameBase:
  getDataBlock                            () - ()Return the datablock this GameBase is using.
  setDataBlock                            () - (DataBlock db)Assign this GameBase to use the specified datablock.
  etc..
 89 Methods from ShapeBase:
  applyDamage                             () - (float amt)
  applyImpulse                            () - (Point3F Pos, VectorF vel)
  etc..
165 Methods from Player:
  addBuddy                                () - (id buddy)
  addIgnore                               () - (id ignore)
  etc..
 10 Methods from AIPlayer:
  clearAim                                () - ()Stop aiming at anything.
  getAimLocation                          () - ()Returns the point the AI is aiming at.
  etc..

note this can also be used to dump global functions which belong to a namespace.
eg, if:
function foo::bar()
{
   // blah blah
}
then:
==>dumpmethods("foo");
Methods from foo:
  bar                                     ()

orion elenzil 2008

#1
02/04/2008 (4:25 pm)
lol :) I was just about posting the same :) I've added also: .dumpFieldsMember and .dumpFieldsTagged
#2
02/04/2008 (4:26 pm)
heheh
#3
02/08/2008 (12:39 pm)
hey bank, if you're watching this, i just made it a bit more useful.
#4
02/08/2008 (12:47 pm)
wow! this is more than a "bit more" useful :) ty for sharing!
#5
11/17/2008 (1:04 pm)
added an improvement,
where it now additionally shows whether each method is a ScriptMethod or an EngineMethod.
#6
02/03/2009 (3:00 pm)
a simple extension of this also yields SimObject::dumpNamespaces():
[2/3/2009 14:58:34][Inf][General] ==>bixxy.dumpNamespaces();
[2/3/2009 14:58:34][Inf][General] 10294-AIPlayer-Bixxy-s-Bixxy
[2/3/2009 14:58:34][Inf][General]  60 Methods from SimObject
[2/3/2009 14:58:34][Inf][General]  10 Methods from NetObject
[2/3/2009 14:58:34][Inf][General]  39 Methods from SceneObject
[2/3/2009 14:58:34][Inf][General]   2 Methods from GameBase
[2/3/2009 14:58:34][Inf][General] 112 Methods from ShapeBase
[2/3/2009 14:58:34][Inf][General] 251 Methods from Player
[2/3/2009 14:58:34][Inf][General]  48 Methods from AIPlayer