/** * fills in the OutAddresses array with the addresses of all of the available objects. * @param InItem The property to get objects from. * @param OutAddresses Storage array for all of the objects' addresses. */ bool FObjectPropertyNode::GetReadAddressUncached( FPropertyNode& InNode, FReadAddressListData& OutAddresses ) const { // Are any objects selected for property editing? if( !GetNumObjects()) { return false; } UProperty* InItemProperty = InNode.GetProperty(); // Is there a InItemProperty bound to the InItemProperty window? if( !InItemProperty ) { return false; } // Write addresses to the output. for ( int32 ObjectIdx = 0 ; ObjectIdx < GetNumObjects() ; ++ObjectIdx ) { const UObject* TempObject = GetUObject(ObjectIdx); if( TempObject != NULL ) { OutAddresses.Add( TempObject, InNode.GetValueBaseAddress( (uint8*)(TempObject) ) ); } } // Everything checked out and we have usable addresses. return true; }
//----------------------------------------------------------------------------- // Purpose: Object has been picked up by this player //----------------------------------------------------------------------------- void CPlayerClass::PickupObject( CBaseObject *pObject ) { // Return the cost of the object if ( !tf2_object_hard_limits.GetBool() ) { int iCost = CalculateObjectCost( pObject->GetType(), GetNumObjects( pObject->GetType() ), m_pPlayer->GetTeamNumber(), true ); m_pPlayer->AddBankResources( iCost ); } }
//----------------------------------------------------------------------------- // Purpose: Player has aborted a build //----------------------------------------------------------------------------- void CPlayerClass::StoppedBuilding( int iObjectType ) { // Return the cost of the object if ( !tf2_object_hard_limits.GetBool() ) { int iCost = CalculateObjectCost( iObjectType, GetNumObjects( iObjectType ), m_pPlayer->GetTeamNumber() ); m_pPlayer->AddBankResources( iCost ); } }
//----------------------------------------------------------------------------- // Purpose: Return true if this player's allowed to build another one of the specified objects //----------------------------------------------------------------------------- int CPlayerClass::CanBuild( int iObjectType ) { int iObjectCount = GetNumObjects( iObjectType ); // Make sure we haven't hit maximum number if ( tf2_object_hard_limits.GetBool() ) { if ( iObjectCount >= GetObjectInfo( iObjectType )->m_nMaxObjects ) return CB_LIMIT_REACHED; } else { // Find out how much the next object should cost int iCost = CalculateObjectCost( iObjectType, GetNumObjects( iObjectType ), m_pPlayer->GetTeamNumber() ); // Make sure we have enough resources if ( m_pPlayer->GetBankResources() < iCost ) return CB_NEED_RESOURCES; } return CB_CAN_BUILD; }
void PhysicsManager::ApplyForceAtIndex(btVector3 force, int index) { if(index < 0 || index >= GetNumObjects()) { cout << "ERROR! PhysicsManager::ApplyForceAtIndex tried to access: " << index << " which is not between 0 and " << GetNumObjects() << "." << endl; return; } btRigidBody* object = btRigidBody::upcast(dynamicsWorld->getCollisionObjectArray()[index]); object->applyCentralImpulse(force); object->clearForces(); }
glm::mat4 PhysicsManager::GetModelMatrixAtIndex(int index) { if(index < 0 || index >= GetNumObjects()) { cout << "ERROR! PhysicsManager::GetModelMatrixAtIndex tried to access: " << index << " which is not between 0 and " << GetNumObjects() << "." << endl; return glm::mat4(1.0f); } btTransform trans; btScalar m[16]; btRigidBody* object = btRigidBody::upcast(dynamicsWorld->getCollisionObjectArray()[index]); object->getMotionState()->getWorldTransform(trans); trans.getOpenGLMatrix(m); glm::mat4 modelMatrix = glm::make_mat4(m); return modelMatrix; }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int C_TFTeam::GetNumObjects( int iObjectType ) { // Asking for a count of a specific object type? if ( iObjectType > 0 ) { int iCount = 0; for ( int i = 0; i < GetNumObjects(); i++ ) { CBaseObject *pObject = GetObject(i); if ( pObject && pObject->GetType() == iObjectType ) { iCount++; } } return iCount; } return m_aObjects.Count(); }
//----------------------------------------------------------------------------- // Purpose: Player has started building an object //----------------------------------------------------------------------------- int CPlayerClass::StartedBuildingObject( int iObjectType ) { // Deduct the cost of the object if ( !tf2_object_hard_limits.GetBool() ) { int iCost = CalculateObjectCost( iObjectType, GetNumObjects( iObjectType ), m_pPlayer->GetTeamNumber() ); if ( iCost > m_pPlayer->GetBankResources() ) { // Player must have lost resources since he started placing return 0; } m_pPlayer->RemoveBankResources( iCost ); // If the object costs 0, we need to return non-0 to mean success if ( !iCost ) return 1; return iCost; } return 1; }
void VulkanRenderer::OutputLog(std::ostream & fout) { fout << GetName() << "\n[" << GetNumVertices() << " vertices] [" << GetNumTriangles() << " triangles] [" << GetNumObjects() << " objects]" << std::endl; fout << "Threads: " << GetNumThreads() << std::endl; if(mUseInstancing) fout << "Pipeline: " << "Instancing" << std::endl; else if (mUseStaticCommandBuffer) fout << "Pipeline: " << "Static command buffers" << std::endl; else fout << "Pipeline: " << "Basic" << std::endl; }
// This test sets node onclick many times to expose a possible memory // leak where all listeners get referenced by the node. TEST_F(ListenerLeakTest, HiddenReferences) { RunTest("listener/listener_leak2.html"); ASSERT_EQ(1, GetNumObjects("EventListenerLeakTestObject2")); }
// This test tries to create a reference cycle between node and its listener. // See http://crbug/17400. TEST_F(ListenerLeakTest, ReferenceCycle) { RunTest("listener/listener_leak1.html"); ASSERT_EQ(0, GetNumObjects("EventListenerLeakTestObject1")); }
void CLiteObjectMgr::ShowInfo(uint32 nUpdateTime) { g_pLTServer->CPrint("\nLiteObjectMgr stats : (%d ticks)", nUpdateTime); typedef std::set<HCLASS> TClassSet; TClassSet aClasses; TObjectList::const_iterator iCurObject; // Set up the class set iCurObject = m_aActiveObjects.begin(); for (; iCurObject != m_aActiveObjects.end(); ++iCurObject) { aClasses.insert((*iCurObject)->GetClass()); } iCurObject = m_aInactiveObjects.begin(); for (; iCurObject != m_aInactiveObjects.end(); ++iCurObject) { aClasses.insert((*iCurObject)->GetClass()); } TClassSet::const_iterator iCurClass; // Figure out how wide the class name field should be uint32 nMaxClassNameWidth = 6; iCurClass = aClasses.begin(); for (; iCurClass != aClasses.end(); ++iCurClass) { char aClassNameBuff[256]; g_pLTServer->GetClassName(*iCurClass, aClassNameBuff, sizeof(aClassNameBuff)); nMaxClassNameWidth = LTMAX(nMaxClassNameWidth, strlen(aClassNameBuff)); } // Print a header char *aClassUnderline = (char*)alloca(nMaxClassNameWidth + 1); memset(aClassUnderline, '-', nMaxClassNameWidth); aClassUnderline[nMaxClassNameWidth] = 0; g_pLTServer->CPrint(" -%s-|--------|----------|-------", aClassUnderline); g_pLTServer->CPrint(" Class %*s | Active | Inactive | Total", nMaxClassNameWidth - 6,""); g_pLTServer->CPrint(" -%s-|--------|----------|-------", aClassUnderline); // Run through the classes and accumulate stats iCurClass = aClasses.begin(); for (; iCurClass != aClasses.end(); ++iCurClass) { uint32 nNumActive = 0; iCurObject = m_aActiveObjects.begin(); for (; iCurObject != m_aActiveObjects.end(); ++iCurObject) { if ((*iCurObject)->GetClass() == *iCurClass) ++nNumActive; } uint32 nNumInactive = 0; iCurObject = m_aInactiveObjects.begin(); for (; iCurObject != m_aInactiveObjects.end(); ++iCurObject) { if ((*iCurObject)->GetClass() == *iCurClass) ++nNumInactive; } char aClassNameBuff[256]; g_pLTServer->GetClassName(*iCurClass, aClassNameBuff, sizeof(aClassNameBuff)); // Here's your output... g_pLTServer->CPrint(" %-*s | %4d | %4d | %4d", nMaxClassNameWidth, aClassNameBuff, nNumActive, nNumInactive, nNumActive + nNumInactive); } // Print the totals g_pLTServer->CPrint(" -%s-|--------|----------|-------", aClassUnderline); g_pLTServer->CPrint(" %-*s | %4d | %4d | %4d", nMaxClassNameWidth, "Total", GetNumActiveObjects(), GetNumInactiveObjects(), GetNumObjects()); }
void SDetailsView::SetObjectArrayPrivate(const TArray< TWeakObjectPtr< UObject > >& InObjects) { double StartTime = FPlatformTime::Seconds(); PreSetObject(InObjects.Num()); // Selected actors for building SelectedActorInfo TArray<AActor*> SelectedRawActors; bViewingClassDefaultObject = InObjects.Num() > 0 ? true : false; bool bOwnedByLockedLevel = false; for( int32 ObjectIndex = 0 ; ObjectIndex < InObjects.Num(); ++ObjectIndex ) { TWeakObjectPtr< UObject > Object = InObjects[ObjectIndex]; if( Object.IsValid() ) { bViewingClassDefaultObject &= Object->HasAnyFlags( RF_ClassDefaultObject ); if(DetailsViewArgs.bAllowMultipleTopLevelObjects) { check(RootPropertyNodes.Num() == InObjects.Num()); RootPropertyNodes[ObjectIndex]->AsObjectNode()->AddObject( Object.Get() ); } else { RootPropertyNodes[0]->AsObjectNode()->AddObject( Object.Get() ); } SelectedObjects.Add( Object ); AActor* Actor = Cast<AActor>( Object.Get() ); if( Actor ) { SelectedActors.Add( Actor ); SelectedRawActors.Add( Actor ); } } } if( InObjects.Num() == 0 ) { // Unlock the view automatically if we are viewing nothing bIsLocked = false; } // Selection changed, refresh the detail area if ( DetailsViewArgs.NameAreaSettings != FDetailsViewArgs::ActorsUseNameArea && DetailsViewArgs.NameAreaSettings != FDetailsViewArgs::ComponentsAndActorsUseNameArea ) { NameArea->Refresh( SelectedObjects ); } else { NameArea->Refresh( SelectedActors, SelectedObjects, DetailsViewArgs.NameAreaSettings ); } // When selection changes rebuild information about the selection SelectedActorInfo = AssetSelectionUtils::BuildSelectedActorInfo( SelectedRawActors ); // @todo Slate Property Window //SetFlags(EPropertyWindowFlags::ReadOnly, bOwnedByLockedLevel); PostSetObject(); // Set the title of the window based on the objects we are viewing // Or call the delegate for handling when the title changed FString Title; if( GetNumObjects() == 0 ) { Title = NSLOCTEXT("PropertyView", "NothingSelectedTitle", "Nothing selected").ToString(); } else if( GetNumObjects() == 1 && RootPropertyNodes[0]->AsObjectNode()->GetNumObjects() > 0) { // if the object is the default metaobject for a UClass, use the UClass's name instead UObject* Object = RootPropertyNodes[0]->AsObjectNode()->GetUObject(0); FString ObjectName = Object->GetName(); if ( Object->GetClass()->GetDefaultObject() == Object ) { ObjectName = Object->GetClass()->GetName(); } else { // Is this an actor? If so, it might have a friendly name to display const AActor* Actor = Cast<const AActor >( Object ); if( Actor != nullptr) { // Use the friendly label for this actor ObjectName = Actor->GetActorLabel(); } } Title = ObjectName; } else if(DetailsViewArgs.bAllowMultipleTopLevelObjects) { Title = FString::Printf(*NSLOCTEXT("PropertyView", "MultipleToLevelObjectsSelected", "%i selected").ToString(), GetNumObjects()); } else { FObjectPropertyNode* RootPropertyNode = RootPropertyNodes[0]->AsObjectNode(); Title = FString::Printf( *NSLOCTEXT("PropertyView", "MultipleSelected", "%s (%i selected)").ToString(), *RootPropertyNode->GetObjectBaseClass()->GetName(), RootPropertyNode->GetNumObjects() ); } OnObjectArrayChanged.ExecuteIfBound(Title, InObjects); double ElapsedTime = FPlatformTime::Seconds() - StartTime; }
bool SDetailsView::ShouldSetNewObjects(const TArray< TWeakObjectPtr< UObject > >& InObjects) const { bool bShouldSetObjects = false; const bool bHadBSPBrushSelected = SelectedActorInfo.bHaveBSPBrush; if( bHadBSPBrushSelected == true ) { // If a BSP brush was selected we need to refresh because surface could have been selected and the object set not updated bShouldSetObjects = true; } else if( InObjects.Num() != GetNumObjects() ) { // If the object arrays differ in size then at least one object is different so we must reset bShouldSetObjects = true; } else if(InObjects.Num() == 0) { // User is likely resetting details panel bShouldSetObjects = true; } else { // Check to see if the objects passed in are different. If not we do not need to set anything TSet< TWeakObjectPtr< UObject > > NewObjects; NewObjects.Append(InObjects); if(DetailsViewArgs.bAllowMultipleTopLevelObjects) { // For multiple top level node support, if the single object in each node is not found in the new object set // then we need to refresh for(int32 RootNodeIndex = 0; RootNodeIndex < RootPropertyNodes.Num(); ++RootNodeIndex) { FObjectPropertyNode* RootPropertyNode = RootPropertyNodes[RootNodeIndex]->AsObjectNode(); if(RootPropertyNode && RootPropertyNode->GetNumObjects() > 0) { if(!NewObjects.Contains(RootPropertyNode->GetUObject(0))) { bShouldSetObjects = true; break; } } else { bShouldSetObjects = true; break; } } } else { ensure(RootPropertyNodes.Num() == 1); FObjectPropertyNode* RootPropertyNode = RootPropertyNodes[0]->AsObjectNode(); if( RootPropertyNode ) { for(TPropObjectIterator Itor(RootPropertyNode->ObjectIterator()); Itor; ++Itor) { TWeakObjectPtr<UObject> Object = *Itor; if(Object.IsValid() && !NewObjects.Contains(Object)) { // An existing object is not in the list of new objects to set bShouldSetObjects = true; break; } else if(!Object.IsValid()) { // An existing object is invalid bShouldSetObjects = true; break; } } } else { bShouldSetObjects = true; } } } if (!bShouldSetObjects && AssetSelectionUtils::IsAnySurfaceSelected(nullptr)) { bShouldSetObjects = true; } return bShouldSetObjects; }
bool FObjectPropertyNode::GetReadAddressUncached(FPropertyNode& InNode, bool InRequiresSingleSelection, FReadAddressListData& OutAddresses, bool bComparePropertyContents, bool bObjectForceCompare, bool bArrayPropertiesCanDifferInSize) const { // Are any objects selected for property editing? if( !GetNumObjects()) { return false; } UProperty* InItemProperty = InNode.GetProperty(); // Is there a InItemProperty bound to the InItemProperty window? if( !InItemProperty ) { return false; } // Requesting a single selection? if( InRequiresSingleSelection && GetNumObjects() > 1) { // Fail: we're editing properties for multiple objects. return false; } //assume all properties are the same unless proven otherwise bool bAllTheSame = true; ////////////////////////////////////////// // If this item is the child of an array, return NULL if there is a different number // of items in the array in different objects, when multi-selecting. if( Cast<UArrayProperty>(InItemProperty->GetOuter()) ) { FPropertyNode* ParentNode = InNode.GetParentNode(); check(ParentNode); const UObject* TempObject = GetUObject(0); if( TempObject ) { uint8* BaseAddr = ParentNode->GetValueBaseAddress( (uint8*)TempObject ); if( BaseAddr ) { const int32 Num = FScriptArrayHelper::Num(BaseAddr); for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects(); ObjIndex++ ) { TempObject = GetUObject(ObjIndex); BaseAddr = ParentNode->GetValueBaseAddress( (uint8*)TempObject ); if( BaseAddr && Num != FScriptArrayHelper::Num( BaseAddr ) ) { bAllTheSame = false; } } } } } uint8* Base = GetUObject(0) ? InNode.GetValueBaseAddress( (uint8*)(GetUObject(0)) ) : NULL; if (Base) { // If the item is an array itself, return NULL if there are a different number of // items in the array in different objects, when multi-selecting. if( Cast<UArrayProperty>(InItemProperty) ) { // This flag is an override for array properties which want to display e.g. the "Clear" and "Empty" // buttons, even though the array properties may differ in the number of elements. if ( !bArrayPropertiesCanDifferInSize ) { const UObject* TempObject = GetUObject(0); int32 const Num = FScriptArrayHelper::Num(InNode.GetValueBaseAddress( (uint8*)TempObject)); for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects() ; ObjIndex++ ) { TempObject = GetUObject(ObjIndex); if( TempObject && Num != FScriptArrayHelper::Num(InNode.GetValueBaseAddress((uint8*)TempObject)) ) { bAllTheSame = false; } } } } else { if ( bComparePropertyContents || !Cast<UObjectPropertyBase>(InItemProperty) || bObjectForceCompare ) { // Make sure the value of this InItemProperty is the same in all selected objects. for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects() ; ObjIndex++ ) { const UObject* TempObject = GetUObject(ObjIndex); if( !InItemProperty->Identical( Base, InNode.GetValueBaseAddress( (uint8*)TempObject ) ) ) { bAllTheSame = false; } } } else { if ( Cast<UObjectPropertyBase>(InItemProperty) ) { // We don't want to exactly compare component properties. However, we // need to be sure that all references are either valid or invalid. // If BaseObj is NON-NULL, all other objects' properties should also be non-NULL. // If BaseObj is NULL, all other objects' properties should also be NULL. UObject* BaseObj = Cast<UObjectPropertyBase>(InItemProperty)->GetObjectPropertyValue(Base); for( int32 ObjIndex = 1 ; ObjIndex < GetNumObjects() ; ObjIndex++ ) { const UObject* TempObject = GetUObject(ObjIndex); UObject* CurObj = Cast<UObjectPropertyBase>(InItemProperty)->GetObjectPropertyValue(InNode.GetValueBaseAddress( (uint8*)TempObject )); if ( ( !BaseObj && CurObj ) // BaseObj is NULL, but this InItemProperty is non-NULL! || ( BaseObj && !CurObj ) ) // BaseObj is non-NULL, but this InItemProperty is NULL! { bAllTheSame = false; } } } } } } // Write addresses to the output. for ( int32 ObjIndex = 0 ; ObjIndex < GetNumObjects(); ++ObjIndex ) { const UObject* TempObject = GetUObject(ObjIndex); if( TempObject ) { OutAddresses.Add( TempObject, InNode.GetValueBaseAddress( (uint8*)(TempObject) ) ); } } // Everything checked out and we have usable addresses. return bAllTheSame; }
void FObjectPropertyNode::InternalInitChildNodes( FName SinglePropertyName ) { HiddenCategories.Empty(); // Assemble a list of category names by iterating over all fields of BaseClass. // build a list of classes that we need to look at TSet<UClass*> ClassesToConsider; for( int32 i = 0; i < GetNumObjects(); ++i ) { UObject* TempObject = GetUObject( i ); if( TempObject ) { ClassesToConsider.Add( TempObject->GetClass() ); } } const bool bShouldShowHiddenProperties = !!HasNodeFlags(EPropertyNodeFlags::ShouldShowHiddenProperties); const bool bShouldShowDisableEditOnInstance = !!HasNodeFlags(EPropertyNodeFlags::ShouldShowDisableEditOnInstance); TSet<FName> Categories; for( TFieldIterator<UProperty> It(BaseClass.Get()); It; ++It ) { bool bHidden = false; FName CategoryName = FObjectEditorUtils::GetCategoryFName(*It); for( UClass* Class : ClassesToConsider ) { if( FEditorCategoryUtils::IsCategoryHiddenFromClass(Class, CategoryName.ToString()) ) { HiddenCategories.Add( CategoryName ); bHidden = true; break; } } bool bMetaDataAllowVisible = true; FString MetaDataVisibilityCheckString = It->GetMetaData(TEXT("bShowOnlyWhenTrue")); if (MetaDataVisibilityCheckString.Len()) { //ensure that the metadata visibility string is actually set to true in order to show this property GConfig->GetBool(TEXT("UnrealEd.PropertyFilters"), *MetaDataVisibilityCheckString, bMetaDataAllowVisible, GEditorUserSettingsIni); } if (bMetaDataAllowVisible) { const bool bShowIfNonHiddenEditableProperty = (*It)->HasAnyPropertyFlags(CPF_Edit) && !bHidden; const bool bShowIfDisableEditOnInstance = !(*It)->HasAnyPropertyFlags(CPF_DisableEditOnInstance) || bShouldShowDisableEditOnInstance; if( bShouldShowHiddenProperties || (bShowIfNonHiddenEditableProperty && bShowIfDisableEditOnInstance) ) { Categories.Add( CategoryName ); } } } ////////////////////////////////////////// // Add the category headers and the child items that belong inside of them. // Only show category headers if this is the top level object window and the parent window allows headers. if( HasNodeFlags(EPropertyNodeFlags::ShowCategories) ) { FString CategoryDelimiterString; CategoryDelimiterString.AppendChar( FPropertyNodeConstants::CategoryDelimiterChar ); TArray< FPropertyNode* > ParentNodesToSort; for( const FName& FullCategoryPath : Categories ) { // Figure out the nesting level for this category TArray< FString > FullCategoryPathStrings; FullCategoryPath.ToString().ParseIntoArray( FullCategoryPathStrings, *CategoryDelimiterString, true ); TSharedPtr<FPropertyNode> ParentLevelNode = SharedThis(this); FString CurCategoryPathString; for( int32 PathLevelIndex = 0; PathLevelIndex < FullCategoryPathStrings.Num(); ++PathLevelIndex ) { // Build up the category path name for the current path level index if( CurCategoryPathString.Len() != 0 ) { CurCategoryPathString += FPropertyNodeConstants::CategoryDelimiterChar; } CurCategoryPathString += FullCategoryPathStrings[ PathLevelIndex ]; const FName CategoryName( *CurCategoryPathString ); // Check to see if we've already created a category at the specified path level bool bFoundMatchingCategory = false; { for( int32 CurNodeIndex = 0; CurNodeIndex < ParentLevelNode->GetNumChildNodes(); ++CurNodeIndex ) { TSharedPtr<FPropertyNode>& ChildNode = ParentLevelNode->GetChildNode( CurNodeIndex ); check( ChildNode.IsValid() ); // Is this a category node? FCategoryPropertyNode* ChildCategoryNode = ChildNode->AsCategoryNode(); if( ChildCategoryNode != NULL ) { // Does the name match? if( ChildCategoryNode->GetCategoryName() == CategoryName ) { // Descend by using the child node as the new parent bFoundMatchingCategory = true; ParentLevelNode = ChildNode; break; } } } } // If we didn't find the category, then we'll need to create it now! if( !bFoundMatchingCategory ) { // Create the category node and assign it to its parent node TSharedPtr<FCategoryPropertyNode> NewCategoryNode( new FCategoryPropertyNode ); { NewCategoryNode->SetCategoryName( CategoryName ); FPropertyNodeInitParams InitParams; InitParams.ParentNode = ParentLevelNode; InitParams.Property = NULL; InitParams.ArrayOffset = 0; InitParams.ArrayIndex = INDEX_NONE; InitParams.bAllowChildren = true; InitParams.bForceHiddenPropertyVisibility = bShouldShowHiddenProperties; InitParams.bCreateDisableEditOnInstanceNodes = bShouldShowDisableEditOnInstance; NewCategoryNode->InitNode( InitParams ); // Recursively expand category properties if the category has been flagged for auto-expansion. if (BaseClass->IsAutoExpandCategory(*CategoryName.ToString()) && !BaseClass->IsAutoCollapseCategory(*CategoryName.ToString())) { NewCategoryNode->SetNodeFlags(EPropertyNodeFlags::Expanded, true); } // Add this node to it's parent. Note that no sorting happens here, so the parent's // list of child nodes will not be in the correct order. We'll keep track of which // nodes we added children to so we can sort them after we're finished adding new nodes. ParentLevelNode->AddChildNode(NewCategoryNode); ParentNodesToSort.AddUnique( ParentLevelNode.Get() ); } // Descend into the newly created category by using this node as the new parent ParentLevelNode = NewCategoryNode; } } } } else { // Iterate over all fields, creating items. for( TFieldIterator<UProperty> It(BaseClass.Get()); It; ++It ) { const bool bShowIfNonHiddenEditableProperty = (*It)->HasAnyPropertyFlags(CPF_Edit) && !FEditorCategoryUtils::IsCategoryHiddenFromClass(BaseClass.Get(), FObjectEditorUtils::GetCategory(*It)); const bool bShowIfDisableEditOnInstance = !(*It)->HasAnyPropertyFlags(CPF_DisableEditOnInstance) || bShouldShowDisableEditOnInstance; if (bShouldShowHiddenProperties || (bShowIfNonHiddenEditableProperty && bShowIfDisableEditOnInstance)) { UProperty* CurProp = *It; if( SinglePropertyName == NAME_None || CurProp->GetFName() == SinglePropertyName ) { TSharedPtr<FItemPropertyNode> NewItemNode( new FItemPropertyNode ); FPropertyNodeInitParams InitParams; InitParams.ParentNode = SharedThis(this); InitParams.Property = CurProp; InitParams.ArrayOffset = 0; InitParams.ArrayIndex = INDEX_NONE; InitParams.bAllowChildren = SinglePropertyName == NAME_None; InitParams.bForceHiddenPropertyVisibility = bShouldShowHiddenProperties; InitParams.bCreateDisableEditOnInstanceNodes = bShouldShowDisableEditOnInstance; NewItemNode->InitNode( InitParams ); AddChildNode(NewItemNode); if( SinglePropertyName != NAME_None ) { // Generate no other children break; } } } } } }