3892 lines
150 KiB
C++
3892 lines
150 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
Class.h: UClass definition.
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "CoreMinimal.h"
|
|
|
|
#include "Concepts/GetTypeHashable.h"
|
|
#include "Math/RandomStream.h"
|
|
#include "Misc/EnumClassFlags.h"
|
|
#include "Misc/FallbackStruct.h"
|
|
#include "Misc/Guid.h"
|
|
#include "Misc/Optional.h"
|
|
#include "Misc/ScopeRWLock.h"
|
|
#include "Templates/IsAbstract.h"
|
|
#include "Templates/IsEnum.h"
|
|
#include "Templates/Models.h"
|
|
#include "UObject/CoreNative.h"
|
|
#include "UObject/GarbageCollection.h"
|
|
#include "UObject/Object.h"
|
|
#include "UObject/ObjectMacros.h"
|
|
#include "UObject/ReflectedTypeAccessors.h"
|
|
#include "UObject/Script.h"
|
|
#include "UObject/UObjectGlobals.h"
|
|
#include "UObject/FieldPath.h"
|
|
|
|
struct FCustomPropertyListNode;
|
|
struct FFrame;
|
|
struct FNetDeltaSerializeInfo;
|
|
struct FObjectInstancingGraph;
|
|
struct FPropertyTag;
|
|
class FField;
|
|
class UPropertyWrapper;
|
|
|
|
COREUOBJECT_API DECLARE_LOG_CATEGORY_EXTERN(LogClass, Log, All);
|
|
COREUOBJECT_API DECLARE_LOG_CATEGORY_EXTERN(LogScriptSerialization, Log, All);
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FRepRecord.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
//
|
|
// Information about a property to replicate.
|
|
//
|
|
struct FRepRecord
|
|
{
|
|
FProperty* Property;
|
|
int32 Index;
|
|
FRepRecord(FProperty* InProperty, int32 InIndex)
|
|
: Property(InProperty), Index(InIndex)
|
|
{}
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
UField.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
//
|
|
// Base class of reflection data objects.
|
|
//
|
|
class COREUOBJECT_API UField: public UObject
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC(UField, UObject, CLASS_Abstract, TEXT("/Script/CoreUObject"), CASTCLASS_UField)
|
|
|
|
typedef UField BaseFieldClass;
|
|
typedef UClass FieldTypeClass;
|
|
|
|
/** Next Field in the linked list */
|
|
UField* Next;
|
|
|
|
// Constructors.
|
|
UField(EStaticConstructor, EObjectFlags InFlags);
|
|
|
|
// UObject interface.
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
virtual void PostLoad() override;
|
|
virtual bool NeedsLoadForClient() const override;
|
|
virtual bool NeedsLoadForServer() const override;
|
|
|
|
// UField interface.
|
|
virtual void AddCppProperty(FProperty* Property);
|
|
virtual void Bind();
|
|
|
|
/** Goes up the outer chain to look for a UClass */
|
|
UClass* GetOwnerClass() const;
|
|
|
|
/** Goes up the outer chain to look for a UStruct */
|
|
UStruct* GetOwnerStruct() const;
|
|
|
|
/**
|
|
* Returns a human readable string that was assigned to this field at creation.
|
|
* By default this is the same as GetName() but it can be overridden if that is an internal-only name.
|
|
* This name is consistent in editor/cooked builds, is not localized, and is useful for data import/export.
|
|
*/
|
|
FString GetAuthoredName() const;
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
/**
|
|
* Finds the localized display name or native display name as a fallback.
|
|
*
|
|
* @return The display name for this object.
|
|
*/
|
|
FText GetDisplayNameText() const;
|
|
|
|
/**
|
|
* Finds the localized tooltip or native tooltip as a fallback.
|
|
*
|
|
* @param bShortTooltip Look for a shorter version of the tooltip (falls back to the long tooltip if none was specified)
|
|
*
|
|
* @return The tooltip for this object.
|
|
*/
|
|
FText GetToolTipText(bool bShortTooltip = false) const;
|
|
|
|
/**
|
|
* Formats a source comment into the form we want to show in the editor, is used by GetToolTipText and anything else that will get a native tooltip
|
|
*
|
|
* @param ToolTipString String parsed out of C++ headers that is modified in place
|
|
* @param bRemoveExtraSections If true, cut off the comment on first line separator or 2 empty lines in a row
|
|
*/
|
|
static void FormatNativeToolTip(FString& ToolTipString, bool bRemoveExtraSections = true);
|
|
|
|
/**
|
|
* Determines if the property has any metadata associated with the key
|
|
*
|
|
* @param Key The key to lookup in the metadata
|
|
* @return true if there is a (possibly blank) value associated with this key
|
|
*/
|
|
bool HasMetaData(const TCHAR* Key) const { return FindMetaData(Key) != nullptr; }
|
|
bool HasMetaData(const FName& Key) const { return FindMetaData(Key) != nullptr; }
|
|
|
|
/**
|
|
* Find the metadata value associated with the key
|
|
*
|
|
* @param Key The key to lookup in the metadata
|
|
* @return The value associated with the key if exists, null otherwise
|
|
*/
|
|
const FString* FindMetaData(const TCHAR* Key) const;
|
|
const FString* FindMetaData(const FName& Key) const;
|
|
|
|
/**
|
|
* Find the metadata value associated with the key
|
|
*
|
|
* @param Key The key to lookup in the metadata
|
|
* @return The value associated with the key
|
|
*/
|
|
const FString& GetMetaData(const TCHAR* Key) const;
|
|
const FString& GetMetaData(const FName& Key) const;
|
|
|
|
/**
|
|
* Find the metadata value associated with the key and localization namespace and key
|
|
*
|
|
* @param Key The key to lookup in the metadata
|
|
* @param LocalizationNamespace Namespace to lookup in the localization manager
|
|
* @param LocalizationKey Key to lookup in the localization manager
|
|
* @return Localized metadata if available, defaults to whatever is provided via GetMetaData
|
|
*/
|
|
FText GetMetaDataText(const TCHAR* MetaDataKey, const FString LocalizationNamespace = FString(), const FString LocalizationKey = FString()) const;
|
|
FText GetMetaDataText(const FName& MetaDataKey, const FString LocalizationNamespace = FString(), const FString LocalizationKey = FString()) const;
|
|
|
|
/**
|
|
* Sets the metadata value associated with the key
|
|
*
|
|
* @param Key The key to lookup in the metadata
|
|
* @return The value associated with the key
|
|
*/
|
|
void SetMetaData(const TCHAR* Key, const TCHAR* InValue);
|
|
void SetMetaData(const FName& Key, const TCHAR* InValue);
|
|
|
|
/**
|
|
* Find the metadata value associated with the key
|
|
* and return bool
|
|
* @param Key The key to lookup in the metadata
|
|
* @return return true if the value was true (case insensitive)
|
|
*/
|
|
bool GetBoolMetaData(const TCHAR* Key) const
|
|
{
|
|
const FString& BoolString = GetMetaData(Key);
|
|
// FString == operator does case insensitive comparison
|
|
return (BoolString == "true");
|
|
}
|
|
bool GetBoolMetaData(const FName& Key) const
|
|
{
|
|
const FString& BoolString = GetMetaData(Key);
|
|
// FString == operator does case insensitive comparison
|
|
return (BoolString == "true");
|
|
}
|
|
|
|
/**
|
|
* Find the metadata value associated with the key
|
|
* and return int32
|
|
* @param Key The key to lookup in the metadata
|
|
* @return the int value stored in the metadata. 0 if not a valid integer.
|
|
*/
|
|
int32 GetIntMetaData(const TCHAR* Key) const
|
|
{
|
|
const FString& IntString = GetMetaData(Key);
|
|
int32 Value = FCString::Atoi(*IntString);
|
|
return Value;
|
|
}
|
|
int32 GetIntMetaData(const FName& Key) const
|
|
{
|
|
const FString& IntString = GetMetaData(Key);
|
|
int32 Value = FCString::Atoi(*IntString);
|
|
return Value;
|
|
}
|
|
|
|
/**
|
|
* Find the metadata value associated with the key
|
|
* and return float
|
|
* @param Key The key to lookup in the metadata
|
|
* @return the float value stored in the metadata. 0 if not a valid float.
|
|
*/
|
|
float GetFloatMetaData(const TCHAR* Key) const
|
|
{
|
|
const FString& FloatString = GetMetaData(Key);
|
|
float Value = FCString::Atof(*FloatString);
|
|
return Value;
|
|
}
|
|
float GetFloatMetaData(const FName& Key) const
|
|
{
|
|
const FString& FloatString = GetMetaData(Key);
|
|
float Value = FCString::Atof(*FloatString);
|
|
return Value;
|
|
}
|
|
|
|
/**
|
|
* Find the metadata value associated with the key
|
|
* and return Class
|
|
* @param Key The key to lookup in the metadata
|
|
* @return the class value stored in the metadata.
|
|
*/
|
|
UClass* GetClassMetaData(const TCHAR* Key) const;
|
|
UClass* GetClassMetaData(const FName& Key) const;
|
|
|
|
/** Clear any metadata associated with the key */
|
|
void RemoveMetaData(const TCHAR* Key);
|
|
void RemoveMetaData(const FName& Key);
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|
|
bool HasAnyCastFlags(const uint64 InCastFlags) const;
|
|
bool HasAllCastFlags(const uint64 InCastFlags) const;
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
/**
|
|
* Gets the FField object associated with this Field
|
|
*/
|
|
virtual FField* GetAssociatedFField();
|
|
/**
|
|
* Sets the FField object associated with this Field
|
|
*/
|
|
virtual void SetAssociatedFField(FField* InField);
|
|
#endif // WITH_EDITORONLY_DATA
|
|
};
|
|
|
|
#if USTRUCT_FAST_ISCHILDOF_IMPL == USTRUCT_ISCHILDOF_STRUCTARRAY
|
|
class FStructBaseChain
|
|
{
|
|
protected:
|
|
COREUOBJECT_API FStructBaseChain();
|
|
COREUOBJECT_API ~FStructBaseChain();
|
|
|
|
// Non-copyable
|
|
FStructBaseChain(const FStructBaseChain&) = delete;
|
|
FStructBaseChain& operator=(const FStructBaseChain&) = delete;
|
|
|
|
COREUOBJECT_API void ReinitializeBaseChainArray();
|
|
|
|
FORCEINLINE bool IsChildOfUsingStructArray(const FStructBaseChain& Parent) const
|
|
{
|
|
int32 NumParentStructBasesInChainMinusOne = Parent.NumStructBasesInChainMinusOne;
|
|
return NumParentStructBasesInChainMinusOne <= NumStructBasesInChainMinusOne && StructBaseChainArray[NumParentStructBasesInChainMinusOne] == &Parent;
|
|
}
|
|
|
|
private:
|
|
FStructBaseChain** StructBaseChainArray;
|
|
int32 NumStructBasesInChainMinusOne;
|
|
|
|
friend class UStruct;
|
|
};
|
|
#endif
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
UStruct.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Base class for all UObject types that contain fields.
|
|
*/
|
|
class COREUOBJECT_API UStruct: public UField
|
|
#if USTRUCT_FAST_ISCHILDOF_IMPL == USTRUCT_ISCHILDOF_STRUCTARRAY
|
|
, private FStructBaseChain
|
|
#endif
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC(UStruct, UField, CLASS_MatchedSerializers, TEXT("/Script/CoreUObject"), CASTCLASS_UStruct)
|
|
|
|
// Variables.
|
|
protected:
|
|
friend struct Z_Construct_UClass_UStruct_Statics;
|
|
|
|
private:
|
|
/** Struct this inherits from, may be null */
|
|
UStruct* SuperStruct;
|
|
|
|
public:
|
|
/** Pointer to start of linked list of child fields */
|
|
UField* Children;
|
|
|
|
/** Pointer to start of linked list of child fields */
|
|
FField* ChildProperties;
|
|
|
|
/** Total size of all UProperties, the allocated structure may be larger due to alignment */
|
|
int32 PropertiesSize;
|
|
/** Alignment of structure in memory, structure will be at least this large */
|
|
int32 MinAlignment;
|
|
|
|
/** Script bytecode associated with this object */
|
|
TArray<uint8> Script;
|
|
|
|
/** In memory only: Linked list of properties from most-derived to base */
|
|
FProperty* PropertyLink;
|
|
/** In memory only: Linked list of object reference properties from most-derived to base */
|
|
FProperty* RefLink;
|
|
/** In memory only: Linked list of properties requiring destruction. Note this does not include things that will be destroyed byt he native destructor */
|
|
FProperty* DestructorLink;
|
|
/** In memory only: Linked list of properties requiring post constructor initialization */
|
|
FProperty* PostConstructLink;
|
|
|
|
/** Array of object references embedded in script code and referenced by FProperties. Mirrored for easy access by realtime garbage collection code */
|
|
TArray<UObject*> ScriptAndPropertyObjectReferences;
|
|
|
|
typedef TArray<TPair<TFieldPath<FField>, int32>> FUnresolvedScriptPropertiesArray;
|
|
/** Contains a list of script properties that couldn't be resolved at load time */
|
|
FUnresolvedScriptPropertiesArray* UnresolvedScriptProperties;
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
/** List of wrapper UObjects for FProperties */
|
|
TArray<UPropertyWrapper*> PropertyWrappers;
|
|
/** Unique id incremented each time this class properties get destroyed */
|
|
int32 FieldPathSerialNumber;
|
|
#endif
|
|
|
|
/** Cached schema for optimized unversioned property serialization, owned by this. */
|
|
mutable const struct FUnversionedStructSchema* UnversionedSchema = nullptr;
|
|
|
|
public:
|
|
// Constructors.
|
|
UStruct(EStaticConstructor, int32 InSize, int32 InAlignment, EObjectFlags InFlags);
|
|
explicit UStruct(UStruct* InSuperStruct, SIZE_T ParamsSize = 0, SIZE_T Alignment = 0);
|
|
explicit UStruct(const FObjectInitializer& ObjectInitializer, UStruct* InSuperStruct, SIZE_T ParamsSize = 0, SIZE_T Alignment = 0);
|
|
virtual ~UStruct();
|
|
|
|
// UObject interface.
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
virtual void Serialize(FStructuredArchive::FRecord Record) override;
|
|
virtual void PostLoad() override;
|
|
virtual void FinishDestroy() override;
|
|
virtual void RegisterDependencies() override;
|
|
static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
|
|
virtual void GetPreloadDependencies(TArray<UObject*>& OutDeps) override;
|
|
virtual void TagSubobjects(EObjectFlags NewFlags) override;
|
|
|
|
// UField interface.
|
|
virtual void AddCppProperty(FProperty* Property) override;
|
|
|
|
/** Searches property link chain for a property with the specified name */
|
|
FProperty* FindPropertyByName(FName InName) const;
|
|
|
|
/**
|
|
* Creates new copies of components
|
|
*
|
|
* @param Data pointer to the address of the subobject referenced by this FProperty
|
|
* @param DefaultData pointer to the address of the default value of the subbject referenced by this FProperty
|
|
* @param DefaultStruct the struct corresponding to the buffer pointed to by DefaultData
|
|
* @param Owner the object that contains the component currently located at Data
|
|
* @param InstanceGraph contains the mappings of instanced objects and components to their templates
|
|
*/
|
|
void InstanceSubobjectTemplates(void* Data, void const* DefaultData, UStruct* DefaultStruct, UObject* Owner, FObjectInstancingGraph* InstanceGraph);
|
|
|
|
/** Returns the structure used for inheritance, may be changed by child types */
|
|
virtual UStruct* GetInheritanceSuper() const { return GetSuperStruct(); }
|
|
|
|
/** Static wrapper for Link, using a dummy archive */
|
|
void StaticLink(bool bRelinkExistingProperties = false);
|
|
|
|
/** Creates the field/property links and gets structure ready for use at runtime */
|
|
virtual void Link(FArchive& Ar, bool bRelinkExistingProperties);
|
|
|
|
/** Serializes struct properties, does not handle defaults*/
|
|
virtual void SerializeBin(FArchive& Ar, void* Data) const final
|
|
{
|
|
SerializeBin(FStructuredArchiveFromArchive(Ar).GetSlot(), Data);
|
|
}
|
|
|
|
/** Serializes struct properties, does not handle defaults */
|
|
virtual void SerializeBin(FStructuredArchive::FSlot Slot, void* Data) const;
|
|
|
|
/**
|
|
* Serializes the class properties that reside in Data if they differ from the corresponding values in DefaultData
|
|
*
|
|
* @param Ar the archive to use for serialization
|
|
* @param Data pointer to the location of the beginning of the property data
|
|
* @param DefaultData pointer to the location of the beginning of the data that should be compared against
|
|
* @param DefaultStruct the struct corresponding to the block of memory located at DefaultData
|
|
*/
|
|
void SerializeBinEx(FStructuredArchive::FSlot Slot, void* Data, void const* DefaultData, UStruct* DefaultStruct) const;
|
|
|
|
/** Serializes list of properties, using property tags to handle mismatches */
|
|
virtual void SerializeTaggedProperties(FArchive& Ar, uint8* Data, UStruct* DefaultsStruct, uint8* Defaults, const UObject* BreakRecursionIfFullyLoad = nullptr) const final
|
|
{
|
|
SerializeTaggedProperties(FStructuredArchiveFromArchive(Ar).GetSlot(), Data, DefaultsStruct, Defaults, BreakRecursionIfFullyLoad);
|
|
}
|
|
|
|
/** Serializes list of properties, using property tags to handle mismatches */
|
|
virtual void SerializeTaggedProperties(FStructuredArchive::FSlot Slot, uint8* Data, UStruct* DefaultsStruct, uint8* Defaults, const UObject* BreakRecursionIfFullyLoad = nullptr) const;
|
|
|
|
/**
|
|
* Initialize a struct over uninitialized memory. This may be done by calling the native constructor or individually initializing properties
|
|
*
|
|
* @param Dest Pointer to memory to initialize
|
|
* @param ArrayDim Number of elements in the array
|
|
* @param Stride Stride of the array, If this default (0), then we will pull the size from the struct
|
|
*/
|
|
virtual void InitializeStruct(void* Dest, int32 ArrayDim = 1) const;
|
|
|
|
/**
|
|
* Destroy a struct in memory. This may be done by calling the native destructor and then the constructor or individually reinitializing properties
|
|
*
|
|
* @param Dest Pointer to memory to destory
|
|
* @param ArrayDim Number of elements in the array
|
|
* @param Stride Stride of the array. If this default (0), then we will pull the size from the struct
|
|
*/
|
|
virtual void DestroyStruct(void* Dest, int32 ArrayDim = 1) const;
|
|
|
|
/** Look up a property by an alternate name if it was not found in the first search, this is overridden for user structs */
|
|
virtual FProperty* CustomFindProperty(const FName InName) const { return nullptr; };
|
|
|
|
/** Serialize an expression to an archive. Returns expression token */
|
|
virtual EExprToken SerializeExpr(int32& iCode, FArchive& Ar);
|
|
|
|
/**
|
|
* Returns the struct/ class prefix used for the C++ declaration of this struct/ class.
|
|
*
|
|
* @return Prefix character used for C++ declaration of this struct/ class.
|
|
*/
|
|
virtual const TCHAR* GetPrefixCPP() const { return TEXT("F"); }
|
|
|
|
/** Total size of all UProperties, the allocated structure may be larger due to alignment */
|
|
FORCEINLINE int32 GetPropertiesSize() const
|
|
{
|
|
return PropertiesSize;
|
|
}
|
|
|
|
/** Alignment of structure in memory, structure will be at least this large */
|
|
FORCEINLINE int32 GetMinAlignment() const
|
|
{
|
|
return MinAlignment;
|
|
}
|
|
|
|
/** Returns actual allocated size of structure in memory */
|
|
FORCEINLINE int32 GetStructureSize() const
|
|
{
|
|
return Align(PropertiesSize, MinAlignment);
|
|
}
|
|
|
|
/** Modifies the property size after it's been recomputed */
|
|
void SetPropertiesSize(int32 NewSize)
|
|
{
|
|
PropertiesSize = NewSize;
|
|
}
|
|
|
|
/** Returns true if this struct either is class T, or is a child of class T. This will not crash on null structs */
|
|
template <class T>
|
|
bool IsChildOf() const
|
|
{
|
|
return IsChildOf(T::StaticClass());
|
|
}
|
|
|
|
/** Returns true if this struct either is SomeBase, or is a child of SomeBase. This will not crash on null structs */
|
|
#if USTRUCT_FAST_ISCHILDOF_COMPARE_WITH_OUTERWALK || USTRUCT_FAST_ISCHILDOF_IMPL == USTRUCT_ISCHILDOF_OUTERWALK
|
|
bool IsChildOf(const UStruct* SomeBase) const;
|
|
#else
|
|
bool IsChildOf(const UStruct* SomeBase) const
|
|
{
|
|
return (SomeBase ? IsChildOfUsingStructArray(*SomeBase) : false);
|
|
}
|
|
#endif
|
|
|
|
/** Struct this inherits from, may be null */
|
|
UStruct* GetSuperStruct() const
|
|
{
|
|
return SuperStruct;
|
|
}
|
|
|
|
/**
|
|
* Sets the super struct pointer and updates hash information as necessary.
|
|
* Note that this is not sufficient to actually reparent a struct, it simply sets a pointer.
|
|
*/
|
|
virtual void SetSuperStruct(UStruct* NewSuperStruct);
|
|
|
|
UE_DEPRECATED(4.23, "Replace with GetAuthoredNameForField or UField::GetAuthoredName")
|
|
virtual FString PropertyNameToDisplayName(FName InName) const;
|
|
|
|
/** Returns a human readable string for a given field, overridden for user defined structs */
|
|
virtual FString GetAuthoredNameForField(const UField* Field) const;
|
|
|
|
/** Returns a human readable string for a given field, overridden for user defined structs */
|
|
virtual FString GetAuthoredNameForField(const FField* Field) const;
|
|
|
|
/** If true, this class has been cleaned and sanitized (trashed) and should not be used */
|
|
virtual bool IsStructTrashed() const
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/** Destroys all properties owned by this struct */
|
|
void DestroyChildPropertiesAndResetPropertyLinks();
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
/** Try and find boolean metadata with the given key. If not found on this class, work up hierarchy looking for it. */
|
|
bool GetBoolMetaDataHierarchical(const FName& Key) const;
|
|
|
|
/** Try and find string metadata with the given key. If not found on this class, work up hierarchy looking for it. */
|
|
bool GetStringMetaDataHierarchical(const FName& Key, FString* OutValue = nullptr) const;
|
|
|
|
/**
|
|
* Determines if the struct or any of its super structs has any metadata associated with the provided key
|
|
*
|
|
* @param Key The key to lookup in the metadata
|
|
* @return pointer to the UStruct that has associated metadata, nullptr if Key is not associated with any UStruct in the hierarchy
|
|
*/
|
|
const UStruct* HasMetaDataHierarchical(const FName& Key) const;
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|
|
#if HACK_HEADER_GENERATOR
|
|
// Required by UHT makefiles for internal data serialization.
|
|
friend struct FStructArchiveProxy;
|
|
#endif // HACK_HEADER_GENERATOR
|
|
|
|
/** Sets the UnresolvedScriptProperties array */
|
|
void SetUnresolvedScriptProperties(FUnresolvedScriptPropertiesArray& InUnresolvedProperties)
|
|
{
|
|
if (!UnresolvedScriptProperties)
|
|
{
|
|
UnresolvedScriptProperties = new FUnresolvedScriptPropertiesArray();
|
|
}
|
|
*UnresolvedScriptProperties = MoveTemp(InUnresolvedProperties);
|
|
}
|
|
|
|
/** Deletes the UnresolvedScriptProperties array */
|
|
FORCEINLINE void DeleteUnresolvedScriptProperties()
|
|
{
|
|
if (UnresolvedScriptProperties)
|
|
{
|
|
delete UnresolvedScriptProperties;
|
|
UnresolvedScriptProperties = nullptr;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Collects UObjects referenced by bytecode
|
|
* @param OutReferencedObjects buffer to store the referenced objects in (not cleared by this function)
|
|
*/
|
|
void CollectBytecodeReferencedObjects(TArray<UObject*>& OutReferencedObjects);
|
|
/**
|
|
* Collects UObjects referenced by properties
|
|
* @param OutReferencedObjects buffer to store the referenced objects in (not cleared by this function)
|
|
*/
|
|
void CollectPropertyReferencedObjects(TArray<UObject*>& OutReferencedObjects);
|
|
/**
|
|
* Collects UObjects referenced by bytecode and properties for faster GC access
|
|
*/
|
|
void CollectBytecodeAndPropertyReferencedObjects();
|
|
|
|
protected:
|
|
/** Returns the property name from the guid */
|
|
virtual FName FindPropertyNameFromGuid(const FGuid& PropertyGuid) const { return NAME_None; }
|
|
|
|
/** Find property guid */
|
|
virtual FGuid FindPropertyGuidFromName(const FName InName) const { return FGuid(); }
|
|
|
|
/** Returns if we have access to property guids */
|
|
virtual bool ArePropertyGuidsAvailable() const { return false; }
|
|
|
|
/** Serializes properties of this struct */
|
|
void SerializeProperties(FArchive& Ar);
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
void ConvertUFieldsToFFields();
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|
|
/** Serializes list of properties to a te, using property tags to handle mismatches */
|
|
void LoadTaggedPropertiesFromText(FStructuredArchive::FSlot Slot, uint8* Data, UStruct* DefaultsStruct, uint8* Defaults, const UObject* BreakRecursionIfFullyLoad) const;
|
|
|
|
private:
|
|
#if USTRUCT_FAST_ISCHILDOF_IMPL == USTRUCT_ISCHILDOF_STRUCTARRAY
|
|
// For UObjectBaseUtility
|
|
friend class UObjectBaseUtility;
|
|
using FStructBaseChain::IsChildOfUsingStructArray;
|
|
using FStructBaseChain::ReinitializeBaseChainArray;
|
|
|
|
friend class FStructBaseChain;
|
|
friend class FBlueprintCompileReinstancer;
|
|
#endif
|
|
|
|
void SerializeVersionedTaggedProperties(FStructuredArchive::FSlot Slot, uint8* Data, UStruct* DefaultsStruct, uint8* Defaults, const UObject* BreakRecursionIfFullyLoad) const;
|
|
};
|
|
|
|
enum EStructFlags
|
|
{
|
|
// State flags.
|
|
STRUCT_NoFlags = 0x00000000,
|
|
STRUCT_Native = 0x00000001,
|
|
|
|
/** If set, this struct will be compared using native code */
|
|
STRUCT_IdenticalNative = 0x00000002,
|
|
|
|
STRUCT_HasInstancedReference = 0x00000004,
|
|
|
|
STRUCT_NoExport = 0x00000008,
|
|
|
|
/** Indicates that this struct should always be serialized as a single unit */
|
|
STRUCT_Atomic = 0x00000010,
|
|
|
|
/** Indicates that this struct uses binary serialization; it is unsafe to add/remove members from this struct without incrementing the package version */
|
|
STRUCT_Immutable = 0x00000020,
|
|
|
|
/** If set, native code needs to be run to find referenced objects */
|
|
STRUCT_AddStructReferencedObjects = 0x00000040,
|
|
|
|
/** Indicates that this struct should be exportable/importable at the DLL layer. Base structs must also be exportable for this to work. */
|
|
STRUCT_RequiredAPI = 0x00000200,
|
|
|
|
/** If set, this struct will be serialized using the CPP net serializer */
|
|
STRUCT_NetSerializeNative = 0x00000400,
|
|
|
|
/** If set, this struct will be serialized using the CPP serializer */
|
|
STRUCT_SerializeNative = 0x00000800,
|
|
|
|
/** If set, this struct will be copied using the CPP operator= */
|
|
STRUCT_CopyNative = 0x00001000,
|
|
|
|
/** If set, this struct will be copied using memcpy */
|
|
STRUCT_IsPlainOldData = 0x00002000,
|
|
|
|
/** If set, this struct has no destructor and non will be called. STRUCT_IsPlainOldData implies STRUCT_NoDestructor */
|
|
STRUCT_NoDestructor = 0x00004000,
|
|
|
|
/** If set, this struct will not be constructed because it is assumed that memory is zero before construction. */
|
|
STRUCT_ZeroConstructor = 0x00008000,
|
|
|
|
/** If set, native code will be used to export text */
|
|
STRUCT_ExportTextItemNative = 0x00010000,
|
|
|
|
/** If set, native code will be used to export text */
|
|
STRUCT_ImportTextItemNative = 0x00020000,
|
|
|
|
/** If set, this struct will have PostSerialize called on it after CPP serializer or tagged property serialization is complete */
|
|
STRUCT_PostSerializeNative = 0x00040000,
|
|
|
|
/** If set, this struct will have SerializeFromMismatchedTag called on it if a mismatched tag is encountered. */
|
|
STRUCT_SerializeFromMismatchedTag = 0x00080000,
|
|
|
|
/** If set, this struct will be serialized using the CPP net delta serializer */
|
|
STRUCT_NetDeltaSerializeNative = 0x00100000,
|
|
|
|
/** If set, this struct will be have PostScriptConstruct called on it after a temporary object is constructed in a running blueprint */
|
|
STRUCT_PostScriptConstruct = 0x00200000,
|
|
|
|
/** If set, this struct can share net serialization state across connections */
|
|
STRUCT_NetSharedSerialization = 0x00400000,
|
|
|
|
/** If set, this struct has been cleaned and sanitized (trashed) and should not be used */
|
|
STRUCT_Trashed = 0x00800000,
|
|
|
|
/** Struct flags that are automatically inherited */
|
|
STRUCT_Inherit = STRUCT_HasInstancedReference | STRUCT_Atomic,
|
|
|
|
/** Flags that are always computed, never loaded or done with code generation */
|
|
STRUCT_ComputedFlags = STRUCT_NetDeltaSerializeNative | STRUCT_NetSerializeNative | STRUCT_SerializeNative | STRUCT_PostSerializeNative | STRUCT_CopyNative | STRUCT_IsPlainOldData | STRUCT_NoDestructor | STRUCT_ZeroConstructor | STRUCT_IdenticalNative | STRUCT_AddStructReferencedObjects | STRUCT_ExportTextItemNative | STRUCT_ImportTextItemNative | STRUCT_SerializeFromMismatchedTag | STRUCT_PostScriptConstruct | STRUCT_NetSharedSerialization
|
|
};
|
|
|
|
/** type traits to cover the custom aspects of a script struct **/
|
|
template <class CPPSTRUCT>
|
|
struct TStructOpsTypeTraitsBase2
|
|
{
|
|
enum
|
|
{
|
|
WithZeroConstructor = false, // struct can be constructed as a valid object by filling its memory footprint with zeroes.
|
|
WithNoInitConstructor = false, // struct has a constructor which takes an EForceInit parameter which will force the constructor to perform initialization, where the default constructor performs 'uninitialization'.
|
|
WithNoDestructor = false, // struct will not have its destructor called when it is destroyed.
|
|
WithCopy = !TIsPODType<CPPSTRUCT>::Value, // struct can be copied via its copy assignment operator.
|
|
WithIdenticalViaEquality = false, // struct can be compared via its operator==. This should be mutually exclusive with WithIdentical.
|
|
WithIdentical = false, // struct can be compared via an Identical(const T* Other, uint32 PortFlags) function. This should be mutually exclusive with WithIdenticalViaEquality.
|
|
WithExportTextItem = false, // struct has an ExportTextItem function used to serialize its state into a string.
|
|
WithImportTextItem = false, // struct has an ImportTextItem function used to deserialize a string into an object of that class.
|
|
WithAddStructReferencedObjects = false, // struct has an AddStructReferencedObjects function which allows it to add references to the garbage collector.
|
|
WithSerializer = false, // struct has a Serialize function for serializing its state to an FArchive.
|
|
WithStructuredSerializer = false, // struct has a Serialize function for serializing its state to an FStructuredArchive.
|
|
WithPostSerialize = false, // struct has a PostSerialize function which is called after it is serialized
|
|
WithNetSerializer = false, // struct has a NetSerialize function for serializing its state to an FArchive used for network replication.
|
|
WithNetDeltaSerializer = false, // struct has a NetDeltaSerialize function for serializing differences in state from a previous NetSerialize operation.
|
|
WithSerializeFromMismatchedTag = false, // struct has a SerializeFromMismatchedTag function for converting from other property tags.
|
|
WithStructuredSerializeFromMismatchedTag = false, // struct has an FStructuredArchive-based SerializeFromMismatchedTag function for converting from other property tags.
|
|
WithPostScriptConstruct = false, // struct has a PostScriptConstruct function which is called after it is constructed in blueprints
|
|
WithNetSharedSerialization = false, // struct has a NetSerialize function that does not require the package map to serialize its state.
|
|
WithPureVirtual = false, // struct has PURE_VIRTUAL functions and cannot be constructed when CHECK_PUREVIRTUALS is true
|
|
};
|
|
};
|
|
|
|
template <class CPPSTRUCT>
|
|
struct TStructOpsTypeTraits: public TStructOpsTypeTraitsBase2<CPPSTRUCT>
|
|
{
|
|
};
|
|
|
|
#if CHECK_PUREVIRTUALS
|
|
#define DISABLE_ABSTRACT_CONSTRUCT TStructOpsTypeTraits<CPPSTRUCT>::WithPureVirtual
|
|
#else
|
|
#define DISABLE_ABSTRACT_CONSTRUCT (false && TStructOpsTypeTraits<CPPSTRUCT>::WithPureVirtual)
|
|
#endif
|
|
|
|
#if !PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
|
|
/**
|
|
* Selection of constructor behavior.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!DISABLE_ABSTRACT_CONSTRUCT && !TStructOpsTypeTraits<CPPSTRUCT>::WithNoInitConstructor>::Type ConstructWithNoInitOrNot(void* Data)
|
|
{
|
|
new (Data) CPPSTRUCT();
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!DISABLE_ABSTRACT_CONSTRUCT && TStructOpsTypeTraits<CPPSTRUCT>::WithNoInitConstructor>::Type ConstructWithNoInitOrNot(void* Data)
|
|
{
|
|
new (Data) CPPSTRUCT(ForceInit);
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<DISABLE_ABSTRACT_CONSTRUCT>::Type ConstructWithNoInitOrNot(void* Data)
|
|
{
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!DISABLE_ABSTRACT_CONSTRUCT && !TStructOpsTypeTraits<CPPSTRUCT>::WithNoInitConstructor>::Type ConstructForTestsWithNoInitOrNot(void* Data)
|
|
{
|
|
new (Data) CPPSTRUCT;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!DISABLE_ABSTRACT_CONSTRUCT && TStructOpsTypeTraits<CPPSTRUCT>::WithNoInitConstructor>::Type ConstructForTestsWithNoInitOrNot(void* Data)
|
|
{
|
|
new (Data) CPPSTRUCT(ForceInit);
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<DISABLE_ABSTRACT_CONSTRUCT>::Type ConstructForTestsWithNoInitOrNot(void* Data)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Selection of Serialize call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithSerializer, bool>::Type SerializeOrNot(FArchive& Ar, CPPSTRUCT* Data)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithSerializer, bool>::Type SerializeOrNot(FArchive& Ar, CPPSTRUCT* Data)
|
|
{
|
|
return Data->Serialize(Ar);
|
|
}
|
|
|
|
/**
|
|
* Selection of structured Serialize call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithStructuredSerializer, bool>::Type SerializeOrNot(FStructuredArchive::FSlot Slot, CPPSTRUCT* Data)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithStructuredSerializer, bool>::Type SerializeOrNot(FStructuredArchive::FSlot Slot, CPPSTRUCT* Data)
|
|
{
|
|
return Data->Serialize(Slot);
|
|
}
|
|
|
|
/**
|
|
* Selection of PostSerialize call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithPostSerialize>::Type PostSerializeOrNot(const FArchive& Ar, CPPSTRUCT* Data)
|
|
{
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithPostSerialize>::Type PostSerializeOrNot(const FArchive& Ar, CPPSTRUCT* Data)
|
|
{
|
|
Data->PostSerialize(Ar);
|
|
}
|
|
|
|
/**
|
|
* Selection of NetSerialize call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithNetSerializer, bool>::Type NetSerializeOrNot(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess, CPPSTRUCT* Data)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithNetSerializer, bool>::Type NetSerializeOrNot(FArchive& Ar, UPackageMap* Map, bool& bOutSuccess, CPPSTRUCT* Data)
|
|
{
|
|
return Data->NetSerialize(Ar, Map, bOutSuccess);
|
|
}
|
|
|
|
/**
|
|
* Selection of NetDeltaSerialize call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithNetDeltaSerializer, bool>::Type NetDeltaSerializeOrNot(FNetDeltaSerializeInfo& DeltaParms, CPPSTRUCT* Data)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithNetDeltaSerializer, bool>::Type NetDeltaSerializeOrNot(FNetDeltaSerializeInfo& DeltaParms, CPPSTRUCT* Data)
|
|
{
|
|
return Data->NetDeltaSerialize(DeltaParms);
|
|
}
|
|
|
|
/**
|
|
* Selection of PostScriptConstruct call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithPostScriptConstruct>::Type PostScriptConstructOrNot(CPPSTRUCT* Data)
|
|
{
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithPostScriptConstruct>::Type PostScriptConstructOrNot(CPPSTRUCT* Data)
|
|
{
|
|
Data->PostScriptConstruct();
|
|
}
|
|
|
|
/**
|
|
* Selection of Copy behavior.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithCopy, bool>::Type CopyOrNot(CPPSTRUCT* Dest, CPPSTRUCT const* Src, int32 ArrayDim)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithCopy, bool>::Type CopyOrNot(CPPSTRUCT* Dest, CPPSTRUCT const* Src, int32 ArrayDim)
|
|
{
|
|
static_assert((!TIsPODType<CPPSTRUCT>::Value), "You probably don't want custom copy for a POD type.");
|
|
for (; ArrayDim; --ArrayDim)
|
|
{
|
|
*Dest++ = *Src++;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Selection of Identical check.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithIdentical && TStructOpsTypeTraits<CPPSTRUCT>::WithIdenticalViaEquality, bool>::Type IdenticalOrNot(const CPPSTRUCT* A, const CPPSTRUCT* B, uint32 PortFlags, bool& bOutResult)
|
|
{
|
|
static_assert(sizeof(CPPSTRUCT) == 0, "Should not have both WithIdenticalViaEquality and WithIdentical.");
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithIdentical && !TStructOpsTypeTraits<CPPSTRUCT>::WithIdenticalViaEquality, bool>::Type IdenticalOrNot(const CPPSTRUCT* A, const CPPSTRUCT* B, uint32 PortFlags, bool& bOutResult)
|
|
{
|
|
bOutResult = false;
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithIdentical && !TStructOpsTypeTraits<CPPSTRUCT>::WithIdenticalViaEquality, bool>::Type IdenticalOrNot(const CPPSTRUCT* A, const CPPSTRUCT* B, uint32 PortFlags, bool& bOutResult)
|
|
{
|
|
bOutResult = A->Identical(B, PortFlags);
|
|
return true;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithIdentical && TStructOpsTypeTraits<CPPSTRUCT>::WithIdenticalViaEquality, bool>::Type IdenticalOrNot(const CPPSTRUCT* A, const CPPSTRUCT* B, uint32 PortFlags, bool& bOutResult)
|
|
{
|
|
bOutResult = (*A == *B);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Selection of ExportTextItem call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithExportTextItem, bool>::Type ExportTextItemOrNot(FString& ValueStr, const CPPSTRUCT* PropertyValue, const CPPSTRUCT* DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithExportTextItem, bool>::Type ExportTextItemOrNot(FString& ValueStr, const CPPSTRUCT* PropertyValue, const CPPSTRUCT* DefaultValue, UObject* Parent, int32 PortFlags, UObject* ExportRootScope)
|
|
{
|
|
return PropertyValue->ExportTextItem(ValueStr, *DefaultValue, Parent, PortFlags, ExportRootScope);
|
|
}
|
|
|
|
/**
|
|
* Selection of ImportTextItem call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithImportTextItem, bool>::Type ImportTextItemOrNot(const TCHAR*& Buffer, CPPSTRUCT* Data, int32 PortFlags, UObject* OwnerObject, FOutputDevice* ErrorText)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithImportTextItem, bool>::Type ImportTextItemOrNot(const TCHAR*& Buffer, CPPSTRUCT* Data, int32 PortFlags, UObject* OwnerObject, FOutputDevice* ErrorText)
|
|
{
|
|
return Data->ImportTextItem(Buffer, PortFlags, OwnerObject, ErrorText);
|
|
}
|
|
|
|
/**
|
|
* Selection of SerializeFromMismatchedTag call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithSerializeFromMismatchedTag, bool>::Type SerializeFromMismatchedTagOrNot(FPropertyTag const& Tag, FArchive& Ar, CPPSTRUCT* Data)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithSerializeFromMismatchedTag, bool>::Type SerializeFromMismatchedTagOrNot(FPropertyTag const& Tag, FArchive& Ar, CPPSTRUCT* Data)
|
|
{
|
|
return Data->SerializeFromMismatchedTag(Tag, Ar);
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithStructuredSerializeFromMismatchedTag, bool>::Type StructuredSerializeFromMismatchedTagOrNot(FPropertyTag const& Tag, FStructuredArchive::FSlot Slot, CPPSTRUCT* Data)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithStructuredSerializeFromMismatchedTag, bool>::Type StructuredSerializeFromMismatchedTagOrNot(FPropertyTag const& Tag, FStructuredArchive::FSlot Slot, CPPSTRUCT* Data)
|
|
{
|
|
return Data->SerializeFromMismatchedTag(Tag, Slot);
|
|
}
|
|
|
|
/**
|
|
* Selection of GetTypeHash call.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TModels<CGetTypeHashable, CPPSTRUCT>::Value, uint32>::Type GetTypeHashOrNot(const CPPSTRUCT* Data)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TModels<CGetTypeHashable, CPPSTRUCT>::Value, uint32>::Type GetTypeHashOrNot(const CPPSTRUCT* Data)
|
|
{
|
|
return GetTypeHash(*Data);
|
|
}
|
|
|
|
#endif
|
|
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
|
|
/**
|
|
* Selection of AddStructReferencedObjects check.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE void AddStructReferencedObjectsOrNot(void* A, FReferenceCollector& Collector)
|
|
{
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithAddStructReferencedObjects)
|
|
{
|
|
((CPPSTRUCT*)A)->AddStructReferencedObjects(Collector);
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
/**
|
|
* Selection of AddStructReferencedObjects check.
|
|
*/
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<!TStructOpsTypeTraits<CPPSTRUCT>::WithAddStructReferencedObjects>::Type AddStructReferencedObjectsOrNot(void* A, FReferenceCollector& Collector)
|
|
{
|
|
}
|
|
|
|
template <class CPPSTRUCT>
|
|
FORCEINLINE typename TEnableIf<TStructOpsTypeTraits<CPPSTRUCT>::WithAddStructReferencedObjects>::Type AddStructReferencedObjectsOrNot(void* A, FReferenceCollector& Collector)
|
|
{
|
|
((CPPSTRUCT*)A)->AddStructReferencedObjects(Collector);
|
|
}
|
|
|
|
#endif
|
|
|
|
/**
|
|
* Reflection data for a standalone structure declared in a header or as a user defined struct
|
|
*/
|
|
class UScriptStruct: public UStruct
|
|
{
|
|
public:
|
|
/** Interface to template to manage dynamic access to C++ struct construction and destruction **/
|
|
struct COREUOBJECT_API ICppStructOps
|
|
{
|
|
/**
|
|
* Constructor
|
|
* @param InSize: sizeof() of the structure
|
|
*/
|
|
ICppStructOps(int32 InSize, int32 InAlignment)
|
|
: Size(InSize), Alignment(InAlignment)
|
|
{
|
|
}
|
|
virtual ~ICppStructOps() {}
|
|
/** return true if this class has a no-op constructor and takes EForceInit to init **/
|
|
virtual bool HasNoopConstructor() = 0;
|
|
/** return true if memset can be used instead of the constructor **/
|
|
virtual bool HasZeroConstructor() = 0;
|
|
/** Call the C++ constructor **/
|
|
virtual void Construct(void* Dest) = 0;
|
|
/** Call the C++ constructor without value-init (new T instead of new T()) **/
|
|
virtual void ConstructForTests(void* Dest) = 0;
|
|
/** return false if this destructor can be skipped **/
|
|
virtual bool HasDestructor() = 0;
|
|
/** Call the C++ destructor **/
|
|
virtual void Destruct(void* Dest) = 0;
|
|
/** return the sizeof() of this structure **/
|
|
FORCEINLINE int32 GetSize()
|
|
{
|
|
return Size;
|
|
}
|
|
/** return the alignof() of this structure **/
|
|
FORCEINLINE int32 GetAlignment()
|
|
{
|
|
return Alignment;
|
|
}
|
|
|
|
/** return true if this class can serialize **/
|
|
virtual bool HasSerializer() = 0;
|
|
/** return true if this class can serialize to a structured archive**/
|
|
virtual bool HasStructuredSerializer() = 0;
|
|
/**
|
|
* Serialize this structure
|
|
* @return true if the package is new enough to support this, if false, it will fall back to ordinary script struct serialization
|
|
*/
|
|
virtual bool Serialize(FArchive& Ar, void* Data) = 0;
|
|
virtual bool Serialize(FStructuredArchive::FSlot Slot, void* Data) = 0;
|
|
|
|
/** return true if this class implements a post serialize call **/
|
|
virtual bool HasPostSerialize() = 0;
|
|
/** Call PostSerialize on this structure */
|
|
virtual void PostSerialize(const FArchive& Ar, void* Data) = 0;
|
|
|
|
/** return true if this struct can net serialize **/
|
|
virtual bool HasNetSerializer() = 0;
|
|
|
|
/** return true if this can share net serialization across connections */
|
|
virtual bool HasNetSharedSerialization() = 0;
|
|
/**
|
|
* Net serialize this structure
|
|
* @return true if the struct was serialized, otherwise it will fall back to ordinary script struct net serialization
|
|
*/
|
|
virtual bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess, void* Data) = 0;
|
|
|
|
/** return true if this struct can net delta serialize delta (serialize a network delta from a base state) **/
|
|
virtual bool HasNetDeltaSerializer() = 0;
|
|
/**
|
|
* Net serialize delta this structure. Serialize a network delta from a base state
|
|
* @return true if the struct was serialized, otherwise it will fall back to ordinary script struct net delta serialization
|
|
*/
|
|
virtual bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms, void* Data) = 0;
|
|
|
|
/** return true if this class implements a post script construct call **/
|
|
virtual bool HasPostScriptConstruct() = 0;
|
|
/** Call PostScriptConstruct on this structure */
|
|
virtual void PostScriptConstruct(void* Data) = 0;
|
|
|
|
/** return true if this struct should be memcopied **/
|
|
virtual bool IsPlainOldData() = 0;
|
|
|
|
/** return true if this struct can copy **/
|
|
virtual bool HasCopy() = 0;
|
|
/**
|
|
* Copy this structure
|
|
* @return true if the copy was handled, otherwise it will fall back to CopySingleValue
|
|
*/
|
|
virtual bool Copy(void* Dest, void const* Src, int32 ArrayDim) = 0;
|
|
|
|
/** return true if this struct can compare **/
|
|
virtual bool HasIdentical() = 0;
|
|
/**
|
|
* Compare this structure
|
|
* @return true if the copy was handled, otherwise it will fall back to FStructProperty::Identical
|
|
*/
|
|
virtual bool Identical(const void* A, const void* B, uint32 PortFlags, bool& bOutResult) = 0;
|
|
|
|
/** return true if this struct can export **/
|
|
virtual bool HasExportTextItem() = 0;
|
|
/**
|
|
* export this structure
|
|
* @return true if the copy was exported, otherwise it will fall back to FStructProperty::ExportTextItem
|
|
*/
|
|
virtual bool ExportTextItem(FString& ValueStr, const void* PropertyValue, const void* DefaultValue, class UObject* Parent, int32 PortFlags, class UObject* ExportRootScope) = 0;
|
|
|
|
/** return true if this struct can import **/
|
|
virtual bool HasImportTextItem() = 0;
|
|
/**
|
|
* import this structure
|
|
* @return true if the copy was imported, otherwise it will fall back to FStructProperty::ImportText
|
|
*/
|
|
virtual bool ImportTextItem(const TCHAR*& Buffer, void* Data, int32 PortFlags, class UObject* OwnerObject, FOutputDevice* ErrorText) = 0;
|
|
|
|
/** return true if this struct has custom GC code **/
|
|
virtual bool HasAddStructReferencedObjects() = 0;
|
|
/**
|
|
* return a pointer to a function that can add referenced objects
|
|
* @return true if the copy was imported, otherwise it will fall back to FStructProperty::ImportText
|
|
*/
|
|
typedef void (*TPointerToAddStructReferencedObjects)(void* A, class FReferenceCollector& Collector);
|
|
virtual TPointerToAddStructReferencedObjects AddStructReferencedObjects() = 0;
|
|
|
|
/** return true if this class wants to serialize from some other tag (usually for conversion purposes) **/
|
|
virtual bool HasSerializeFromMismatchedTag() = 0;
|
|
virtual bool HasStructuredSerializeFromMismatchedTag() = 0;
|
|
|
|
/**
|
|
* Serialize this structure, from some other tag
|
|
* @return true if this succeeded, false will trigger a warning and not serialize at all
|
|
*/
|
|
virtual bool SerializeFromMismatchedTag(struct FPropertyTag const& Tag, FArchive& Ar, void* Data) = 0;
|
|
virtual bool StructuredSerializeFromMismatchedTag(struct FPropertyTag const& Tag, FStructuredArchive::FSlot Slot, void* Data) = 0;
|
|
|
|
/** return true if this struct has a GetTypeHash */
|
|
virtual bool HasGetTypeHash() = 0;
|
|
|
|
/** Calls GetTypeHash if enabled */
|
|
virtual uint32 GetStructTypeHash(const void* Src) = 0;
|
|
|
|
/** Returns property flag values that can be computed at compile time */
|
|
virtual EPropertyFlags GetComputedPropertyFlags() const = 0;
|
|
|
|
/** return true if this struct is abstract **/
|
|
virtual bool IsAbstract() const = 0;
|
|
|
|
private:
|
|
/** sizeof() of the structure **/
|
|
const int32 Size;
|
|
/** alignof() of the structure **/
|
|
const int32 Alignment;
|
|
};
|
|
|
|
/** Template to manage dynamic access to C++ struct construction and destruction **/
|
|
template <class CPPSTRUCT>
|
|
struct TCppStructOps: public ICppStructOps
|
|
{
|
|
typedef TStructOpsTypeTraits<CPPSTRUCT> TTraits;
|
|
TCppStructOps()
|
|
: ICppStructOps(sizeof(CPPSTRUCT), alignof(CPPSTRUCT))
|
|
{
|
|
}
|
|
virtual bool HasNoopConstructor() override
|
|
{
|
|
return TTraits::WithNoInitConstructor;
|
|
}
|
|
virtual bool HasZeroConstructor() override
|
|
{
|
|
return TTraits::WithZeroConstructor;
|
|
}
|
|
virtual void Construct(void* Dest) override
|
|
{
|
|
check(!TTraits::WithZeroConstructor); // don't call this if we have indicated it is not necessary
|
|
// that could have been an if statement, but we might as well force optimization above the virtual call
|
|
// could also not attempt to call the constructor for types where this is not possible, but I didn't do that here
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
#if CHECK_PUREVIRTUALS
|
|
if constexpr (!TStructOpsTypeTraits<CPPSTRUCT>::WithPureVirtual)
|
|
#endif
|
|
{
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithNoInitConstructor)
|
|
{
|
|
new (Dest) CPPSTRUCT(ForceInit);
|
|
}
|
|
else
|
|
{
|
|
new (Dest) CPPSTRUCT();
|
|
}
|
|
}
|
|
#else
|
|
ConstructWithNoInitOrNot<CPPSTRUCT>(Dest);
|
|
#endif
|
|
}
|
|
virtual void ConstructForTests(void* Dest) override
|
|
{
|
|
check(!TTraits::WithZeroConstructor); // don't call this if we have indicated it is not necessary
|
|
// that could have been an if statement, but we might as well force optimization above the virtual call
|
|
// could also not attempt to call the constructor for types where this is not possible, but I didn't do that here
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
#if CHECK_PUREVIRTUALS
|
|
if constexpr (!TStructOpsTypeTraits<CPPSTRUCT>::WithPureVirtual)
|
|
#endif
|
|
{
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithNoInitConstructor)
|
|
{
|
|
new (Dest) CPPSTRUCT(ForceInit);
|
|
}
|
|
else
|
|
{
|
|
new (Dest) CPPSTRUCT;
|
|
}
|
|
}
|
|
#else
|
|
ConstructForTestsWithNoInitOrNot<CPPSTRUCT>(Dest);
|
|
#endif
|
|
}
|
|
virtual bool HasDestructor() override
|
|
{
|
|
return !(TTraits::WithNoDestructor || TIsPODType<CPPSTRUCT>::Value);
|
|
}
|
|
virtual void Destruct(void* Dest) override
|
|
{
|
|
check(!(TTraits::WithNoDestructor || TIsPODType<CPPSTRUCT>::Value)); // don't call this if we have indicated it is not necessary
|
|
// that could have been an if statement, but we might as well force optimization above the virtual call
|
|
// could also not attempt to call the destructor for types where this is not possible, but I didn't do that here
|
|
((CPPSTRUCT*)Dest)->~CPPSTRUCT();
|
|
}
|
|
virtual bool HasSerializer() override
|
|
{
|
|
return TTraits::WithSerializer;
|
|
}
|
|
virtual bool HasStructuredSerializer() override
|
|
{
|
|
return TTraits::WithStructuredSerializer;
|
|
}
|
|
virtual bool Serialize(FArchive& Ar, void* Data) override
|
|
{
|
|
check(TTraits::WithSerializer); // don't call this if we have indicated it is not necessary
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithSerializer)
|
|
{
|
|
return ((CPPSTRUCT*)Data)->Serialize(Ar);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return SerializeOrNot(Ar, (CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
virtual bool Serialize(FStructuredArchive::FSlot Slot, void* Data) override
|
|
{
|
|
check(TTraits::WithStructuredSerializer); // don't call this if we have indicated it is not necessary
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithStructuredSerializer)
|
|
{
|
|
return ((CPPSTRUCT*)Data)->Serialize(Slot);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return SerializeOrNot(Slot, (CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
virtual bool HasPostSerialize() override
|
|
{
|
|
return TTraits::WithPostSerialize;
|
|
}
|
|
virtual void PostSerialize(const FArchive& Ar, void* Data) override
|
|
{
|
|
check(TTraits::WithPostSerialize); // don't call this if we have indicated it is not necessary
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithPostSerialize)
|
|
{
|
|
((CPPSTRUCT*)Data)->PostSerialize(Ar);
|
|
}
|
|
#else
|
|
PostSerializeOrNot(Ar, (CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
virtual bool HasNetSerializer() override
|
|
{
|
|
return TTraits::WithNetSerializer;
|
|
}
|
|
virtual bool HasNetSharedSerialization() override
|
|
{
|
|
return TTraits::WithNetSharedSerialization;
|
|
}
|
|
virtual bool HasNetDeltaSerializer() override
|
|
{
|
|
return TTraits::WithNetDeltaSerializer;
|
|
}
|
|
virtual bool NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess, void* Data) override
|
|
{
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithNetSerializer)
|
|
{
|
|
return ((CPPSTRUCT*)Data)->NetSerialize(Ar, Map, bOutSuccess);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return NetSerializeOrNot(Ar, Map, bOutSuccess, (CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
virtual bool NetDeltaSerialize(FNetDeltaSerializeInfo& DeltaParms, void* Data) override
|
|
{
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithNetDeltaSerializer)
|
|
{
|
|
return ((CPPSTRUCT*)Data)->NetDeltaSerialize(DeltaParms);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return NetDeltaSerializeOrNot(DeltaParms, (CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
virtual bool HasPostScriptConstruct() override
|
|
{
|
|
return TTraits::WithPostScriptConstruct;
|
|
}
|
|
virtual void PostScriptConstruct(void* Data) override
|
|
{
|
|
check(TTraits::WithPostScriptConstruct); // don't call this if we have indicated it is not necessary
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithPostScriptConstruct)
|
|
{
|
|
((CPPSTRUCT*)Data)->PostScriptConstruct();
|
|
}
|
|
#else
|
|
PostScriptConstructOrNot((CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
virtual bool IsPlainOldData() override
|
|
{
|
|
return TIsPODType<CPPSTRUCT>::Value;
|
|
}
|
|
virtual bool HasCopy() override
|
|
{
|
|
return TTraits::WithCopy;
|
|
}
|
|
virtual bool Copy(void* Dest, void const* Src, int32 ArrayDim) override
|
|
{
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithCopy)
|
|
{
|
|
static_assert((!TIsPODType<CPPSTRUCT>::Value), "You probably don't want custom copy for a POD type.");
|
|
|
|
CPPSTRUCT* TypedDest = (CPPSTRUCT*)Dest;
|
|
const CPPSTRUCT* TypedSrc = (const CPPSTRUCT*)Src;
|
|
|
|
for (; ArrayDim; --ArrayDim)
|
|
{
|
|
*TypedDest++ = *TypedSrc++;
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return CopyOrNot((CPPSTRUCT*)Dest, (CPPSTRUCT const*)Src, ArrayDim);
|
|
#endif
|
|
}
|
|
virtual bool HasIdentical() override
|
|
{
|
|
return TTraits::WithIdentical || TTraits::WithIdenticalViaEquality;
|
|
}
|
|
virtual bool Identical(const void* A, const void* B, uint32 PortFlags, bool& bOutResult) override
|
|
{
|
|
check((TTraits::WithIdentical || TTraits::WithIdenticalViaEquality)); // don't call this if we have indicated it is not necessary
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithIdentical)
|
|
{
|
|
static_assert(!TStructOpsTypeTraits<CPPSTRUCT>::WithIdenticalViaEquality, "Should not have both WithIdenticalViaEquality and WithIdentical.");
|
|
|
|
bOutResult = ((const CPPSTRUCT*)A)->Identical((const CPPSTRUCT*)B, PortFlags);
|
|
return true;
|
|
}
|
|
else if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithIdenticalViaEquality)
|
|
{
|
|
bOutResult = (*(const CPPSTRUCT*)A == *(const CPPSTRUCT*)B);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
bOutResult = false;
|
|
return false;
|
|
}
|
|
#else
|
|
return IdenticalOrNot((const CPPSTRUCT*)A, (const CPPSTRUCT*)B, PortFlags, bOutResult);
|
|
#endif
|
|
}
|
|
virtual bool HasExportTextItem() override
|
|
{
|
|
return TTraits::WithExportTextItem;
|
|
}
|
|
virtual bool ExportTextItem(FString& ValueStr, const void* PropertyValue, const void* DefaultValue, class UObject* Parent, int32 PortFlags, class UObject* ExportRootScope) override
|
|
{
|
|
check(TTraits::WithExportTextItem); // don't call this if we have indicated it is not necessary
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithExportTextItem)
|
|
{
|
|
return ((const CPPSTRUCT*)PropertyValue)->ExportTextItem(ValueStr, *(const CPPSTRUCT*)DefaultValue, Parent, PortFlags, ExportRootScope);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return ExportTextItemOrNot(ValueStr, (const CPPSTRUCT*)PropertyValue, (const CPPSTRUCT*)DefaultValue, Parent, PortFlags, ExportRootScope);
|
|
#endif
|
|
}
|
|
virtual bool HasImportTextItem() override
|
|
{
|
|
return TTraits::WithImportTextItem;
|
|
}
|
|
virtual bool ImportTextItem(const TCHAR*& Buffer, void* Data, int32 PortFlags, class UObject* OwnerObject, FOutputDevice* ErrorText) override
|
|
{
|
|
check(TTraits::WithImportTextItem); // don't call this if we have indicated it is not necessary
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithImportTextItem)
|
|
{
|
|
return ((CPPSTRUCT*)Data)->ImportTextItem(Buffer, PortFlags, OwnerObject, ErrorText);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return ImportTextItemOrNot(Buffer, (CPPSTRUCT*)Data, PortFlags, OwnerObject, ErrorText);
|
|
#endif
|
|
}
|
|
virtual bool HasAddStructReferencedObjects() override
|
|
{
|
|
return TTraits::WithAddStructReferencedObjects;
|
|
}
|
|
virtual TPointerToAddStructReferencedObjects AddStructReferencedObjects() override
|
|
{
|
|
check(TTraits::WithAddStructReferencedObjects); // don't call this if we have indicated it is not necessary
|
|
return &AddStructReferencedObjectsOrNot<CPPSTRUCT>;
|
|
}
|
|
virtual bool HasSerializeFromMismatchedTag() override
|
|
{
|
|
return TTraits::WithSerializeFromMismatchedTag;
|
|
}
|
|
virtual bool SerializeFromMismatchedTag(struct FPropertyTag const& Tag, FArchive& Ar, void* Data) override
|
|
{
|
|
check(TTraits::WithSerializeFromMismatchedTag); // don't call this if we have indicated it is not allowed
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithSerializeFromMismatchedTag)
|
|
{
|
|
return ((CPPSTRUCT*)Data)->SerializeFromMismatchedTag(Tag, Ar);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return SerializeFromMismatchedTagOrNot(Tag, Ar, (CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
virtual bool HasStructuredSerializeFromMismatchedTag() override
|
|
{
|
|
return TTraits::WithStructuredSerializeFromMismatchedTag;
|
|
}
|
|
virtual bool StructuredSerializeFromMismatchedTag(struct FPropertyTag const& Tag, FStructuredArchive::FSlot Slot, void* Data) override
|
|
{
|
|
check(TTraits::WithStructuredSerializeFromMismatchedTag); // don't call this if we have indicated it is not allowed
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TStructOpsTypeTraits<CPPSTRUCT>::WithStructuredSerializeFromMismatchedTag)
|
|
{
|
|
return ((CPPSTRUCT*)Data)->SerializeFromMismatchedTag(Tag, Slot);
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
#else
|
|
return StructuredSerializeFromMismatchedTagOrNot(Tag, Slot, (CPPSTRUCT*)Data);
|
|
#endif
|
|
}
|
|
|
|
static_assert(!(TTraits::WithSerializeFromMismatchedTag && TTraits::WithStructuredSerializeFromMismatchedTag), "Structs cannot have both WithSerializeFromMismatchedTag and WithStructuredSerializeFromMismatchedTag set");
|
|
|
|
virtual bool HasGetTypeHash() override
|
|
{
|
|
return TModels<CGetTypeHashable, CPPSTRUCT>::Value;
|
|
}
|
|
uint32 GetStructTypeHash(const void* Src) override
|
|
{
|
|
ensure(HasGetTypeHash());
|
|
|
|
#if PLATFORM_COMPILER_HAS_IF_CONSTEXPR
|
|
if constexpr (TModels<CGetTypeHashable, CPPSTRUCT>::Value)
|
|
{
|
|
return GetTypeHash(*(const CPPSTRUCT*)Src);
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
#else
|
|
return GetTypeHashOrNot((const CPPSTRUCT*)Src);
|
|
#endif
|
|
}
|
|
virtual EPropertyFlags GetComputedPropertyFlags() const override
|
|
{
|
|
return (TIsPODType<CPPSTRUCT>::Value ? CPF_IsPlainOldData : CPF_None) | (TIsTriviallyDestructible<CPPSTRUCT>::Value ? CPF_NoDestructor : CPF_None) | (TIsZeroConstructType<CPPSTRUCT>::Value ? CPF_ZeroConstructor : CPF_None) | (TModels<CGetTypeHashable, CPPSTRUCT>::Value ? CPF_HasGetValueTypeHash : CPF_None);
|
|
}
|
|
bool IsAbstract() const override
|
|
{
|
|
return TIsAbstract<CPPSTRUCT>::Value;
|
|
}
|
|
};
|
|
|
|
/** Template for noexport classes to autoregister before main starts **/
|
|
template <class CPPSTRUCT>
|
|
struct TAutoCppStructOps
|
|
{
|
|
TAutoCppStructOps(FName InName)
|
|
{
|
|
DeferCppStructOps(InName, new TCppStructOps<CPPSTRUCT>);
|
|
}
|
|
};
|
|
#define IMPLEMENT_STRUCT(BaseName) \
|
|
static UScriptStruct::TAutoCppStructOps<F##BaseName> BaseName##_Ops(TEXT(#BaseName));
|
|
|
|
DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR(UScriptStruct, UStruct, CLASS_MatchedSerializers, TEXT("/Script/CoreUObject"), CASTCLASS_UScriptStruct, COREUOBJECT_API)
|
|
|
|
COREUOBJECT_API UScriptStruct(EStaticConstructor, int32 InSize, int32 InAlignment, EObjectFlags InFlags);
|
|
COREUOBJECT_API explicit UScriptStruct(const FObjectInitializer& ObjectInitializer, UScriptStruct* InSuperStruct, ICppStructOps* InCppStructOps = nullptr, EStructFlags InStructFlags = STRUCT_NoFlags, SIZE_T ExplicitSize = 0, SIZE_T ExplicitAlignment = 0);
|
|
COREUOBJECT_API explicit UScriptStruct(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
|
|
|
public:
|
|
EStructFlags StructFlags;
|
|
|
|
#if HACK_HEADER_GENERATOR
|
|
int32 StructMacroDeclaredLineNumber;
|
|
|
|
// Required by UHT makefiles for internal data serialization.
|
|
friend struct FScriptStructArchiveProxy;
|
|
#endif
|
|
|
|
protected:
|
|
/** true if we have performed PrepareCppStructOps **/
|
|
bool bPrepareCppStructOpsCompleted;
|
|
/** Holds the Cpp ctors and dtors, sizeof, etc. Is not owned by this and is not released. **/
|
|
ICppStructOps* CppStructOps;
|
|
|
|
public:
|
|
// UObject Interface
|
|
virtual COREUOBJECT_API void Serialize(FArchive& Ar) override;
|
|
virtual COREUOBJECT_API void Serialize(FStructuredArchive::FRecord Record) override;
|
|
|
|
// UStruct interface.
|
|
virtual COREUOBJECT_API void Link(FArchive& Ar, bool bRelinkExistingProperties) override;
|
|
virtual COREUOBJECT_API void InitializeStruct(void* Dest, int32 ArrayDim = 1) const override;
|
|
virtual COREUOBJECT_API void DestroyStruct(void* Dest, int32 ArrayDim = 1) const override;
|
|
virtual COREUOBJECT_API bool IsStructTrashed() const override;
|
|
// End of UStruct interface.
|
|
|
|
/** Sets or unsets the trashed flag on this struct */
|
|
void COREUOBJECT_API SetStructTrashed(bool bIsTrash);
|
|
|
|
/**
|
|
* Stash a CppStructOps for future use
|
|
* @param Target Name of the struct
|
|
* @param InCppStructOps Cpp ops for this struct
|
|
*/
|
|
static COREUOBJECT_API void DeferCppStructOps(FName Target, ICppStructOps* InCppStructOps);
|
|
|
|
template <class CPPSTRUCT>
|
|
static typename TEnableIf<!DISABLE_ABSTRACT_CONSTRUCT>::Type DeferCppStructOps(FName Target)
|
|
{
|
|
DeferCppStructOps(Target, new UScriptStruct::TCppStructOps<CPPSTRUCT>);
|
|
}
|
|
template <class CPPSTRUCT>
|
|
static typename TEnableIf<DISABLE_ABSTRACT_CONSTRUCT>::Type DeferCppStructOps(FName Target)
|
|
{
|
|
DeferCppStructOps(Target, nullptr);
|
|
}
|
|
|
|
/** Look for the CppStructOps and hook it up **/
|
|
virtual COREUOBJECT_API void PrepareCppStructOps();
|
|
|
|
/** Returns the CppStructOps that can be used to do custom operations */
|
|
FORCEINLINE ICppStructOps* GetCppStructOps() const
|
|
{
|
|
checkf(bPrepareCppStructOpsCompleted, TEXT("GetCppStructOps: PrepareCppStructOps() has not been called for class %s"), *GetName());
|
|
return CppStructOps;
|
|
}
|
|
|
|
/** Resets currently assigned CppStructOps, called when loading a struct */
|
|
void ClearCppStructOps()
|
|
{
|
|
StructFlags = EStructFlags(StructFlags & ~STRUCT_ComputedFlags);
|
|
bPrepareCppStructOpsCompleted = false;
|
|
CppStructOps = nullptr;
|
|
}
|
|
|
|
/**
|
|
* If it is native, it is assumed to have defaults because it has a constructor
|
|
* @return true if this struct has defaults
|
|
*/
|
|
FORCEINLINE bool HasDefaults() const
|
|
{
|
|
return !!GetCppStructOps();
|
|
}
|
|
|
|
/**
|
|
* Returns whether this struct should be serialized atomically.
|
|
* @param Ar Archive the struct is going to be serialized with later on
|
|
*/
|
|
bool ShouldSerializeAtomically(FArchive& Ar) const
|
|
{
|
|
if ((StructFlags & STRUCT_Atomic) != 0)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/** Returns true if this struct has a native serialize function */
|
|
bool UseNativeSerialization() const
|
|
{
|
|
if ((StructFlags & (STRUCT_SerializeNative)) != 0)
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/** Returns true if this struct should be binary serialized for the given archive */
|
|
COREUOBJECT_API bool UseBinarySerialization(const FArchive& Ar) const;
|
|
|
|
/**
|
|
* Serializes a specific instance of a struct
|
|
*
|
|
* @param Slot The structured archive slot we are serializing to
|
|
* @param Value Pointer to memory of struct
|
|
* @param Defaults Default value for this struct, pass nullptr to not use defaults
|
|
*/
|
|
COREUOBJECT_API void SerializeItem(FArchive& Ar, void* Value, void const* Defaults);
|
|
COREUOBJECT_API void SerializeItem(FStructuredArchive::FSlot Slot, void* Value, void const* Defaults);
|
|
|
|
/**
|
|
* Export script struct to a string that can later be imported
|
|
*
|
|
* @param ValueStr String to write to
|
|
* @param Value Actual struct being exported
|
|
* @param Defaults Default value for this struct, pass nullptr to not use defaults
|
|
* @param OwnerObject UObject that contains this struct
|
|
* @param PortFlags EPropertyPortFlags controlling export behavior
|
|
* @param ExportRootScope The scope to create relative paths from, if the PPF_ExportsNotFullyQualified flag is passed in. If NULL, the package containing the object will be used instead.
|
|
* @param bAllowNativeOverride If true, will try to run native version of export text on the struct
|
|
*/
|
|
COREUOBJECT_API void ExportText(FString& ValueStr, const void* Value, const void* Defaults, UObject* OwnerObject, int32 PortFlags, UObject* ExportRootScope, bool bAllowNativeOverride = true) const;
|
|
|
|
/**
|
|
* Sets value of script struct based on imported string
|
|
*
|
|
* @param Buffer String to read text data out of
|
|
* @param Value Struct that will be modified
|
|
* @param OwnerObject UObject that contains this struct
|
|
* @param PortFlags EPropertyPortFlags controlling import behavior
|
|
* @param ErrorText What to print import errors to
|
|
* @param StructName Name of struct, used in error display
|
|
* @param bAllowNativeOverride If true, will try to run native version of export text on the struct
|
|
* @return Buffer after parsing has succeeded, or NULL on failure
|
|
*/
|
|
COREUOBJECT_API const TCHAR* ImportText(const TCHAR* Buffer, void* Value, UObject* OwnerObject, int32 PortFlags, FOutputDevice* ErrorText, const FString& StructName, bool bAllowNativeOverride = true);
|
|
|
|
/**
|
|
* Sets value of script struct based on imported string
|
|
*
|
|
* @param Buffer String to read text data out of
|
|
* @param Value Struct that will be modified
|
|
* @param OwnerObject UObject that contains this struct
|
|
* @param PortFlags EPropertyPortFlags controlling import behavior
|
|
* @param ErrorText What to print import errors to
|
|
* @param StructNameGetter Function to return the struct name to avoid doing work if no error message is forthcoming
|
|
* @param bAllowNativeOverride If true, will try to run native version of export text on the struct
|
|
* @return Buffer after parsing has succeeded, or NULL on failure
|
|
*/
|
|
COREUOBJECT_API const TCHAR* ImportText(const TCHAR* Buffer, void* Value, UObject* OwnerObject, int32 PortFlags, FOutputDevice* ErrorText, const TFunctionRef<FString()>& StructNameGetter, bool bAllowNativeOverride = true);
|
|
|
|
/**
|
|
* Compare two script structs
|
|
*
|
|
* @param Dest Pointer to memory to a struct
|
|
* @param Src Pointer to memory to the other struct
|
|
* @param PortFlags Comparison flags
|
|
* @return true if the structs are identical
|
|
*/
|
|
COREUOBJECT_API bool CompareScriptStruct(const void* A, const void* B, uint32 PortFlags) const;
|
|
|
|
/**
|
|
* Copy a struct over an existing struct
|
|
*
|
|
* @param Dest Pointer to memory to initialize
|
|
* @param Src Pointer to memory to copy from
|
|
* @param ArrayDim Number of elements in the array
|
|
* @param Stride Stride of the array, If this default (0), then we will pull the size from the struct
|
|
*/
|
|
COREUOBJECT_API void CopyScriptStruct(void* Dest, void const* Src, int32 ArrayDim = 1) const;
|
|
|
|
/**
|
|
* Reinitialize a struct in memory. This may be done by calling the native destructor and then the constructor or individually reinitializing properties
|
|
*
|
|
* @param Dest Pointer to memory to reinitialize
|
|
* @param ArrayDim Number of elements in the array
|
|
* @param Stride Stride of the array, only relevant if there more than one element. If this default (0), then we will pull the size from the struct
|
|
*/
|
|
COREUOBJECT_API void ClearScriptStruct(void* Dest, int32 ArrayDim = 1) const;
|
|
|
|
/**
|
|
* Calls GetTypeHash for native structs, otherwise computes a hash of all struct members
|
|
*
|
|
* @param Src Pointer to instance to hash
|
|
* @return hashed value of Src
|
|
*/
|
|
virtual COREUOBJECT_API uint32 GetStructTypeHash(const void* Src) const;
|
|
|
|
/** Used by User Defined Structs to preload this struct and any child objects */
|
|
virtual COREUOBJECT_API void RecursivelyPreload();
|
|
|
|
/** Returns the custom Guid assigned to this struct for User Defined Structs, or an invalid Guid */
|
|
virtual COREUOBJECT_API FGuid GetCustomGuid() const;
|
|
|
|
/** Returns the (native, c++) name of the struct */
|
|
virtual COREUOBJECT_API FString GetStructCPPName() const;
|
|
|
|
/**
|
|
* Initializes this structure to its default values
|
|
* @param InStructData The memory location to initialize
|
|
*/
|
|
virtual COREUOBJECT_API void InitializeDefaultValue(uint8* InStructData) const;
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
UFunction.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
//
|
|
// Reflection data for a replicated or Kismet callable function.
|
|
//
|
|
class COREUOBJECT_API UFunction: public UStruct
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC(UFunction, UStruct, 0, TEXT("/Script/CoreUObject"), CASTCLASS_UFunction)
|
|
DECLARE_WITHIN(UClass)
|
|
public:
|
|
// Persistent variables.
|
|
|
|
/** EFunctionFlags set defined for this function */
|
|
EFunctionFlags FunctionFlags;
|
|
|
|
// Variables in memory only.
|
|
|
|
/** Number of parameters total */
|
|
uint8 NumParms;
|
|
/** Total size of parameters in memory */
|
|
uint16 ParmsSize;
|
|
/** Memory offset of return value property */
|
|
uint16 ReturnValueOffset;
|
|
/** Id of this RPC function call (must be FUNC_Net & (FUNC_NetService|FUNC_NetResponse)) */
|
|
uint16 RPCId;
|
|
/** Id of the corresponding response call (must be FUNC_Net & FUNC_NetService) */
|
|
uint16 RPCResponseId;
|
|
|
|
/** pointer to first local struct property in this UFunction that contains defaults */
|
|
FProperty* FirstPropertyToInit;
|
|
|
|
#if UE_BLUEPRINT_EVENTGRAPH_FASTCALLS
|
|
/** The event graph this function calls in to (persistent) */
|
|
UFunction* EventGraphFunction;
|
|
|
|
/** The state offset inside of the event graph (persistent) */
|
|
int32 EventGraphCallOffset;
|
|
#endif
|
|
|
|
private:
|
|
/** C++ function this is bound to */
|
|
FNativeFuncPtr Func;
|
|
|
|
public:
|
|
/**
|
|
* Returns the native func pointer.
|
|
*
|
|
* @return The native function pointer.
|
|
*/
|
|
FORCEINLINE FNativeFuncPtr GetNativeFunc() const
|
|
{
|
|
return Func;
|
|
}
|
|
|
|
/**
|
|
* Sets the native func pointer.
|
|
*
|
|
* @param InFunc - The new function pointer.
|
|
*/
|
|
FORCEINLINE void SetNativeFunc(FNativeFuncPtr InFunc)
|
|
{
|
|
Func = InFunc;
|
|
}
|
|
|
|
/**
|
|
* Invokes the UFunction on a UObject.
|
|
*
|
|
* @param Obj - The object to invoke the function on.
|
|
* @param Stack - The parameter stack for the function call.
|
|
* @param Result - The result of the function.
|
|
*/
|
|
void Invoke(UObject* Obj, FFrame& Stack, RESULT_DECL);
|
|
|
|
// Constructors.
|
|
explicit UFunction(const FObjectInitializer& ObjectInitializer, UFunction* InSuperFunction, EFunctionFlags InFunctionFlags = FUNC_None, SIZE_T ParamsSize = 0);
|
|
explicit UFunction(UFunction* InSuperFunction, EFunctionFlags InFunctionFlags = FUNC_None, SIZE_T ParamsSize = 0);
|
|
|
|
/** Initializes transient members like return value offset */
|
|
void InitializeDerivedMembers();
|
|
|
|
// UObject interface.
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
virtual void PostLoad() override;
|
|
|
|
// UField interface.
|
|
virtual void Bind() override;
|
|
|
|
// UStruct interface.
|
|
virtual UStruct* GetInheritanceSuper() const override { return nullptr; }
|
|
virtual void Link(FArchive& Ar, bool bRelinkExistingProperties) override;
|
|
|
|
/** Returns parent function if there is one, or null */
|
|
UFunction* GetSuperFunction() const;
|
|
|
|
/** Returns the return value property if there is one, or null */
|
|
FProperty* GetReturnProperty() const;
|
|
|
|
/** Returns the owning UClass* without branching */
|
|
FORCEINLINE UClass* GetOuterUClassUnchecked() const
|
|
{
|
|
// declaration order mandates reinterpret_cast:
|
|
return reinterpret_cast<UClass*>(GetOuter());
|
|
}
|
|
|
|
/**
|
|
* Used to safely check whether the passed in flag is set.
|
|
*
|
|
* @param FlagToCheck Class flag to check for
|
|
*
|
|
* @return true if the passed in flag is set, false otherwise
|
|
* (including no flag passed in, unless the FlagsToCheck is CLASS_AllFlags)
|
|
*/
|
|
FORCEINLINE bool HasAnyFunctionFlags(EFunctionFlags FlagsToCheck) const
|
|
{
|
|
return (FunctionFlags & FlagsToCheck) != 0 || FlagsToCheck == FUNC_AllFlags;
|
|
}
|
|
|
|
/**
|
|
* Used to safely check whether all of the passed in flags are set.
|
|
*
|
|
* @param FlagsToCheck Function flags to check for
|
|
* @return true if all of the passed in flags are set (including no flags passed in), false otherwise
|
|
*/
|
|
FORCEINLINE bool HasAllFunctionFlags(EFunctionFlags FlagsToCheck) const
|
|
{
|
|
return ((FunctionFlags & FlagsToCheck) == FlagsToCheck);
|
|
}
|
|
|
|
/**
|
|
* Returns the flags that are ignored by default when comparing function signatures.
|
|
*/
|
|
FORCEINLINE static uint64 GetDefaultIgnoredSignatureCompatibilityFlags()
|
|
{
|
|
//@TODO: UCREMOVAL: CPF_ConstParm added as a hack to get blueprints compiling with a const DamageType parameter.
|
|
const uint64 IgnoreFlags = CPF_PersistentInstance | CPF_ExportObject | CPF_InstancedReference | CPF_ContainsInstancedReference | CPF_ComputedFlags | CPF_ConstParm | CPF_UObjectWrapper | CPF_NativeAccessSpecifiers | CPF_AdvancedDisplay | CPF_BlueprintVisible | CPF_BlueprintReadOnly;
|
|
return IgnoreFlags;
|
|
}
|
|
|
|
/**
|
|
* Determines if two functions have an identical signature (note: currently doesn't allow
|
|
* matches with class parameters that differ only in how derived they are; there is no
|
|
* directionality to the call)
|
|
*
|
|
* @param OtherFunction Function to compare this function against.
|
|
*
|
|
* @return true if function signatures are compatible.
|
|
*/
|
|
bool IsSignatureCompatibleWith(const UFunction* OtherFunction) const;
|
|
|
|
/**
|
|
* Determines if two functions have an identical signature (note: currently doesn't allow
|
|
* matches with class parameters that differ only in how derived they are; there is no
|
|
* directionality to the call)
|
|
*
|
|
* @param OtherFunction Function to compare this function against.
|
|
* @param IgnoreFlags Custom flags to ignore when comparing parameters between the functions.
|
|
*
|
|
* @return true if function signatures are compatible.
|
|
*/
|
|
bool IsSignatureCompatibleWith(const UFunction* OtherFunction, uint64 IgnoreFlags) const;
|
|
};
|
|
|
|
//
|
|
// Function definition used by dynamic delegate declarations
|
|
//
|
|
class COREUOBJECT_API UDelegateFunction: public UFunction
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC(UDelegateFunction, UFunction, 0, TEXT("/Script/CoreUObject"), CASTCLASS_UDelegateFunction)
|
|
DECLARE_WITHIN(UObject)
|
|
public:
|
|
explicit UDelegateFunction(const FObjectInitializer& ObjectInitializer, UFunction* InSuperFunction, EFunctionFlags InFunctionFlags = FUNC_None, SIZE_T ParamsSize = 0);
|
|
explicit UDelegateFunction(UFunction* InSuperFunction, EFunctionFlags InFunctionFlags = FUNC_None, SIZE_T ParamsSize = 0);
|
|
};
|
|
|
|
//
|
|
// Function definition used by sparse dynamic delegate declarations
|
|
//
|
|
class COREUOBJECT_API USparseDelegateFunction: public UDelegateFunction
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC(USparseDelegateFunction, UDelegateFunction, 0, TEXT("/Script/CoreUObject"), CASTCLASS_USparseDelegateFunction)
|
|
DECLARE_WITHIN(UObject)
|
|
public:
|
|
explicit USparseDelegateFunction(const FObjectInitializer& ObjectInitializer, UFunction* InSuperFunction, EFunctionFlags InFunctionFlags = FUNC_None, SIZE_T ParamsSize = 0);
|
|
explicit USparseDelegateFunction(UFunction* InSuperFunction, EFunctionFlags InFunctionFlags = FUNC_None, SIZE_T ParamsSize = 0);
|
|
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
|
|
FName OwningClassName;
|
|
FName DelegateName;
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
UEnum.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
typedef FText (*FEnumDisplayNameFn)(int32);
|
|
|
|
/** Optional flags for the UEnum::Get*ByName() functions. */
|
|
enum class EGetByNameFlags
|
|
{
|
|
None = 0,
|
|
|
|
/** Outputs an warning if the enum lookup fails */
|
|
ErrorIfNotFound = 0x01,
|
|
|
|
/** Does a case sensitive match */
|
|
CaseSensitive = 0x02,
|
|
|
|
/** Checks the GetAuthoredNameStringByIndex value as well as normal names */
|
|
CheckAuthoredName = 0x04,
|
|
};
|
|
|
|
ENUM_CLASS_FLAGS(EGetByNameFlags)
|
|
|
|
//
|
|
// Reflection data for an enumeration.
|
|
//
|
|
class COREUOBJECT_API UEnum: public UField
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR(UEnum, UField, 0, TEXT("/Script/CoreUObject"), CASTCLASS_UEnum, NO_API)
|
|
UEnum(const FObjectInitializer& ObjectInitialzer);
|
|
|
|
public:
|
|
/** How this enum is declared in C++, affects the internal naming of enum values */
|
|
enum class ECppForm
|
|
{
|
|
Regular,
|
|
Namespaced,
|
|
EnumClass
|
|
};
|
|
|
|
/** This will be the true type of the enum as a string, e.g. "ENamespacedEnum::InnerType" or "ERegularEnum" or "EEnumClass" */
|
|
FString CppType;
|
|
|
|
// Index is the internal index into the Enum array, and is not useful outside of the Enum system
|
|
// Value is the value set in the Enum Class in C++ or Blueprint
|
|
// Enums can be sparse, which means that not every valid Index is a proper Value, and they are not necessarily equal
|
|
// It is not safe to cast an Index to a Enum Class, always do that with a Value instead
|
|
|
|
/** Gets the internal index for an enum value. Returns INDEX_None if not valid */
|
|
FORCEINLINE int32 GetIndexByValue(int64 InValue) const
|
|
{
|
|
for (int32 i = 0; i < Names.Num(); ++i)
|
|
{
|
|
if (Names[i].Value == InValue)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return INDEX_NONE;
|
|
}
|
|
|
|
/** Gets enum value by index in Names array. Asserts on invalid index */
|
|
FORCEINLINE int64 GetValueByIndex(int32 Index) const
|
|
{
|
|
check(Names.IsValidIndex(Index));
|
|
return Names[Index].Value;
|
|
}
|
|
|
|
/** Gets enum name by index in Names array. Returns NAME_None if Index is not valid. */
|
|
FName GetNameByIndex(int32 Index) const;
|
|
|
|
/** Gets index of name in enum, returns INDEX_NONE and optionally errors when name is not found. This is faster than ByNameString if the FName is exact, but will fall back if needed */
|
|
int32 GetIndexByName(FName InName, EGetByNameFlags Flags = EGetByNameFlags::None) const;
|
|
|
|
/** Gets enum name by value. Returns NAME_None if value is not found. */
|
|
FName GetNameByValue(int64 InValue) const;
|
|
|
|
/** Gets enum value by name, returns INDEX_NONE and optionally errors when name is not found. This is faster than ByNameString if the FName is exact, but will fall back if needed */
|
|
int64 GetValueByName(FName InName, EGetByNameFlags Flags = EGetByNameFlags::None) const;
|
|
|
|
/** Returns the short name at the enum index, returns empty string if invalid */
|
|
FString GetNameStringByIndex(int32 InIndex) const;
|
|
|
|
/** Gets index of name in enum, returns INDEX_NONE and optionally errors when name is not found. Handles full or short names. */
|
|
int32 GetIndexByNameString(const FString& SearchString, EGetByNameFlags Flags = EGetByNameFlags::None) const;
|
|
|
|
/** Returns the short name matching the enum Value, returns empty string if invalid */
|
|
FString GetNameStringByValue(int64 InValue) const;
|
|
|
|
/** Looks for a name with a given value and returns true and writes the name to Out if one was found */
|
|
bool FindNameStringByValue(FString& Out, int64 InValue) const;
|
|
|
|
/** Gets enum value by name, returns INDEX_NONE and optionally errors when name is not found. Handles full or short names */
|
|
int64 GetValueByNameString(const FString& SearchString, EGetByNameFlags Flags = EGetByNameFlags::None) const;
|
|
|
|
/**
|
|
* Finds the localized display name or native display name as a fallback.
|
|
* If called from a cooked build this will normally return the short name as Metadata is not available.
|
|
*
|
|
* @param InIndex Index of the enum value to get Display Name for
|
|
*
|
|
* @return The display name for this object, or an empty text if Index is invalid
|
|
*/
|
|
virtual FText GetDisplayNameTextByIndex(int32 InIndex) const;
|
|
|
|
/** Version of GetDisplayNameTextByIndex that takes a value instead */
|
|
FText GetDisplayNameTextByValue(int64 InValue) const;
|
|
|
|
/** Looks for a display name with a given value and returns true and writes the name to Out if one was found */
|
|
bool FindDisplayNameTextByValue(FText& Out, int64 InValue) const;
|
|
|
|
/**
|
|
* Returns the unlocalized logical name originally assigned to the enum at creation.
|
|
* By default this is the same as the short name but it is overridden in child classes with different internal name storage.
|
|
* This name is consistent in cooked and editor builds and is useful for things like external data import/export.
|
|
*
|
|
* @param InIndex Index of the enum value to get Display Name for
|
|
*
|
|
* @return The author-specified name, or an empty string if Index is invalid
|
|
*/
|
|
virtual FString GetAuthoredNameStringByIndex(int32 InIndex) const;
|
|
|
|
/** Version of GetAuthoredNameByIndex that takes a value instead */
|
|
FString GetAuthoredNameStringByValue(int64 InValue) const;
|
|
|
|
/** Looks for a display name with a given value and returns true and writes the unlocalized logical name to Out if one was found */
|
|
bool FindAuthoredNameStringByValue(FString& Out, int64 InValue) const;
|
|
|
|
/** Gets max value of Enum. Defaults to zero if there are no entries. */
|
|
int64 GetMaxEnumValue() const;
|
|
|
|
/** Checks if enum has entry with given value. Includes autogenerated _MAX entry. */
|
|
bool IsValidEnumValue(int64 InValue) const;
|
|
|
|
/** Checks if enum has entry with given name. Includes autogenerated _MAX entry. */
|
|
bool IsValidEnumName(FName InName) const;
|
|
|
|
/** Removes the Names in this enum from the master AllEnumNames list */
|
|
void RemoveNamesFromMasterList();
|
|
|
|
/** Try to update an out-of-date enum index after an enum changes at runtime */
|
|
virtual int64 ResolveEnumerator(FArchive& Ar, int64 EnumeratorIndex) const;
|
|
|
|
/** Associate a function for looking up Enum display names by index, only intended for use by generated code */
|
|
void SetEnumDisplayNameFn(FEnumDisplayNameFn InEnumDisplayNameFn)
|
|
{
|
|
EnumDisplayNameFn = InEnumDisplayNameFn;
|
|
}
|
|
|
|
/**
|
|
* Returns the type of enum: whether it's a regular enum, namespaced enum or C++11 enum class.
|
|
*
|
|
* @return The enum type.
|
|
*/
|
|
ECppForm GetCppForm() const
|
|
{
|
|
return CppForm;
|
|
}
|
|
|
|
bool HasAnyEnumFlags(EEnumFlags InFlags) const
|
|
{
|
|
return EnumHasAnyFlags(EnumFlags, InFlags);
|
|
}
|
|
|
|
/**
|
|
* Checks if a enum name is fully qualified name.
|
|
*
|
|
* @param InEnumName Name to check.
|
|
* @return true if the specified name is full enum name, false otherwise.
|
|
*/
|
|
static bool IsFullEnumName(const TCHAR* InEnumName)
|
|
{
|
|
return !!FCString::Strstr(InEnumName, TEXT("::"));
|
|
}
|
|
|
|
/**
|
|
* Generates full name including EnumName:: given enum name.
|
|
*
|
|
* @param InEnumName Enum name.
|
|
* @return Full enum name.
|
|
*/
|
|
virtual FString GenerateFullEnumName(const TCHAR* InEnumName) const;
|
|
|
|
/** searches the list of all enum value names for the specified name
|
|
* @return the value the specified name represents if found, otherwise INDEX_NONE
|
|
*/
|
|
static int64 LookupEnumName(FName TestName, UEnum** FoundEnum = nullptr)
|
|
{
|
|
UEnum* TheEnum = AllEnumNames.FindRef(TestName);
|
|
if (FoundEnum != nullptr)
|
|
{
|
|
*FoundEnum = TheEnum;
|
|
}
|
|
return (TheEnum != nullptr) ? TheEnum->GetValueByName(TestName) : INDEX_NONE;
|
|
}
|
|
|
|
/** searches the list of all enum value names for the specified name
|
|
* @return the value the specified name represents if found, otherwise INDEX_NONE
|
|
*/
|
|
static int64 LookupEnumNameSlow(const TCHAR* InTestShortName, UEnum** FoundEnum = nullptr)
|
|
{
|
|
int64 Result = LookupEnumName(InTestShortName, FoundEnum);
|
|
if (Result == INDEX_NONE)
|
|
{
|
|
FString TestShortName = FString(TEXT("::")) + InTestShortName;
|
|
UEnum* TheEnum = nullptr;
|
|
for (TMap<FName, UEnum*>::TIterator It(AllEnumNames); It; ++It)
|
|
{
|
|
if (It.Key().ToString().Contains(TestShortName))
|
|
{
|
|
TheEnum = It.Value();
|
|
}
|
|
}
|
|
if (FoundEnum != nullptr)
|
|
{
|
|
*FoundEnum = TheEnum;
|
|
}
|
|
Result = (TheEnum != nullptr) ? TheEnum->GetValueByName(InTestShortName) : INDEX_NONE;
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
/** parses the passed in string for a name, then searches for that name in any Enum (in any package)
|
|
* @param Str pointer to string to parse; if we successfully find an enum, this pointer is advanced past the name found
|
|
* @return index of the value the parsed enum name matches, or INDEX_NONE if no matches
|
|
*/
|
|
static int64 ParseEnum(const TCHAR*& Str);
|
|
|
|
/**
|
|
* Tests if the enum contains a MAX value
|
|
*
|
|
* @return true if the enum contains a MAX enum, false otherwise.
|
|
*/
|
|
bool ContainsExistingMax() const;
|
|
|
|
/**
|
|
* Sets the array of enums.
|
|
*
|
|
* @param InNames List of enum names.
|
|
* @param InCppForm The form of enum.
|
|
* @param bAddMaxKeyIfMissing Should a default Max item be added.
|
|
* @return true unless the MAX enum already exists and isn't the last enum.
|
|
*/
|
|
virtual bool SetEnums(TArray<TPair<FName, int64>>& InNames, ECppForm InCppForm, EEnumFlags InFlags = EEnumFlags::None, bool bAddMaxKeyIfMissing = true);
|
|
|
|
/**
|
|
* @return The number of enum names.
|
|
*/
|
|
int32 NumEnums() const
|
|
{
|
|
return Names.Num();
|
|
}
|
|
|
|
/**
|
|
* Find the longest common prefix of all items in the enumeration.
|
|
*
|
|
* @return the longest common prefix between all items in the enum. If a common prefix
|
|
* cannot be found, returns the full name of the enum.
|
|
*/
|
|
FString GenerateEnumPrefix() const;
|
|
|
|
#if WITH_EDITOR
|
|
/**
|
|
* Finds the localized tooltip or native tooltip as a fallback.
|
|
*
|
|
* @param NameIndex Index of the enum value to get tooltip for
|
|
*
|
|
* @return The tooltip for this object.
|
|
*/
|
|
FText GetToolTipTextByIndex(int32 NameIndex) const;
|
|
|
|
UE_DEPRECATED(4.16, "GetToolTipText with name index is deprecated, call GetToolTipTextByIndex instead")
|
|
FText GetToolTipText(int32 NameIndex) const { return GetToolTipTextByIndex(NameIndex); }
|
|
#endif
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
/**
|
|
* Wrapper method for easily determining whether this enum has metadata associated with it.
|
|
*
|
|
* @param Key the metadata tag to check for
|
|
* @param NameIndex if specified, will search for metadata linked to a specified value in this enum; otherwise, searches for metadata for the enum itself
|
|
*
|
|
* @return true if the specified key exists in the list of metadata for this enum, even if the value of that key is empty
|
|
*/
|
|
bool HasMetaData(const TCHAR* Key, int32 NameIndex = INDEX_NONE) const;
|
|
|
|
/**
|
|
* Return the metadata value associated with the specified key.
|
|
*
|
|
* @param Key the metadata tag to find the value for
|
|
* @param NameIndex if specified, will search the metadata linked for that enum value; otherwise, searches the metadata for the enum itself
|
|
* @param bAllowRemap if true, the returned value may be remapped from a .ini if the value starts with ini: Pass false when you need the exact string, including any ini:
|
|
*
|
|
* @return the value for the key specified, or an empty string if the key wasn't found or had no value.
|
|
*/
|
|
FString GetMetaData(const TCHAR* Key, int32 NameIndex = INDEX_NONE, bool bAllowRemap = true) const;
|
|
|
|
/**
|
|
* Set the metadata value associated with the specified key.
|
|
*
|
|
* @param Key the metadata tag to find the value for
|
|
* @param NameIndex if specified, will search the metadata linked for that enum value; otherwise, searches the metadata for the enum itself
|
|
* @param InValue Value of the metadata for the key
|
|
*
|
|
*/
|
|
void SetMetaData(const TCHAR* Key, const TCHAR* InValue, int32 NameIndex = INDEX_NONE) const;
|
|
|
|
/**
|
|
* Remove given key meta data
|
|
*
|
|
* @param Key the metadata tag to find the value for
|
|
* @param NameIndex if specified, will search the metadata linked for that enum value; otherwise, searches the metadata for the enum itself
|
|
*
|
|
*/
|
|
void RemoveMetaData(const TCHAR* Key, int32 NameIndex = INDEX_NONE) const;
|
|
#endif // WITH_EDITORONLY_DATA
|
|
|
|
/**
|
|
* @param EnumPath Full enum path.
|
|
* @param EnumeratorValue Enumerator VAlue.
|
|
*
|
|
* @return the string associated with the enumerator for the specified enum value for the enum specified by a path.
|
|
*/
|
|
template <typename T>
|
|
FORCEINLINE static FString GetValueAsString(const TCHAR* EnumPath, const T EnumeratorValue)
|
|
{
|
|
// For the C++ enum.
|
|
static_assert(TIsEnum<T>::Value, "Should only call this with enum types");
|
|
return GetValueAsString_Internal(EnumPath, (int64)EnumeratorValue);
|
|
}
|
|
|
|
template <typename T>
|
|
FORCEINLINE static FString GetValueAsString(const TCHAR* EnumPath, const TEnumAsByte<T> EnumeratorValue)
|
|
{
|
|
return GetValueAsString_Internal(EnumPath, (int64)EnumeratorValue.GetValue());
|
|
}
|
|
|
|
template <class T>
|
|
FORCEINLINE static void GetValueAsString(const TCHAR* EnumPath, const T EnumeratorValue, FString& out_StringValue)
|
|
{
|
|
out_StringValue = GetValueAsString(EnumPath, EnumeratorValue);
|
|
}
|
|
|
|
/**
|
|
* @param EnumPath Full enum path.
|
|
* @param EnumeratorValue Enumerator Value.
|
|
*
|
|
* @return the localized display string associated with the specified enum value for the enum specified by a path
|
|
*/
|
|
template <typename T>
|
|
FORCEINLINE static FText GetDisplayValueAsText(const TCHAR* EnumPath, const T EnumeratorValue)
|
|
{
|
|
// For the C++ enum.
|
|
static_assert(TIsEnum<T>::Value, "Should only call this with enum types");
|
|
return GetDisplayValueAsText_Internal(EnumPath, (int64)EnumeratorValue);
|
|
}
|
|
|
|
template <typename T>
|
|
FORCEINLINE static FText GetDisplayValueAsText(const TCHAR* EnumPath, const TEnumAsByte<T> EnumeratorValue)
|
|
{
|
|
return GetDisplayValueAsText_Internal(EnumPath, (int64)EnumeratorValue.GetValue());
|
|
}
|
|
|
|
template <class T>
|
|
FORCEINLINE static void GetDisplayValueAsText(const TCHAR* EnumPath, const T EnumeratorValue, FText& out_TextValue)
|
|
{
|
|
out_TextValue = GetDisplayValueAsText(EnumPath, EnumeratorValue);
|
|
}
|
|
|
|
/**
|
|
* @param EnumeratorValue Enumerator Value.
|
|
*
|
|
* @return the name associated with the enumerator for the specified enum value for the enum specified by the template type.
|
|
*/
|
|
template <typename EnumType>
|
|
FORCEINLINE static FName GetValueAsName(const EnumType EnumeratorValue)
|
|
{
|
|
// For the C++ enum.
|
|
static_assert(TIsEnum<EnumType>::Value, "Should only call this with enum types");
|
|
UEnum* EnumClass = StaticEnum<EnumType>();
|
|
check(EnumClass != nullptr);
|
|
return EnumClass->GetNameByValue((int64)EnumeratorValue);
|
|
}
|
|
|
|
template <typename EnumType>
|
|
FORCEINLINE static FName GetValueAsName(const TEnumAsByte<EnumType> EnumeratorValue)
|
|
{
|
|
return GetValueAsName(EnumeratorValue.GetValue());
|
|
}
|
|
|
|
template <typename EnumType>
|
|
FORCEINLINE static void GetValueAsName(const EnumType EnumeratorValue, FName& out_NameValue)
|
|
{
|
|
out_NameValue = GetValueAsName(EnumeratorValue);
|
|
}
|
|
|
|
/**
|
|
* @param EnumeratorValue Enumerator Value.
|
|
*
|
|
* @return the string associated with the enumerator for the specified enum value for the enum specified by the template type.
|
|
*/
|
|
template <typename EnumType>
|
|
FORCEINLINE static FString GetValueAsString(const EnumType EnumeratorValue)
|
|
{
|
|
// For the C++ enum.
|
|
static_assert(TIsEnum<EnumType>::Value, "Should only call this with enum types");
|
|
return GetValueAsName(EnumeratorValue).ToString();
|
|
}
|
|
|
|
template <typename EnumType>
|
|
FORCEINLINE static FString GetValueAsString(const TEnumAsByte<EnumType> EnumeratorValue)
|
|
{
|
|
return GetValueAsString(EnumeratorValue.GetValue());
|
|
}
|
|
|
|
template <typename EnumType>
|
|
FORCEINLINE static void GetValueAsString(const EnumType EnumeratorValue, FString& out_StringValue)
|
|
{
|
|
out_StringValue = GetValueAsString(EnumeratorValue);
|
|
}
|
|
|
|
/**
|
|
* @param EnumeratorValue Enumerator Value.
|
|
*
|
|
* @return the localized display string associated with the specified enum value for the enum specified by the template type.
|
|
*/
|
|
template <typename EnumType>
|
|
FORCEINLINE static FText GetDisplayValueAsText(const EnumType EnumeratorValue)
|
|
{
|
|
// For the C++ enum.
|
|
static_assert(TIsEnum<EnumType>::Value, "Should only call this with enum types");
|
|
UEnum* EnumClass = StaticEnum<EnumType>();
|
|
check(EnumClass != nullptr);
|
|
return EnumClass->GetDisplayNameTextByValue((int64)EnumeratorValue);
|
|
}
|
|
|
|
template <typename EnumType>
|
|
FORCEINLINE static FText GetDisplayValueAsText(const TEnumAsByte<EnumType> EnumeratorValue)
|
|
{
|
|
return GetDisplayValueAsText(EnumeratorValue.GetValue());
|
|
}
|
|
|
|
template <typename EnumType>
|
|
FORCEINLINE static void GetDisplayValueAsText(const EnumType EnumeratorValue, FText& out_TextValue)
|
|
{
|
|
out_TextValue = GetDisplayValueAsText(EnumeratorValue);
|
|
}
|
|
|
|
// Deprecated Functions
|
|
UE_DEPRECATED(4.16, "FindEnumIndex is deprecated, call GetIndexByName or GetValueByName instead")
|
|
int32 FindEnumIndex(FName InName) const { return GetIndexByName(InName, EGetByNameFlags::ErrorIfNotFound); }
|
|
|
|
UE_DEPRECATED(4.16, "FindEnumRedirects is deprecated, call GetIndexByNameString instead")
|
|
static int32 FindEnumRedirects(const UEnum* Enum, FName EnumEntryName) { return Enum->GetIndexByNameString(EnumEntryName.ToString()); }
|
|
|
|
UE_DEPRECATED(4.16, "GetEnum is deprecated, call GetNameByIndex instead")
|
|
FName GetEnum(int32 InIndex) const { return GetNameByIndex(InIndex); }
|
|
|
|
UE_DEPRECATED(4.16, "GetEnumNameStringByValue is deprecated, call GetNameStringByValue instead")
|
|
FString GetEnumNameStringByValue(int64 InValue) const { return GetNameStringByValue(InValue); }
|
|
|
|
UE_DEPRECATED(4.16, "GetEnumName is deprecated, call GetNameStringByIndex instead")
|
|
FString GetEnumName(int32 InIndex) const { return GetNameStringByIndex(InIndex); }
|
|
|
|
UE_DEPRECATED(4.16, "GetDisplayNameText with name index is deprecated, call GetDisplayNameTextByIndex instead")
|
|
FText GetDisplayNameText(int32 NameIndex) const { return GetDisplayNameTextByIndex(NameIndex); }
|
|
|
|
UE_DEPRECATED(4.16, "GetEnumText with name index is deprecated, call GetDisplayNameTextByIndex instead")
|
|
FText GetEnumText(int32 NameIndex) const { return GetDisplayNameTextByIndex(NameIndex); }
|
|
|
|
UE_DEPRECATED(4.16, "GetEnumTextByValue with name index is deprecated, call GetDisplayNameTextByValue instead")
|
|
FText GetEnumTextByValue(int64 Value) { return GetDisplayNameTextByValue(Value); }
|
|
|
|
// UObject interface.
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
virtual void BeginDestroy() override;
|
|
// End of UObject interface.
|
|
|
|
protected:
|
|
/** List of pairs of all enum names and values. */
|
|
TArray<TPair<FName, int64>> Names;
|
|
|
|
/** How the enum was originally defined. */
|
|
ECppForm CppForm;
|
|
|
|
/** Enum flags. */
|
|
EEnumFlags EnumFlags;
|
|
|
|
/** pointer to function used to look up the enum's display name. Currently only assigned for UEnums generated for nativized blueprints */
|
|
FEnumDisplayNameFn EnumDisplayNameFn;
|
|
|
|
/** global list of all value names used by all enums in memory, used for property text import */
|
|
static TMap<FName, UEnum*> AllEnumNames;
|
|
|
|
/** adds the Names in this enum to the master AllEnumNames list */
|
|
void AddNamesToMasterList();
|
|
|
|
private:
|
|
FORCEINLINE static FString GetValueAsString_Internal(const TCHAR* EnumPath, const int64 EnumeratorValue)
|
|
{
|
|
UEnum* EnumClass = FindObject<UEnum>(nullptr, EnumPath);
|
|
UE_CLOG(!EnumClass, LogClass, Fatal, TEXT("Couldn't find enum '%s'"), EnumPath);
|
|
return EnumClass->GetNameStringByValue(EnumeratorValue);
|
|
}
|
|
|
|
FORCEINLINE static FText GetDisplayValueAsText_Internal(const TCHAR* EnumPath, const int64 EnumeratorValue)
|
|
{
|
|
UEnum* EnumClass = FindObject<UEnum>(nullptr, EnumPath);
|
|
UE_CLOG(!EnumClass, LogClass, Fatal, TEXT("Couldn't find enum '%s'"), EnumPath);
|
|
return EnumClass->GetDisplayNameTextByValue(EnumeratorValue);
|
|
}
|
|
|
|
/**
|
|
* Renames enum values to use duplicated enum name instead of base one, e.g.:
|
|
*
|
|
* MyEnum::MyVal
|
|
* MyEnum::MyEnum_MAX
|
|
*
|
|
* becomes
|
|
*
|
|
* MyDuplicatedEnum::MyVal
|
|
* MyDuplicatedEnum::MyDuplicatedEnum_MAX
|
|
*/
|
|
void RenameNamesAfterDuplication();
|
|
|
|
/** Gets name of enum "this" is duplicate of. If we're not duplicating, just returns "this" name. */
|
|
FString GetBaseEnumNameOnDuplication() const;
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
UClass.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/** Base definition for C++ class type traits */
|
|
struct FCppClassTypeTraitsBase
|
|
{
|
|
enum
|
|
{
|
|
IsAbstract = false
|
|
};
|
|
};
|
|
|
|
/** Defines traits for specific C++ class types */
|
|
template <class CPPCLASS>
|
|
struct TCppClassTypeTraits: public FCppClassTypeTraitsBase
|
|
{
|
|
enum
|
|
{
|
|
IsAbstract = TIsAbstract<CPPCLASS>::Value
|
|
};
|
|
};
|
|
|
|
/** Interface for accessing attributes of the underlying C++ class, for native class types */
|
|
struct ICppClassTypeInfo
|
|
{
|
|
/** Return true if the underlying C++ class is abstract (i.e. declares at least one pure virtual function) */
|
|
virtual bool IsAbstract() const = 0;
|
|
};
|
|
|
|
struct FCppClassTypeInfoStatic
|
|
{
|
|
bool bIsAbstract;
|
|
};
|
|
|
|
/** Implements the type information interface for specific C++ class types */
|
|
struct FCppClassTypeInfo: ICppClassTypeInfo
|
|
{
|
|
explicit FCppClassTypeInfo(const FCppClassTypeInfoStatic* InInfo)
|
|
: Info(InInfo)
|
|
{
|
|
}
|
|
|
|
// Non-copyable
|
|
FCppClassTypeInfo(const FCppClassTypeInfo&) = delete;
|
|
FCppClassTypeInfo& operator=(const FCppClassTypeInfo&) = delete;
|
|
|
|
// ICppClassTypeInfo implementation
|
|
virtual bool IsAbstract() const override
|
|
{
|
|
return Info->bIsAbstract;
|
|
}
|
|
|
|
private:
|
|
const FCppClassTypeInfoStatic* Info;
|
|
};
|
|
|
|
/** information about an interface a class implements */
|
|
struct COREUOBJECT_API FImplementedInterface
|
|
{
|
|
/** the interface class */
|
|
UClass* Class;
|
|
/** the pointer offset of the interface's vtable */
|
|
int32 PointerOffset;
|
|
/** whether or not this interface has been implemented via K2 */
|
|
bool bImplementedByK2;
|
|
|
|
FImplementedInterface()
|
|
: Class(nullptr), PointerOffset(0), bImplementedByK2(false)
|
|
{}
|
|
FImplementedInterface(UClass* InClass, int32 InOffset, bool InImplementedByK2)
|
|
: Class(InClass), PointerOffset(InOffset), bImplementedByK2(InImplementedByK2)
|
|
{}
|
|
|
|
friend COREUOBJECT_API FArchive& operator<<(FArchive& Ar, FImplementedInterface& A);
|
|
};
|
|
|
|
/** A struct that maps a string name to a native function */
|
|
struct FNativeFunctionLookup
|
|
{
|
|
FName Name;
|
|
FNativeFuncPtr Pointer;
|
|
|
|
FNativeFunctionLookup(FName InName, FNativeFuncPtr InPointer)
|
|
: Name(InName), Pointer(InPointer)
|
|
{}
|
|
};
|
|
|
|
namespace EIncludeSuperFlag
|
|
{
|
|
enum Type
|
|
{
|
|
ExcludeSuper,
|
|
IncludeSuper
|
|
};
|
|
} // namespace EIncludeSuperFlag
|
|
|
|
struct FClassFunctionLinkInfo
|
|
{
|
|
UFunction* (*CreateFuncPtr)();
|
|
const char* FuncNameUTF8;
|
|
};
|
|
|
|
/**
|
|
* An object class.
|
|
*/
|
|
class COREUOBJECT_API UClass: public UStruct
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR(UClass, UStruct, 0, TEXT("/Script/CoreUObject"), CASTCLASS_UClass, NO_API)
|
|
DECLARE_WITHIN_UPACKAGE()
|
|
|
|
public:
|
|
friend class FRestoreClassInfo;
|
|
friend class FBlueprintEditorUtils;
|
|
|
|
typedef void (*ClassConstructorType)(const FObjectInitializer&);
|
|
typedef UObject* (*ClassVTableHelperCtorCallerType)(FVTableHelper& Helper);
|
|
typedef void (*ClassAddReferencedObjectsType)(UObject*, class FReferenceCollector&);
|
|
typedef UClass* (*StaticClassFunctionType)();
|
|
|
|
ClassConstructorType ClassConstructor;
|
|
ClassVTableHelperCtorCallerType ClassVTableHelperCtorCaller;
|
|
/** Pointer to a static AddReferencedObjects method. */
|
|
ClassAddReferencedObjectsType ClassAddReferencedObjects;
|
|
|
|
/** Class pseudo-unique counter; used to accelerate unique instance name generation */
|
|
mutable uint32 ClassUnique : 31;
|
|
|
|
/** Used to check if the class was cooked or not */
|
|
uint32 bCooked : 1;
|
|
|
|
/** Class flags; See EClassFlags for more information */
|
|
EClassFlags ClassFlags;
|
|
|
|
/** Cast flags used to accelerate dynamic_cast<T*> on objects of this type for common T */
|
|
EClassCastFlags ClassCastFlags;
|
|
|
|
/** The required type for the outer of instances of this class */
|
|
UClass* ClassWithin;
|
|
|
|
/** This is the blueprint that caused the generation of this class, or null if it is a native compiled-in class */
|
|
UObject* ClassGeneratedBy;
|
|
|
|
#if WITH_EDITORONLY_DATA
|
|
/** Linked list of properties to be destroyed when this class is destroyed that couldn't be destroyed in PurgeClass **/
|
|
FField* PropertiesPendingDestruction;
|
|
|
|
/** Destroys properties that couldn't be destroyed in PurgeClass */
|
|
void DestroyPropertiesPendingDestruction();
|
|
#endif
|
|
|
|
#if WITH_EDITOR
|
|
/**
|
|
* Conditionally recompiles the class after loading, in case any dependencies were also newly loaded
|
|
* @param ObjLoaded If set this is the list of objects that are currently loading, usualy GObjLoaded
|
|
*/
|
|
virtual void ConditionalRecompileClass(FUObjectSerializeContext* InLoadContext) {}
|
|
virtual void FlushCompilationQueueForLevel() {}
|
|
#endif // WITH_EDITOR
|
|
|
|
/** Which Name.ini file to load Config variables out of */
|
|
FName ClassConfigName;
|
|
|
|
/** List of replication records */
|
|
TArray<FRepRecord> ClassReps;
|
|
|
|
/** List of network relevant fields (functions) */
|
|
TArray<UField*> NetFields;
|
|
|
|
/** Index of the first ClassRep that belongs to this class. Anything before that was defined by / belongs to parent classes. */
|
|
int32 FirstOwnedClassRep = 0;
|
|
|
|
#if WITH_EDITOR || HACK_HEADER_GENERATOR
|
|
// Editor only properties
|
|
void GetHideFunctions(TArray<FString>& OutHideFunctions) const;
|
|
bool IsFunctionHidden(const TCHAR* InFunction) const;
|
|
void GetAutoExpandCategories(TArray<FString>& OutAutoExpandCategories) const;
|
|
bool IsAutoExpandCategory(const TCHAR* InCategory) const;
|
|
void GetAutoCollapseCategories(TArray<FString>& OutAutoCollapseCategories) const;
|
|
bool IsAutoCollapseCategory(const TCHAR* InCategory) const;
|
|
void GetClassGroupNames(TArray<FString>& OutClassGroupNames) const;
|
|
bool IsClassGroupName(const TCHAR* InGroupName) const;
|
|
#endif
|
|
/**
|
|
* Calls AddReferencedObjects static method on the specified object.
|
|
*
|
|
* @param This Object to call ARO on.
|
|
* @param Collector Reference collector.
|
|
*/
|
|
FORCEINLINE void CallAddReferencedObjects(UObject* This, FReferenceCollector& Collector) const
|
|
{
|
|
// The object must of this class type.
|
|
check(This->IsA(this));
|
|
// This is should always be set to something, at the very least to UObject::ARO
|
|
check(ClassAddReferencedObjects != nullptr);
|
|
ClassAddReferencedObjects(This, Collector);
|
|
}
|
|
|
|
/** The class default object; used for delta serialization and object initialization */
|
|
UObject* ClassDefaultObject;
|
|
|
|
protected:
|
|
/** This is where we store the data that is only changed per class instead of per instance */
|
|
UPROPERTY()
|
|
void* SparseClassData;
|
|
|
|
/** The struct used to store sparse class data. */
|
|
UPROPERTY()
|
|
UScriptStruct* SparseClassDataStruct;
|
|
|
|
public:
|
|
/**
|
|
* Returns a pointer to the sidecar data structure. This function will create an instance of the data structure if one has been specified and it has not yet been created.
|
|
*/
|
|
void* GetOrCreateSparseClassData() { return SparseClassData ? SparseClassData : CreateSparseClassData(); }
|
|
|
|
/**
|
|
* Returns a pointer to the type of the sidecar data structure if one is specified.
|
|
*/
|
|
virtual UScriptStruct* GetSparseClassDataStruct() const;
|
|
|
|
void SetSparseClassDataStruct(UScriptStruct* InSparseClassDataStruct);
|
|
|
|
/** Assemble reference token streams for all classes if they haven't had it assembled already */
|
|
static void AssembleReferenceTokenStreams();
|
|
|
|
#if WITH_EDITOR
|
|
void GenerateFunctionList(TArray<FName>& OutArray) const
|
|
{
|
|
FuncMap.GenerateKeyArray(OutArray);
|
|
}
|
|
#endif // WITH_EDITOR
|
|
|
|
private:
|
|
void* CreateSparseClassData();
|
|
|
|
void CleanupSparseClassData();
|
|
|
|
#if WITH_EDITOR
|
|
/** Provides access to attributes of the underlying C++ class. Should never be unset. */
|
|
TOptional<FCppClassTypeInfo> CppTypeInfo;
|
|
#endif
|
|
|
|
/** Map of all functions by name contained in this class */
|
|
TMap<FName, UFunction*> FuncMap;
|
|
|
|
/** A cache of all functions by name that exist in a parent (superclass or interface) context */
|
|
mutable TMap<FName, UFunction*> SuperFuncMap;
|
|
|
|
/** Scope lock to avoid the SuperFuncMap being read and written to simultaneously on multiple threads. */
|
|
mutable FRWLock SuperFuncMapLock;
|
|
|
|
public:
|
|
/**
|
|
* The list of interfaces which this class implements, along with the pointer property that is located at the offset of the interface's vtable.
|
|
* If the interface class isn't native, the property will be null.
|
|
*/
|
|
TArray<FImplementedInterface> Interfaces;
|
|
|
|
/** Reference token stream used by realtime garbage collector, finalized in AssembleReferenceTokenStream */
|
|
FGCReferenceTokenStream ReferenceTokenStream;
|
|
/** CS for the token stream. Token stream can assemble code can sometimes be called from two threads throuh a web of async loading calls. */
|
|
FCriticalSection ReferenceTokenStreamCritical;
|
|
|
|
/** This class's native functions. */
|
|
TArray<FNativeFunctionLookup> NativeFunctionLookupTable;
|
|
|
|
public:
|
|
// Constructors
|
|
UClass(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
|
explicit UClass(const FObjectInitializer& ObjectInitializer, UClass* InSuperClass);
|
|
UClass(EStaticConstructor, FName InName, uint32 InSize, uint32 InAlignment, EClassFlags InClassFlags, EClassCastFlags InClassCastFlags,
|
|
const TCHAR* InClassConfigName, EObjectFlags InFlags, ClassConstructorType InClassConstructor,
|
|
ClassVTableHelperCtorCallerType InClassVTableHelperCtorCaller,
|
|
ClassAddReferencedObjectsType InClassAddReferencedObjects);
|
|
|
|
#if WITH_HOT_RELOAD
|
|
/**
|
|
* Called when a class is reloading from a DLL...updates various information in-place.
|
|
* @param InSize sizeof the class
|
|
* @param InClassFlags Class flags for the class
|
|
* @param InClassCastFlags Cast Flags for the class
|
|
* @param InConfigName Config Name
|
|
* @param InClassConstructor Pointer to InternalConstructor<TClass>
|
|
* @param TClass_Super_StaticClass Static class of the super class
|
|
* @param TClass_WithinClass_StaticClass Static class of the WithinClass
|
|
*/
|
|
bool HotReloadPrivateStaticClass(
|
|
uint32 InSize,
|
|
EClassFlags InClassFlags,
|
|
EClassCastFlags InClassCastFlags,
|
|
const TCHAR* InConfigName,
|
|
ClassConstructorType InClassConstructor,
|
|
ClassVTableHelperCtorCallerType InClassVTableHelperCtorCaller,
|
|
ClassAddReferencedObjectsType InClassAddReferencedObjects,
|
|
class UClass* TClass_Super_StaticClass,
|
|
class UClass* TClass_WithinClass_StaticClass);
|
|
|
|
/**
|
|
* Replace a native function in the internal native function table
|
|
* @param InName name of the function
|
|
* @param InPointer pointer to the function
|
|
* @param bAddToFunctionRemapTable For C++ hot-reloading, UFunctions are patched in a deferred manner and this should be true
|
|
* For script hot-reloading, script integrations may have a many to 1 mapping of UFunction to native pointer
|
|
* because dispatch is shared, so the C++ remap table does not work in this case, and this should be false
|
|
* @return true if the function was found and replaced, false if it was not
|
|
*/
|
|
bool ReplaceNativeFunction(FName InName, FNativeFuncPtr InPointer, bool bAddToFunctionRemapTable);
|
|
#endif
|
|
|
|
/**
|
|
* If there are potentially multiple versions of this class (e.g. blueprint generated classes), this function will return the authoritative version, which should be used for references
|
|
*
|
|
* @return The version of this class that references should be stored to
|
|
*/
|
|
virtual UClass* GetAuthoritativeClass();
|
|
const UClass* GetAuthoritativeClass() const { return const_cast<UClass*>(this)->GetAuthoritativeClass(); }
|
|
|
|
/**
|
|
* Add a native function to the internal native function table
|
|
* @param InName name of the function
|
|
* @param InPointer pointer to the function
|
|
*/
|
|
void AddNativeFunction(const ANSICHAR* InName, FNativeFuncPtr InPointer);
|
|
|
|
/**
|
|
* Add a native function to the internal native function table, but with a unicode name. Used when generating code from blueprints,
|
|
* which can have unicode identifiers for functions and properties.
|
|
* @param InName name of the function
|
|
* @param InPointer pointer to the function
|
|
*/
|
|
void AddNativeFunction(const WIDECHAR* InName, FNativeFuncPtr InPointer);
|
|
|
|
/** Add a function to the function map */
|
|
void AddFunctionToFunctionMap(UFunction* Function, FName FuncName)
|
|
{
|
|
FuncMap.Add(FuncName, Function);
|
|
}
|
|
|
|
void CreateLinkAndAddChildFunctionsToMap(const FClassFunctionLinkInfo* Functions, uint32 NumFunctions);
|
|
|
|
/** Remove a function from the function map */
|
|
void RemoveFunctionFromFunctionMap(UFunction* Function)
|
|
{
|
|
FuncMap.Remove(Function->GetFName());
|
|
}
|
|
|
|
/** Clears the function name caches, in case things have changed */
|
|
void ClearFunctionMapsCaches();
|
|
|
|
/** Looks for a given function name */
|
|
UFunction* FindFunctionByName(FName InName, EIncludeSuperFlag::Type IncludeSuper = EIncludeSuperFlag::IncludeSuper) const;
|
|
|
|
// UObject interface.
|
|
virtual void Serialize(FArchive& Ar) override;
|
|
virtual void PostLoad() override;
|
|
virtual void FinishDestroy() override;
|
|
virtual void DeferredRegister(UClass* UClassStaticClass, const TCHAR* PackageName, const TCHAR* InName) override;
|
|
virtual bool Rename(const TCHAR* NewName = nullptr, UObject* NewOuter = nullptr, ERenameFlags Flags = REN_None) override;
|
|
virtual void TagSubobjects(EObjectFlags NewFlags) override;
|
|
virtual void PostInitProperties() override;
|
|
static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
|
|
virtual FRestoreForUObjectOverwrite* GetRestoreForUObjectOverwrite() override;
|
|
virtual FString GetDesc() override;
|
|
virtual void GetAssetRegistryTags(TArray<FAssetRegistryTag>& OutTags) const override;
|
|
virtual bool IsAsset() const override { return false; }
|
|
virtual bool IsNameStableForNetworking() const override { return true; } // For now, assume all classes have stable net names
|
|
// End of UObject interface.
|
|
|
|
// UField interface.
|
|
virtual void Bind() override;
|
|
virtual const TCHAR* GetPrefixCPP() const override;
|
|
// End of UField interface.
|
|
|
|
// UStruct interface.
|
|
virtual void Link(FArchive& Ar, bool bRelinkExistingProperties) override;
|
|
virtual void SetSuperStruct(UStruct* NewSuperStruct) override;
|
|
virtual bool IsStructTrashed() const override;
|
|
// End of UStruct interface.
|
|
|
|
#if WITH_EDITOR
|
|
/** Provides access to C++ type info. */
|
|
const ICppClassTypeInfo* GetCppTypeInfo() const
|
|
{
|
|
return CppTypeInfo ? &CppTypeInfo.GetValue() : nullptr;
|
|
}
|
|
#endif
|
|
|
|
/** Sets C++ type information. Should not be NULL. */
|
|
void SetCppTypeInfoStatic(const FCppClassTypeInfoStatic* InCppTypeInfoStatic)
|
|
{
|
|
#if WITH_EDITOR
|
|
check(InCppTypeInfoStatic);
|
|
CppTypeInfo.Emplace(InCppTypeInfoStatic);
|
|
#endif
|
|
}
|
|
|
|
/**
|
|
* Translates the hardcoded script config names (engine, editor, input and
|
|
* game) to their global pendants and otherwise uses config(myini) name to
|
|
* look for a game specific implementation and creates one based on the
|
|
* default if it doesn't exist yet.
|
|
*
|
|
* @return name of the class specific ini file
|
|
*/
|
|
const FString GetConfigName() const;
|
|
|
|
/** Returns parent class, the parent of a Class is always another class */
|
|
UClass* GetSuperClass() const
|
|
{
|
|
return (UClass*)GetSuperStruct();
|
|
}
|
|
|
|
/** Feedback context for default property import **/
|
|
static class FFeedbackContext& GetDefaultPropertiesFeedbackContext();
|
|
|
|
/** Returns amount of memory used by default object */
|
|
int32 GetDefaultsCount()
|
|
{
|
|
return ClassDefaultObject != nullptr ? GetPropertiesSize() : 0;
|
|
}
|
|
|
|
/**
|
|
* Get the default object from the class
|
|
* @param bCreateIfNeeded if true (default) then the CDO is created if it is null
|
|
* @return the CDO for this class
|
|
*/
|
|
UObject* GetDefaultObject(bool bCreateIfNeeded = true) const
|
|
{
|
|
if (ClassDefaultObject == nullptr && bCreateIfNeeded)
|
|
{
|
|
const_cast<UClass*>(this)->CreateDefaultObject();
|
|
}
|
|
|
|
return ClassDefaultObject;
|
|
}
|
|
|
|
/**
|
|
* Called after PostInitProperties during object construction to allow class specific initialization of an object instance.
|
|
*/
|
|
virtual void PostInitInstance(UObject* InObj) {}
|
|
|
|
/**
|
|
* Helper method to assist with initializing object properties from an explicit list.
|
|
*
|
|
* @param InStruct the current scope for which the given property list applies
|
|
* @param DataPtr destination address (where to start copying values to)
|
|
* @param DefaultDataPtr source address (where to start copying the defaults data from)
|
|
*/
|
|
virtual void InitPropertiesFromCustomList(uint8* DataPtr, const uint8* DefaultDataPtr) {}
|
|
|
|
/**
|
|
* Allows class to provide data to the object initializer that can affect how native class subobjects are created.
|
|
*/
|
|
virtual void SetupObjectInitializer(FObjectInitializer& ObjectInitializer) const {}
|
|
|
|
/**
|
|
* Get the name of the CDO for the this class
|
|
* @return The name of the CDO
|
|
*/
|
|
FName GetDefaultObjectName() const;
|
|
|
|
/** Returns memory used to store temporary data on an instance, used by blueprints */
|
|
virtual uint8* GetPersistentUberGraphFrame(UObject* Obj, UFunction* FuncToCheck) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
/** Creates memory to store temporary data */
|
|
virtual void CreatePersistentUberGraphFrame(UObject* Obj, bool bCreateOnlyIfEmpty = false, bool bSkipSuperClass = false, UClass* OldClass = nullptr) const
|
|
{
|
|
}
|
|
|
|
/** Clears memory to store temporary data */
|
|
virtual void DestroyPersistentUberGraphFrame(UObject* Obj, bool bSkipSuperClass = false) const
|
|
{
|
|
}
|
|
|
|
virtual bool SupportSavePersistentUberGraphFrameProperties()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual void PushPersistentUberGraphFrameProperties(uint8* UberGraphFrame, FProperty* Property, FFrame* ThisFrame)
|
|
{
|
|
}
|
|
|
|
virtual void PopPersistentUberGraphFrameProperties(uint8* UberGraphFrame, FFrame* ThisFrame)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Get the default object from the class and cast to a particular type
|
|
* @return the CDO for this class
|
|
*/
|
|
template <class T>
|
|
T* GetDefaultObject() const
|
|
{
|
|
UObject* Ret = GetDefaultObject();
|
|
check(Ret->IsA(T::StaticClass()));
|
|
return (T*)Ret;
|
|
}
|
|
|
|
/** Searches for the default instanced object (often a component) by name **/
|
|
UObject* GetDefaultSubobjectByName(FName ToFind);
|
|
|
|
/** Adds a new default instance map item **/
|
|
void AddDefaultSubobject(UObject* NewSubobject, UClass* BaseClass)
|
|
{
|
|
// this compoonent must be a derived class of the base class
|
|
check(NewSubobject->IsA(BaseClass));
|
|
// the outer of the component must be of my class or some superclass of me
|
|
check(IsChildOf(NewSubobject->GetOuter()->GetClass()));
|
|
}
|
|
|
|
/**
|
|
* Gets all default instanced objects (often components).
|
|
*
|
|
* @param OutDefaultSubobjects An array to be filled with default subobjects.
|
|
*/
|
|
void GetDefaultObjectSubobjects(TArray<UObject*>& OutDefaultSubobjects);
|
|
|
|
/**
|
|
* Used to safely check whether the passed in flag is set.
|
|
*
|
|
* @param FlagsToCheck Class flag(s) to check for
|
|
*
|
|
* @return true if the passed in flag is set, false otherwise
|
|
* (including no flag passed in, unless the FlagsToCheck is CLASS_AllFlags)
|
|
*/
|
|
FORCEINLINE bool HasAnyClassFlags(EClassFlags FlagsToCheck) const
|
|
{
|
|
return EnumHasAnyFlags(ClassFlags, FlagsToCheck) != 0;
|
|
}
|
|
|
|
/**
|
|
* Used to safely check whether all of the passed in flags are set.
|
|
*
|
|
* @param FlagsToCheck Class flags to check for
|
|
* @return true if all of the passed in flags are set (including no flags passed in), false otherwise
|
|
*/
|
|
FORCEINLINE bool HasAllClassFlags(EClassFlags FlagsToCheck) const
|
|
{
|
|
return EnumHasAllFlags(ClassFlags, FlagsToCheck);
|
|
}
|
|
|
|
/**
|
|
* Gets the class flags.
|
|
*
|
|
* @return The class flags.
|
|
*/
|
|
FORCEINLINE EClassFlags GetClassFlags() const
|
|
{
|
|
return ClassFlags;
|
|
}
|
|
|
|
/**
|
|
* Used to safely check whether the passed in flag is set.
|
|
*
|
|
* @param FlagToCheck the cast flag to check for (value should be one of the EClassCastFlags enums)
|
|
*
|
|
* @return true if the passed in flag is set, false otherwise
|
|
* (including no flag passed in)
|
|
*/
|
|
FORCEINLINE bool HasAnyCastFlag(EClassCastFlags FlagToCheck) const
|
|
{
|
|
return (ClassCastFlags & FlagToCheck) != 0;
|
|
}
|
|
FORCEINLINE bool HasAllCastFlags(EClassCastFlags FlagsToCheck) const
|
|
{
|
|
return (ClassCastFlags & FlagsToCheck) == FlagsToCheck;
|
|
}
|
|
|
|
FString GetDescription() const;
|
|
|
|
/**
|
|
* Realtime garbage collection helper function used to emit token containing information about a
|
|
* direct UObject reference at the passed in offset.
|
|
*
|
|
* @param Offset Offset into object at which object reference is stored.
|
|
* @param DebugName DebugName for this objects token. Only used in non-shipping builds.
|
|
* @param Kind Optional parameter the describe the type of the reference.
|
|
*/
|
|
void EmitObjectReference(int32 Offset, const FName& DebugName, EGCReferenceType Kind = GCRT_Object);
|
|
|
|
/**
|
|
* Realtime garbage collection helper function used to emit token containing information about a
|
|
* an array of UObject references at the passed in offset. Handles both TArray and TTransArray.
|
|
*
|
|
* @param Offset Offset into object at which array of objects is stored.
|
|
* @param DebugName DebugName for this objects token. Only used in non-shipping builds.
|
|
*/
|
|
void EmitObjectArrayReference(int32 Offset, const FName& DebugName);
|
|
|
|
/**
|
|
* Realtime garbage collection helper function used to indicate an array of structs at the passed in
|
|
* offset.
|
|
*
|
|
* @param Offset Offset into object at which array of structs is stored
|
|
* @param DebugName DebugName for this objects token. Only used in non-shipping builds.
|
|
* @param Stride Size/stride of struct
|
|
* @return Index into token stream at which later on index to next token after the array is stored
|
|
* which is used to skip over empty dynamic arrays
|
|
*/
|
|
uint32 EmitStructArrayBegin(int32 Offset, const FName& DebugName, int32 Stride);
|
|
|
|
/**
|
|
* Realtime garbage collection helper function used to indicate the end of an array of structs. The
|
|
* index following the current one will be written to the passed in SkipIndexIndex in order to be
|
|
* able to skip tokens for empty dynamic arrays.
|
|
*
|
|
* @param SkipIndexIndex
|
|
*/
|
|
void EmitStructArrayEnd(uint32 SkipIndexIndex);
|
|
|
|
/**
|
|
* Realtime garbage collection helper function used to indicate the beginning of a fixed array.
|
|
* All tokens issues between Begin and End will be replayed Count times.
|
|
*
|
|
* @param Offset Offset at which fixed array starts.
|
|
* @param DebugName DebugName for this objects token. Only used in non-shipping builds.
|
|
* @param Stride Stride of array element, e.g. sizeof(struct) or sizeof(UObject*).
|
|
* @param Count Fixed array count.
|
|
*/
|
|
void EmitFixedArrayBegin(int32 Offset, const FName& DebugName, int32 Stride, int32 Count);
|
|
|
|
/**
|
|
* Realtime garbage collection helper function used to indicated the end of a fixed array.
|
|
*/
|
|
void EmitFixedArrayEnd();
|
|
|
|
/**
|
|
* Realtime garbage collection helper function used to emit token containing information about an
|
|
* external package reference.
|
|
*/
|
|
void EmitExternalPackageReference();
|
|
|
|
/**
|
|
* Assembles the token stream for realtime garbage collection by combining the per class only
|
|
* token stream for each class in the class hierarchy. This is only done once and duplicate
|
|
* work is avoided by using an object flag.
|
|
* @param bForce Assemble the stream even if it has been already assembled (deletes the old one)
|
|
*/
|
|
void AssembleReferenceTokenStream(bool bForce = false);
|
|
|
|
/**
|
|
* This will return whether or not this class implements the passed in class / interface
|
|
*
|
|
* @param SomeClass - the interface to check and see if this class implements it
|
|
*/
|
|
bool ImplementsInterface(const class UClass* SomeInterface) const;
|
|
|
|
/** serializes the passed in object as this class's default object using the given archive slot
|
|
* @param Object the object to serialize as default
|
|
* @param Slot the structured archive slot to serialize from
|
|
*/
|
|
virtual void SerializeDefaultObject(UObject* Object, FStructuredArchive::FSlot Slot);
|
|
|
|
/** serializes the passed in object as this class's default object using the given archive
|
|
* @param Object the object to serialize as default
|
|
* @param Ar the archive to serialize from
|
|
*/
|
|
virtual void SerializeDefaultObject(UObject* Object, FArchive& Ar) final
|
|
{
|
|
SerializeDefaultObject(Object, FStructuredArchiveFromArchive(Ar).GetSlot());
|
|
}
|
|
|
|
/** serializes the associated sparse class data for the passed in object using the given archive slot. This should only be called if the class has an associated sparse data structure.
|
|
* @param Slot the structured archive slot to serialize from
|
|
*/
|
|
void SerializeSparseClassData(FStructuredArchive::FSlot Slot);
|
|
|
|
/** Wraps the PostLoad() call for the class default object.
|
|
* @param Object the default object to call PostLoad() on
|
|
*/
|
|
virtual void PostLoadDefaultObject(UObject* Object) { Object->PostLoad(); }
|
|
|
|
/**
|
|
* Purges out the properties of this class in preparation for it to be regenerated
|
|
* @param bRecompilingOnLoad - true if we are recompiling on load
|
|
*
|
|
* In editor, properties are not freed until DestroyPropertiesPendingDestruction is called.
|
|
*/
|
|
virtual void PurgeClass(bool bRecompilingOnLoad);
|
|
|
|
/**
|
|
* Finds the common base class that parents the two classes passed in.
|
|
*
|
|
* @param InClassA the first class to find the common base for
|
|
* @param InClassB the second class to find the common base for
|
|
* @return the common base class or NULL
|
|
*/
|
|
static UClass* FindCommonBase(UClass* InClassA, UClass* InClassB);
|
|
|
|
/**
|
|
* Finds the common base class that parents the array of classes passed in.
|
|
*
|
|
* @param InClasses the array of classes to find the common base for
|
|
* @return the common base class or NULL
|
|
*/
|
|
static UClass* FindCommonBase(const TArray<UClass*>& InClasses);
|
|
|
|
/**
|
|
* Determines if the specified function has been implemented in a Blueprint
|
|
*
|
|
* @param InFunctionName The name of the function to test
|
|
* @return True if the specified function exists and is implemented in a blueprint generated class
|
|
*/
|
|
virtual bool IsFunctionImplementedInScript(FName InFunctionName) const;
|
|
|
|
UE_DEPRECATED(4.23, "IsFunctionImplementedInBlueprint is deprecated, call IsFunctionImplementedInScript instead")
|
|
bool IsFunctionImplementedInBlueprint(FName InFunctionName) const { return IsFunctionImplementedInScript(InFunctionName); }
|
|
|
|
/**
|
|
* Checks if the property exists on this class or a parent class.
|
|
* @param InProperty The property to check if it is contained in this or a parent class.
|
|
* @return True if the property exists on this or a parent class.
|
|
*/
|
|
virtual bool HasProperty(FProperty* InProperty) const;
|
|
|
|
/** Finds the object that is used as the parent object when serializing properties, overridden for blueprints */
|
|
virtual UObject* FindArchetype(const UClass* ArchetypeClass, const FName ArchetypeName) const { return nullptr; }
|
|
|
|
/** Returns archetype object for CDO */
|
|
virtual UObject* GetArchetypeForCDO() const;
|
|
|
|
/** Returns archetype for sparse class data */
|
|
virtual void* GetArchetypeForSparseClassData() const;
|
|
|
|
/** Returns the struct used by the sparse class data archetype */
|
|
UScriptStruct* GetSparseClassDataArchetypeStruct() const;
|
|
|
|
/**
|
|
* Returns all objects that should be preloaded before the class default object is serialized at load time. Only used by the EDL.
|
|
*
|
|
* @param OutDeps All objects that should be preloaded before the class default object is serialized at load time.
|
|
*/
|
|
virtual void GetDefaultObjectPreloadDependencies(TArray<UObject*>& OutDeps) {}
|
|
|
|
/**
|
|
* Initializes the ClassReps and NetFields arrays used by replication.
|
|
* This happens lazily based on the CLASS_ReplicationDataIsSetUp flag,
|
|
* and will generally occur in Link or PostLoad. It's possible that replicated UFunctions
|
|
* will load after their owning class, so UFunction::PostLoad will clear the flag on its owning class
|
|
* to force lazy initialization next time the data is needed.
|
|
* Also happens after blueprint compiliation.
|
|
*/
|
|
void SetUpRuntimeReplicationData();
|
|
|
|
#if HACK_HEADER_GENERATOR
|
|
void SetUpUhtReplicationData();
|
|
#endif // HACK_HEADER_GENERATOR
|
|
|
|
/**
|
|
* Helper function for determining if the given class is compatible with structured archive serialization
|
|
*/
|
|
static bool IsSafeToSerializeToStructuredArchives(UClass* InClass);
|
|
|
|
private:
|
|
/**
|
|
* This signature intentionally hides the method declared in UObjectBaseUtility to make it private.
|
|
* Call IsChildOf instead; Hidden because calling IsA on a class almost always indicates an error where the caller should use IsChildOf
|
|
*/
|
|
bool IsA(const UClass* Parent) const
|
|
{
|
|
return UObject::IsA(Parent);
|
|
}
|
|
|
|
/**
|
|
* This signature intentionally hides the method declared in UObject to make it private.
|
|
* Call FindFunctionByName instead; This method will search for a function declared in UClass instead of the class it was called on
|
|
*/
|
|
UFunction* FindFunction(FName InName) const
|
|
{
|
|
return UObject::FindFunction(InName);
|
|
}
|
|
|
|
/**
|
|
* This signature intentionally hides the method declared in UObject to make it private.
|
|
* Call FindFunctionByName instead; This method will search for a function declared in UClass instead of the class it was called on
|
|
*/
|
|
UFunction* FindFunctionChecked(FName InName) const
|
|
{
|
|
return UObject::FindFunctionChecked(InName);
|
|
}
|
|
|
|
/**
|
|
* Tests if all properties tagged with Replicate were registered in GetLifetimeReplicatedProps
|
|
*/
|
|
void ValidateRuntimeReplicationData();
|
|
|
|
protected:
|
|
/**
|
|
* Get the default object from the class, creating it if missing, if requested or under a few other circumstances
|
|
* @return the CDO for this class
|
|
**/
|
|
virtual UObject* CreateDefaultObject();
|
|
|
|
#if HACK_HEADER_GENERATOR
|
|
// Required by UHT makefiles for internal data serialization.
|
|
friend struct FClassArchiveProxy;
|
|
#endif // HACK_HEADER_GENERATOR
|
|
};
|
|
|
|
/**
|
|
* Dynamic class (can be constructed after initial startup)
|
|
*/
|
|
class COREUOBJECT_API UDynamicClass: public UClass
|
|
{
|
|
DECLARE_CASTED_CLASS_INTRINSIC_NO_CTOR(UDynamicClass, UClass, 0, TEXT("/Script/CoreUObject"), CASTCLASS_None, NO_API)
|
|
DECLARE_WITHIN_UPACKAGE()
|
|
|
|
public:
|
|
typedef void (*DynamicClassInitializerType)(UDynamicClass*);
|
|
|
|
UDynamicClass(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
|
|
explicit UDynamicClass(const FObjectInitializer& ObjectInitializer, UClass* InSuperClass);
|
|
UDynamicClass(EStaticConstructor, FName InName, uint32 InSize, uint32 InAlignment, EClassFlags InClassFlags, EClassCastFlags InClassCastFlags,
|
|
const TCHAR* InClassConfigName, EObjectFlags InFlags, ClassConstructorType InClassConstructor,
|
|
ClassVTableHelperCtorCallerType InClassVTableHelperCtorCaller,
|
|
ClassAddReferencedObjectsType InClassAddReferencedObjects,
|
|
DynamicClassInitializerType InDynamicClassInitializer);
|
|
|
|
// UObject interface.
|
|
static void AddReferencedObjects(UObject* InThis, FReferenceCollector& Collector);
|
|
|
|
// UClass interface
|
|
virtual UObject* CreateDefaultObject();
|
|
virtual void PurgeClass(bool bRecompilingOnLoad) override;
|
|
virtual UObject* FindArchetype(const UClass* ArchetypeClass, const FName ArchetypeName) const override;
|
|
virtual void SetupObjectInitializer(FObjectInitializer& ObjectInitializer) const override;
|
|
|
|
/** Find a struct property, called from generated code */
|
|
FStructProperty* FindStructPropertyChecked(const TCHAR* PropertyName) const;
|
|
|
|
/** Misc objects owned by the class. */
|
|
TArray<UObject*> MiscConvertedSubobjects;
|
|
|
|
/** Additional converted fields, that are used by the class. */
|
|
TArray<UField*> ReferencedConvertedFields;
|
|
|
|
/** Outer assets used by the class */
|
|
TArray<UObject*> UsedAssets;
|
|
|
|
/** Specialized sub-object containers */
|
|
TArray<UObject*> DynamicBindingObjects;
|
|
TArray<UObject*> ComponentTemplates;
|
|
TArray<UObject*> Timelines;
|
|
|
|
/** Array of blueprint overrides of component classes in parent classes */
|
|
TArray<TPair<FName, UClass*>> ComponentClassOverrides;
|
|
|
|
/** IAnimClassInterface (UAnimClassData) or null */
|
|
UObject* AnimClassImplementation;
|
|
|
|
DynamicClassInitializerType DynamicClassInitializer;
|
|
|
|
/** Prefix for the temporary package where the dynamic classes are stored when being generated */
|
|
static const FString& GetTempPackagePrefix();
|
|
};
|
|
|
|
/**
|
|
* Helper template to call the default constructor for a class
|
|
*/
|
|
template <class T>
|
|
void InternalConstructor(const FObjectInitializer& X)
|
|
{
|
|
T::__DefaultConstructor(X);
|
|
}
|
|
|
|
/**
|
|
* Helper template to call the vtable ctor caller for a class
|
|
*/
|
|
template <class T>
|
|
UObject* InternalVTableHelperCtorCaller(FVTableHelper& Helper)
|
|
{
|
|
return T::__VTableCtorCaller(Helper);
|
|
}
|
|
|
|
COREUOBJECT_API void InitializePrivateStaticClass(
|
|
class UClass* TClass_Super_StaticClass,
|
|
class UClass* TClass_PrivateStaticClass,
|
|
class UClass* TClass_WithinClass_StaticClass,
|
|
const TCHAR* PackageName,
|
|
const TCHAR* Name);
|
|
|
|
/**
|
|
* Helper template allocate and construct a UClass
|
|
*
|
|
* @param PackageName name of the package this class will be inside
|
|
* @param Name of the class
|
|
* @param ReturnClass reference to pointer to result. This must be PrivateStaticClass.
|
|
* @param RegisterNativeFunc Native function registration function pointer.
|
|
* @param InSize Size of the class
|
|
* @param InAlignment Alignment of the class
|
|
* @param InClassFlags Class flags
|
|
* @param InClassCastFlags Class cast flags
|
|
* @param InConfigName Class config name
|
|
* @param InClassConstructor Class constructor function pointer
|
|
* @param InClassVTableHelperCtorCaller Class constructor function for vtable pointer
|
|
* @param InClassAddReferencedObjects Class AddReferencedObjects function pointer
|
|
* @param InSuperClassFn Super class function pointer
|
|
* @param WithinClass Within class
|
|
* @param bIsDynamic true if the class can be constructed dynamically at runtime
|
|
*/
|
|
COREUOBJECT_API void GetPrivateStaticClassBody(
|
|
const TCHAR* PackageName,
|
|
const TCHAR* Name,
|
|
UClass*& ReturnClass,
|
|
void (*RegisterNativeFunc)(),
|
|
uint32 InSize,
|
|
uint32 InAlignment,
|
|
EClassFlags InClassFlags,
|
|
EClassCastFlags InClassCastFlags,
|
|
const TCHAR* InConfigName,
|
|
UClass::ClassConstructorType InClassConstructor,
|
|
UClass::ClassVTableHelperCtorCallerType InClassVTableHelperCtorCaller,
|
|
UClass::ClassAddReferencedObjectsType InClassAddReferencedObjects,
|
|
UClass::StaticClassFunctionType InSuperClassFn,
|
|
UClass::StaticClassFunctionType InWithinClassFn,
|
|
bool bIsDynamic = false,
|
|
UDynamicClass::DynamicClassInitializerType InDynamicClassInitializer = nullptr);
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FObjectInstancingGraph.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
struct COREUOBJECT_API FObjectInstancingGraph
|
|
{
|
|
public:
|
|
/**
|
|
* Default Constructor
|
|
* @param bDisableInstancing - if true, start with component instancing disabled
|
|
**/
|
|
FObjectInstancingGraph(bool bDisableInstancing = false);
|
|
|
|
/**
|
|
* Standard constructor
|
|
*
|
|
* @param DestinationSubobjectRoot the top-level object that is being created
|
|
*/
|
|
FObjectInstancingGraph(class UObject* DestinationSubobjectRoot);
|
|
|
|
/**
|
|
* Sets the DestinationRoot for this instancing graph.
|
|
*
|
|
* @param DestinationSubobjectRoot the top-level object that is being created
|
|
* @param InSourceRoot Archetype of DestinationSubobjectRoot
|
|
*/
|
|
void SetDestinationRoot(class UObject* DestinationSubobjectRoot, class UObject* InSourceRoot = nullptr);
|
|
|
|
/**
|
|
* Finds the destination object instance corresponding to the specified source object.
|
|
*
|
|
* @param SourceObject the object to find the corresponding instance for
|
|
*/
|
|
class UObject* GetDestinationObject(class UObject* SourceObject);
|
|
|
|
/**
|
|
* Returns the component that has SourceComponent as its archetype, instancing the component as necessary.
|
|
*
|
|
* @param SourceComponent the component to find the corresponding component instance for
|
|
* @param CurrentValue the component currently assigned as the value for the component property
|
|
* being instanced. Used when updating archetypes to ensure that the new instanced component
|
|
* replaces the existing component instance in memory.
|
|
* @param CurrentObject the object that owns the component property currently being instanced; this is NOT necessarily the object
|
|
* that should be the Outer for the new component.
|
|
* @param bIsTransient is this for a transient property?
|
|
* @param bCausesInstancing if true, then this property causes an instance to be created...if false, this is just a pointer to a uobject that should be remapped if the object is instanced for some other property
|
|
* @param bAllowSelfReference If true, instance the reference to the subobjectroot, so far only delegates remap a self reference
|
|
*
|
|
* @return As with GetInstancedSubobject, above, but also deals with archetype creation and a few other special cases
|
|
*/
|
|
class UObject* InstancePropertyValue(class UObject* SourceComponent, class UObject* CurrentValue, class UObject* CurrentObject, bool bIsTransient, bool bCausesInstancing = false, bool bAllowSelfReference = false);
|
|
|
|
/**
|
|
* Adds a partially built object instance to the map(s) of source objects to their instances.
|
|
* @param ObjectInstance Object that was just allocated, but has not been constructed yet
|
|
* @param InArchetype Archetype of ObjectInstance
|
|
*/
|
|
void AddNewObject(class UObject* ObjectInstance, class UObject* InArchetype = nullptr);
|
|
|
|
/**
|
|
* Adds an object instance to the map of source objects to their instances. If there is already a mapping for this object, it will be replaced
|
|
* and the value corresponding to ObjectInstance's archetype will now point to ObjectInstance.
|
|
*
|
|
* @param ObjectInstance the object that should be added as the corresopnding instance for ObjectSource
|
|
* @param InArchetype Archetype of ObjectInstance
|
|
*/
|
|
void AddNewInstance(class UObject* ObjectInstance, class UObject* InArchetype = nullptr);
|
|
|
|
/**
|
|
* Retrieves a list of objects that have the specified Outer
|
|
*
|
|
* @param SearchOuter the object to retrieve object instances for
|
|
* @param out_Components receives the list of objects contained by SearchOuter
|
|
*/
|
|
void RetrieveObjectInstances(class UObject* SearchOuter, TArray<class UObject*>& out_Objects);
|
|
|
|
/**
|
|
* Allows looping over instances that were created during this instancing.
|
|
*
|
|
* @param Pred the object to retrieve object instances for
|
|
*/
|
|
template <typename Predicate>
|
|
void ForEachObjectInstance(Predicate Pred)
|
|
{
|
|
for (TMap<UObject*, UObject*>::TIterator It(SourceToDestinationMap); It; ++It)
|
|
{
|
|
UObject* InstancedObject = It.Value();
|
|
Pred(InstancedObject);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Enables / disables component instancing.
|
|
*/
|
|
void EnableSubobjectInstancing(bool bEnabled)
|
|
{
|
|
bEnableSubobjectInstancing = bEnabled;
|
|
}
|
|
|
|
/**
|
|
* Returns whether component instancing is enabled
|
|
*/
|
|
bool IsSubobjectInstancingEnabled() const
|
|
{
|
|
return bEnableSubobjectInstancing;
|
|
}
|
|
|
|
/**
|
|
* Sets whether DestinationRoot is currently being loaded from disk.
|
|
*/
|
|
void SetLoadingObject(bool bIsLoading)
|
|
{
|
|
bLoadingObject = bIsLoading;
|
|
}
|
|
|
|
private:
|
|
/**
|
|
* Returns whether this instancing graph has a valid destination root.
|
|
*/
|
|
bool HasDestinationRoot() const
|
|
{
|
|
return DestinationRoot != nullptr;
|
|
}
|
|
|
|
/**
|
|
* Returns whether DestinationRoot corresponds to an archetype object.
|
|
*
|
|
* @param bUserGeneratedOnly true indicates that we only care about cases where the user selected "Create [or Update] Archetype" in the editor
|
|
* false causes this function to return true even if we are just loading an archetype from disk
|
|
*/
|
|
bool IsCreatingArchetype(bool bUserGeneratedOnly = true) const
|
|
{
|
|
// if we only want cases where we are creating an archetype in response to user input, return false if we are in fact just loading the object from disk
|
|
return bCreatingArchetype && (!bUserGeneratedOnly || !bLoadingObject);
|
|
}
|
|
|
|
/**
|
|
* Returns whether DestinationRoot is currently being loaded from disk.
|
|
*/
|
|
bool IsLoadingObject() const
|
|
{
|
|
return bLoadingObject;
|
|
}
|
|
|
|
/**
|
|
* Returns the component that has SourceComponent as its archetype, instancing the component as necessary.
|
|
*
|
|
* @param SourceComponent the component to find the corresponding component instance for
|
|
* @param CurrentValue the component currently assigned as the value for the component property
|
|
* being instanced. Used when updating archetypes to ensure that the new instanced component
|
|
* replaces the existing component instance in memory.
|
|
* @param CurrentObject the object that owns the component property currently being instanced; this is NOT necessarily the object
|
|
* that should be the Outer for the new component.
|
|
* @param bDoNotCreateNewInstance If true, then we do not create a new instance, but we will reassign one if there is already a mapping in the table
|
|
* @param bAllowSelfReference If true, instance the reference to the subobjectroot, so far only delegates remap a self reference
|
|
*
|
|
* @return if SourceComponent is contained within SourceRoot, returns a pointer to a unique component instance corresponding to
|
|
* SourceComponent if SourceComponent is allowed to be instanced in this context, or NULL if the component isn't allowed to be
|
|
* instanced at this time (such as when we're a client and the component isn't loaded on clients)
|
|
* if SourceComponent is not contained by SourceRoot, return INVALID_OBJECT, indicating that the that has SourceComponent as its ObjectArchetype, or NULL if SourceComponent is not contained within
|
|
* SourceRoot.
|
|
*/
|
|
class UObject* GetInstancedSubobject(class UObject* SourceSubobject, class UObject* CurrentValue, class UObject* CurrentObject, bool bDoNotCreateNewInstance, bool bAllowSelfReference);
|
|
|
|
/**
|
|
* The root of the object tree that is the source used for instancing components;
|
|
* - when placing an instance of an actor class, this would be the actor class default object
|
|
* - when placing an instance of an archetype, this would be the archetype
|
|
* - when creating an archetype, this would be the actor instance
|
|
* - when duplicating an object, this would be the duplication source
|
|
*/
|
|
class UObject* SourceRoot;
|
|
|
|
/**
|
|
* The root of the object tree that is the destination used for instancing components
|
|
* - when placing an instance of an actor class, this would be the placed actor
|
|
* - when placing an instance of an archetype, this would be the placed actor
|
|
* - when creating an archetype, this would be the actor archetype
|
|
* - when updating an archetype, this would be the source archetype
|
|
* - when duplicating an object, this would be the copied object (destination)
|
|
*/
|
|
class UObject* DestinationRoot;
|
|
|
|
/**
|
|
* Indicates whether we are currently instancing components for an archetype. true if we are creating or updating an archetype.
|
|
*/
|
|
bool bCreatingArchetype;
|
|
|
|
/**
|
|
* If false, components will not be instanced.
|
|
*/
|
|
bool bEnableSubobjectInstancing;
|
|
|
|
/**
|
|
* true when loading object data from disk.
|
|
*/
|
|
bool bLoadingObject;
|
|
|
|
/**
|
|
* Maps the source (think archetype) to the destination (think instance)
|
|
*/
|
|
TMap<class UObject*, class UObject*> SourceToDestinationMap;
|
|
};
|
|
|
|
// UFunction interface.
|
|
|
|
inline UFunction* UFunction::GetSuperFunction() const
|
|
{
|
|
UStruct* Result = GetSuperStruct();
|
|
checkSlow(!Result || Result->IsA<UFunction>());
|
|
return (UFunction*)Result;
|
|
}
|
|
|
|
// UObject.h
|
|
|
|
/**
|
|
* Returns true if this object implements the interface T, false otherwise.
|
|
*/
|
|
template <class T>
|
|
FORCEINLINE bool UObject::Implements() const
|
|
{
|
|
UClass const* const MyClass = GetClass();
|
|
return MyClass && MyClass->ImplementsInterface(T::StaticClass());
|
|
}
|
|
|
|
// UObjectGlobals.h
|
|
|
|
/**
|
|
* Gets the default object of a class.
|
|
*
|
|
* In most cases, class default objects should not be modified. This method therefore returns
|
|
* an immutable pointer. If you need to modify the default object, use GetMutableDefault instead.
|
|
*
|
|
* @param Class - The class to get the CDO for.
|
|
*
|
|
* @return Class default object (CDO).
|
|
*
|
|
* @see GetMutableDefault
|
|
*/
|
|
template <class T>
|
|
inline const T* GetDefault(UClass* Class)
|
|
{
|
|
check(Class->GetDefaultObject()->IsA(T::StaticClass()));
|
|
return (const T*)Class->GetDefaultObject();
|
|
}
|
|
|
|
/**
|
|
* Gets the mutable default object of a class.
|
|
*
|
|
* @param Class - The class to get the CDO for.
|
|
*
|
|
* @return Class default object (CDO).
|
|
*
|
|
* @see GetDefault
|
|
*/
|
|
template <class T>
|
|
inline T* GetMutableDefault(UClass* Class)
|
|
{
|
|
check(Class->GetDefaultObject()->IsA(T::StaticClass()));
|
|
return (T*)Class->GetDefaultObject();
|
|
}
|
|
|
|
struct FStructUtils
|
|
{
|
|
static bool ArePropertiesTheSame(const FProperty* A, const FProperty* B, bool bCheckPropertiesNames);
|
|
|
|
/** Do structures have exactly the same memory layout */
|
|
COREUOBJECT_API static bool TheSameLayout(const UStruct* StructA, const UStruct* StructB, bool bCheckPropertiesNames = false);
|
|
|
|
/** Locates a named structure in the package with the given name. Not expected to fail */
|
|
COREUOBJECT_API static UStruct* FindStructureInPackageChecked(const TCHAR* StructName, const TCHAR* PackageName);
|
|
|
|
#if !(UE_BUILD_TEST || UE_BUILD_SHIPPING)
|
|
/** Looks for uninitialized script struct pointers. Returns the number found */
|
|
COREUOBJECT_API static int32 AttemptToFindUninitializedScriptStructMembers();
|
|
#endif
|
|
};
|
|
|
|
// Helper struct to test if member initialization tests work properly
|
|
struct FTestUninitializedScriptStructMembersTest
|
|
{
|
|
UObject* UninitializedObjectReference;
|
|
UObject* InitializedObjectReference = nullptr;
|
|
float UnusedValue;
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Mirrors of mirror structures in Object.h. These are used by generated code
|
|
to facilitate correct offsets and alignments for structures containing these
|
|
odd types.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
template <class T>
|
|
struct TBaseStructure
|
|
{
|
|
static UScriptStruct* Get()
|
|
{
|
|
return T::StaticStruct();
|
|
}
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FRotator>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FQuat>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FTransform>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FLinearColor>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FColor>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FPlane>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FVector>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FVector2D>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FVector4>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FRandomStream>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FGuid>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FBox2D>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FFallbackStruct>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FFloatRangeBound>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FFloatRange>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FInt32RangeBound>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FInt32Range>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FFloatInterval>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FInt32Interval>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FFrameNumber;
|
|
template <>
|
|
struct TBaseStructure<FFrameNumber>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FFrameTime;
|
|
template <>
|
|
struct TBaseStructure<FFrameTime>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FSoftObjectPath;
|
|
template <>
|
|
struct TBaseStructure<FSoftObjectPath>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FSoftClassPath;
|
|
template <>
|
|
struct TBaseStructure<FSoftClassPath>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FPrimaryAssetType;
|
|
template <>
|
|
struct TBaseStructure<FPrimaryAssetType>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FPrimaryAssetId;
|
|
template <>
|
|
struct TBaseStructure<FPrimaryAssetId>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FDateTime;
|
|
template <>
|
|
struct TBaseStructure<FDateTime>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FPolyglotTextData;
|
|
template <>
|
|
struct TBaseStructure<FPolyglotTextData>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
struct FAssetBundleData;
|
|
template <>
|
|
struct TBaseStructure<FAssetBundleData>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|
|
|
|
template <>
|
|
struct TBaseStructure<FTestUninitializedScriptStructMembersTest>
|
|
{
|
|
COREUOBJECT_API static UScriptStruct* Get();
|
|
};
|