Exemplo n.º 1
0
/**
 * 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;
}
Exemplo n.º 2
0
//-----------------------------------------------------------------------------
// 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 );
	}
}
Exemplo n.º 3
0
//-----------------------------------------------------------------------------
// 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 );
	}
}
Exemplo n.º 4
0
//-----------------------------------------------------------------------------
// 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;
}
Exemplo n.º 7
0
//-----------------------------------------------------------------------------
// 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();
}
Exemplo n.º 8
0
//-----------------------------------------------------------------------------
// 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;
}
Exemplo n.º 9
0
	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;
	}
Exemplo n.º 10
0
// 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"));
}
Exemplo n.º 11
0
// 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"));
}
Exemplo n.º 12
0
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());
}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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;
}
Exemplo n.º 16
0
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;
					}
				}
			}
		}
	}

}