You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
814 lines
28 KiB
C++
814 lines
28 KiB
C++
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "PropertyPath.h"
|
|
|
|
DECLARE_LOG_CATEGORY_EXTERN(LogPropertyNode, Log, All);
|
|
|
|
namespace EPropertyNodeFlags
|
|
{
|
|
typedef uint32 Type;
|
|
|
|
const Type IsSeen = 1 << 0; /** true if this node can be seen based on current parent expansion. Does not take into account clipping*/
|
|
const Type IsSeenDueToFiltering = 1 << 1; /** true if this node has been accepted by the filter*/
|
|
const Type IsSeenDueToChildFiltering = 1 << 2; /** true if this node or one of it's children is seen due to filtering. It will then be forced on as well.*/
|
|
const Type IsParentSeenDueToFiltering = 1 << 3; /** True if the parent was visible due to filtering*/
|
|
const Type IsSeenDueToChildFavorite = 1 << 4; /** True if this node is seen to it having a favorite as a child */
|
|
|
|
const Type Expanded = 1 << 5; /** true if this node should display its children*/
|
|
const Type CanBeExpanded = 1 << 6; /** true if this node is able to be expanded */
|
|
|
|
const Type EditInline = 1 << 7; /** true if the property can be expanded into the property window. */
|
|
|
|
const Type SingleSelectOnly = 1 << 8; /** true if only a single object is selected. */
|
|
const Type ShowCategories = 1 << 9; /** true if this node should show categories. Different*/
|
|
|
|
const Type HasEverBeenExpanded = 1 << 10; /** true if expand has ever been called on this node */
|
|
|
|
const Type IsBeingFiltered = 1 << 11; /** true if the node is being filtered. If this is true, seen flags should be checked for visibility. If this is false the node has no filter and is visible */
|
|
|
|
const Type IsFavorite = 1 << 12; /** true if this item has been dubbed a favorite by the user */
|
|
|
|
const Type NoChildrenDueToCircularReference= 1 << 13; /** true if this node has no children (but normally would) due to circular referencing */
|
|
|
|
const Type AutoExpanded = 1 << 14; /** true if this node was autoexpanded due to being filtered */
|
|
const Type ShouldShowHiddenProperties = 1 << 15; /** true if this node should all properties not just those with the correct flag(s) to be shown in the editor */
|
|
const Type IsAdvanced = 1 << 16; /** true if the property node is advanced (i.e it only shows up in advanced sections) */
|
|
const Type IsCustomized = 1 << 17; /** true if this node's visual representation has been customized by the editor */
|
|
|
|
const Type RequiresValidation = 1 << 18; /** true if this node could unexpectedly change (array changes, editinlinenew changes) */
|
|
const Type NoFlags = 0;
|
|
|
|
};
|
|
|
|
namespace FPropertyNodeConstants
|
|
{
|
|
const int32 NoDepthRestrictions = -1;
|
|
|
|
/** Character used to deliminate sub-categories in category path names */
|
|
const TCHAR CategoryDelimiterChar = TCHAR( ',' );
|
|
};
|
|
|
|
class FPropertySettings
|
|
{
|
|
public:
|
|
static FPropertySettings& Get();
|
|
bool ShowFriendlyPropertyNames() const { return bShowFriendlyPropertyNames; }
|
|
bool ShowHiddenProperties() const { return bShowHiddenProperties; }
|
|
bool ExpandDistributions() const { return bExpandDistributions; }
|
|
private:
|
|
FPropertySettings();
|
|
private:
|
|
bool bShowFriendlyPropertyNames;
|
|
bool bExpandDistributions;
|
|
bool bShowHiddenProperties;
|
|
};
|
|
|
|
class FPropertyItemValueDataTrackerSlate;
|
|
class FPropertyNode;
|
|
|
|
struct FAddressPair
|
|
{
|
|
FAddressPair(const UObject* InObject, uint8* Address, bool bInIsStruct)
|
|
: Object( InObject)
|
|
, ReadAddress( Address )
|
|
, bIsStruct(bInIsStruct)
|
|
{}
|
|
TWeakObjectPtr<const UObject> Object;
|
|
uint8* ReadAddress;
|
|
bool bIsStruct;
|
|
};
|
|
|
|
template<> struct TIsPODType<FAddressPair> { enum { Value = true }; };
|
|
|
|
struct FReadAddressListData
|
|
{
|
|
public:
|
|
FReadAddressListData()
|
|
: bAllValuesTheSame( false )
|
|
, bRequiresCache( true )
|
|
{
|
|
}
|
|
void Add(const UObject* Object, uint8* Address, bool bIsStruct = false)
|
|
{
|
|
ReadAddresses.Add(FAddressPair(Object, Address, bIsStruct));
|
|
}
|
|
|
|
int32 Num() const
|
|
{
|
|
return ReadAddresses.Num();
|
|
}
|
|
|
|
uint8* GetAddress( int32 Index )
|
|
{
|
|
const FAddressPair& Pair = ReadAddresses[Index];
|
|
return (Pair.Object.IsValid() || Pair.bIsStruct) ? Pair.ReadAddress : NULL;
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
ReadAddresses.Reset();
|
|
bAllValuesTheSame = false;
|
|
bRequiresCache = true;
|
|
}
|
|
|
|
bool bAllValuesTheSame;
|
|
bool bRequiresCache;
|
|
private:
|
|
TArray<FAddressPair> ReadAddresses;
|
|
};
|
|
|
|
/**
|
|
* A list of read addresses for a property node which contains the address for the nodes UProperty on each object
|
|
*/
|
|
class FReadAddressList
|
|
{
|
|
friend class FPropertyNode;
|
|
public:
|
|
FReadAddressList()
|
|
: ReadAddressListData( NULL )
|
|
{}
|
|
|
|
int32 Num() const
|
|
{
|
|
return (ReadAddressListData != NULL) ? ReadAddressListData->Num() : 0;
|
|
}
|
|
|
|
uint8* GetAddress( int32 Index )
|
|
{
|
|
return ReadAddressListData->GetAddress( Index );
|
|
}
|
|
|
|
void Reset()
|
|
{
|
|
if (ReadAddressListData != NULL)
|
|
{
|
|
ReadAddressListData->Reset();
|
|
}
|
|
}
|
|
|
|
private:
|
|
FReadAddressListData* ReadAddressListData;
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
* Parameters for initializing a property node
|
|
*/
|
|
struct FPropertyNodeInitParams
|
|
{
|
|
/** The parent of the property node */
|
|
TSharedPtr<FPropertyNode> ParentNode;
|
|
/** The property that the node observes and modifies*/
|
|
UProperty* Property;
|
|
/** Offset to the property data within either a fixed array or a dynamic array */
|
|
int32 ArrayOffset;
|
|
/** Index of the property in its array parent */
|
|
int32 ArrayIndex;
|
|
/** Whether or not to create any children */
|
|
bool bAllowChildren;
|
|
/** Whether or not to allow hidden properties (ones without CPF_Edit) to be visible */
|
|
bool bForceHiddenPropertyVisibility;
|
|
/** Whether or not to create category nodes (note: this setting is only valid for the root node of a property tree. The setting will propagate to children) */
|
|
bool bCreateCategoryNodes;
|
|
FPropertyNodeInitParams()
|
|
: ParentNode( NULL )
|
|
, Property( NULL )
|
|
, ArrayOffset(0)
|
|
, ArrayIndex( INDEX_NONE )
|
|
, bAllowChildren( true )
|
|
, bForceHiddenPropertyVisibility( false )
|
|
, bCreateCategoryNodes( true )
|
|
{}
|
|
};
|
|
|
|
/** Describes in which way an array property change has happend. This is used
|
|
for propagation of array property changes to the instances of archetype objects. */
|
|
struct EPropertyArrayChangeType
|
|
{
|
|
enum Type
|
|
{
|
|
/** A value was added to the array */
|
|
Add,
|
|
/** The array was cleared */
|
|
Clear,
|
|
/** A new item has been inserted. */
|
|
Insert,
|
|
/** An item has been deleted */
|
|
Delete,
|
|
/** An item has been duplicated */
|
|
Duplicate,
|
|
};
|
|
};
|
|
|
|
class FComplexPropertyNode;
|
|
|
|
/**
|
|
* The base class for all property nodes
|
|
*/
|
|
class FPropertyNode : public TSharedFromThis<FPropertyNode>
|
|
{
|
|
public:
|
|
|
|
enum DataValidationResult
|
|
{
|
|
/** The object(s) being viewed are now invalid */
|
|
ObjectInvalid,
|
|
/** Non dynamic array property nodes were added or removed that would require a refresh */
|
|
PropertiesChanged,
|
|
/** An edit inline new value changed, In the tree this rebuilds the nodes, in the details view we don't need to do this */
|
|
EditInlineNewValueChanged,
|
|
/** The size of an array changed (delete,insert,add) */
|
|
ArraySizeChanged,
|
|
/** All data is valid */
|
|
DataValid,
|
|
};
|
|
|
|
FPropertyNode(void);
|
|
virtual ~FPropertyNode(void);
|
|
|
|
/**
|
|
* Init Tree Node internally (used only derived classes to pass through variables that are common to all nodes
|
|
* @param InitParams Parameters for how the node should be initialized
|
|
*/
|
|
void InitNode( const FPropertyNodeInitParams& InitParams );
|
|
|
|
/**
|
|
* Indicates that children of this node should be rebuilt next tick. Some topology changes will require this
|
|
*/
|
|
void RequestRebuildChildren() { bRebuildChildrenRequested = true; }
|
|
|
|
/**
|
|
* Used for rebuilding this nodes children
|
|
*/
|
|
void RebuildChildren();
|
|
|
|
/**
|
|
* For derived windows to be able to add their nodes to the child array
|
|
*/
|
|
void AddChildNode( TSharedPtr<FPropertyNode> InNode);
|
|
|
|
/**
|
|
* Clears cached read address data
|
|
*/
|
|
void ClearCachedReadAddresses( bool bRecursive = true );
|
|
|
|
/**
|
|
* Interface function to get at the dervied FObjectPropertyNodeWx class
|
|
*/
|
|
virtual class FObjectPropertyNode* AsObjectNode() { return NULL; }
|
|
virtual const FObjectPropertyNode* AsObjectNode() const { return NULL; }
|
|
|
|
virtual FComplexPropertyNode* AsComplexNode() { return NULL; }
|
|
virtual const FComplexPropertyNode* AsComplexNode() const { return NULL; }
|
|
|
|
/**
|
|
* Interface function to get at the dervied FCategoryPropertyNodeWx class
|
|
*/
|
|
virtual class FCategoryPropertyNode* AsCategoryNode() { return NULL; }
|
|
|
|
/**
|
|
* Interface function to get at the dervied FItemPropertyNodeWx class
|
|
*/
|
|
virtual class FItemPropertyNode* AsItemPropertyNode() { return NULL; }
|
|
|
|
/**
|
|
* Follows the chain of items upwards until it finds the object window that houses this item.
|
|
*/
|
|
class FComplexPropertyNode* FindComplexParent();
|
|
const class FComplexPropertyNode* FindComplexParent() const;
|
|
|
|
class FObjectPropertyNode* FindObjectItemParent();
|
|
const class FObjectPropertyNode* FindObjectItemParent() const;
|
|
|
|
/**
|
|
* Follows the top-most object window that contains this property window item.
|
|
*/
|
|
class FObjectPropertyNode* FindRootObjectItemParent();
|
|
|
|
/**
|
|
* Used to see if any data has been destroyed from under the property tree. Should only be called during Tick
|
|
*/
|
|
FPropertyNode::DataValidationResult EnsureDataIsValid();
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//Flags
|
|
uint32 HasNodeFlags (const EPropertyNodeFlags::Type InTestFlags) const{ return PropertyNodeFlags & InTestFlags; }
|
|
/**
|
|
* Sets the flags used by the window and the root node
|
|
* @param InFlags - flags to turn on or off
|
|
* @param InOnOff - whether to toggle the bits on or off
|
|
*/
|
|
void SetNodeFlags (const EPropertyNodeFlags::Type InFlags, const bool InOnOff);
|
|
|
|
/**
|
|
* Finds a child of this property node
|
|
*
|
|
* @param InPropertyName The name of the property to find
|
|
* @param bRecurse true if we should recurse into children's children and so on.
|
|
*/
|
|
TSharedPtr<FPropertyNode> FindChildPropertyNode(const FName InPropertyName, bool bRecurse = false );
|
|
|
|
/**
|
|
* Returns the parent node in the hierarchy
|
|
*/
|
|
FPropertyNode* GetParentNode() { return ParentNodeWeakPtr.IsValid() ? ParentNodeWeakPtr.Pin().Get() : NULL; }
|
|
const FPropertyNode* GetParentNode() const { return ParentNodeWeakPtr.IsValid() ? ParentNodeWeakPtr.Pin().Get() : NULL; }
|
|
TSharedPtr<FPropertyNode> GetParentNodeSharedPtr() { return ParentNodeWeakPtr.Pin(); }
|
|
/**
|
|
* Returns the Property this Node represents
|
|
*/
|
|
UProperty* GetProperty() { return Property.Get(); }
|
|
const UProperty* GetProperty() const { return Property.Get(); }
|
|
|
|
/**
|
|
* Accessor functions for internals
|
|
*/
|
|
const int32 GetArrayOffset() const { return ArrayOffset; }
|
|
const int32 GetArrayIndex() const { return ArrayIndex; }
|
|
|
|
/**
|
|
* Return number of children that survived being filtered
|
|
*/
|
|
int32 GetNumChildNodes() const { return ChildNodes.Num(); }
|
|
|
|
/**
|
|
* Returns the matching Child node
|
|
*/
|
|
TSharedPtr<FPropertyNode>& GetChildNode(const int32 ChildIndex)
|
|
{
|
|
check(ChildNodes[ChildIndex].IsValid());
|
|
return ChildNodes[ChildIndex];
|
|
}
|
|
|
|
/**
|
|
* Returns the matching Child node
|
|
*/
|
|
const TSharedPtr<FPropertyNode>& GetChildNode(const int32 ChildIndex) const
|
|
{
|
|
check(ChildNodes[ChildIndex].IsValid());
|
|
return ChildNodes[ChildIndex];
|
|
}
|
|
|
|
/** @return whether this window's property is constant (can't be edited by the user) */
|
|
bool IsEditConst() const;
|
|
|
|
/**
|
|
* Gets the full name of this node
|
|
* @param PathPlusIndex - return value with full path of node
|
|
* @param bWithArrayIndex - If True, adds an array index (where appropriate)
|
|
* @param StopParent - Stop at this parent (if any). Does NOT include it in the path
|
|
* @param bIgnoreCategories - Skip over categories
|
|
*/
|
|
virtual bool GetQualifiedName( FString& PathPlusIndex, const bool bWithArrayIndex, const FPropertyNode* StopParent = nullptr, bool bIgnoreCategories = false ) const;
|
|
|
|
// The bArrayPropertiesCanDifferInSize 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.
|
|
bool GetReadAddress(
|
|
bool InRequiresSingleSelection,
|
|
FReadAddressList& OutAddresses,
|
|
bool bComparePropertyContents = true,
|
|
bool bObjectForceCompare = false,
|
|
bool bArrayPropertiesCanDifferInSize = false);
|
|
|
|
/**
|
|
* fills in the OutAddresses array with the addresses of all of the available objects.
|
|
* @param OutAddresses Storage array for all of the objects' addresses.
|
|
*/
|
|
bool GetReadAddress(FReadAddressList& OutAddresses);
|
|
|
|
/**
|
|
* Gets read addresses without accessing cached data. Is less efficient but gets the must up to date data
|
|
*/
|
|
virtual bool GetReadAddressUncached(FPropertyNode& InNode, bool InRequiresSingleSelection, FReadAddressListData& OutAddresses, bool bComparePropertyContents = true, bool bObjectForceCompare = false, bool bArrayPropertiesCanDifferInSize = false) const;
|
|
virtual bool GetReadAddressUncached(FPropertyNode& InNode, FReadAddressListData& OutAddresses) const;
|
|
|
|
/**
|
|
* Calculates the memory address for the data associated with this item's property. This is typically the value of a UProperty or a UObject address.
|
|
*
|
|
* @param StartAddress the location to use as the starting point for the calculation; typically the address of the object that contains this property.
|
|
*
|
|
* @return a pointer to a UProperty value or UObject. (For dynamic arrays, you'd cast this value to an FArray*)
|
|
*/
|
|
virtual uint8* GetValueBaseAddress( uint8* Base );
|
|
|
|
/**
|
|
* Calculates the memory address for the data associated with this item's value. For most properties, identical to GetValueBaseAddress. For items corresponding
|
|
* to dynamic array elements, the pointer returned will be the location for that element's data.
|
|
*
|
|
* @return a pointer to a UProperty value or UObject. (For dynamic arrays, you'd cast this value to whatever type is the Inner for the dynamic array)
|
|
*/
|
|
virtual uint8* GetValueAddress( uint8* Base );
|
|
|
|
/**
|
|
* Sets the display name override to use instead of the display name
|
|
*/
|
|
virtual void SetDisplayNameOverride( const FString& InDisplayNameOverride ) {}
|
|
|
|
/**
|
|
* @return The formatted display name for the property in this node
|
|
*/
|
|
virtual FString GetDisplayName() const { return FString(); }
|
|
|
|
/**
|
|
* Sets the tooltip override to use instead of the property tooltip
|
|
*/
|
|
virtual void SetToolTipOverride( const FString& InToolTipOverride ) {}
|
|
|
|
/**
|
|
* @return The tooltip for the property in this node
|
|
*/
|
|
virtual FString GetToolTipText() const { return FString(); }
|
|
|
|
/**
|
|
* If there is a property, sees if it matches. Otherwise sees if the entire parent structure matches
|
|
*/
|
|
bool GetDiffersFromDefault();
|
|
|
|
/**
|
|
* @return The label for displaying a reset to default value
|
|
*/
|
|
FText GetResetToDefaultLabel();
|
|
|
|
/**
|
|
* If there is a property, resets it to default. Otherwise resets the entire parent structure
|
|
*/
|
|
void ResetToDefault( FNotifyHook* InNotifyHook );
|
|
|
|
/**Walks up the hierarchy and return true if any parent node is a favorite*/
|
|
bool IsChildOfFavorite (void) const;
|
|
|
|
void NotifyPreChange( UProperty* PropertyAboutToChange, class FNotifyHook* InNotifyHook );
|
|
|
|
void NotifyPostChange( FPropertyChangedEvent& InPropertyChangedEvent, class FNotifyHook* InNotifyHook );
|
|
|
|
void SetOnRebuildChildren( FSimpleDelegate InOnRebuildChildren );
|
|
|
|
/**
|
|
* Propagates the property change to all instances of an archetype
|
|
*
|
|
* @param ModifiedObject Object which property has been modified
|
|
* @param NewValue New value of the property
|
|
* @param PreviousValue Value of the property before the modification
|
|
*/
|
|
void PropagatePropertyChange( UObject* ModifiedObject, const TCHAR* NewValue, const FString& PreviousValue);
|
|
|
|
/**
|
|
* Propagates the property change of an array property to all instances of an archetype
|
|
*
|
|
* @param ModifiedObject Object which property has been modified
|
|
* @param OriginalArrayContent Original content of the array before the modification ( as returned by ExportText_Direct )
|
|
* @param ChangeType In which way was the array modified
|
|
* @param Index Index of the modified item
|
|
*/
|
|
void PropagateArrayPropertyChange( UObject* ModifiedObject, const FString& OriginalArrayContent,
|
|
EPropertyArrayChangeType::Type ChangeType, int32 Index);
|
|
|
|
/** Broadcasts when a property value changes */
|
|
DECLARE_EVENT( FPropertyNode, FPropertyValueChangedEvent );
|
|
FPropertyValueChangedEvent& OnPropertyValueChanged() { return PropertyValueChangedEvent; }
|
|
|
|
/**
|
|
* Marks window's seem due to filtering flags
|
|
* @param InFilterStrings - List of strings that must be in the property name in order to display
|
|
* Empty InFilterStrings means display as normal
|
|
* All strings must match in order to be accepted by the filter
|
|
* @param bParentAllowsVisible - is NOT true for an expander that is NOT expanded
|
|
*/
|
|
void FilterNodes(const TArray<FString>& InFilterStrings, const bool bParentSeenDueToFiltering = false);
|
|
|
|
/**
|
|
* Marks windows as visible based on the filter strings or standard visibility
|
|
*
|
|
* @param bParentAllowsVisible - is NOT true for an expander that is NOT expanded
|
|
*/
|
|
void ProcessSeenFlags(const bool bParentAllowsVisible);
|
|
|
|
/**
|
|
* Marks windows as visible based their favorites status
|
|
*/
|
|
void ProcessSeenFlagsForFavorites(void);
|
|
|
|
/**
|
|
* @return true if this node should be visible in a tree
|
|
*/
|
|
bool IsVisible() const { return HasNodeFlags( EPropertyNodeFlags::IsBeingFiltered ) == 0 || HasNodeFlags( EPropertyNodeFlags::IsSeen ) || HasNodeFlags( EPropertyNodeFlags::IsSeenDueToChildFiltering ); };
|
|
|
|
static TSharedRef< FPropertyPath > CreatePropertyPath( const TSharedRef< FPropertyNode >& PropertyNode )
|
|
{
|
|
TArray< FPropertyInfo > Properties;
|
|
FPropertyNode* CurrentNode = &PropertyNode.Get();
|
|
while ( CurrentNode != NULL )
|
|
{
|
|
if ( CurrentNode->AsItemPropertyNode() != NULL )
|
|
{
|
|
FPropertyInfo NewPropInfo;
|
|
NewPropInfo.Property = CurrentNode->GetProperty();
|
|
NewPropInfo.ArrayIndex = CurrentNode->GetArrayIndex();
|
|
|
|
Properties.Add( NewPropInfo );
|
|
}
|
|
|
|
CurrentNode = CurrentNode->GetParentNode();
|
|
}
|
|
|
|
TSharedRef< FPropertyPath > NewPath = MakeShareable( new FPropertyPath() );
|
|
|
|
for( int PropertyIndex = Properties.Num() - 1; PropertyIndex >= 0; --PropertyIndex )
|
|
{
|
|
NewPath->AddProperty( Properties[ PropertyIndex ] );
|
|
}
|
|
|
|
return NewPath;
|
|
}
|
|
|
|
static TSharedPtr< FPropertyNode > FindPropertyNodeByPath( const TSharedPtr< FPropertyPath > Path, const TSharedRef< FPropertyNode >& StartingNode )
|
|
{
|
|
if ( !Path.IsValid() || Path->GetNumProperties() == 0 )
|
|
{
|
|
return StartingNode;
|
|
}
|
|
|
|
bool FailedToFindProperty = false;
|
|
TSharedPtr< FPropertyNode > PropertyNode = StartingNode;
|
|
for (int PropertyIndex = 0; PropertyIndex < Path->GetNumProperties() && !FailedToFindProperty; PropertyIndex++)
|
|
{
|
|
FailedToFindProperty = true;
|
|
const FPropertyInfo& PropInfo = Path->GetPropertyInfo( PropertyIndex );
|
|
|
|
TArray< TSharedRef< FPropertyNode > > ChildrenStack;
|
|
ChildrenStack.Push( PropertyNode.ToSharedRef() );
|
|
while ( ChildrenStack.Num() > 0 )
|
|
{
|
|
const TSharedRef< FPropertyNode > CurrentNode = ChildrenStack.Pop();
|
|
|
|
for( int32 ChildIndex = 0; ChildIndex < CurrentNode->GetNumChildNodes(); ++ChildIndex )
|
|
{
|
|
const TSharedPtr< FPropertyNode > ChildNode = CurrentNode->GetChildNode( ChildIndex );
|
|
|
|
if ( ChildNode->AsItemPropertyNode() == NULL )
|
|
{
|
|
ChildrenStack.Add( ChildNode.ToSharedRef() );
|
|
}
|
|
else if ( ChildNode.IsValid() &&
|
|
ChildNode->GetProperty() == PropInfo.Property.Get() &&
|
|
ChildNode->GetArrayIndex() == PropInfo.ArrayIndex )
|
|
{
|
|
PropertyNode = ChildNode;
|
|
FailedToFindProperty = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( FailedToFindProperty )
|
|
{
|
|
PropertyNode = NULL;
|
|
}
|
|
|
|
return PropertyNode;
|
|
}
|
|
|
|
|
|
static TArray< FPropertyInfo > GetPossibleExtensionsForPath( const TSharedPtr< FPropertyPath > Path, const TSharedRef< FPropertyNode >& StartingNode )
|
|
{
|
|
TArray< FPropertyInfo > PossibleExtensions;
|
|
TSharedPtr< FPropertyNode > PropertyNode = FindPropertyNodeByPath( Path, StartingNode );
|
|
|
|
if ( !PropertyNode.IsValid() )
|
|
{
|
|
return PossibleExtensions;
|
|
}
|
|
|
|
for( int32 ChildIndex = 0; ChildIndex < PropertyNode->GetNumChildNodes(); ++ChildIndex )
|
|
{
|
|
TSharedPtr< FPropertyNode > CurrentNode = PropertyNode->GetChildNode( ChildIndex );
|
|
|
|
if ( CurrentNode.IsValid() && CurrentNode->AsItemPropertyNode() != NULL )
|
|
{
|
|
FPropertyInfo NewPropInfo;
|
|
NewPropInfo.Property = CurrentNode->GetProperty();
|
|
NewPropInfo.ArrayIndex = CurrentNode->GetArrayIndex();
|
|
|
|
bool AlreadyExists = false;
|
|
for( auto ExtensionIter = PossibleExtensions.CreateConstIterator(); ExtensionIter; ++ExtensionIter )
|
|
{
|
|
if ( *ExtensionIter == NewPropInfo )
|
|
{
|
|
AlreadyExists = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( !AlreadyExists )
|
|
{
|
|
PossibleExtensions.Add( NewPropInfo );
|
|
}
|
|
}
|
|
}
|
|
|
|
return PossibleExtensions;
|
|
}
|
|
|
|
/**
|
|
* Adds a restriction to the possible values for this property.
|
|
* @param Restriction The restriction being added to this property.
|
|
*/
|
|
virtual void AddRestriction( TSharedRef<const class FPropertyRestriction> Restriction );
|
|
|
|
/**
|
|
* Tests if a value is restricted for this property
|
|
* @param Value The value to test for restriction.
|
|
* @return True if this value is restricted.
|
|
*/
|
|
virtual bool IsRestricted(const FString& Value) const;
|
|
|
|
/**
|
|
* Tests if a value is restricted for this property.
|
|
* @param Value The value to test for restriction.
|
|
* @param OutReasons Outputs an array of the reasons why this value is restricted.
|
|
* @return True if this value is restricted.
|
|
*/
|
|
virtual bool IsRestricted(const FString& Value, TArray<FText>& OutReasons) const;
|
|
|
|
/**
|
|
* Generates a consistent tooltip describing this restriction for use in the editor.
|
|
* @param Value The value to test for restriction and generate the tooltip from.
|
|
* @param OutTooltip The tooltip describing why this value is restricted.
|
|
* @return True if this value is restricted.
|
|
*/
|
|
virtual bool GenerateRestrictionToolTip(const FString& Value, FText& OutTooltip)const;
|
|
|
|
const TArray<TSharedRef<const class FPropertyRestriction>>& GetRestrictions() const
|
|
{
|
|
return Restrictions;
|
|
}
|
|
|
|
FPropertyChangedEvent& FixPropertiesInEvent(FPropertyChangedEvent& Event);
|
|
|
|
/** Returns true if this property node should be highlighted by the view */
|
|
bool IsHighlighted() const { return bIsHighlighted; }
|
|
|
|
/** Sets the highlighted flag to the requested value */
|
|
void SetIsHighlighted( bool bInIsHighlighted ) { bIsHighlighted = bInIsHighlighted; }
|
|
|
|
/** Returns the IDetailTreeNode associated with this property node */
|
|
TSharedPtr< class IDetailTreeNode > GetTreeNode() { return TreeNode.Pin(); }
|
|
|
|
/** Sets the IDetailTreeNode associated with this property node */
|
|
void SetTreeNode( TSharedPtr< class IDetailTreeNode > InTreeNode ) { TreeNode = InTreeNode; }
|
|
|
|
protected:
|
|
|
|
TSharedRef<FEditPropertyChain> BuildPropertyChain( UProperty* PropertyAboutToChange );
|
|
|
|
/**
|
|
* Destroys all node within the hierarchy
|
|
*/
|
|
void DestroyTree(const bool bInDestroySelf=true);
|
|
|
|
/**
|
|
* Interface function for Custom Setup of Node (priot to node flags being set)
|
|
*/
|
|
virtual void InitBeforeNodeFlags () {};
|
|
|
|
/**
|
|
* Interface function for Custom expansion Flags. Default is objects and categories which always expand
|
|
*/
|
|
virtual void InitExpansionFlags (){ SetNodeFlags(EPropertyNodeFlags::CanBeExpanded, true); };
|
|
|
|
/**
|
|
* Interface function for Creating Child Nodes
|
|
*/
|
|
virtual void InitChildNodes() = 0;
|
|
|
|
/**
|
|
* Does the string compares to ensure this Name is acceptable to the filter that is passed in
|
|
*/
|
|
bool IsFilterAcceptable(const TArray<FString>& InAcceptableNames, const TArray<FString>& InFilterStrings);
|
|
/**
|
|
* Make sure that parent nodes are expanded
|
|
*/
|
|
void ExpandParent( bool bInRecursive );
|
|
|
|
/** @return The property stored at this node, to be passed to Pre/PostEditChange. */
|
|
UProperty* GetStoredProperty() { return NULL; }
|
|
|
|
bool GetDiffersFromDefaultForObject( FPropertyItemValueDataTrackerSlate& ValueTracker, UProperty* InProperty );
|
|
|
|
FString GetDefaultValueAsStringForObject( FPropertyItemValueDataTrackerSlate& ValueTracker, UObject* InObject, UProperty* InProperty );
|
|
|
|
/**
|
|
* Gets the default value of the property as string.
|
|
*/
|
|
FString GetDefaultValueAsString();
|
|
|
|
/**
|
|
* Helper function to obtain the display name for an enum property
|
|
* @param InEnum The enum whose metadata to pull from
|
|
* @param DisplayName The name of the enum value to adjust
|
|
*
|
|
* @return true if the DisplayName has been changed
|
|
*/
|
|
bool AdjustEnumPropDisplayName( UEnum *InEnum, FString& DisplayName ) const;
|
|
|
|
/**
|
|
* Helper function for derived members to be able to
|
|
* broadcast property changed notifications
|
|
*/
|
|
void BroadcastPropertyValueChanged() const;
|
|
|
|
/**
|
|
* Gets a value tracker for the default of this property in the passed in object
|
|
*
|
|
* @param Object The object to get the value for
|
|
* @param ObjIndex The index of the object in the parent property node's object array (for caching)
|
|
*/
|
|
TSharedPtr< FPropertyItemValueDataTrackerSlate > GetValueTracker( UObject* Object, uint32 ObjIndex );
|
|
protected:
|
|
/**
|
|
* The node that is the parent of this node or NULL for the root
|
|
*/
|
|
TWeakPtr<FPropertyNode> ParentNodeWeakPtr;
|
|
//@todo consolidate with ParentNodeWeakPtr, ParentNode is legacy
|
|
FPropertyNode* ParentNode;
|
|
|
|
/** Cached read addresses for this property node */
|
|
FReadAddressListData CachedReadAddresses;
|
|
|
|
/** List of per object default value trackers associated with this property node */
|
|
TArray< TSharedPtr<FPropertyItemValueDataTrackerSlate> > ObjectDefaultValueTrackers;
|
|
|
|
/** List of all child nodes this node is responsible for */
|
|
TArray< TSharedPtr<FPropertyNode> > ChildNodes;
|
|
|
|
/** Called when this node's children are rebuilt */
|
|
FSimpleDelegate OnRebuildChildren;
|
|
|
|
/** Called when this node's property value has changed (called during NotifyPostChange) */
|
|
FPropertyValueChangedEvent PropertyValueChangedEvent;
|
|
|
|
/** The property being displayed/edited. */
|
|
TWeakObjectPtr<UProperty> Property;
|
|
|
|
/** Offset to the property data within either a fixed array or a dynamic array */
|
|
int32 ArrayOffset;
|
|
|
|
/** The index of the property if it is inside an array */
|
|
int32 ArrayIndex;
|
|
|
|
/** Safety Value representing Depth in the property tree used to stop diabolical topology cases
|
|
* -1 = No limit on children
|
|
* 0 = No more children are allowed. Do not process child nodes
|
|
* >0 = A limit has been set by the property and will tick down for successive children
|
|
*/
|
|
int32 MaxChildDepthAllowed;
|
|
|
|
/**
|
|
* Used for flags to determine if the node is seen (if not seen and never been created, don't create it on display)
|
|
*/
|
|
EPropertyNodeFlags::Type PropertyNodeFlags;
|
|
|
|
/** If true, children of this node will be rebuilt next tick. */
|
|
bool bRebuildChildrenRequested;
|
|
|
|
/** Used to display a highlight on this node */
|
|
bool bIsHighlighted;
|
|
|
|
/** An array of restrictions limiting this property's potential values in property editors.*/
|
|
TArray<TSharedRef<const class FPropertyRestriction>> Restrictions;
|
|
|
|
/** Optional reference to a tree node that is displaying this property */
|
|
TWeakPtr< class IDetailTreeNode > TreeNode;
|
|
};
|
|
|
|
class FComplexPropertyNode : public FPropertyNode
|
|
{
|
|
public:
|
|
|
|
enum EPropertyType
|
|
{
|
|
EPT_Object,
|
|
EPT_StandaloneStructure,
|
|
};
|
|
|
|
FComplexPropertyNode() : FPropertyNode() {}
|
|
virtual ~FComplexPropertyNode() {}
|
|
|
|
virtual FComplexPropertyNode* AsComplexNode() override{ return this; }
|
|
virtual const FComplexPropertyNode* AsComplexNode() const override{ return this; }
|
|
|
|
virtual UStruct* GetBaseStructure() = 0;
|
|
virtual const UStruct* GetBaseStructure() const = 0;
|
|
|
|
virtual int32 GetInstancesNum() const = 0;
|
|
virtual uint8* GetMemoryOfInstance(int32 Index) = 0;
|
|
virtual TWeakObjectPtr<UObject> GetInstanceAsUObject(int32 Index) = 0;
|
|
virtual EPropertyType GetPropertyType() const = 0;
|
|
|
|
virtual void Disconnect() = 0;
|
|
};
|