Exemplo n.º 1
0
static void dumpVariable(  Stream& stream,
                           Dictionary::Entry* entry,
                           const char* inClass = NULL )
{
   // Skip variables defined in script.
   
   if( entry->type < 0 )
      return;
         
   // Skip internals... don't export them.
   if (  entry->mUsage &&
         ( dStrstr( entry->mUsage, "@hide" ) || dStrstr( entry->mUsage, "@internal" ) ) )
      return;

   // Split up qualified name.

   Vector< String > nameComponents;
   String( entry->name ).split( "::", nameComponents );
   if( !nameComponents.size() ) // Safety check.
      return;
      
   // Match filter.
   
   if( inClass )
   {
      // Make sure first qualifier in name components is a
      // namespace qualifier matching the given class name.
      
      if( nameComponents.size() <= 1 || dStricmp( nameComponents.first().c_str() + 1, inClass ) != 0 ) // Skip '$'.
         return;
   }
   else
   {
      // Make sure, this is *not* in a class namespace.
      
      if( nameComponents.size() > 1 && Con::lookupNamespace( nameComponents.first().c_str() + 1 )->mClassRep )
         return;
   }
            
   // Skip variables for which we can't decipher their type.

   ConsoleBaseType* type = ConsoleBaseType::getType( entry->type );
   if( !type )
   {
      Con::errorf( "Can't find type for variable '%s'", entry->name );
      return;
   }

   // Write doc comment.
   
   stream.writeText( "/*!\r\n" );
   
   if( !inClass )
   {
      stream.writeText( "@var " );
      stream.writeText( type->getTypeClassName() );
      stream.writeText( " " );
      stream.writeText( entry->name );
      stream.writeText( ";\r\n" );
   }
   
   dumpDoc( stream, entry->mUsage );
   
   stream.writeText( "*/\r\n" );
   
   // Write definition.
   
   const U32 numNameComponents = nameComponents.size();
   if( !inClass && numNameComponents > 1 )
      for( U32 i = 0; i < ( numNameComponents - 1 ); ++ i )
      {
         stream.writeText( "namespace " );
         stream.writeText( nameComponents[ i ] );
         stream.writeText( " { " );
      }
   
   if( inClass )
      stream.writeText( "static " );
      
   if( entry->mIsConstant )
      stream.writeText( "const " );
      
   stream.writeText( type->getTypeClassName() );
   stream.writeText( " " );
   stream.writeText( nameComponents.last() );
   stream.writeText( ";" );
   
   if( !inClass && numNameComponents > 1 )
      for( U32 i = 0; i < ( numNameComponents - 1 ); ++ i )
         stream.writeText( " } " );
         
   stream.writeText( "\r\n" );
}
Exemplo n.º 2
0
GuiInspectorField* GuiInspectorGroup::constructField( S32 fieldType )
{
   // See if we can construct a field of this type
   ConsoleBaseType *cbt = ConsoleBaseType::getType(fieldType);
   if( !cbt )
      return NULL;

   // Alright, is it a datablock?
   if(cbt->isDatablock())
   {
      // Default to GameBaseData
      StringTableEntry typeClassName = cbt->getTypeClassName();

      if (mTarget && !dStricmp(typeClassName, "GameBaseData"))
      {
         // Try and setup the classname based on the object type
         char className[256];
         dSprintf(className,256,"%sData",mTarget->getClassName());
         // Walk the ACR list and find a matching class if any.
         AbstractClassRep *walk = AbstractClassRep::getClassList();
         while(walk)
         {
            if(!dStricmp(walk->getClassName(), className))
               break;

            walk = walk->getNextClass();
         }

         // We found a valid class
         if (walk)
            typeClassName = walk->getClassName();

      }


      GuiInspectorDatablockField *dbFieldClass = new GuiInspectorDatablockField( typeClassName );
      if( dbFieldClass != NULL )
      {
         // return our new datablock field with correct datablock type enumeration info
         return dbFieldClass;
      }
   }

   // Nope, not a datablock. So maybe it has a valid inspector field override we can use?
   if(!cbt->getInspectorFieldType())
      // Nothing, so bail.
      return NULL;

   // Otherwise try to make it!
   ConsoleObject *co = create(cbt->getInspectorFieldType());
   GuiInspectorField *gif = dynamic_cast<GuiInspectorField*>(co);

   if(!gif)
   {
      // Wasn't appropriate type, bail.
      delete co;
      return NULL;
   }

   return gif;
}
Exemplo n.º 3
0
bool GuiInspectorGroup::inspectGroup()
{
   // We can't inspect a group without a target!
   if( !mTarget )
      return false;

   // to prevent crazy resizing, we'll just freeze our stack for a sec..
   mStack->freeze(true);

   bool bNoGroup = false;

   // Un-grouped fields are all sorted into the 'general' group
   if ( dStricmp( mCaption, "General" ) == 0 )
      bNoGroup = true;

   AbstractClassRep::FieldList &fieldList = mTarget->getModifiableFieldList();
   AbstractClassRep::FieldList::iterator itr;

   bool bGrabItems = false;
   bool bNewItems = false;
   bool bMakingArray = false;
   GuiStackControl *pArrayStack = NULL;
   GuiRolloutCtrl *pArrayRollout = NULL;

   // Just delete all fields and recreate them (like the dynamicGroup)
   // because that makes creating controls for array fields a lot easier
   clearFields();

   for ( itr = fieldList.begin(); itr != fieldList.end(); itr++ )
   {
      if( itr->type == AbstractClassRep::StartGroupFieldType )
      {
         // If we're dealing with general fields, always set grabItems to true (to skip them)
         if( bNoGroup == true )
            bGrabItems = true;
         else if( itr->pGroupname != NULL && dStricmp( itr->pGroupname, mCaption ) == 0 )
            bGrabItems = true;
         continue;
      }
      else if ( itr->type == AbstractClassRep::EndGroupFieldType )
      {
         // If we're dealing with general fields, always set grabItems to false (to grab them)
         if( bNoGroup == true )
            bGrabItems = false;
         else if( itr->pGroupname != NULL && dStricmp( itr->pGroupname, mCaption ) == 0 )
            bGrabItems = false;
         continue;
      }

      if( ( bGrabItems == true || ( bNoGroup == true && bGrabItems == false ) ) && itr->type != AbstractClassRep::DeprecatedFieldType )
      {
         if( bNoGroup == true && bGrabItems == true )
            continue; 

          if ( itr->type == AbstractClassRep::StartArrayFieldType )
          {
             // Starting an array...
             // Create a rollout for the Array, give it the array's name.
             GuiRolloutCtrl *arrayRollout = new GuiRolloutCtrl();            
             GuiControlProfile *arrayRolloutProfile = dynamic_cast<GuiControlProfile*>( Sim::findObject( "GuiInspectorRolloutProfile0" ) );
 
             arrayRollout->setControlProfile(arrayRolloutProfile);
             //arrayRollout->mCaption = StringTable->insert( String::ToString( "%s (%i)", itr->pGroupname, itr->elementCount ) );
             arrayRollout->mCaption = StringTable->insert( itr->pGroupname );
             arrayRollout->mMargin.set( 14, 0, 0, 0 );
             arrayRollout->registerObject();
 
             GuiStackControl *arrayStack = new GuiStackControl();
             arrayStack->registerObject();
             arrayStack->freeze(true);
             arrayRollout->addObject(arrayStack);
 
             // Allocate a rollout for each element-count in the array
             // Give it the element count name.
             for ( U32 i = 0; i < itr->elementCount; i++ )
             {
                GuiRolloutCtrl *elementRollout = new GuiRolloutCtrl();            
                GuiControlProfile *elementRolloutProfile = dynamic_cast<GuiControlProfile*>( Sim::findObject( "GuiInspectorRolloutProfile0" ) );
 
                char buf[256];
                dSprintf( buf, 256, "  [%i]", i ); 
 
                elementRollout->setControlProfile(elementRolloutProfile);
                elementRollout->mCaption = StringTable->insert(buf);
                elementRollout->mMargin.set( 14, 0, 0, 0 );
                elementRollout->registerObject();
 
                GuiStackControl *elementStack = new GuiStackControl();
                elementStack->registerObject();            
                elementRollout->addObject(elementStack);
                elementRollout->instantCollapse();
 
                arrayStack->addObject( elementRollout );
             }
 
             pArrayRollout = arrayRollout;
             pArrayStack = arrayStack;
             arrayStack->freeze(false);
             pArrayRollout->instantCollapse();
             mStack->addObject(arrayRollout);
 
             bMakingArray = true;
             continue;
          }      
          else if ( itr->type == AbstractClassRep::EndArrayFieldType )
          {
             bMakingArray = false;
             continue;
          }
 
          if ( bMakingArray )
          {
             // Add a GuiInspectorField for this field, 
             // for every element in the array...
             for ( U32 i = 0; i < pArrayStack->size(); i++ )
             {
                FrameTemp<char> intToStr( 64 );
                dSprintf( intToStr, 64, "%d", i );
 
                // The array stack should have a rollout for each element
                // as children...
                GuiRolloutCtrl *pRollout = dynamic_cast<GuiRolloutCtrl*>(pArrayStack->at(i));
                // And the each of those rollouts should have a stack for 
                // fields...
                GuiStackControl *pStack = dynamic_cast<GuiStackControl*>(pRollout->at(0));
 
                // And we add a new GuiInspectorField to each of those stacks...            
                GuiInspectorField *field = constructField( itr->type );
                if ( field == NULL )                
                   field = new GuiInspectorField();
                                
                field->init( mParent, this, mTarget );
                StringTableEntry caption = StringTable->insert( itr->pFieldname );
                field->setInspectorField( itr, caption, intToStr );
 
                if( field->registerObject() )
                {
                   mChildren.push_back( field );
                   pStack->addObject( field );
                }
                else
                   delete field;
             }
 
             continue;
          }

         // This is weird, but it should work for now. - JDD
         // We are going to check to see if this item is an array
         // if so, we're going to construct a field for each array element
         if( itr->elementCount > 1 )
         {
            // Make a rollout control for this array
            //
            GuiRolloutCtrl *rollout = new GuiRolloutCtrl();  
            rollout->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorRolloutProfile0" );            
            rollout->mCaption = StringTable->insert(String::ToString( "%s (%i)", itr->pFieldname, itr->elementCount));
            rollout->mMargin.set( 14, 0, 0, 0 );
            rollout->registerObject();
            mArrayCtrls.push_back(rollout);
            
            // Put a stack control within the rollout
            //
            GuiStackControl *stack = new GuiStackControl();
            stack->setDataField( StringTable->insert("profile"), NULL, "GuiInspectorStackProfile" );
            stack->registerObject();
            stack->freeze(true);
            rollout->addObject(stack);

            mStack->addObject(rollout);

            // Create each field and add it to the stack.
            //
            for (S32 nI = 0; nI < itr->elementCount; nI++)
            {
               FrameTemp<char> intToStr( 64 );
               dSprintf( intToStr, 64, "%d", nI );

               // Construct proper ValueName[nI] format which is "ValueName0" for index 0, etc.
               
               String fieldName = String::ToString( "%s%d", itr->pFieldname, nI );

               // If the field already exists, just update it
               GuiInspectorField *field = findField( fieldName );
               if( field != NULL )
               {
                  field->updateValue();
                  continue;
               }

               bNewItems = true;

               field = constructField( itr->type );
               if ( field == NULL )               
                  field = new GuiInspectorField();
               
               field->init( mParent, this, mTarget );               
               StringTableEntry caption = StringTable->insert( String::ToString("   [%i]",nI) );
               field->setInspectorField( itr, caption, intToStr );

               if ( field->registerObject() )
               {
                  mChildren.push_back( field );
                  stack->addObject( field );
               }
               else
                  delete field;
            }

            stack->freeze(false);
            stack->updatePanes();
            rollout->instantCollapse();
         }
         else
         {
            // If the field already exists, just update it
            GuiInspectorField *field = findField( itr->pFieldname );
            if ( field != NULL )
            {
               field->updateValue();
               continue;
            }

            bNewItems = true;

            field = constructField( itr->type );
            if ( field == NULL )
               field = new GuiInspectorField();
            
            field->init( mParent, this, mTarget );            
            field->setInspectorField( itr );            

            if ( field->registerObject() )
            {
               mChildren.push_back( field );
               mStack->addObject( field );
            }
            else
               delete field;
         }       
      }
   }
   mStack->freeze(false);
   mStack->updatePanes();

   // If we've no new items, there's no need to resize anything!
   if( bNewItems == false && !mChildren.empty() )
      return true;

   sizeToContents();

   setUpdate();

   return true;
}
Exemplo n.º 4
0
bool StandardMainLoop::handleCommandLine( S32 argc, const char **argv )
{
   // Allow the window manager to process command line inputs; this is
   // done to let web plugin functionality happen in a fairly transparent way.
   PlatformWindowManager::get()->processCmdLineArgs(argc, argv);

   Process::handleCommandLine( argc, argv );

   // Set up the command line args for the console scripts...
   Con::setIntVariable("Game::argc", argc);
   U32 i;
   for (i = 0; i < argc; i++)
      Con::setVariable(avar("Game::argv%d", i), argv[i]);

   Platform::FS::InstallFileSystems(); // install all drives for now until we have everything using the volume stuff
   Platform::FS::MountDefaults();

   // Set our working directory.
   Torque::FS::SetCwd( "game:/" );

   // Set our working directory.
   Platform::setCurrentDirectory( Platform::getMainDotCsDir() );

#ifdef TORQUE_PLAYER
   if(argc > 2 && dStricmp(argv[1], "-project") == 0)
   {
      char playerPath[1024];
      Platform::makeFullPathName(argv[2], playerPath, sizeof(playerPath));
      Platform::setCurrentDirectory(playerPath);

      argv += 2;
      argc -= 2;

      // Re-locate the game:/ asset mount.

      Torque::FS::Unmount( "game" );
      Torque::FS::Mount( "game", Platform::FS::createNativeFS( playerPath ) );
   }
#endif

   // Executes an entry script file. This is "main.cs"
   // by default, but any file name (with no whitespace
   // in it) may be run if it is specified as the first
   // command-line parameter. The script used, default
   // or otherwise, is not compiled and is loaded here
   // directly because the resource system restricts
   // access to the "root" directory.

#ifdef TORQUE_ENABLE_VFS
   Zip::ZipArchive *vfs = openEmbeddedVFSArchive();
   bool useVFS = vfs != NULL;
#endif

   Stream *mainCsStream = NULL;

   // The working filestream.
   FileStream str; 

   const char *defaultScriptName = "main.cs";
   bool useDefaultScript = true;

   // Check if any command-line parameters were passed (the first is just the app name).
   if (argc > 1)
   {
      // If so, check if the first parameter is a file to open.
      if ( (dStrcmp(argv[1], "") != 0 ) && (str.open(argv[1], Torque::FS::File::Read)) )
      {
         // If it opens, we assume it is the script to run.
         useDefaultScript = false;
#ifdef TORQUE_ENABLE_VFS
         useVFS = false;
#endif
         mainCsStream = &str;
      }
   }

   if (useDefaultScript)
   {
      bool success = false;

#ifdef TORQUE_ENABLE_VFS
      if(useVFS)
         success = (mainCsStream = vfs->openFile(defaultScriptName, Zip::ZipArchive::Read)) != NULL;
      else
#endif
         success = str.open(defaultScriptName, Torque::FS::File::Read);

#if defined( TORQUE_DEBUG ) && defined (TORQUE_TOOLS) && !defined( _XBOX )
      if (!success)
      {
         OpenFileDialog ofd;
         FileDialogData &fdd = ofd.getData();
         fdd.mFilters = StringTable->insert("Main Entry Script (main.cs)|main.cs|");
         fdd.mTitle   = StringTable->insert("Locate Game Entry Script");

         // Get the user's selection
         if( !ofd.Execute() )
            return false;

         // Process and update CWD so we can run the selected main.cs
         S32 pathLen = dStrlen( fdd.mFile );
         FrameTemp<char> szPathCopy( pathLen + 1);

         dStrcpy( szPathCopy, fdd.mFile );
         //forwardslash( szPathCopy );

         const char *path = dStrrchr(szPathCopy, '/');
         if(path)
         {
            U32 len = path - (const char*)szPathCopy;
            szPathCopy[len+1] = 0;

            Platform::setCurrentDirectory(szPathCopy);

            // Re-locate the game:/ asset mount.

            Torque::FS::Unmount( "game" );
            Torque::FS::Mount( "game", Platform::FS::createNativeFS( ( const char* ) szPathCopy ) );

            success = str.open(fdd.mFile, Torque::FS::File::Read);
            if(success)
               defaultScriptName = fdd.mFile;
         }
      }
#endif
      if( !success )
      {
         char msg[1024];
         dSprintf(msg, sizeof(msg), "Failed to open \"%s\".", defaultScriptName);
         Platform::AlertOK("Error", msg);
#ifdef TORQUE_ENABLE_VFS
         closeEmbeddedVFSArchive();
#endif

         return false;
      }

#ifdef TORQUE_ENABLE_VFS
      if(! useVFS)
#endif
         mainCsStream = &str;
   }

   // This should rarely happen, but lets deal with
   // it gracefully if it does.
   if ( mainCsStream == NULL )
      return false;

   U32 size = mainCsStream->getStreamSize();
   char *script = new char[size + 1];
   mainCsStream->read(size, script);

#ifdef TORQUE_ENABLE_VFS
   if(useVFS)
      vfs->closeFile(mainCsStream);
   else
#endif
      str.close();

   script[size] = 0;

   char buffer[1024], *ptr;
   Platform::makeFullPathName(useDefaultScript ? defaultScriptName : argv[1], buffer, sizeof(buffer), Platform::getCurrentDirectory());
   ptr = dStrrchr(buffer, '/');
   if(ptr != NULL)
      *ptr = 0;
   Platform::setMainDotCsDir(buffer);
   Platform::setCurrentDirectory(buffer);

   Con::evaluate(script, false, useDefaultScript ? defaultScriptName : argv[1]); 
   delete[] script;

#ifdef TORQUE_ENABLE_VFS
   closeEmbeddedVFSArchive();
#endif

   return true;
}
Exemplo n.º 5
0
void GuiTextEditCtrl::onStaticModified(const char* slotName, const char* newValue)
{
   if(!dStricmp(slotName, "text"))
      setText(mText);
}
Exemplo n.º 6
0
/// Check if one string ends with another
bool dStrEndsWith(const char* str1, const char* str2)
{
   const char *p = str1 + dStrlen(str1) - dStrlen(str2);
   return ((p >= str1) && !dStricmp(p, str2));
}
Exemplo n.º 7
0
bool dAtob(const char *str)
{
   return !dStricmp(str, "true") || !dStricmp(str, "1") || (0!=dAtoi(str));
}   
bool Net::stringToAddress(const char *addressString, NetAddress  *address)
{
   if(!dStrnicmp(addressString, "ipx:", 4))
      // ipx support deprecated
      return false;

   if(!dStrnicmp(addressString, "ip:", 3))
      addressString += 3;  // eat off the ip:

   sockaddr_in ipAddr;
   char remoteAddr[256];
   if(strlen(addressString) > 255)
      return false;

   dStrcpy(remoteAddr, addressString);

   char *portString = dStrchr(remoteAddr, ':');
   if(portString)
      *portString++ = '\0';

   if(!dStricmp(remoteAddr, "broadcast"))
      ipAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
   else
   {
      ipAddr.sin_addr.s_addr = inet_addr(remoteAddr);

      if (ipAddr.sin_addr.s_addr == INADDR_NONE) // error
      {
         // On the Xbox, 'gethostbyname' does not exist so...
#ifndef TORQUE_OS_XENON
         struct hostent *hp;
         if((hp = gethostbyname(remoteAddr)) == 0)
            return false;
         else
            memcpy(&ipAddr.sin_addr.s_addr, hp->h_addr,  sizeof(in_addr));
#else
         // On the Xbox do XNetDnsLookup
         XNDNS *pxndns = NULL;
         HANDLE hEvent = CreateEvent(NULL, false, false, NULL);
         XNetDnsLookup(remoteAddr, hEvent, &pxndns);

         // Wait for event (passing NULL as a handle to XNetDnsLookup will NOT
         // cause it to behave synchronously, so do not remove the handle/wait
         while(pxndns->iStatus == WSAEINPROGRESS) 
            WaitForSingleObject(hEvent, INFINITE);

         bool foundAddr = pxndns->iStatus == 0 && pxndns->cina > 0;
         if(foundAddr)
         {
            // Lets just grab the first address returned, for now
            memcpy(&ipAddr.sin_addr, pxndns->aina,  sizeof(IN_ADDR));
         }

         XNetDnsRelease(pxndns);
         CloseHandle(hEvent);

         // If we didn't successfully resolve the DNS lookup, bail after the
         // handles are released
         if(!foundAddr)
            return false;
#endif
      }
   }
   if(portString)
      ipAddr.sin_port = htons(dAtoi(portString));
   else
      ipAddr.sin_port = htons(defaultPort);
   ipAddr.sin_family = AF_INET;
   IPSocketToNetAddress(&ipAddr, address);
   return true;
}
NetSocket Net::openConnectTo(const char *addressString)
{
   if(!dStrnicmp(addressString, "ipx:", 4))
      // ipx support deprecated
      return InvalidSocket;
   if(!dStrnicmp(addressString, "ip:", 3))
      addressString += 3;  // eat off the ip:
   char remoteAddr[256];
   dStrcpy(remoteAddr, addressString);

   char *portString = dStrchr(remoteAddr, ':');

   U16 port;
   if(portString)
   {
      *portString++ = 0;
      port = htons(dAtoi(portString));
   }
   else
      port = htons(defaultPort);

   if(!dStricmp(remoteAddr, "broadcast"))
      return InvalidSocket;

   if(Journal::IsPlaying())
   {
      U32 ret;
      Journal::Read(&ret);
      return NetSocket(ret);
   }
   NetSocket sock = openSocket();
   setBlocking(sock, false);

   sockaddr_in ipAddr;
   dMemset(&ipAddr, 0, sizeof(ipAddr));
   ipAddr.sin_addr.s_addr = inet_addr(remoteAddr);

   if(ipAddr.sin_addr.s_addr != INADDR_NONE)
   {
      ipAddr.sin_port = port;
      ipAddr.sin_family = AF_INET;
      if(::connect(sock, (struct sockaddr *)&ipAddr, sizeof(ipAddr)) ==  -1)
      {
         S32 err = getLastError();
         if(err != Net::WouldBlock)
         {
            Con::errorf("Error connecting %s: %s",
               addressString, strerror(err));
            ::closesocket(sock);
            sock = InvalidSocket;
         }
      }
      if(sock != InvalidSocket) 
      {
         // add this socket to our list of polled sockets
         addPolledSocket(sock, ConnectionPending);
      }
   }
   else
   {
      // need to do an asynchronous name lookup.  first, add the socket
      // to the polled list
      addPolledSocket(sock, NameLookupRequired, remoteAddr, port);
      // queue the lookup
      gNetAsync.queueLookup(remoteAddr, sock);
   }
   if(Journal::IsRecording())
      Journal::Write(U32(sock));
   return sock;
}
Exemplo n.º 10
0
//-----------------------------------------------------------------------------
// GuiInspectorMountingGroup - inspectGroup override
//-----------------------------------------------------------------------------
bool GuiInspectorMountingGroup::inspectGroup()
{
   // We can't inspect a group without a target!
   if( !mParent->getNumInspectObjects() )
      return false;

   // to prevent crazy resizing, we'll just freeze our stack for a sec..
   mStack->freeze(true);

   bool bNoGroup = false;

   // Un-grouped fields are all sorted into the 'general' group
   if ( dStricmp( mCaption, "General" ) == 0 )
      bNoGroup = true;
      
   // Just delete all fields and recreate them (like the dynamicGroup)
   // because that makes creating controls for array fields a lot easier
   clearFields();
   
   bool bNewItems = false;
   bool bMakingArray = false;
   GuiStackControl *pArrayStack = NULL;
   GuiRolloutCtrl *pArrayRollout = NULL;
   bool bGrabItems = false;

   AbstractClassRep* commonAncestorClass = findCommonAncestorClass();
   AbstractClassRep::FieldList& fieldList = commonAncestorClass->mFieldList;
   for( AbstractClassRep::FieldList::iterator itr = fieldList.begin();
        itr != fieldList.end(); ++ itr )
   {
      AbstractClassRep::Field* field = &( *itr );
      if( field->type == AbstractClassRep::StartGroupFieldType )
      {
         // If we're dealing with general fields, always set grabItems to true (to skip them)
         if( bNoGroup == true )
            bGrabItems = true;
         else if( dStricmp( field->pGroupname, mCaption ) == 0 )
            bGrabItems = true;
         continue;
      }
      else if ( field->type == AbstractClassRep::EndGroupFieldType )
      {
         // If we're dealing with general fields, always set grabItems to false (to grab them)
         if( bNoGroup == true )
            bGrabItems = false;
         else if( dStricmp( field->pGroupname, mCaption ) == 0 )
            bGrabItems = false;
         continue;
      }
      
      // Skip field if it has the HideInInspectors flag set.
      
      if( field->flag.test( AbstractClassRep::FIELD_HideInInspectors ) )
         continue;

      if( ( bGrabItems == true || ( bNoGroup == true && bGrabItems == false ) ) && itr->type != AbstractClassRep::DeprecatedFieldType )
      {
         if( bNoGroup == true && bGrabItems == true )
            continue;

         // If the field already exists, just update it
			GuiInspectorField *fieldGui = findField( field->pFieldname );
			if ( fieldGui != NULL )
			{
				fieldGui->updateValue();
				continue;
			}
            
			bNewItems = true;
            
			if(field->pFieldname == StringTable->insert("mountNode"))
			{
				fieldGui = new GuiInspectorNodeListField();

				Entity* e = dynamic_cast<Entity*>(mParent->getInspectObject(0));
				if(e)
					(dynamic_cast<GuiInspectorNodeListField*>(fieldGui))->setTargetEntity(e);
			}
			else
			{
				fieldGui = constructField( field->type );
				if ( fieldGui == NULL )
					fieldGui = new GuiInspectorField();
			}

			fieldGui->init( mParent, this );            
			fieldGui->setInspectorField( field );
                     
			if( fieldGui->registerObject() )
			{
				#ifdef DEBUG_SPEW
				Platform::outputDebugString( "[GuiInspectorGroup] Adding field '%s'",
					field->pFieldname );
				#endif

				mChildren.push_back( fieldGui );
				mStack->addObject( fieldGui );
			}
			else
			{
				SAFE_DELETE( fieldGui );
			}
      }
   }
   mStack->freeze(false);
   mStack->updatePanes();

   // If we've no new items, there's no need to resize anything!
   if( bNewItems == false && !mChildren.empty() )
      return true;

   sizeToContents();

   setUpdate();

   return true;
}