Files
UnrealEngineUWP/Engine/Source/Editor/PropertyEditor/Private/StructurePropertyNode.cpp
mikko mononen 410e700e79 Added EnsureDataIsValid() for structure property node
- Extended  the EnsureDataIsValid() to

#preflight 645356cbd863ba2621614cca

[CL 25331981 by mikko mononen in ue5-main branch]
2023-05-04 04:47:23 -04:00

122 lines
4.3 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "StructurePropertyNode.h"
#include "ItemPropertyNode.h"
#include "PropertyEditorHelpers.h"
void FStructurePropertyNode::InitChildNodes()
{
const bool bShouldShowHiddenProperties = !!HasNodeFlags(EPropertyNodeFlags::ShouldShowHiddenProperties);
const bool bShouldShowDisableEditOnInstance = !!HasNodeFlags(EPropertyNodeFlags::ShouldShowDisableEditOnInstance);
const UStruct* Struct = GetBaseStructure();
TArray<FProperty*> StructMembers;
for (TFieldIterator<FProperty> It(Struct); It; ++It)
{
FProperty* StructMember = *It;
if (PropertyEditorHelpers::ShouldBeVisible(*this, StructMember))
{
StructMembers.Add(StructMember);
}
}
PropertyEditorHelpers::OrderPropertiesFromMetadata(StructMembers);
for (FProperty* StructMember : StructMembers)
{
TSharedPtr<FItemPropertyNode> NewItemNode(new FItemPropertyNode);
FPropertyNodeInitParams InitParams;
InitParams.ParentNode = SharedThis(this);
InitParams.Property = StructMember;
InitParams.ArrayOffset = 0;
InitParams.ArrayIndex = INDEX_NONE;
InitParams.bAllowChildren = true;
InitParams.bForceHiddenPropertyVisibility = bShouldShowHiddenProperties;
InitParams.bCreateDisableEditOnInstanceNodes = bShouldShowDisableEditOnInstance;
InitParams.bCreateCategoryNodes = false;
NewItemNode->InitNode(InitParams);
AddChildNode(NewItemNode);
}
}
uint8* FStructurePropertyNode::GetValueBaseAddress(uint8* StartAddress, bool bIsSparseData, bool bIsStruct) const
{
// If called with struct data, we expect that it is compatible with the first structure node down in the property node chain, return the address as is.
// This gets called usually when the calling code is dealing with a parent complex node.
if (bIsStruct)
{
return StartAddress;
}
if (StructProvider)
{
// Assume that this code gets called with an object or object sparse data.
//
// The passed object might not be the one that contains the values provided by struct provider.
// For example this function might get called on an edited object's template object.
// In that case the data structure is expected to match between the data edited by this node and the foreign object.
// If the structure provider is set up as indirection, then it knows how to translate parent node's value address to
// new value address even on data that is not the same as in the structure provider.
if (StructProvider->IsPropertyIndirection())
{
const TSharedPtr<FPropertyNode> ParentNode = ParentNodeWeakPtr.Pin();
if (!ensureMsgf(ParentNode, TEXT("Expecting valid parent node when indirection structure provider is called with Object data.")))
{
return nullptr;
}
// Resolve from parent nodes data.
uint8* ParentValueAddress = ParentNode->GetValueAddress(StartAddress, bIsSparseData);
uint8* ValueAddress = StructProvider->GetValueBaseAddress(ParentValueAddress, GetBaseStructure());
return ValueAddress;
}
// The struct is really standalone, in which case we always return the standalone struct data.
// In that case we can only support one instance, since we cannot discern them.
// Note: Multiple standalone structure instances are supported when bIsStruct is true (e.g. when the structure property is root node).
TArray<TSharedPtr<FStructOnScope>> Instances;
StructProvider->GetInstances(Instances);
ensureMsgf(Instances.Num() <= 1, TEXT("Expecting max one instance on standalone structure provider."));
if (Instances.Num() == 1 && Instances[0].IsValid())
{
return Instances[0]->GetStructMemory();
}
}
return nullptr;
}
EPropertyDataValidationResult FStructurePropertyNode::EnsureDataIsValid()
{
CachedReadAddresses.Reset();
const UStruct* BaseStruct = GetBaseStructure();
// Check that struct node's children still belong to the current base struct.
for (const TSharedPtr<FPropertyNode>& ChildNode : ChildNodes)
{
if (ChildNode.IsValid())
{
if (const FProperty* ChildProperty = ChildNode->GetProperty())
{
const UStruct* OwnerStruct = ChildProperty->GetOwnerStruct();
if (!OwnerStruct
|| OwnerStruct->IsStructTrashed()
|| !BaseStruct
|| !BaseStruct->IsChildOf(OwnerStruct)) // OwnerStruct can be BaseStruct or one of structs BaseStruct is derived from.
{
RebuildChildren();
return EPropertyDataValidationResult::ChildrenRebuilt;
}
}
}
}
return FPropertyNode::EnsureDataIsValid();
}