void run() { for( AbstractClassRep* classRep = AbstractClassRep::getClassList(); classRep != NULL; classRep = classRep->getNextClass() ) { // Create object. ConsoleObject* object = classRep->create(); test( object, avar( "AbstractClassRep::create failed for class '%s'", classRep->getClassName() ) ); if( !object ) continue; // Make sure it's a SimObject. SimObject* simObject = dynamic_cast< SimObject* >( object ); if( !simObject ) { SAFE_DELETE( object ); continue; } // Register the object. bool result = simObject->registerObject(); test( result, avar( "registerObject failed for object of class '%s'", classRep->getClassName() ) ); if( result ) simObject->deleteObject(); else SAFE_DELETE( simObject ); } }
S32 script_simobject_find(const char* classname, const char* name) { SimObject *object; if( Sim::findObject( name, object ) ) { // if we specified a classname do type checking if (classname && dStrlen(classname)) { AbstractClassRep* ocr = object->getClassRep(); while (ocr) { if (!dStricmp(ocr->getClassName(), classname)) return object->getId(); ocr = ocr->getParentClass(); } } // invalid type return 0; } // didn't find object return 0; }
//-------------------------------------- ConsoleObject* AbstractClassRep::create(const U32 groupId, const U32 typeId, const U32 in_classId) { AbstractClassRep* classRep = findClassRep( groupId, typeId, in_classId ); if( !classRep ) return NULL; return classRep->create(); }
void SimDataBlockEvent::unpack(NetConnection *cptr, BitStream *bstream) { if(bstream->readFlag()) { mProcess = true; id = bstream->readInt(DataBlockObjectIdBitSize) + DataBlockObjectIdFirst; S32 classId = bstream->readClassId(NetClassTypeDataBlock, cptr->getNetClassGroup()); mIndex = bstream->readInt(DataBlockObjectIdBitSize); mTotal = bstream->readInt(DataBlockObjectIdBitSize + 1); SimObject* ptr; if( Sim::findObject( id, ptr ) ) { // An object with the given ID already exists. Make sure it has the right class. AbstractClassRep* classRep = AbstractClassRep::findClassRep( cptr->getNetClassGroup(), NetClassTypeDataBlock, classId ); if( classRep && dStrcmp( classRep->getClassName(), ptr->getClassName() ) != 0 ) { Con::warnf( "A '%s' datablock with id: %d already existed. " "Clobbering it with new '%s' datablock from server.", ptr->getClassName(), id, classRep->getClassName() ); ptr->deleteObject(); ptr = NULL; } } if( !ptr ) ptr = ( SimObject* ) ConsoleObject::create( cptr->getNetClassGroup(), NetClassTypeDataBlock, classId ); mObj = dynamic_cast< SimDataBlock* >( ptr ); if( mObj != NULL ) { #ifdef DEBUG_SPEW Con::printf(" - SimDataBlockEvent: unpacking event of type: %s", mObj->getClassName()); #endif mObj->unpackData( bstream ); } else { #ifdef DEBUG_SPEW Con::printf(" - SimDataBlockEvent: INVALID PACKET! Could not create class with classID: %d", classId); #endif delete ptr; cptr->setLastError("Invalid packet in SimDataBlockEvent::unpack()"); } #ifdef TORQUE_DEBUG_NET U32 checksum = bstream->readInt(32); AssertISV( (checksum ^ DebugChecksum) == (U32)classId, avar("unpack did not match pack for event of class %s.", mObj->getClassName()) ); #endif } }
bool EditorIconRegistry::hasIconNoRecurse( const SimObject *object ) { AbstractClassRep *classRep = object->getClassRep(); StringNoCase key( classRep->getClassName() ); IconMap::Iterator icon = mIcons.find( key ); return icon != mIcons.end(); }
AbstractClassRep* AbstractClassRep::findClassRep(const char* in_pClassName) { AssertFatal(initialized, "AbstractClassRep::findClassRep() - Tried to find an AbstractClassRep before AbstractClassRep::initialize()."); for (AbstractClassRep *walk = classLinkList; walk; walk = walk->nextClass) if (!dStricmp(walk->getClassName(), in_pClassName)) return walk; return NULL; }
void EditorIconRegistry::loadFromPath( const String &path, bool overwrite ) { AbstractClassRep *classRep = AbstractClassRep::getClassList(); while ( classRep ) { String iconFile = String::ToString( "%s%s", path.c_str(), classRep->getClassName() ); add( classRep->getClassName(), iconFile.c_str(), overwrite ); classRep = classRep->getNextClass(); } String defaultIconFile = path + "default"; mDefaultIcon.set( defaultIconFile, &GFXDefaultPersistentProfile, avar("%s() - mIcons[] (line %d)", __FUNCTION__, __LINE__) ); }
AbstractClassRep* GuiInspectorGroup::findCommonAncestorClass() { AbstractClassRep* classRep = getInspector()->getInspectObject( 0 )->getClassRep(); const U32 numInspectObjects = getInspector()->getNumInspectObjects(); for( U32 i = 1; i < numInspectObjects; ++ i ) { SimObject* object = getInspector()->getInspectObject( i ); while( !object->getClassRep()->isClass( classRep ) ) { classRep = classRep->getParentClass(); AssertFatal( classRep, "GuiInspectorGroup::findcommonAncestorClass - Walked above ConsoleObject!" ); } } return classRep; }
void TypeValidator::consoleError(SimObject *object, const char *format, ...) { char buffer[1024]; va_list argptr; va_start(argptr, format); dVsprintf(buffer, sizeof(buffer), format, argptr); va_end(argptr); AbstractClassRep *rep = object->getClassRep(); AbstractClassRep::Field &fld = rep->mFieldList[fieldIndex]; const char *objectName = object->getName(); if(!objectName) objectName = "unnamed"; Con::warnf("%s - %s(%d) - invalid value for %s: %s", rep->getClassName(), objectName, object->getId(), fld.pFieldname, buffer); }
void GuiInspectorDatablockField::setClassName( StringTableEntry className ) { // Walk the ACR list and find a matching class if any. AbstractClassRep *walk = AbstractClassRep::getClassList(); while(walk) { if(!dStricmp(walk->getClassName(), className)) { // Match! mDesiredClass = walk; return; } walk = walk->getNextClass(); } // No dice. Con::warnf("GuiInspectorDatablockField::setClassName - no class '%s' found!", className); return; }
GFXTexHandle EditorIconRegistry::findIcon( const char *className ) { // On the chance we have this className already in the map, // check there first because its a lot faster... StringNoCase key( className ); IconMap::Iterator icon = mIcons.find( key ); if ( icon != mIcons.end() && icon->value.isValid() ) return icon->value; // Well, we could still have an icon for a parent class, // so find the AbstractClassRep for the className. // // Unfortunately the only way to do this is looping through // the AbstractClassRep linked list. bool found = false; AbstractClassRep* pClassRep = AbstractClassRep::getClassList(); while ( pClassRep ) { if ( key.equal( pClassRep->getClassName(), String::NoCase ) ) { found = true; break; } pClassRep = pClassRep->getNextClass(); } if ( !found ) { Con::errorf( "EditorIconRegistry::findIcon, passed className %s was not an AbstractClassRep!", key.c_str() ); return mDefaultIcon; } // Now do a find by AbstractClassRep recursively up the class tree... return findIcon( pClassRep ); }
AbstractClassRep *AbstractClassRep::getCommonParent( const AbstractClassRep *otherClass ) const { // CodeReview: This may be a noob way of doing it. There may be some kind of // super-spiffy algorithm to do what the code below does, but this appeared // to make sense to me, and it is pretty easy to see what it is doing [6/23/2007 Pat] static VectorPtr<AbstractClassRep *> thisClassHeirarchy; thisClassHeirarchy.clear(); AbstractClassRep *walk = const_cast<AbstractClassRep *>( this ); while( walk != NULL ) { thisClassHeirarchy.push_front( walk ); walk = walk->getParentClass(); } static VectorPtr<AbstractClassRep *> compClassHeirarchy; compClassHeirarchy.clear(); walk = const_cast<AbstractClassRep *>( otherClass ); while( walk != NULL ) { compClassHeirarchy.push_front( walk ); walk = walk->getParentClass(); } // Make sure we only iterate over the list the number of times we can S32 maxIterations = getMin( compClassHeirarchy.size(), thisClassHeirarchy.size() ); U32 i = 0; for( ; i < maxIterations; i++ ) { if( compClassHeirarchy[i] != thisClassHeirarchy[i] ) break; } return compClassHeirarchy[i]; }
void XMLExport::exportNamespaces() { // keep track of which enumTables are in use Vector < const EnumTable*> enumTables; mXML->pushNewElement("Namespaces"); for (Namespace *walk = Namespace::mNamespaceList; walk; walk = walk->mNext) { if ( walk->mName && !walk->isClass() ) continue; const char *name = walk->mName ? walk->mName : ""; mXML->pushNewElement("Namespace"); mXML->setAttribute("name", name); Namespace *p = walk->mParent; mXML->pushNewElement("Parents"); while (p) { if (p->mName == walk->mName) { p = p->mParent; continue; } const char* pname = p->mName ? p->mName : ""; mXML->pushNewElement("Parent"); mXML->setAttribute("name", pname); mXML->popElement(); // Parent p = p->mParent; } mXML->popElement(); // Parents // Entries (Engine/Script Methods/Functions) mXML->pushNewElement("Entries"); Namespace::Entry *entry; VectorPtr<Namespace::Entry *> vec; walk->getEntryList(&vec); for( NamespaceEntryListIterator compItr = vec.begin(); compItr != vec.end(); compItr++ ) { entry = *compItr; if (entry->mNamespace != walk) continue; if (entry->mNamespace->mName != walk->mName) continue; mXML->pushNewElement("Entry"); //consistently name functions char functionName[512]; dSprintf(functionName, 512, entry->mFunctionName); functionName[0] = dTolower(functionName[0]); S32 minArgs = entry->mMinArgs; S32 maxArgs = entry->mMaxArgs; if (maxArgs < minArgs) maxArgs = minArgs; mXML->setAttribute("name", functionName); mXML->setAttribute("minArgs", avar("%i", minArgs)); mXML->setAttribute("maxArgs", avar("%i", maxArgs)); const char* usage = ""; if (entry->mUsage && entry->mUsage[0]) usage = entry->mUsage; mXML->setAttribute("usage", usage); mXML->setAttribute("package", entry->mPackage ? entry->mPackage : ""); mXML->setAttribute("entryType", avar("%i", entry->mType)); mXML->popElement(); // Entry } mXML->popElement(); // Entries // Fields mXML->pushNewElement("Fields"); AbstractClassRep *rep = walk->mClassRep; Vector<U32> classFields; if (rep) { AbstractClassRep *parentRep = rep->getParentClass(); const AbstractClassRep::FieldList& flist = rep->mFieldList; for(U32 i = 0; i < flist.size(); i++) { if (parentRep) { if (parentRep->findField(flist[i].pFieldname)) continue; } classFields.push_back(i); } for(U32 i = 0; i < classFields.size(); i++) { U32 index = classFields[i]; char fieldName[256]; dSprintf(fieldName, 256, flist[index].pFieldname); //consistently name fields fieldName[0] = dToupper(fieldName[0]); mXML->pushNewElement("Field"); mXML->setAttribute("name", fieldName); mXML->setAttribute("type", avar("%i", flist[index].type)); // RD: temporarily deactivated; TypeEnum is no more; need to sync this up // if (flist[index].type == TypeEnum && flist[index].table && dStrlen(flist[index].table->name)) // { // if (!enumTables.contains(flist[index].table)) // enumTables.push_back(flist[index].table); // // mXML->setAttribute("enumTable", flist[index].table->name); // // } const char* pFieldDocs = ""; if (flist[index].pFieldDocs && flist[index].pFieldDocs[0]) pFieldDocs = flist[index].pFieldDocs; mXML->setAttribute("docs", pFieldDocs); mXML->setAttribute("elementCount", avar("%i", flist[index].elementCount)); mXML->popElement(); // Field } } mXML->popElement(); // Fields mXML->popElement(); // Namespace } mXML->popElement(); // Namespaces mXML->pushNewElement("EnumTables"); // write out the used EnumTables for (S32 i = 0; i < enumTables.size(); i++) { mXML->pushNewElement("EnumTable"); const EnumTable* table = enumTables[i]; mXML->setAttribute("name", table->name); mXML->setAttribute("firstFlag", avar("%i", table->firstFlag)); mXML->setAttribute("mask", avar("%i", table->mask)); mXML->pushNewElement("Enums"); for (S32 j = 0; j < table->size; j++) { mXML->pushNewElement("Enum"); mXML->setAttribute("name", table->table[j].label); mXML->setAttribute("index", avar("%i", table->table[j].index)); mXML->popElement(); // Enum } mXML->popElement(); //Enums mXML->popElement(); // EnumTable } mXML->popElement(); // EnumTables }
void AbstractClassRep::initialize() { AssertFatal(!initialized, "Duplicate call to AbstractClassRep::initialize()!"); Vector<AbstractClassRep *> dynamicTable(__FILE__, __LINE__); AbstractClassRep *walk; // Initialize namespace references... for (walk = classLinkList; walk; walk = walk->nextClass) { walk->mNamespace = Con::lookupNamespace(StringTable->insert(walk->getClassName())); walk->mNamespace->mUsage = walk->getDocString(); walk->mNamespace->mClassRep = walk; } // Initialize field lists... (and perform other console registration). for (walk = classLinkList; walk; walk = walk->nextClass) { // sg_tempFieldList is used as a staging area for field lists // (see addField, addGroup, etc.) sg_tempFieldList.setSize(0); walk->init(); // So if we have things in it, copy it over... if (sg_tempFieldList.size() != 0) walk->mFieldList = sg_tempFieldList; // And of course delete it every round. sg_tempFieldList.clear(); } // Calculate counts and bit sizes for the various NetClasses. for (U32 group = 0; group < NetClassGroupsCount; group++) { U32 groupMask = 1 << group; // Specifically, for each NetClass of each NetGroup... for(U32 type = 0; type < NetClassTypesCount; type++) { // Go through all the classes and find matches... for (walk = classLinkList; walk; walk = walk->nextClass) { if(walk->mClassType == type && walk->mClassGroupMask & groupMask) dynamicTable.push_back(walk); } // Set the count for this NetGroup and NetClass NetClassCount[group][type] = dynamicTable.size(); if(!NetClassCount[group][type]) continue; // If no classes matched, skip to next. // Sort by type and then by name. dQsort((void *) &dynamicTable[0], dynamicTable.size(), sizeof(AbstractClassRep *), ACRCompare); // Allocate storage in the classTable classTable[group][type] = new AbstractClassRep*[NetClassCount[group][type]]; // Fill this in and assign class ids for this group. for(U32 i = 0; i < NetClassCount[group][type];i++) { classTable[group][type][i] = dynamicTable[i]; dynamicTable[i]->mClassId[group] = i; } // And calculate the size of bitfields for this group and type. NetClassBitSize[group][type] = getBinLog2(getNextPow2(NetClassCount[group][type] + 1)); AssertFatal(NetClassCount[group][type] < (1 << NetClassBitSize[group][type]), "NetClassBitSize too small!"); dynamicTable.clear(); } } // Ok, we're golden! initialized = true; }
bool SceneObject::isSelectionEnabled() const { AbstractClassRep *classRep = getClassRep(); return ( mObjectFlags.test( SelectionEnabledFlag ) && classRep->isSelectionEnabled() ); }
void TamlBinaryReader::parseChildren( Stream& stream, TamlCallbacks* pCallbacks, SimObject* pSimObject, const U32 versionId ) { // Debug Profiling. PROFILE_SCOPE(TamlBinaryReader_ParseChildren); // Sanity! AssertFatal( pSimObject != NULL, "Taml: Cannot parse children on a NULL object." ); // Fetch children count. U32 childrenCount; stream.read( &childrenCount ); // Finish if no children. if ( childrenCount == 0 ) return; // Fetch the Taml children. TamlChildren* pChildren = dynamic_cast<TamlChildren*>( pSimObject ); // Is this a sim set? if ( pChildren == NULL ) { // No, so warn. Con::warnf("Taml: Child element found under parent but object cannot have children." ); return; } // Fetch any container child class specifier. AbstractClassRep* pContainerChildClass = pSimObject->getClassRep()->getContainerChildClass( true ); // Iterate children. for ( U32 index = 0; index < childrenCount; ++ index ) { // Parse child element. SimObject* pChildSimObject = parseElement( stream, versionId ); // Finish if child failed. if ( pChildSimObject == NULL ) return; // Do we have a container child class? if ( pContainerChildClass != NULL ) { // Yes, so is the child object the correctly derived type? if ( !pChildSimObject->getClassRep()->isClass( pContainerChildClass ) ) { // No, so warn. Con::warnf("Taml: Child element '%s' found under parent '%s' but object is restricted to children of type '%s'.", pChildSimObject->getClassName(), pSimObject->getClassName(), pContainerChildClass->getClassName() ); // NOTE: We can't delete the object as it may be referenced elsewhere! pChildSimObject = NULL; // Skip. continue; } } // Add child. pChildren->addTamlChild( pChildSimObject ); // Find Taml callbacks for child. TamlCallbacks* pChildCallbacks = dynamic_cast<TamlCallbacks*>( pChildSimObject ); // Do we have callbacks on the child? if ( pChildCallbacks != NULL ) { // Yes, so perform callback. mpTaml->tamlAddParent( pChildCallbacks, pSimObject ); } } }
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( mParent->getNumInspectObjects() == 1 && !dStricmp(typeClassName, "GameBaseData") ) { // Try and setup the classname based on the object type char className[256]; dSprintf(className,256,"%sData", mParent->getInspectObject( 0 )->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; }
static void dumpClasses( Stream &stream ) { Namespace::trashCache(); VectorPtr<Namespace*> vec; vec.reserve( 1024 ); // We use mHashSequence to mark if we have traversed... // so mark all as zero to start. for ( Namespace *walk = Namespace::mNamespaceList; walk; walk = walk->mNext ) walk->mHashSequence = 0; for(Namespace *walk = Namespace::mNamespaceList; walk; walk = walk->mNext) { VectorPtr<Namespace*> stack; stack.reserve( 1024 ); // Get all the parents of this namespace... (and mark them as we go) Namespace *parentWalk = walk; while(parentWalk) { if(parentWalk->mHashSequence != 0) break; if(parentWalk->mPackage == 0) { parentWalk->mHashSequence = 1; // Mark as traversed. stack.push_back(parentWalk); } parentWalk = parentWalk->mParent; } // Load stack into our results vector. while(stack.size()) { vec.push_back(stack[stack.size() - 1]); stack.pop_back(); } } // Go through previously discovered classes U32 i; for(i = 0; i < vec.size(); i++) { const char *className = vec[i]->mName; const char *superClassName = vec[i]->mParent ? vec[i]->mParent->mName : NULL; // Skip the global namespace, that gets dealt with in dumpFunctions if(!className) continue; // We're just dumping engine functions, then we don't want to dump // a class that only contains script functions. So, we iterate over // all the functions. bool found = false; for( Namespace::Entry *ewalk = vec[i]->mEntryList; ewalk; ewalk = ewalk->mNext ) { if( ewalk->mType != Namespace::Entry::ConsoleFunctionType ) { found = true; break; } } // If we don't have engine functions and the namespace name // doesn't match the class name... then its a script class. if ( !found && !vec[i]->isClass() ) continue; // If we hit a class with no members and no classRep, do clever filtering. if(vec[i]->mEntryList == NULL && vec[i]->mClassRep == NULL) { // Print out a short stub so we get a proper class hierarchy. if ( superClassName ) { // Filter hack; we don't want non-inheriting classes... dumpClassHeader( stream, NULL, className, superClassName ); dumpClassFooter( stream ); } continue; } // Skip over hidden or internal classes. if( vec[i]->mUsage && ( dStrstr( vec[i]->mUsage, "@hide" ) || dStrstr( vec[i]->mUsage, "@internal" ) ) ) continue; // Print the header for the class.. dumpClassHeader( stream, vec[i]->mUsage, className, superClassName ); // Dump all fragments for this class. for( ConsoleDocFragment* fragment = ConsoleDocFragment::smFirst; fragment != NULL; fragment = fragment->mNext ) if( fragment->mClass && dStricmp( fragment->mClass, className ) == 0 ) dumpFragment( stream, fragment ); // Dump member functions. dumpNamespaceEntries( stream, vec[ i ], false ); // Dump callbacks. dumpGroupStart( stream, "Callbacks" ); dumpNamespaceEntries( stream, vec[ i ], true ); dumpGroupEnd( stream ); // Dump static member variables. dumpVariables( stream, className ); // Deal with the classRep (to get members)... AbstractClassRep *rep = vec[i]->mClassRep; AbstractClassRep::FieldList emptyList; AbstractClassRep::FieldList *parentList = &emptyList; AbstractClassRep::FieldList *fieldList = &emptyList; if ( rep ) { // Get information about the parent's fields... AbstractClassRep *parentRep = vec[i]->mParent ? vec[i]->mParent->mClassRep : NULL; if(parentRep) parentList = &(parentRep->mFieldList); // Get information about our fields fieldList = &(rep->mFieldList); // Go through all our fields... for(U32 j = 0; j < fieldList->size(); j++) { const AbstractClassRep::Field &field = (*fieldList)[j]; switch( field.type ) { case AbstractClassRep::StartArrayFieldType: case AbstractClassRep::EndArrayFieldType: break; case AbstractClassRep::StartGroupFieldType: dumpGroupStart( stream, field.pGroupname, field.pFieldDocs ); break; case AbstractClassRep::EndGroupFieldType: dumpGroupEnd( stream ); break; default: case AbstractClassRep::DeprecatedFieldType: // Skip over fields that are already defined in // our parent class. if ( parentRep && parentRep->findField( field.pFieldname ) ) continue; dumpClassMember( stream, field ); break; } } } // Close the class/namespace. dumpClassFooter( stream ); } }