You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden #rb none ========================== MAJOR FEATURES + CHANGES ========================== Change 3026763 on 2016/06/24 by Phillip.Kavan [UE-32259] Fix missing heat map coloration on pure nodes. change summary: - modified FScriptExecutionNode::RefreshStats() to ensure that child nodes are updated for 'standard' exec node types. #jira UE-32259 Change 3026829 on 2016/06/24 by Mike.Beach Mirroring CL 3025832 from Release-4.12 Guarding GetClassDefault nodes against asserts while loading cyclically dependent content. Regenerating one Blueprint could trigger a ReconstructNode() in a separate Blueprint (that had already been regenerated). However, not all objects in that Blueprint's package have been post-loaded, so object Rename() will assert is you try to reset loaders with it. #jira UE-32356 Change 3026888 on 2016/06/24 by Mike.Beach PR #2460: Functionality to flag blueprint as abstract (Contributed by Pierdek) Change 3027245 on 2016/06/24 by Phillip.Kavan [UEBP-180] Alternate treatment for Blueprint profiler tree view node expander icon (to differentiate from exec pin icons). change summary: - added SProfilerStatExpander (from BenC) - modified original to replace indicator icons w/ FontAwesome glyphs (they're a bit clearer) - see screenshot attached to JIRA #jira UEBP-180 Change 3027279 on 2016/06/24 by Ryan.Rauschkolb Fixed issue where unsupported pins could be added to custom Event nodes which can lead to a crash #jira UE-31148 Change 3027606 on 2016/06/25 by Dan.Oconnor Back out changelist 3027279, this change breaks custom events coupled to multicast delegate nodes (see ProjRocket.uasset in shooter game for an example) Change 3028731 on 2016/06/27 by Ben.Cosh Minor change to the spacing around the new expander icons for the blueprint profiler. #Jira UEBP-180 - Pin icons are too similar to the tree expander icons in the node execution graph display. #Proj Kismet Change 3028740 on 2016/06/27 by Ben.Cosh This change modifies the way the blueprint profiler detects and maps delegate events that are created at blueprint compile time. #Jira UE-32055 - Assert when profiling timelines in the blueprint profiler #Proj BlueprintProfiler, KismetCompiler, BlueprintGraph, LiveEditor, Kismet, Engine Change 3028844 on 2016/06/27 by Maciej.Mroz #jira UE-32470 Nativized Orion: Sparrow has no Rentless ability. Better way to find Placeholder classes in BlueprintNativeCodeGenModule. Change 3029573 on 2016/06/27 by Ryan.Rauschkolb Fixed issue where Preview Connection would be drawn incorrectly when an input and output pin share the same name #jira UE-32211 Change 3030335 on 2016/06/28 by Maciej.Mroz #jira UE-30858 Nativized Orion - Some particle effects are not rendering List of AssetRegistrySearchable properties, that should be stored for DynamicClasses in moved to .ini file. Added SearchDynamicClassCues function in GameplayCueManager.cpp Change 3030492 on 2016/06/28 by Ben.Cosh CIS Mac Build fix Change 3030494 on 2016/06/28 by Ben.Cosh This change reworks the way the blueprint profiler maps latent re-entry points to address problems that could be triggered when multiple re-entries happenned within close proximity. #Jira UE-32452 - Blueprint profiler asserts when a second latent entry is triggered #Proj BlueprintProfiler, CoreUObject, Engine, Kismet Change3030612on 2016/06/28 by Maciej.Mroz typo fixed Change 3031461 on 2016/06/28 by Dan.Oconnor Fixed for crash involving a stale UEdGraphPin after performing an undo/redo operation inolving UEdGraphNode(s) #jira UE-32553 Change 3031537 on 2016/06/28 by Ben.Cosh Fix for a problem introduced in CL 3030494 and recent graph pin changes that caused problems uniquely naming tunnel entry/exit pins. #Jira UE-32578 - Crash when profiling blueprint containing a for-loop #Proj BlueprintProfiler Change 3031556 on 2016/06/28 by Ben.Cosh This fixes a problem with the profiler tracking of PIE actor instances adding a mechanism to refresh the actor references when a subsequent PIE session is started. #Jira UE-32595 - Running two subsequent PIE sessions with a latent entry point causes an assert. #Proj BlueprintProfiler, Kismet Change 3031588 on 2016/06/28 by Ryan.Rauschkolb Fixed issue where unsupported pins could be added to custom Event nodes which can lead to a crash #jira UE-31148 Change 3031887 on 2016/06/28 by Dan.Oconnor Fix for crash caused by stale pin access in SGraphPin, also fixes 'double opacity' effect when ctrl+dragging off of a macro #jira UE-32604 Change 3031932 on 2016/06/28 by Dan.Oconnor Fix for major regression in pin value visibility #jira UE-32614 Change 3032568 on 2016/06/29 by Phillip.Kavan [UE-31681] Ensure that cached component data cache template objects are referenced during garbage collection. change summary: - modified AActor::AddReferencedObjects() to include CurrentTransactionAnnotation - added UChildActorComponent::AddReferencedObjects() to include CachedInstanceData - also added FChildActorComponentInstanceData::AddReferencedObjects() to include ComponentInstanceData (just in case some future task happens to trigger a reference gather during its lifetime) additional notes: - should also resolve UE-32558 #jira UE-31681 Change 3032998 on 2016/06/29 by Dan.Oconnor Fixing shutdown crash after LinkedTo lists are corrupted. An ensure couldn't fire when a node had already been destroyed. UE-32631 tracks the actual ensure. #jira UE-32634 Change 3033448 on 2016/06/29 by Ryan.Rauschkolb Discard Return Nodes that have no outputs when collapsing to function #jira UE-23381 Change 3034407 on 2016/06/30 by Phillip.Kavan [UE-32675] Fix no-editor compile issue. Change 3034691 on 2016/06/30 by Ryan.Rauschkolb Fixed issue where Macro nodes with ambiguous links could be collapsed into a function Change 3034701 on 2016/06/30 by Ryan.Rauschkolb Cleaned up UEdGraphSchema_K2::GetVariableTypeTree to use a filter rather than several booleans Change 3035093 on 2016/06/30 by Maciej.Mroz #jira UE-32683 BP_Hero Blueprint failing to compile in Orion - K2Node_CustomEvent_1050 is out of date Temporary fix. Change 3035440 on 2016/07/01 by Maciej.Mroz #jira UE-32706 Nativized Orion crash - Cannot find "Root" subobject in ABP_HeroPedestal_C... Make sure, the CDO of DynamicClass (and its subobjects) have AsyncLoading flag cleared. Change 3035442 on 2016/07/01 by Maciej.Mroz Added UDynamicClass::FindArchetype #jira UE-30667 Ground material in Agora incorrect in Nativized Orion Change 3036233 on 2016/07/01 by Dan.Oconnor Proper handling of null pin references in compiler results logs Change 3036541 on 2016/07/01 by Dan.Oconnor Fix for more assymetry in LinkedTo after undo/redo. This solution addresses both UE-32645 and UE-32553. The key to correct behavior is to explictly detect the case where only one of the two nodes in a peer (LinkedTo) relationship are in the transaction buffer. Added IsObjectTransacting to transaction interface to detect this. #jira UE-32645 Change 3036581 on 2016/07/02 by Dan.Oconnor Non-editor fix Change 3036632 on 2016/07/02 by Maciej.Mroz Removed too strict check in BlueprintNativeCodeGenModule Change 3036715 on 2016/07/02 by Maciej.Mroz #jira UE-32612 Odin emits a error when nativized - attempting to access a hidden boolean bitfield property - Private bitfield can be used as LHS expression in generated code. - Refactoring. Introduced ENativizedTermUsage. Change 3037014 on 2016/07/04 by Maciej.Mroz #jira UE-32729 Orion failing to package for PS4 with Nativization Make sure that temporary variable used in ternary operator: "context ? context->variable : temp-variable", has exactly the same type as the wanted variable. Change 3037300 on 2016/07/05 by Maciej.Mroz #jira UE-31756 Fixup hardcoded function names in BP=>Cpp backend Change 3037303 on 2016/07/05 by Maciej.Mroz #jira UE-31756 Nativization - fixed hardcoded string. Change 3037307 on 2016/07/05 by Maciej.Mroz AutomationTool: Fixed issue: A nativized client was compiled with both client and server NativizedAssets plugins. Paths to nativized BP plugin is stored in a map. Change 3037712 on 2016/07/05 by Mike.Beach Adding a non-const version of MultiFindPointer() for TMultiMap. Change 3037790 on 2016/07/05 by Mike.Beach Fixing a bug where overridden components in Blueprints could load with cleared properties - this could happen in cyclically dependent parent/child Blueprints (where the child's component would be zeroed). In this case, the Blueprint's CDO would be deferred, so to solve this new issue we now defer the Blueprint's sub-object overrides as well. #jira UE-32693 Change 3038014 on 2016/07/05 by Ben.Cosh Refactor of the blueprint profiler tunnel mapping and playback to address issues blocking MVP #Jira UE-32056 - The blueprint profiler can still get hung up with cyclic links in the graph #Proj Kismet, BlueprintProfiler, KismetCompiler, BlueprintGraph, UnrealEd Change 3038533 on 2016/07/05 by Mike.Beach PR #2558: Stopping Zoom-to-Fit On User Input (Fixed) (Contributed by MichaelSchoell) Change 3038608 on 2016/07/05 by Dan.Oconnor Fix for crash when altering ConstructObjectFromClass nodes, removed now unused InvalidateAndTrash function from UEdGraphPin, removed subpin leak counter #jira FORT-26495 Change 3038770 on 2016/07/05 by Dan.Oconnor Hiding TThreadSingleton<FBlueprintExceptionTracker>::Get() to fix clang for windows link error #jira UE-31935 Change 3038841 on 2016/07/05 by Dan.Oconnor Simple null check to prevent crash after loading a blueprint to diff. The diff'd blueprint is ending up in other blueprint's DependentBlueprintsToRecompile, for now this is the safest fix #jira UE-31115 Change 3039179 on 2016/07/06 by Maciej.Mroz #jira UE-31987 Editor crashes when transforming actor after applying instances changes Selected (in Level editor) instance components are still selected after they are converted to regular components. Change 3039216 on 2016/07/06 by Maciej.Mroz #jira UE-31767 [CrashReport] UE4Editor_Engine!AActor::GetLevel() [actor.cpp:1663] FIxed unsafe code. Change 3040046 on 2016/07/06 by Ben.Cosh This fixes a problem found where tunnel instances inside tunnel graphs fail to map correctly in the blueprint profiler #Jira UE-32862 - Tunnel instances inside tunnels do not map correctly in the blueprint profiler #Proj BlueprintProfiler Change 3040061 on 2016/07/06 by Ben.Cosh fix for bad unshelve before submit in CL 3040046 - Phillip already reviewed this version of the file and not what was actually submitted. Change 3040346 on 2016/07/06 by Maciej.Mroz #jira UE-32840 //UE4/Dev-Blueprints: UE4_StaticAnalysis completed with Warnings - 2 Warnings Fix(?) for warning C28182 Change 3040349 on 2016/07/06 by Dan.Oconnor Updating test data Change 3040473 on 2016/07/06 by Dan.Oconnor Fix SMyBlueprint in blueprint diff tool so that kismet inspector is updated with the object selected in SMyBlueprint, needed to investigate UE-18200 Change 3040536 on 2016/07/06 by Dan.Oconnor Call to APITestFunction Change 3040565 on 2016/07/06 by Dan.Oconnor Clone saved GeneratedClass when not doing COL. Groundwork to fix for UE-17268. Change 3040603 on 2016/07/06 by Dan.Oconnor PR #2539: Option to disable Grid in the blueprint and material editor and change grid colors (Contributed by CelPlays) #jira UE-32497 Change 3040798 on 2016/07/07 by Maciej.Mroz Fixed warning C6011: Dereferencing NULL pointer 'Object'. Added some comments. #jira UE-32840 Change 3041185 on 2016/07/07 by Ben.Cosh This fixes problems with the blueprint profiler with name collisions for nodes in different graphs and improves nested tunnel detection. #Jira UE-32862 - Tunnel instances inside tunnels do not map correctly in the blueprint profiler #Jira UE-32889 - Name collisions can now occur in the blueprint profiler for stat nodes. #Proj BlueprintProfiler, Kismet Notes: This attempts to continue to address fall out from CL 3040046 to improve stability. Previously execution nodes were patched into the function contexts that called a tunnel instance. However this proved problematic after spotting a rare case where node names collide between between event and tunnel graphs and caused havok in the node mapping. This change moves to an approach that patches in tunnel contexts and any dependent contexts and instead attempts to locate critical path nodes using a new node search system making use of these child function contexts. CL 3040046 also modified TunnelContext's to be actually more representative of a tunnel instance context, I have updated naming conventions to reflect this for clarity. The changes here also add a single function context for tunnel graphs which contain the bulk of the nodes in the graph and the tunnel instance contexts reference this and make use of it to create non boundary / tunnel instance nodes so they are located in a single place for all instances of that tunnel graph. Change 3041603 on 2016/07/07 by Dan.Oconnor Fix for check failure: PreviousCDO != nullptr, when loading blueprints that have circularly dependent interfaces #jira UE-31639 Change 3042058 on 2016/07/07 by Dan.Oconnor Ensures that the correct ComponentClass is assigned to our template node. This pins are normally allocated lazilly in BlueprintActionFilterImpl::HasMatchingPin, so not a huge change #jira UE-32769 Change3042468on 2016/07/08 by Maciej.Mroz #jira UE-32882, UE-32887 Fixed Crash in UHT. Fixed "Ambiguous search" error, when delegate has owner class declared. Change 3042739 on 2016/07/08 by Maciej.Mroz Nativization. Included headers for native subobjects. Change 3042747 on 2016/07/08 by Maciej.Mroz Minor changes in Orion code, necessary to compile the project with nativized Blueprints Change 3042758 on 2016/07/08 by Maciej.Mroz "OrionGame.h" is included in NativizedAssets module. [CL 3043181 by Mike Beach in Main branch]
1852 lines
52 KiB
C++
1852 lines
52 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
#include "ClassMaps.h"
|
|
#include "UniqueObj.h"
|
|
|
|
extern class FCompilerMetadataManager GScriptHelper;
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FPropertyBase.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
enum EFunctionExportFlags
|
|
{
|
|
FUNCEXPORT_Final =0x00000001, // function declaration included "final" keyword. Used to differentiate between functions that have FUNC_Final only because they're private
|
|
// =0x00000002,
|
|
// =0x00000004,
|
|
FUNCEXPORT_RequiredAPI =0x00000008, // Function should be exported as a public API function
|
|
FUNCEXPORT_Inline =0x00000010, // export as an inline static C++ function
|
|
FUNCEXPORT_CppStatic =0x00000020, // Export as a real C++ static function, causing thunks to call via ClassName::FuncName instead of this->FuncName
|
|
FUNCEXPORT_CustomThunk =0x00000040, // Export no thunk function; the user will manually define a custom one
|
|
FUNCEXPORT_NeedsProto =0x00000080, // Export a .proto file from the parameters of this function
|
|
FUNCEXPORT_NeedsMCP =0x00000100, // Export a .java file from the parameters of this function
|
|
};
|
|
|
|
enum EPropertyHeaderExportFlags
|
|
{
|
|
PROPEXPORT_Public =0x00000001, // property should be exported as public
|
|
PROPEXPORT_Private =0x00000002, // property should be exported as private
|
|
PROPEXPORT_Protected =0x00000004, // property should be exported as protected
|
|
};
|
|
|
|
struct EPointerType
|
|
{
|
|
enum Type
|
|
{
|
|
None,
|
|
Native
|
|
};
|
|
};
|
|
|
|
struct EArrayType
|
|
{
|
|
enum Type
|
|
{
|
|
None,
|
|
Static,
|
|
Dynamic,
|
|
Set
|
|
};
|
|
};
|
|
|
|
struct ERefQualifier
|
|
{
|
|
enum Type
|
|
{
|
|
None,
|
|
ConstRef,
|
|
NonConstRef
|
|
};
|
|
};
|
|
|
|
enum class EIntType
|
|
{
|
|
None,
|
|
Sized, // e.g. int32, int16
|
|
Unsized // e.g. int, unsigned int
|
|
};
|
|
|
|
#ifndef CASE_TEXT
|
|
#define CASE_TEXT(txt) case txt: return TEXT(#txt)
|
|
#endif
|
|
|
|
/**
|
|
* Basic information describing a type.
|
|
*/
|
|
class FPropertyBase : public TSharedFromThis<FPropertyBase>
|
|
{
|
|
public:
|
|
// Variables.
|
|
EPropertyType Type;
|
|
EArrayType::Type ArrayType;
|
|
uint64 PropertyFlags;
|
|
uint64 ImpliedPropertyFlags;
|
|
ERefQualifier::Type RefQualifier; // This is needed because of legacy stuff - FString mangles the flags for reasons that have become lost in time but we need this info for testing for invalid replicated function signatures.
|
|
|
|
TSharedPtr<FPropertyBase> MapKeyProp;
|
|
|
|
/**
|
|
* A mask of EPropertyHeaderExportFlags which are used for modifying how this property is exported to the native class header
|
|
*/
|
|
uint32 PropertyExportFlags;
|
|
union
|
|
{
|
|
class UEnum* Enum;
|
|
class UClass* PropertyClass;
|
|
class UScriptStruct* Struct;
|
|
class UFunction* Function;
|
|
#if PLATFORM_64BITS
|
|
int64 StringSize;
|
|
#else
|
|
int32 StringSize;
|
|
#endif
|
|
};
|
|
|
|
UClass* MetaClass;
|
|
FName DelegateName;
|
|
UClass* DelegateSignatureOwnerClass;
|
|
FName RepNotifyName;
|
|
|
|
/** Raw string (not type-checked) used for specifying special text when exporting a property to the *Classes.h file */
|
|
FString ExportInfo;
|
|
|
|
/** Map of key value pairs that will be added to the package's UMetaData for this property */
|
|
TMap<FName, FString> MetaData;
|
|
|
|
EPointerType::Type PointerType;
|
|
EIntType IntType;
|
|
|
|
public:
|
|
/** @name Constructors */
|
|
//@{
|
|
explicit FPropertyBase(EPropertyType InType)
|
|
: Type (InType)
|
|
, ArrayType (EArrayType::None)
|
|
, PropertyFlags (0)
|
|
, ImpliedPropertyFlags(0)
|
|
, RefQualifier (ERefQualifier::None)
|
|
, PropertyExportFlags (PROPEXPORT_Public)
|
|
, StringSize (0)
|
|
, MetaClass (nullptr)
|
|
, DelegateName (NAME_None)
|
|
, DelegateSignatureOwnerClass(nullptr)
|
|
, RepNotifyName (NAME_None)
|
|
, PointerType (EPointerType::None)
|
|
, IntType (GetSizedIntTypeFromPropertyType(InType))
|
|
{
|
|
}
|
|
|
|
explicit FPropertyBase(EPropertyType InType, EIntType InIntType)
|
|
: Type (InType)
|
|
, ArrayType (EArrayType::None)
|
|
, PropertyFlags (0)
|
|
, ImpliedPropertyFlags(0)
|
|
, RefQualifier (ERefQualifier::None)
|
|
, PropertyExportFlags (PROPEXPORT_Public)
|
|
, StringSize (0)
|
|
, MetaClass (nullptr)
|
|
, DelegateName (NAME_None)
|
|
, DelegateSignatureOwnerClass(nullptr)
|
|
, RepNotifyName (NAME_None)
|
|
, PointerType (EPointerType::None)
|
|
, IntType (InIntType)
|
|
{
|
|
}
|
|
|
|
explicit FPropertyBase(UEnum* InEnum, EPropertyType InType)
|
|
: Type (InType)
|
|
, ArrayType (EArrayType::None)
|
|
, PropertyFlags (0)
|
|
, ImpliedPropertyFlags(0)
|
|
, RefQualifier (ERefQualifier::None)
|
|
, PropertyExportFlags (PROPEXPORT_Public)
|
|
, Enum (InEnum)
|
|
, MetaClass (nullptr)
|
|
, DelegateName (NAME_None)
|
|
, DelegateSignatureOwnerClass(nullptr)
|
|
, RepNotifyName (NAME_None)
|
|
, PointerType (EPointerType::None)
|
|
, IntType (GetSizedIntTypeFromPropertyType(InType))
|
|
{
|
|
}
|
|
|
|
explicit FPropertyBase(UClass* InClass, UClass* InMetaClass=NULL, bool bAllowWeak = false, bool bIsWeak = false, bool bWeakIsAuto = false, bool bIsLazy = false, bool bIsAsset = false)
|
|
: Type (CPT_ObjectReference)
|
|
, ArrayType (EArrayType::None)
|
|
, PropertyFlags (0)
|
|
, ImpliedPropertyFlags(0)
|
|
, RefQualifier (ERefQualifier::None)
|
|
, PropertyExportFlags (PROPEXPORT_Public)
|
|
, PropertyClass (InClass)
|
|
, MetaClass (InMetaClass)
|
|
, DelegateName (NAME_None)
|
|
, DelegateSignatureOwnerClass(nullptr)
|
|
, RepNotifyName (NAME_None)
|
|
, PointerType (EPointerType::None)
|
|
, IntType (EIntType::None)
|
|
{
|
|
// if this is an interface class, we use the UInterfaceProperty class instead of UObjectProperty
|
|
if ( InClass->HasAnyClassFlags(CLASS_Interface) )
|
|
{
|
|
Type = CPT_Interface;
|
|
}
|
|
if (bAllowWeak)
|
|
{
|
|
UClass* TestClass = InClass;
|
|
while (TestClass) // inherited class flags might not yet be propagated, so lets search
|
|
{
|
|
if ( TestClass->HasAnyClassFlags(CLASS_PointersDefaultToAutoWeak) )
|
|
{
|
|
bIsWeak = true;
|
|
bWeakIsAuto = true;
|
|
break;
|
|
}
|
|
if ( TestClass->HasAnyClassFlags(CLASS_PointersDefaultToWeak) )
|
|
{
|
|
bIsWeak = true;
|
|
}
|
|
TestClass = TestClass->GetSuperClass();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bIsWeak = false;
|
|
}
|
|
if (bIsLazy)
|
|
{
|
|
Type = CPT_LazyObjectReference;
|
|
}
|
|
else if (bIsAsset)
|
|
{
|
|
Type = CPT_AssetObjectReference;
|
|
}
|
|
else if (bIsWeak)
|
|
{
|
|
Type = CPT_WeakObjectReference;
|
|
if (bWeakIsAuto)
|
|
{
|
|
PropertyFlags |= CPF_AutoWeak;
|
|
}
|
|
}
|
|
}
|
|
|
|
explicit FPropertyBase(UScriptStruct* InStruct)
|
|
: Type (CPT_Struct)
|
|
, ArrayType (EArrayType::None)
|
|
, PropertyFlags (0)
|
|
, ImpliedPropertyFlags(0)
|
|
, RefQualifier (ERefQualifier::None)
|
|
, PropertyExportFlags (PROPEXPORT_Public)
|
|
, Struct (InStruct)
|
|
, MetaClass (NULL)
|
|
, DelegateName (NAME_None)
|
|
, DelegateSignatureOwnerClass(nullptr)
|
|
, RepNotifyName (NAME_None)
|
|
, PointerType (EPointerType::None)
|
|
, IntType (EIntType::None)
|
|
{
|
|
}
|
|
|
|
explicit FPropertyBase(UProperty* Property)
|
|
: PropertyExportFlags(PROPEXPORT_Public)
|
|
, DelegateName (NAME_None)
|
|
, DelegateSignatureOwnerClass(nullptr)
|
|
, RepNotifyName (NAME_None)
|
|
, IntType (EIntType::None)
|
|
{
|
|
checkSlow(Property);
|
|
|
|
EArrayType::Type ArrType = EArrayType::None;
|
|
uint64 PropagateFlags = 0;
|
|
UClass* ClassOfProperty = Property->GetClass();
|
|
|
|
if( ClassOfProperty==UArrayProperty::StaticClass() )
|
|
{
|
|
ArrType = EArrayType::Dynamic;
|
|
|
|
// if we're an array, save up Parm flags so we can propagate them.
|
|
// below the array will be assigned the inner property flags. This allows propagation of Parm flags (out, optional..)
|
|
PropagateFlags = Property->PropertyFlags & CPF_ParmFlags;
|
|
Property = CastChecked<UArrayProperty>(Property)->Inner;
|
|
ClassOfProperty = Property->GetClass();
|
|
}
|
|
|
|
if( ClassOfProperty==UByteProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Byte);
|
|
Enum = Cast<UByteProperty>(Property)->Enum;
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UInt8Property::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Int8);
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UInt16Property::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Int16);
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UIntProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Int);
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UInt64Property::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Int64);
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UUInt16Property::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_UInt16);
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UUInt32Property::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_UInt32);
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UUInt64Property::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_UInt64);
|
|
IntType = EIntType::Sized;
|
|
}
|
|
else if( ClassOfProperty==UBoolProperty::StaticClass() )
|
|
{
|
|
UBoolProperty* BoolProperty = Cast<UBoolProperty>(Property);
|
|
if (BoolProperty->IsNativeBool())
|
|
{
|
|
*this = FPropertyBase(CPT_Bool);
|
|
}
|
|
else
|
|
{
|
|
switch( BoolProperty->ElementSize )
|
|
{
|
|
case sizeof(uint8):
|
|
*this = FPropertyBase(CPT_Bool8);
|
|
break;
|
|
case sizeof(uint16):
|
|
*this = FPropertyBase(CPT_Bool16);
|
|
break;
|
|
case sizeof(uint32):
|
|
*this = FPropertyBase(CPT_Bool32);
|
|
break;
|
|
case sizeof(uint64):
|
|
*this = FPropertyBase(CPT_Bool64);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if( ClassOfProperty==UFloatProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Float);
|
|
}
|
|
else if( ClassOfProperty==UDoubleProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Double);
|
|
}
|
|
else if( ClassOfProperty==UClassProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_ObjectReference);
|
|
PropertyClass = Cast<UClassProperty>(Property)->PropertyClass;
|
|
MetaClass = Cast<UClassProperty>(Property)->MetaClass;
|
|
}
|
|
else if( ClassOfProperty==UObjectProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_ObjectReference);
|
|
PropertyClass = Cast<UObjectProperty>(Property)->PropertyClass;
|
|
}
|
|
else if( ClassOfProperty==UWeakObjectProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_WeakObjectReference);
|
|
PropertyClass = Cast<UWeakObjectProperty>(Property)->PropertyClass;
|
|
}
|
|
else if( ClassOfProperty==ULazyObjectProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_LazyObjectReference);
|
|
PropertyClass = Cast<ULazyObjectProperty>(Property)->PropertyClass;
|
|
}
|
|
else if( ClassOfProperty==UAssetClassProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_AssetObjectReference);
|
|
PropertyClass = Cast<UAssetClassProperty>(Property)->PropertyClass;
|
|
MetaClass = Cast<UAssetClassProperty>(Property)->MetaClass;
|
|
}
|
|
else if( ClassOfProperty==UAssetObjectProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_AssetObjectReference);
|
|
PropertyClass = Cast<UAssetObjectProperty>(Property)->PropertyClass;
|
|
}
|
|
else if( ClassOfProperty==UNameProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Name);
|
|
}
|
|
else if( ClassOfProperty==UStrProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_String);
|
|
}
|
|
else if( ClassOfProperty==UTextProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Text);
|
|
}
|
|
else if( ClassOfProperty==UStructProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Struct);
|
|
Struct = Cast<UStructProperty>(Property)->Struct;
|
|
}
|
|
else if( ClassOfProperty==UDelegateProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Delegate);
|
|
Function = Cast<UDelegateProperty>(Property)->SignatureFunction;
|
|
}
|
|
else if( ClassOfProperty==UMulticastDelegateProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_MulticastDelegate);
|
|
// @todo delegate: Any other setup for calling multi-cast delegates from script needed?
|
|
Function = Cast<UMulticastDelegateProperty>(Property)->SignatureFunction;
|
|
}
|
|
else if ( ClassOfProperty==UInterfaceProperty::StaticClass() )
|
|
{
|
|
*this = FPropertyBase(CPT_Interface);
|
|
PropertyClass = Cast<UInterfaceProperty>(Property)->InterfaceClass;
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogCompile, Fatal, TEXT("Unknown property type '%s'"), *Property->GetFullName() );
|
|
}
|
|
ArrayType = ArrType;
|
|
PropertyFlags = Property->PropertyFlags | PropagateFlags;
|
|
ImpliedPropertyFlags = 0;
|
|
RefQualifier = ERefQualifier::None;
|
|
PointerType = EPointerType::None;
|
|
}
|
|
//@}
|
|
|
|
/** @name Functions */
|
|
//@{
|
|
|
|
/**
|
|
* Returns whether this token represents an object reference
|
|
*/
|
|
bool IsObject() const
|
|
{
|
|
return Type == CPT_ObjectReference || Type == CPT_Interface || Type == CPT_WeakObjectReference || Type == CPT_LazyObjectReference || Type == CPT_AssetObjectReference;
|
|
}
|
|
|
|
bool IsContainer() const
|
|
{
|
|
return (ArrayType != EArrayType::None || MapKeyProp.IsValid());
|
|
}
|
|
|
|
/**
|
|
* Determines whether this token's type is compatible with another token's type.
|
|
*
|
|
* @param Other the token to check against this one.
|
|
* Given the following example expressions, VarA is Other and VarB is 'this':
|
|
* VarA = VarB;
|
|
*
|
|
* function func(type VarB) {}
|
|
* func(VarA);
|
|
*
|
|
* static operator==(type VarB_1, type VarB_2) {}
|
|
* if ( VarA_1 == VarA_2 ) {}
|
|
*
|
|
* @param bDisallowGeneralization controls whether it should be considered a match if this token's type is a generalization
|
|
* of the other token's type (or vice versa, when dealing with structs
|
|
* @param bIgnoreImplementedInterfaces controls whether two types can be considered a match if one type is an interface implemented
|
|
* by the other type.
|
|
*/
|
|
bool MatchesType( const FPropertyBase& Other, bool bDisallowGeneralization, bool bIgnoreImplementedInterfaces=false ) const
|
|
{
|
|
check(Type!=CPT_None || !bDisallowGeneralization);
|
|
|
|
bool bIsObjectType = IsObject();
|
|
bool bOtherIsObjectType = Other.IsObject();
|
|
bool bIsObjectComparison = bIsObjectType && bOtherIsObjectType;
|
|
bool bReverseClassChainCheck = true;
|
|
|
|
// If converting to an l-value, we require an exact match with an l-value.
|
|
if( (PropertyFlags&CPF_OutParm) != 0 )
|
|
{
|
|
// if the other type is not an l-value, disallow
|
|
if ( (Other.PropertyFlags&CPF_OutParm) == 0 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// if the other type is const and we are not const, disallow
|
|
if ( (Other.PropertyFlags&CPF_ConstParm) != 0 && (PropertyFlags&CPF_ConstParm) == 0 )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if ( Type == CPT_Struct )
|
|
{
|
|
// Allow derived structs to be passed by reference, unless this is a dynamic array of structs
|
|
bDisallowGeneralization = bDisallowGeneralization || ArrayType == EArrayType::Dynamic || Other.ArrayType == EArrayType::Dynamic;
|
|
}
|
|
|
|
// if Type == CPT_ObjectReference, out object function parm; allow derived classes to be passed in
|
|
// if Type == CPT_Interface, out interface function parm; allow derived classes to be passed in
|
|
else if ( (PropertyFlags & CPF_ConstParm) == 0 || !IsObject() )
|
|
{
|
|
// all other variable types must match exactly when passed as the value to an 'out' parameter
|
|
bDisallowGeneralization = true;
|
|
}
|
|
|
|
// both types are objects, but one is an interface and one is an object reference
|
|
else if ( bIsObjectComparison && Type != Other.Type )
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
else if ((Type == CPT_ObjectReference || Type == CPT_WeakObjectReference || Type == CPT_LazyObjectReference || Type == CPT_AssetObjectReference) && Other.Type != CPT_Interface && (PropertyFlags & CPF_ReturnParm))
|
|
{
|
|
bReverseClassChainCheck = false;
|
|
}
|
|
|
|
// Check everything.
|
|
if( Type==CPT_None && (Other.Type==CPT_None || !bDisallowGeneralization) )
|
|
{
|
|
// If Other has no type, accept anything.
|
|
return true;
|
|
}
|
|
else if( Type != Other.Type && !bIsObjectComparison )
|
|
{
|
|
// Mismatched base types.
|
|
return false;
|
|
}
|
|
else if( ArrayType != Other.ArrayType )
|
|
{
|
|
// Mismatched array types.
|
|
return false;
|
|
}
|
|
else if( Type==CPT_Byte )
|
|
{
|
|
// Make sure enums match, or we're generalizing.
|
|
return Enum==Other.Enum || (Enum==NULL && !bDisallowGeneralization);
|
|
}
|
|
else if( bIsObjectType )
|
|
{
|
|
check(PropertyClass!=NULL);
|
|
|
|
// Make sure object types match, or we're generalizing.
|
|
if( bDisallowGeneralization )
|
|
{
|
|
// Exact match required.
|
|
return PropertyClass==Other.PropertyClass && MetaClass==Other.MetaClass;
|
|
}
|
|
else if( Other.PropertyClass==NULL )
|
|
{
|
|
// Cannonical 'None' matches all object classes.
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Generalization is ok (typical example of this check would look like: VarA = VarB;, where this is VarB and Other is VarA)
|
|
if ( Other.PropertyClass->IsChildOf(PropertyClass) )
|
|
{
|
|
if ( !bIgnoreImplementedInterfaces || ((Type == CPT_Interface) == (Other.Type == CPT_Interface)) )
|
|
{
|
|
if ( !PropertyClass->IsChildOf(UClass::StaticClass()) || MetaClass == NULL || Other.MetaClass->IsChildOf(MetaClass) ||
|
|
(bReverseClassChainCheck && (Other.MetaClass == NULL || MetaClass->IsChildOf(Other.MetaClass))) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
// check the opposite class chain for object types
|
|
else if (bReverseClassChainCheck && Type != CPT_Interface && bIsObjectComparison && PropertyClass != NULL && PropertyClass->IsChildOf(Other.PropertyClass))
|
|
{
|
|
if (!Other.PropertyClass->IsChildOf(UClass::StaticClass()) || MetaClass == NULL || Other.MetaClass == NULL || MetaClass->IsChildOf(Other.MetaClass) || Other.MetaClass->IsChildOf(MetaClass))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if ( PropertyClass->HasAnyClassFlags(CLASS_Interface) && !bIgnoreImplementedInterfaces )
|
|
{
|
|
if ( Other.PropertyClass->ImplementsInterface(PropertyClass) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
else if( Type==CPT_Struct )
|
|
{
|
|
check(Struct!=NULL);
|
|
check(Other.Struct!=NULL);
|
|
|
|
if ( Struct == Other.Struct )
|
|
{
|
|
// struct types match exactly
|
|
return true;
|
|
}
|
|
|
|
// returning false here prevents structs related through inheritance from being used interchangeably, such as passing a derived struct as the value for a parameter
|
|
// that expects the base struct, or vice versa. An easier example is assignment (e.g. Vector = Plane or Plane = Vector).
|
|
// there are two cases to consider (let's use vector and plane for the example):
|
|
// - Vector = Plane;
|
|
// in this expression, 'this' is the vector, and Other is the plane. This is an unsafe conversion, as the destination property type is used to copy the r-value to the l-value
|
|
// so in this case, the VM would call CopyCompleteValue on the FPlane struct, which would copy 16 bytes into the l-value's buffer; However, the l-value buffer will only be
|
|
// 12 bytes because that is the size of FVector
|
|
// - Plane = Vector;
|
|
// in this expression, 'this' is the plane, and Other is the vector. This is a safe conversion, since only 12 bytes would be copied from the r-value into the l-value's buffer
|
|
// (which would be 16 bytes). The problem with allowing this conversion is that what to do with the extra member (e.g. Plane.W); should it be left alone? should it be zeroed?
|
|
// difficult to say what the correct behavior should be, so let's just ignore inheritance for the sake of determining whether two structs are identical
|
|
|
|
// Previously, the logic for determining whether this is a generalization of Other was reversed; this is very likely the culprit behind all current issues with
|
|
// using derived structs interchangeably with their base versions. The inheritance check has been fixed; for now, allow struct generalization and see if we can find any further
|
|
// issues with allowing conversion. If so, then we disable all struct generalization by returning false here.
|
|
// return false;
|
|
|
|
if ( bDisallowGeneralization )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Generalization is ok if this is not a dynamic array
|
|
if ( ArrayType != EArrayType::Dynamic && Other.ArrayType != EArrayType::Dynamic )
|
|
{
|
|
if ( !Other.Struct->IsChildOf(Struct) && Struct->IsChildOf(Other.Struct) )
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// General match.
|
|
return true;
|
|
}
|
|
}
|
|
|
|
FString Describe()
|
|
{
|
|
return FString::Printf(
|
|
TEXT("Type:%s Flags:%lli ImpliedFlags:%lli Enum:%s PropertyClass:%s Struct:%s Function:%s MetaClass:%s"),
|
|
GetPropertyTypeText(Type), PropertyFlags, ImpliedPropertyFlags,
|
|
Enum!=NULL?*Enum->GetName():TEXT(""),
|
|
PropertyClass!=NULL?*PropertyClass->GetName():TEXT("NULL"),
|
|
Struct!=NULL?*Struct->GetName():TEXT("NULL"),
|
|
Function!=NULL?*Function->GetName():TEXT("NULL"),
|
|
MetaClass!=NULL?*MetaClass->GetName():TEXT("NULL")
|
|
);
|
|
}
|
|
//@}
|
|
|
|
EIntType GetSizedIntTypeFromPropertyType(EPropertyType PropType)
|
|
{
|
|
switch (PropType)
|
|
{
|
|
case CPT_Byte:
|
|
case CPT_UInt16:
|
|
case CPT_UInt32:
|
|
case CPT_UInt64:
|
|
case CPT_Int8:
|
|
case CPT_Int16:
|
|
case CPT_Int:
|
|
case CPT_Int64:
|
|
return EIntType::Sized;
|
|
|
|
default:
|
|
return EIntType::None;
|
|
}
|
|
}
|
|
|
|
static const TCHAR* GetPropertyTypeText( EPropertyType Type );
|
|
|
|
friend struct FPropertyBaseArchiveProxy;
|
|
};
|
|
|
|
//
|
|
// Token types.
|
|
//
|
|
enum ETokenType
|
|
{
|
|
TOKEN_None = 0x00, // No token.
|
|
TOKEN_Identifier = 0x01, // Alphanumeric identifier.
|
|
TOKEN_Symbol = 0x02, // Symbol.
|
|
TOKEN_Const = 0x03, // A constant.
|
|
TOKEN_Max = 0x0D
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
FToken.
|
|
-----------------------------------------------------------------------------*/
|
|
//
|
|
// Information about a token that was just parsed.
|
|
//
|
|
class FToken : public FPropertyBase
|
|
{
|
|
public:
|
|
/** @name Variables */
|
|
//@{
|
|
/** Type of token. */
|
|
ETokenType TokenType;
|
|
/** Name of token. */
|
|
FName TokenName;
|
|
/** Starting position in script where this token came from. */
|
|
int32 StartPos;
|
|
/** Starting line in script. */
|
|
int32 StartLine;
|
|
/** Always valid. */
|
|
TCHAR Identifier[NAME_SIZE];
|
|
/** property that corresponds to this FToken - null if this Token doesn't correspond to a UProperty */
|
|
UProperty* TokenProperty;
|
|
|
|
union
|
|
{
|
|
// TOKEN_Const values.
|
|
uint8 Byte; // If CPT_Byte.
|
|
int32 Int; // If CPT_Int.
|
|
bool NativeBool; // if CPT_Bool
|
|
float Float; // If CPT_Float.
|
|
double Double; // If CPT_Double.
|
|
uint8 NameBytes[sizeof(FName)]; // If CPT_Name.
|
|
TCHAR String[MAX_STRING_CONST_SIZE]; // If CPT_String
|
|
};
|
|
//@}
|
|
|
|
/**
|
|
* Copies the properties from this token into another.
|
|
*
|
|
* @param Other the token to copy this token's properties to.
|
|
*/
|
|
void Clone( const FToken& Other );
|
|
|
|
FString GetConstantValue()
|
|
{
|
|
if (TokenType == TOKEN_Const)
|
|
{
|
|
switch (Type)
|
|
{
|
|
case CPT_Byte:
|
|
return FString::Printf(TEXT("%u"), Byte);
|
|
case CPT_Int:
|
|
return FString::Printf(TEXT("%i"), Int);
|
|
case CPT_Bool:
|
|
// Don't use GTrue/GFalse here because they can be localized
|
|
return FString::Printf(TEXT("%s"), NativeBool ? *(FName::GetEntry(NAME_TRUE)->GetPlainNameString()) : *(FName::GetEntry(NAME_FALSE)->GetPlainNameString()));
|
|
case CPT_Float:
|
|
return FString::Printf(TEXT("%f"), Float);
|
|
case CPT_Double:
|
|
return FString::Printf(TEXT("%f"), Double);
|
|
case CPT_Name:
|
|
return FString::Printf(TEXT("%s"), *(*(FName*)NameBytes).ToString());
|
|
case CPT_String:
|
|
return String;
|
|
|
|
// unsupported (parsing never produces a constant token of these types)
|
|
case CPT_Vector:
|
|
case CPT_Rotation:
|
|
case CPT_Int8:
|
|
case CPT_Int16:
|
|
case CPT_Int64:
|
|
case CPT_UInt16:
|
|
case CPT_UInt32:
|
|
case CPT_UInt64:
|
|
case CPT_Bool8:
|
|
case CPT_Bool16:
|
|
case CPT_Bool32:
|
|
case CPT_Bool64:
|
|
case CPT_Range:
|
|
case CPT_Struct:
|
|
case CPT_ObjectReference:
|
|
case CPT_WeakObjectReference:
|
|
case CPT_LazyObjectReference:
|
|
case CPT_AssetObjectReference:
|
|
case CPT_Interface:
|
|
case CPT_Delegate:
|
|
case CPT_MulticastDelegate:
|
|
default:
|
|
return TEXT("InvalidTypeForAToken");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return TEXT("NotConstant");
|
|
}
|
|
}
|
|
|
|
// Constructors.
|
|
FToken()
|
|
: FPropertyBase(CPT_None)
|
|
, TokenProperty(NULL)
|
|
{
|
|
InitToken(CPT_None);
|
|
}
|
|
|
|
// copy constructors
|
|
explicit FToken(EPropertyType InType)
|
|
: FPropertyBase(InType)
|
|
, TokenProperty(NULL)
|
|
{
|
|
InitToken(InType);
|
|
}
|
|
|
|
// copy constructors
|
|
FToken(const FPropertyBase& InType)
|
|
: FPropertyBase(CPT_None)
|
|
, TokenProperty(NULL)
|
|
{
|
|
InitToken( CPT_None );
|
|
(FPropertyBase&)*this = InType;
|
|
}
|
|
|
|
// Inlines.
|
|
void InitToken( EPropertyType InType )
|
|
{
|
|
(FPropertyBase&)*this = FPropertyBase(InType);
|
|
TokenType = TOKEN_None;
|
|
TokenName = NAME_None;
|
|
StartPos = 0;
|
|
StartLine = 0;
|
|
*Identifier = 0;
|
|
FMemory::Memzero(String);
|
|
}
|
|
bool Matches( const TCHAR* Str, ESearchCase::Type SearchCase = ESearchCase::IgnoreCase ) const
|
|
{
|
|
return (TokenType==TOKEN_Identifier || TokenType==TOKEN_Symbol) && ((SearchCase == ESearchCase::CaseSensitive) ? !FCString::Strcmp(Identifier, Str) : !FCString::Stricmp(Identifier, Str));
|
|
}
|
|
bool Matches( const FName& Name ) const
|
|
{
|
|
return TokenType==TOKEN_Identifier && TokenName==Name;
|
|
}
|
|
bool StartsWith( const TCHAR* Str, bool bCaseSensitive = false ) const
|
|
{
|
|
const int32 StrLength = FCString::Strlen(Str);
|
|
return (TokenType==TOKEN_Identifier || TokenType==TOKEN_Symbol) && (bCaseSensitive ? (!FCString::Strncmp(Identifier, Str, StrLength)) : (!FCString::Strnicmp(Identifier, Str, StrLength)));
|
|
}
|
|
bool IsBool() const
|
|
{
|
|
return Type == CPT_Bool || Type == CPT_Bool8 || Type == CPT_Bool16 || Type == CPT_Bool32 || Type == CPT_Bool64;
|
|
}
|
|
|
|
// Setters.
|
|
|
|
void SetConstInt( int32 InInt )
|
|
{
|
|
(FPropertyBase&)*this = FPropertyBase(CPT_Int);
|
|
Int = InInt;
|
|
TokenType = TOKEN_Const;
|
|
}
|
|
void SetConstBool( bool InBool )
|
|
{
|
|
(FPropertyBase&)*this = FPropertyBase(CPT_Bool);
|
|
NativeBool = InBool;
|
|
TokenType = TOKEN_Const;
|
|
}
|
|
void SetConstFloat( float InFloat )
|
|
{
|
|
(FPropertyBase&)*this = FPropertyBase(CPT_Float);
|
|
Float = InFloat;
|
|
TokenType = TOKEN_Const;
|
|
}
|
|
void SetConstDouble( double InDouble )
|
|
{
|
|
(FPropertyBase&)*this = FPropertyBase(CPT_Double);
|
|
Double = InDouble;
|
|
TokenType = TOKEN_Const;
|
|
}
|
|
void SetConstName( FName InName )
|
|
{
|
|
(FPropertyBase&)*this = FPropertyBase(CPT_Name);
|
|
*(FName *)NameBytes = InName;
|
|
TokenType = TOKEN_Const;
|
|
}
|
|
void SetConstString( TCHAR* InString, int32 MaxLength=MAX_STRING_CONST_SIZE )
|
|
{
|
|
check(MaxLength>0);
|
|
(FPropertyBase&)*this = FPropertyBase(CPT_String);
|
|
if( InString != String )
|
|
{
|
|
FCString::Strncpy( String, InString, MaxLength );
|
|
}
|
|
TokenType = TOKEN_Const;
|
|
}
|
|
void SetConstChar(TCHAR InChar)
|
|
{
|
|
//@TODO: Treating this like a string for now, nothing consumes it
|
|
(FPropertyBase&)*this = FPropertyBase(CPT_String);
|
|
String[0] = InChar;
|
|
String[1] = 0;
|
|
TokenType = TOKEN_Const;
|
|
}
|
|
//!!struct constants
|
|
|
|
// Getters.
|
|
bool GetConstInt( int32& I ) const
|
|
{
|
|
if( TokenType==TOKEN_Const && Type==CPT_Int )
|
|
{
|
|
I = Int;
|
|
return 1;
|
|
}
|
|
else if( TokenType==TOKEN_Const && Type==CPT_Byte )
|
|
{
|
|
I = Byte;
|
|
return 1;
|
|
}
|
|
else if( TokenType==TOKEN_Const && Type==CPT_Float && Float==FMath::TruncToInt(Float))
|
|
{
|
|
I = (int32) Float;
|
|
return 1;
|
|
}
|
|
else if (TokenType == TOKEN_Const && Type == CPT_Double && Float == FMath::TruncToInt(Double))
|
|
{
|
|
I = (int32) Double;
|
|
return 1;
|
|
}
|
|
else return 0;
|
|
}
|
|
|
|
FString Describe()
|
|
{
|
|
return FString::Printf(
|
|
TEXT("Property:%s Type:%s TokenName:%s ConstValue:%s Struct:%s Flags:%lli Implied:%lli"),
|
|
TokenProperty!=NULL?*TokenProperty->GetName():TEXT("NULL"),
|
|
GetPropertyTypeText(Type), *TokenName.ToString(), *GetConstantValue(),
|
|
Struct!=NULL?*Struct->GetName():TEXT("NULL"),
|
|
PropertyFlags,
|
|
ImpliedPropertyFlags
|
|
);
|
|
}
|
|
|
|
friend struct FTokenArchiveProxy;
|
|
};
|
|
|
|
/**
|
|
* A group of FTokens. Used for keeping track of reference chains tokens
|
|
* e.g. SomeObject.default.Foo.DoSomething()
|
|
*/
|
|
class FTokenChain : public TArray<FToken>
|
|
{
|
|
public:
|
|
FToken& operator+=( const FToken& NewToken )
|
|
{
|
|
FToken& Token = (*this)[AddZeroed()] = NewToken;
|
|
return Token;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Information about a function being compiled.
|
|
*/
|
|
struct FFuncInfo
|
|
{
|
|
/** @name Variables */
|
|
//@{
|
|
/** Name of the function or operator. */
|
|
FToken Function;
|
|
/** Function flags. */
|
|
uint32 FunctionFlags;
|
|
/** Function flags which are only required for exporting */
|
|
uint32 FunctionExportFlags;
|
|
/** Number of parameters expected for operator. */
|
|
int32 ExpectParms;
|
|
/** Pointer to the UFunction corresponding to this FFuncInfo */
|
|
UFunction* FunctionReference;
|
|
/** Name of the wrapper function that marshalls the arguments and does the indirect call **/
|
|
FString MarshallAndCallName;
|
|
/** Name of the actual implementation **/
|
|
FString CppImplName;
|
|
/** Name of the actual validation implementation **/
|
|
FString CppValidationImplName;
|
|
/** Name for callback-style names **/
|
|
FString UnMarshallAndCallName;
|
|
/** Identifier for an RPC call to a platform service */
|
|
int16 RPCId;
|
|
/** Identifier for an RPC call expecting a response */
|
|
int16 RPCResponseId;
|
|
/** Whether this function represents a sealed event */
|
|
bool bSealedEvent;
|
|
/** Delegate macro line in header. */
|
|
int32 MacroLine;
|
|
/** Position in file where this function was declared. Points to first char of function name. */
|
|
int32 InputPos;
|
|
/** TRUE if the function is being forced to be considered as impure by the user */
|
|
bool bForceBlueprintImpure;
|
|
|
|
//@}
|
|
|
|
/** Constructor. */
|
|
FFuncInfo()
|
|
: Function()
|
|
, FunctionFlags(0)
|
|
, FunctionExportFlags(0)
|
|
, ExpectParms(0)
|
|
, FunctionReference(NULL)
|
|
, CppImplName(TEXT(""))
|
|
, CppValidationImplName(TEXT(""))
|
|
, RPCId(0)
|
|
, RPCResponseId(0)
|
|
, bSealedEvent(false)
|
|
, MacroLine(-1)
|
|
, InputPos(-1)
|
|
, bForceBlueprintImpure(false)
|
|
{}
|
|
|
|
FFuncInfo(const FFuncInfo& Other)
|
|
: FunctionFlags(Other.FunctionFlags)
|
|
, FunctionExportFlags(Other.FunctionExportFlags)
|
|
, ExpectParms(Other.ExpectParms)
|
|
, FunctionReference(Other.FunctionReference)
|
|
, CppImplName(Other.CppImplName)
|
|
, CppValidationImplName(Other.CppValidationImplName)
|
|
, RPCId(Other.RPCId)
|
|
, RPCResponseId(Other.RPCResponseId)
|
|
, MacroLine(Other.MacroLine)
|
|
, InputPos(Other.InputPos)
|
|
, bForceBlueprintImpure(Other.bForceBlueprintImpure)
|
|
{
|
|
Function.Clone(Other.Function);
|
|
if (FunctionReference)
|
|
{
|
|
SetFunctionNames();
|
|
}
|
|
}
|
|
|
|
/** Set the internal function names based on flags **/
|
|
void SetFunctionNames()
|
|
{
|
|
FString FunctionName = FunctionReference->GetName();
|
|
if( FunctionReference->HasAnyFunctionFlags( FUNC_Delegate ) )
|
|
{
|
|
FunctionName = FunctionName.LeftChop( FString( TEXT( "__DelegateSignature" ) ).Len() );
|
|
}
|
|
UnMarshallAndCallName = FString(TEXT("exec")) + FunctionName;
|
|
|
|
if (FunctionReference->HasAnyFunctionFlags(FUNC_BlueprintEvent))
|
|
{
|
|
MarshallAndCallName = FunctionName;
|
|
}
|
|
else
|
|
{
|
|
MarshallAndCallName = FString(TEXT("event")) + FunctionName;
|
|
}
|
|
|
|
if (FunctionReference->HasAllFunctionFlags(FUNC_Native | FUNC_Net))
|
|
{
|
|
MarshallAndCallName = FunctionName;
|
|
if (FunctionReference->HasAllFunctionFlags(FUNC_NetResponse))
|
|
{
|
|
// Response function implemented by programmer and called directly from thunk
|
|
CppImplName = FunctionReference->GetName();
|
|
}
|
|
else
|
|
{
|
|
if (CppImplName.IsEmpty())
|
|
{
|
|
CppImplName = FunctionReference->GetName() + TEXT("_Implementation");
|
|
}
|
|
else if (CppImplName == FunctionName)
|
|
{
|
|
FError::Throwf(TEXT("Native implementation function must be different than original function name."));
|
|
}
|
|
|
|
if (CppValidationImplName.IsEmpty() && FunctionReference->HasAllFunctionFlags(FUNC_NetValidate))
|
|
{
|
|
CppValidationImplName = FunctionReference->GetName() + TEXT("_Validate");
|
|
}
|
|
else if(CppValidationImplName == FunctionName)
|
|
{
|
|
FError::Throwf(TEXT("Validation function must be different than original function name."));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (FunctionReference->HasAllFunctionFlags(FUNC_Delegate))
|
|
{
|
|
MarshallAndCallName = FString(TEXT("delegate")) + FunctionName;
|
|
}
|
|
|
|
if (FunctionReference->HasAllFunctionFlags(FUNC_BlueprintEvent | FUNC_Native))
|
|
{
|
|
MarshallAndCallName = FunctionName;
|
|
CppImplName = FunctionReference->GetName() + TEXT("_Implementation");
|
|
}
|
|
|
|
if (CppImplName.IsEmpty())
|
|
{
|
|
CppImplName = FunctionName;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Stores "compiler" data about an FToken. "Compiler" data is data that is associated with a
|
|
* specific property, function or class that is only needed during script compile.
|
|
* This class is designed to make adding new compiler data very simple.
|
|
*
|
|
* - stores the raw evaluated bytecode associated with an FToken
|
|
*/
|
|
struct FTokenData
|
|
{
|
|
/** The token tracked by this FTokenData. */
|
|
FToken Token;
|
|
|
|
/** @name Constructors */
|
|
//@{
|
|
/**
|
|
* Defalt constructor
|
|
*/
|
|
FTokenData()
|
|
{}
|
|
|
|
/**
|
|
* Copy constructor
|
|
*/
|
|
FTokenData(const FToken& inToken)
|
|
: Token(inToken)
|
|
{}
|
|
//@}
|
|
};
|
|
|
|
/**
|
|
* Class for storing data about a list of properties. Though FToken contains a reference to its
|
|
* associated UProperty, it's faster lookup to use the UProperty as the key in a TMap.
|
|
*/
|
|
class FPropertyData : public TMap< UProperty*, TSharedPtr<FTokenData> >
|
|
{
|
|
typedef TMap<UProperty*, TSharedPtr<FTokenData> > Super;
|
|
|
|
public:
|
|
/**
|
|
* Returns the value associated with a specified key.
|
|
* @param Key - The key to search for.
|
|
* @return A pointer to the value associated with the specified key, or NULL if the key isn't contained in this map. The pointer
|
|
* is only valid until the next change to any key in the map.
|
|
*/
|
|
FTokenData* Find(UProperty* Key)
|
|
{
|
|
FTokenData* Result = NULL;
|
|
|
|
TSharedPtr<FTokenData>* pResult = Super::Find(Key);
|
|
if ( pResult != NULL )
|
|
{
|
|
Result = pResult->Get();
|
|
}
|
|
return Result;
|
|
}
|
|
const FTokenData* Find(UProperty* Key) const
|
|
{
|
|
const FTokenData* Result = NULL;
|
|
|
|
const TSharedPtr<FTokenData>* pResult = Super::Find(Key);
|
|
if ( pResult != NULL )
|
|
{
|
|
Result = pResult->Get();
|
|
}
|
|
return Result;
|
|
}
|
|
|
|
/**
|
|
* Sets the value associated with a key. If the key already exists in the map, uses the same
|
|
* value pointer and reinitalized the FTokenData with the input value.
|
|
*
|
|
* @param InKey the property to get a token wrapper for
|
|
* @param InValue the token wrapper for the specified key
|
|
*
|
|
* @return a pointer to token data created associated with the property
|
|
*/
|
|
FTokenData* Set(UProperty* InKey, const FTokenData& InValue, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile);
|
|
|
|
/**
|
|
* (debug) Dumps the values of this FPropertyData to the log file
|
|
*
|
|
* @param Indent number of spaces to insert at the beginning of each line
|
|
*/
|
|
void Dump( int32 Indent )
|
|
{
|
|
for (auto& Kvp : *this)
|
|
{
|
|
TSharedPtr<FTokenData>& PointerVal = Kvp.Value;
|
|
FToken& Token = PointerVal->Token;
|
|
if ( Token.Type != CPT_None )
|
|
{
|
|
UE_LOG(LogCompile, Log, TEXT("%s%s"), FCString::Spc(Indent), *Token.Describe());
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Class for storing additional data about compiled structs and struct properties
|
|
*/
|
|
class FStructData
|
|
{
|
|
public:
|
|
/** info about the struct itself */
|
|
FToken StructData;
|
|
|
|
private:
|
|
/** info for the properties contained in this struct */
|
|
FPropertyData StructPropertyData;
|
|
|
|
public:
|
|
/**
|
|
* Adds a new struct property token
|
|
*
|
|
* @param PropertyToken token that should be added to the list
|
|
*/
|
|
void AddStructProperty(const FTokenData& PropertyToken, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
|
|
{
|
|
check(PropertyToken.Token.TokenProperty);
|
|
StructPropertyData.Set(PropertyToken.Token.TokenProperty, PropertyToken, UHTMakefile, UnrealSourceFile);
|
|
}
|
|
|
|
FPropertyData& GetStructPropertyData()
|
|
{
|
|
return StructPropertyData;
|
|
}
|
|
const FPropertyData& GetStructPropertyData() const
|
|
{
|
|
return StructPropertyData;
|
|
}
|
|
|
|
/**
|
|
* (debug) Dumps the values of this FStructData to the log file
|
|
*
|
|
* @param Indent number of spaces to insert at the beginning of each line
|
|
*/
|
|
void Dump( int32 Indent )
|
|
{
|
|
UE_LOG(LogCompile, Log, TEXT("%s%s"), FCString::Spc(Indent), *StructData.Describe());
|
|
|
|
UE_LOG(LogCompile, Log, TEXT("%sproperties:"), FCString::Spc(Indent));
|
|
StructPropertyData.Dump(Indent + 4);
|
|
}
|
|
|
|
/** Constructor */
|
|
FStructData( const FToken& StructToken ) : StructData(StructToken) {}
|
|
|
|
friend struct FStructDataArchiveProxy;
|
|
};
|
|
|
|
/**
|
|
* Class for storing additional data about compiled function properties.
|
|
*/
|
|
class FFunctionData
|
|
{
|
|
/** info about the function associated with this FFunctionData */
|
|
FFuncInfo FunctionData;
|
|
|
|
/** return value for this function */
|
|
FTokenData ReturnTypeData;
|
|
|
|
/** function parameter data */
|
|
FPropertyData ParameterData;
|
|
|
|
/**
|
|
* Adds a new parameter token
|
|
*
|
|
* @param PropertyToken token that should be added to the list
|
|
*/
|
|
void AddParameter(const FToken& PropertyToken, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
|
|
{
|
|
check(PropertyToken.TokenProperty);
|
|
ParameterData.Set(PropertyToken.TokenProperty, PropertyToken, UHTMakefile, UnrealSourceFile);
|
|
}
|
|
|
|
/**
|
|
* Sets the value of the return token for this function
|
|
*
|
|
* @param PropertyToken token that should be added
|
|
*/
|
|
void SetReturnData( const FToken& PropertyToken )
|
|
{
|
|
check(PropertyToken.TokenProperty);
|
|
ReturnTypeData.Token = PropertyToken;
|
|
}
|
|
|
|
public:
|
|
/** Constructors */
|
|
FFunctionData() {}
|
|
FFunctionData( const FFunctionData& Other )
|
|
{
|
|
(*this) = Other;
|
|
}
|
|
FFunctionData( const FFuncInfo& inFunctionData )
|
|
: FunctionData(inFunctionData)
|
|
{}
|
|
|
|
/** Copy operator */
|
|
FFunctionData& operator=( const FFunctionData& Other )
|
|
{
|
|
FunctionData = Other.FunctionData;
|
|
ParameterData = Other.ParameterData;
|
|
ReturnTypeData.Token.Clone(Other.ReturnTypeData.Token);
|
|
return *this;
|
|
}
|
|
|
|
/** @name getters */
|
|
//@{
|
|
const FFuncInfo& GetFunctionData() const { return FunctionData; }
|
|
const FToken& GetReturnData() const { return ReturnTypeData.Token; }
|
|
const FPropertyData& GetParameterData() const { return ParameterData; }
|
|
FPropertyData& GetParameterData() { return ParameterData; }
|
|
FTokenData* GetReturnTokenData() { return &ReturnTypeData; }
|
|
//@}
|
|
|
|
void UpdateFunctionData(FFuncInfo& UpdatedFuncData)
|
|
{
|
|
//@TODO: UCREMOVAL: Some more thorough evaluation should be done here
|
|
FunctionData.FunctionFlags |= UpdatedFuncData.FunctionFlags;
|
|
FunctionData.FunctionExportFlags |= UpdatedFuncData.FunctionExportFlags;
|
|
}
|
|
|
|
/**
|
|
* Adds a new function property to be tracked. Determines whether the property is a
|
|
* function parameter, local property, or return value, and adds it to the appropriate
|
|
* list
|
|
*
|
|
* @param PropertyToken the property to add
|
|
*/
|
|
void AddProperty(const FToken& PropertyToken, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
|
|
{
|
|
const UProperty* Prop = PropertyToken.TokenProperty;
|
|
check(Prop);
|
|
check( (Prop->PropertyFlags&CPF_Parm) != 0 );
|
|
|
|
if ( (Prop->PropertyFlags&CPF_ReturnParm) != 0 )
|
|
{
|
|
SetReturnData(PropertyToken);
|
|
}
|
|
else
|
|
{
|
|
AddParameter(PropertyToken, UHTMakefile, UnrealSourceFile);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* (debug) Dumps the values of this FFunctionData to the log file
|
|
*
|
|
* @param Indent number of spaces to insert at the beginning of each line
|
|
*/
|
|
void Dump( int32 Indent )
|
|
{
|
|
UE_LOG(LogCompile, Log, TEXT("%sparameters:"), FCString::Spc(Indent));
|
|
ParameterData.Dump(Indent + 4);
|
|
|
|
UE_LOG(LogCompile, Log, TEXT("%sreturn prop:"), FCString::Spc(Indent));
|
|
if ( ReturnTypeData.Token.Type != CPT_None )
|
|
{
|
|
UE_LOG(LogCompile, Log, TEXT("%s%s"), FCString::Spc(Indent + 4), *ReturnTypeData.Token.Describe());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Sets the specified function export flags
|
|
*/
|
|
void SetFunctionExportFlag( uint32 NewFlags )
|
|
{
|
|
FunctionData.FunctionExportFlags |= NewFlags;
|
|
}
|
|
|
|
/**
|
|
* Clears the specified function export flags
|
|
*/
|
|
void ClearFunctionExportFlags( uint32 ClearFlags )
|
|
{
|
|
FunctionData.FunctionExportFlags &= ~ClearFlags;
|
|
}
|
|
|
|
/**
|
|
* Finds function data for given function object.
|
|
*/
|
|
static FFunctionData* FindForFunction(UFunction* Function);
|
|
|
|
/**
|
|
* Adds function data object for given function object.
|
|
*/
|
|
static FFunctionData* Add(UFunction* Function);
|
|
|
|
/**
|
|
* Adds function data object for given function object.
|
|
*/
|
|
static FFunctionData* Add(const FFuncInfo& FunctionInfo);
|
|
|
|
/**
|
|
* Tries to find function data for given function object.
|
|
*/
|
|
static bool TryFindForFunction(UFunction* Function, FFunctionData*& OutData);
|
|
|
|
private:
|
|
static TMap<UFunction*, TUniqueObj<FFunctionData> > FunctionDataMap;
|
|
};
|
|
|
|
/**
|
|
* Tracks information about a multiple inheritance parent declaration for native script classes.
|
|
*/
|
|
struct FMultipleInheritanceBaseClass
|
|
{
|
|
/**
|
|
* The name to use for the base class when exporting the script class to header file.
|
|
*/
|
|
FString ClassName;
|
|
|
|
/**
|
|
* For multiple inheritance parents declared using 'Implements', corresponds to the UClass for the interface. For multiple inheritance parents declared
|
|
* using 'Inherits', this value will be NULL.
|
|
*/
|
|
UClass* InterfaceClass;
|
|
|
|
/**
|
|
* Constructors
|
|
*/
|
|
FMultipleInheritanceBaseClass(const FString& BaseClassName)
|
|
: ClassName(BaseClassName), InterfaceClass(NULL)
|
|
{}
|
|
|
|
FMultipleInheritanceBaseClass(UClass* ImplementedInterfaceClass)
|
|
: InterfaceClass(ImplementedInterfaceClass)
|
|
{
|
|
ClassName = FString::Printf(TEXT("I%s"), *ImplementedInterfaceClass->GetName());
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Class for storing compiler metadata about a class's properties.
|
|
*/
|
|
class FClassMetaData
|
|
{
|
|
/** member properties for this class */
|
|
FPropertyData GlobalPropertyData;
|
|
|
|
/** base classes to multiply inherit from (other than the main base class */
|
|
TArray<FMultipleInheritanceBaseClass*> MultipleInheritanceParents;
|
|
|
|
/** whether this class declares delegate functions or properties */
|
|
bool bContainsDelegates;
|
|
|
|
/** The line of UCLASS/UINTERFACE macro in this class. */
|
|
int32 PrologLine;
|
|
|
|
/** The line of GENERATED_BODY/GENERATED_UCLASS_BODY macro in this class. */
|
|
int32 GeneratedBodyLine;
|
|
|
|
/** Same as above, but for interface class associated with this class. */
|
|
int32 InterfaceGeneratedBodyLine;
|
|
|
|
public:
|
|
/** Default constructor */
|
|
FClassMetaData()
|
|
: bContainsDelegates(false)
|
|
, PrologLine(-1)
|
|
, GeneratedBodyLine(-1)
|
|
, InterfaceGeneratedBodyLine(-1)
|
|
, bConstructorDeclared(false)
|
|
, bDefaultConstructorDeclared(false)
|
|
, bObjectInitializerConstructorDeclared(false)
|
|
#if WITH_HOT_RELOAD_CTORS
|
|
, bCustomVTableHelperConstructorDeclared(false)
|
|
#endif // WITH_HOT_RELOAD_CTORS
|
|
, GeneratedBodyMacroAccessSpecifier(ACCESS_NotAnAccessSpecifier)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Gets prolog line number for this class.
|
|
*/
|
|
int32 GetPrologLine() const
|
|
{
|
|
check(PrologLine > 0);
|
|
return PrologLine;
|
|
}
|
|
|
|
/**
|
|
* Gets generated body line number for this class.
|
|
*/
|
|
int32 GetGeneratedBodyLine() const
|
|
{
|
|
check(GeneratedBodyLine > 0);
|
|
return GeneratedBodyLine;
|
|
}
|
|
|
|
/**
|
|
* Gets interface generated body line number for this class.
|
|
*/
|
|
int32 GetInterfaceGeneratedBodyLine() const
|
|
{
|
|
check(InterfaceGeneratedBodyLine > 0);
|
|
return InterfaceGeneratedBodyLine;
|
|
}
|
|
|
|
/**
|
|
* Sets prolog line number for this class.
|
|
*/
|
|
void SetPrologLine(int32 Line)
|
|
{
|
|
check(Line > 0);
|
|
PrologLine = Line;
|
|
}
|
|
|
|
/**
|
|
* Sets generated body line number for this class.
|
|
*/
|
|
void SetGeneratedBodyLine(int32 Line)
|
|
{
|
|
check(Line > 0);
|
|
GeneratedBodyLine = Line;
|
|
}
|
|
|
|
/**
|
|
* Sets interface generated body line number for this class.
|
|
*/
|
|
void SetInterfaceGeneratedBodyLine(int32 Line)
|
|
{
|
|
check(Line > 0);
|
|
InterfaceGeneratedBodyLine = Line;
|
|
}
|
|
|
|
/**
|
|
* Sets contains delegates flag for this class.
|
|
*/
|
|
void MarkContainsDelegate()
|
|
{
|
|
bContainsDelegates = true;
|
|
}
|
|
|
|
/**
|
|
* Adds a new property to be tracked. Determines the correct list for the property based on
|
|
* its owner (function, struct, etc).
|
|
*
|
|
* @param PropertyToken the property to add
|
|
*/
|
|
void AddProperty(const FToken& PropertyToken, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile)
|
|
{
|
|
UProperty* Prop = PropertyToken.TokenProperty;
|
|
check(Prop);
|
|
|
|
UObject* Outer = Prop->GetOuter();
|
|
UStruct* OuterClass = Cast<UStruct>(Outer);
|
|
if ( OuterClass != NULL )
|
|
{
|
|
// global property
|
|
GlobalPropertyData.Set(Prop, PropertyToken, UHTMakefile, UnrealSourceFile);
|
|
}
|
|
else
|
|
{
|
|
checkNoEntry();
|
|
UFunction* OuterFunction = Cast<UFunction>(Outer);
|
|
if ( OuterFunction != NULL )
|
|
{
|
|
// function parameter, return, or local property
|
|
FFunctionData::FindForFunction(OuterFunction)->AddProperty(PropertyToken, UHTMakefile, UnrealSourceFile);
|
|
}
|
|
}
|
|
|
|
// update the optimization flags
|
|
if ( !bContainsDelegates )
|
|
{
|
|
if( Prop->IsA( UDelegateProperty::StaticClass() ) || Prop->IsA( UMulticastDelegateProperty::StaticClass() ) )
|
|
{
|
|
bContainsDelegates = true;
|
|
}
|
|
else
|
|
{
|
|
UArrayProperty* ArrayProp = Cast<UArrayProperty>(Prop);
|
|
if ( ArrayProp != NULL )
|
|
{
|
|
if( ArrayProp->Inner->IsA( UDelegateProperty::StaticClass() ) || ArrayProp->Inner->IsA( UMulticastDelegateProperty::StaticClass() ) )
|
|
{
|
|
bContainsDelegates = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds new editor-only metadata (key/value pairs) to the class or struct that
|
|
* owns this property or function.
|
|
*
|
|
* @param Field the property or function to add to
|
|
* @param InMetaData the metadata to add
|
|
*/
|
|
static void AddMetaData(UField* Field, const TMap<FName, FString>& InMetaData)
|
|
{
|
|
// only add if we have some!
|
|
if (InMetaData.Num())
|
|
{
|
|
check(Field);
|
|
|
|
// get (or create) a metadata object for this package
|
|
UMetaData* MetaData = Field->GetOutermost()->GetMetaData();
|
|
|
|
// set the metadata for this field
|
|
MetaData->SetObjectValues(Field, InMetaData);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Finds the metadata for the function specified
|
|
*
|
|
* @param Func the function to search for
|
|
*
|
|
* @return pointer to the metadata for the function specified, or NULL
|
|
* if the function doesn't exist in the list (for example, if it
|
|
* is declared in a package that is already compiled and has had its
|
|
* source stripped)
|
|
*/
|
|
FFunctionData* FindFunctionData( UFunction* Func );
|
|
|
|
/**
|
|
* Finds the metadata for the property specified
|
|
*
|
|
* @param Prop the property to search for
|
|
*
|
|
* @return pointer to the metadata for the property specified, or NULL
|
|
* if the property doesn't exist in the list (for example, if it
|
|
* is declared in a package that is already compiled and has had its
|
|
* source stripped)
|
|
*/
|
|
FTokenData* FindTokenData( UProperty* Prop );
|
|
|
|
/**
|
|
* (debug) Dumps the values of this FFunctionData to the log file
|
|
*
|
|
* @param Indent number of spaces to insert at the beginning of each line
|
|
*/
|
|
void Dump( int32 Indent );
|
|
|
|
/**
|
|
* Add a string to the list of inheritance parents for this class.
|
|
*
|
|
* @param Inparent The C++ class name to add to the multiple inheritance list
|
|
* @param UHTMakefile Makefile to save parsing data to.
|
|
* @param UnrealSourceFile Currently parsed source file.
|
|
*/
|
|
void AddInheritanceParent(const FString& InParent, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile);
|
|
|
|
/**
|
|
* Add a string to the list of inheritance parents for this class.
|
|
*
|
|
* @param Inparent The C++ class name to add to the multiple inheritance list
|
|
* @param UHTMakefile Makefile to save parsing data to.
|
|
* @param UnrealSourceFile Currently parsed source file.
|
|
*/
|
|
void AddInheritanceParent(UClass* ImplementedInterfaceClass, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile);
|
|
|
|
/**
|
|
* Return the list of inheritance parents
|
|
*/
|
|
const TArray<FMultipleInheritanceBaseClass*>& GetInheritanceParents() const
|
|
{
|
|
return MultipleInheritanceParents;
|
|
}
|
|
|
|
/**
|
|
* Returns whether this class contains any delegate properties which need to be fixed up.
|
|
*/
|
|
bool ContainsDelegates() const
|
|
{
|
|
return bContainsDelegates;
|
|
}
|
|
|
|
/**
|
|
* Shrink TMaps to avoid slack in Pairs array.
|
|
*/
|
|
void Shrink()
|
|
{
|
|
GlobalPropertyData.Shrink();
|
|
MultipleInheritanceParents.Shrink();
|
|
}
|
|
|
|
// Is constructor declared?
|
|
bool bConstructorDeclared;
|
|
|
|
// Is default constructor declared?
|
|
bool bDefaultConstructorDeclared;
|
|
|
|
// Is ObjectInitializer constructor (i.e. a constructor with only one parameter of type FObjectInitializer) declared?
|
|
bool bObjectInitializerConstructorDeclared;
|
|
|
|
#if WITH_HOT_RELOAD_CTORS
|
|
// Is custom VTable helper constructor declared?
|
|
bool bCustomVTableHelperConstructorDeclared;
|
|
#endif // WITH_HOT_RELOAD_CTORS
|
|
|
|
// GENERATED_BODY access specifier to preserve.
|
|
EAccessSpecifier GeneratedBodyMacroAccessSpecifier;
|
|
|
|
friend struct FClassMetaDataArchiveProxy;
|
|
};
|
|
|
|
/**
|
|
* Class for storing and linking data about properties and functions that is only required by the compiler.
|
|
* The type of data tracked by this class is data that would otherwise only be accessible by adding a
|
|
* member property to UFunction/UProperty.
|
|
*/
|
|
class FCompilerMetadataManager : protected TMap<UStruct*, TScopedPointer<FClassMetaData> >
|
|
{
|
|
public:
|
|
/**
|
|
* Adds a new class to be tracked
|
|
*
|
|
* @param Struct the UStruct to add
|
|
*
|
|
* @return a pointer to the newly added metadata for the class specified
|
|
*/
|
|
FClassMetaData* AddClassData(UStruct* Struct, FUHTMakefile& UHTMakefile, FUnrealSourceFile* UnrealSourceFile);
|
|
|
|
/**
|
|
* Find the metadata associated with the class specified
|
|
*
|
|
* @param Struct the UStruct to add
|
|
*
|
|
* @return a pointer to the newly added metadata for the class specified
|
|
*/
|
|
FClassMetaData* FindClassData(UStruct* Struct)
|
|
{
|
|
FClassMetaData* Result = NULL;
|
|
|
|
TScopedPointer<FClassMetaData>* pClassData = Find(Struct);
|
|
if (pClassData)
|
|
{
|
|
Result = pClassData->GetOwnedPointer();
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
/**
|
|
* Shrink TMaps to avoid slack in Pairs array.
|
|
*/
|
|
void Shrink()
|
|
{
|
|
TMap<UStruct*, TScopedPointer<FClassMetaData> >::Shrink();
|
|
for (TMap<UStruct*, TScopedPointer<FClassMetaData> >::TIterator It(*this); It; ++It)
|
|
{
|
|
FClassMetaData* MetaData = It.Value();
|
|
MetaData->Shrink();
|
|
}
|
|
}
|
|
|
|
friend struct FCompilerMetadataManagerArchiveProxy;
|
|
};
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
Retry points.
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* A point in the header parsing state that can be set and returned to
|
|
* using InitScriptLocation() and ReturnToLocation(). This is used in cases such as testing
|
|
* to see which overridden operator should be used, where code must be compiled
|
|
* and then "undone" if it was found not to match.
|
|
* <p>
|
|
* Retries are not allowed to cross command boundaries (and thus nesting
|
|
* boundaries). Retries can occur across a single command or expressions and
|
|
* subexpressions within a command.
|
|
*/
|
|
struct FScriptLocation
|
|
{
|
|
static class FHeaderParser* Compiler;
|
|
|
|
/** the text buffer for the class associated with this retry point */
|
|
const TCHAR* Input;
|
|
|
|
/** the position into the Input buffer where this retry point is located */
|
|
int32 InputPos;
|
|
|
|
/** the LineNumber of the compiler when this retry point was created */
|
|
int32 InputLine;
|
|
|
|
/** Constructor */
|
|
FScriptLocation();
|
|
};
|
|
|
|
/////////////////////////////////////////////////////
|
|
// FNameLookupCPP
|
|
|
|
/**
|
|
* Helper class used to cache UClass* -> TCHAR* name lookup for finding the named used for C++ declaration.
|
|
*/
|
|
struct FNameLookupCPP
|
|
{
|
|
/**
|
|
* Destructor, cleaning up allocated memory.
|
|
*/
|
|
~FNameLookupCPP()
|
|
{
|
|
for (TMap<UStruct*,TCHAR*>::TIterator It(StructNameMap); It; ++It)
|
|
{
|
|
TCHAR* Name = It.Value();
|
|
delete [] Name;
|
|
}
|
|
|
|
for (TArray<TCHAR*>::TIterator It(InterfaceAllocations); It; ++It)
|
|
{
|
|
TCHAR* Name = *It;
|
|
delete [] Name;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the name used for declaring the passed in struct in C++
|
|
*
|
|
* @param Struct UStruct to obtain C++ name for
|
|
* @return Name used for C++ declaration
|
|
*/
|
|
const TCHAR* GetNameCPP( UStruct* Struct, bool bForceInterface = false );
|
|
|
|
void SetUHTMakefile(FUHTMakefile* InUHTMakefile)
|
|
{
|
|
UHTMakefile = InUHTMakefile;
|
|
}
|
|
void SetCurrentSourceFile(FUnrealSourceFile* InUnrealSourceFile)
|
|
{
|
|
UnrealSourceFile = InUnrealSourceFile;
|
|
}
|
|
private:
|
|
/** Map of UStruct pointers to C++ names */
|
|
TMap<UStruct*,TCHAR*> StructNameMap;
|
|
TArray<TCHAR*> InterfaceAllocations;
|
|
|
|
friend class FUHTMakefile;
|
|
FUHTMakefile* UHTMakefile;
|
|
FUnrealSourceFile* UnrealSourceFile;
|
|
};
|
|
|
|
extern FNameLookupCPP NameLookupCPP;
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
// FAdvancedDisplayParameterHandler - used by FHeaderParser::ParseParameterList, to check if a property if a function parameter has 'AdvancedDisplay' flag
|
|
|
|
/**
|
|
* AdvancedDisplay can be used in two ways:
|
|
* 1. 'AdvancedDisplay = "3"' - the number tells how many parameters (from beginning) should NOT BE marked
|
|
* 2. 'AdvancedDisplay = "AttachPointName, Location, LocationType"' - list the parameters, that should BE marked
|
|
*/
|
|
class FAdvancedDisplayParameterHandler
|
|
{
|
|
TArray<FString> ParametersNames;
|
|
|
|
int32 NumberLeaveUnmarked;
|
|
int32 AlreadyLeft;
|
|
|
|
bool bUseNumber;
|
|
public:
|
|
FAdvancedDisplayParameterHandler(const TMap<FName, FString>* MetaData);
|
|
|
|
/**
|
|
* return if given parameter should be marked as Advance View,
|
|
* the function should be called only once for any parameter
|
|
*/
|
|
bool ShouldMarkParameter(const FString& ParameterName);
|
|
|
|
/** return if more parameters can be marked */
|
|
bool CanMarkMore() const;
|
|
};
|