Game Development Community

No error on "%someObject.undefinedField

by Orion Elenzil · in Torque Game Engine · 10/14/2007 (1:38 pm) · 5 replies

Howdy!

when i evaluate "%someUndefinedVariable", torquescript nicely throws a warning.
however evaluating "%someObject.undefinedField" yields no such warning, it just quietly resolves as "".

anyone know where to hook in a warning along those lines ?

will this cause problems with fields of objects who's default values are, in fact, "" and have been saved to files ?

#1
10/14/2007 (2:05 pm)
This happens because of (probably) two things:

--you've previously set the pref to warn on variable use without initialization sometime in your project's history.

--this pref isn't checked for fields, so it defaults to the normal behavior of simply adding the field and initializing it to "" on first use.

I can't see any "problems", other than not being warned if you make a typo while scripting a field, but it wouldn't be a bad idea to expand the preference I mentioned (I can never remember what it is unfortunately, sorry ;( ) but standard "find in files" on the warning you do get should help track it down.

I'd take a look at SimObject::getDataField() for a starting point trying to find to extend the pref's utilization to dynamic fields.
#2
10/14/2007 (2:16 pm)
Perfecto!
thanks stephen !

will add.
#3
10/14/2007 (3:05 pm)
Well, it looks like it's too late for us - we've relied on the quiet conversion from undefined->"" for too long,
and the list of warns this produces is Huge.

thanks anyhow!

ooo
#4
10/15/2007 (10:54 am)
Some might find this useful:

ConsoleMethod(SimObject, hasFieldValue, bool, 3, 3, "obj.hasFieldValue(fieldName);")
{
   S32 fieldNameLen = dStrlen(argv[2]);

   char* buf = new char[fieldNameLen + 1];

   const char* p = argv[2];
   char*       q = buf;

   // collapse simple subscript notation:
   for (p = argv[2]; *p != '[[60c1f9b82f3ca]]'; p++)
   {
      switch(*p)
      {
      default:
         *q++ = *p;
         break;
      case ',':
         *q++ = '_';
         break;
      case ' ':
      case '\t':
      case '\n':
      case '[':
      case ']':
         break;
      }
   }
   *q         = '[[60c1f9b82f3ca]]';

   const char *fieldName = StringTable->insert(buf);

   delete [] buf;

   return object->hasDataField( fieldName, NULL );
}

there's gotta be a more formal way to deal with subscripts,
but this gets the basics going.

ie, works for %foo.hasFieldValue("bar[1, 3,4]") but wouldn't work for %foo.hasFieldValue("bar[someFunction()]").
#5
10/15/2007 (10:55 am)
Oh, and of course, the core of it:
bool SimObject::hasDataField(StringTableEntry slotName, const char *arrayIndex)
{
   if(mFlags.test(ModStaticFields))
   {
      S32 array1 = arrayIndex ? dAtoi(arrayIndex) : -1;
      const AbstractClassRep::Field *fld = findField(slotName);
      if(fld)
      {
         if(array1 == -1 && fld->elementCount == 1)
            return true;
         if(array1 >= 0 && array1 < fld->elementCount)
            return true;
         return false;
      }
   }
   if(mFlags.test(ModDynamicFields))
   {
      if(!mFieldDictionary)
         return false;
         
      if(!arrayIndex) {
         if (const char* val = mFieldDictionary->getFieldValue(slotName))
            return true;
      }
      else
      {
         static char buf[256];
         dStrcpy(buf, slotName);
         dStrcat(buf, arrayIndex);
         if (const char* val = mFieldDictionary->getFieldValue(StringTable->insert(buf)))
            return true;
      }
   }
   return false;
}