// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "EdGraph/EdGraphPin.h" #include "IDetailPropertyExtensionHandler.h" #include "PropertyBindingBindingCollection.h" #include "PropertyBindingBindingCollectionOwner.h" #include "PropertyBindingPath.h" #include "UObject/WeakInterfacePtr.h" class FMenuBuilder; class IDetailLayoutBuilder; class IPropertyAccessEditor; class IPropertyBindingBindingCollectionOwner; class IPropertyHandle; struct FBindingChainElement; struct FBindingContextStruct; struct FPropertyBindingBindableStructDescriptor; struct FPropertyBindingDataView; struct FPropertyBindingPath; struct FPropertyBindingBinding; namespace UE::PropertyBinding { struct FPropertyInfoOverride { /** Display Name Text of the Ref Type */ FText TypeNameText; /** Ref Type expressed as a Pin Type */ FEdGraphPinType PinType; }; namespace Meta::Private { // valid keywords for the UCLASS, UPROPERTY and USTRUCT macro enum { // [ClassMetadata] [PropertyMetadata] [StructMetadata] The property cannot be bound to (target of a binding). NoBinding, // [ClassMetadata] [PropertyMetadata] [StructMetadata] The property cannot be promoted to parameters. NoPromoteToParameter, }; } // namespace Meta::Private const FLazyName MetaDataStructIDName("StructIDForPropertyBinding"); const FLazyName MetaDataNoBindingName("NoBinding"); const FLazyName MetaDataNoPromoteToParameter("NoPromoteToParameter"); PROPERTYBINDINGUTILSEDITOR_API extern FText GetPropertyTypeText(const FProperty* Property); /** * Returns property path for a specific property. * Walks towards root up until a property with metadata "MetaDataName" is found. * The property's metadata "MetaDataName" is expected to specify the containing struct ID. * @param InPropertyHandle Handle to the property to find path for. * @param OutPath Resulting property path. * @param InFallbackStructID If no bindable struct are found this ID will be used to build the property path. * @return property handle of the property found with the required metadata. */ PROPERTYBINDINGUTILSEDITOR_API extern TSharedPtr MakeStructPropertyPathFromPropertyHandle( const TSharedPtr& InPropertyHandle , FPropertyBindingPath& OutPath , FGuid InFallbackStructID = {} ); /** * Returns true if provided Property is bindable. */ PROPERTYBINDINGUTILSEDITOR_API bool IsPropertyBindable(const FProperty& Property); struct FCachedBindingData { PROPERTYBINDINGUTILSEDITOR_API FCachedBindingData(IPropertyBindingBindingCollectionOwner* InPropertyBindingsOwner , const FPropertyBindingPath& InTargetPath , const TSharedPtr& InPropertyHandle , const TConstArrayView> InAccessibleStructs ); virtual ~FCachedBindingData() = default; [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API bool HasBinding(FPropertyBindingBindingCollection::ESearchMode SearchMode) const; PROPERTYBINDINGUTILSEDITOR_API void AddBinding(TConstArrayView InBindingChain); PROPERTYBINDINGUTILSEDITOR_API void RemoveBinding(FPropertyBindingBindingCollection::ESearchMode RemoveMode); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API UStruct* ResolveIndirection(TConstArrayView InBindingChain); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API bool CanAcceptPropertyOrChildren(const FProperty* SourceProperty, TConstArrayView InBindingChain); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API bool CanBindToProperty(const FProperty* SourceProperty, TConstArrayView InBindingChain); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API bool CanBindToContextStruct(const UStruct* InStruct, int32 InStructIndex); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API bool CanCreateParameter(const FPropertyBindingBindableStructDescriptor& InStructDesc, TArray>& OutPropertyInfoOverrides) const; PROPERTYBINDINGUTILSEDITOR_API void PromoteToParameter(FName InPropertyName, TConstStructView InStructDesc, TSharedPtr InPropertyInfoOverride); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API FText GetText(); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API FText GetTooltipText(); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API FLinearColor GetColor(); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API const FSlateBrush* GetImage(); protected: [[nodiscard]] TConstStructView GetBindableStructDescriptor(int32 InStructIndex) const; [[nodiscard]] TStructView GetMutableBindableStructDescriptor(int32 InStructIndex); [[nodiscard]] TWeakObjectPtr<> GetWeakOwner() const; [[nodiscard]] UObject* GetOwner() const; [[nodiscard]] const IPropertyHandle* GetPropertyHandle() const; [[nodiscard]] const FPropertyBindingPath& GetSourcePath() const; [[nodiscard]] const FPropertyBindingPath& GetTargetPath() const; [[nodiscard]] TConstArrayView> GetAccessibleStructs() const; [[nodiscard]] FText GetFormatableText() const; [[nodiscard]] FText GetFormatableTooltipText() const; [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool IsPropertyReference(const FProperty& InProperty); PROPERTYBINDINGUTILSEDITOR_API virtual void UpdateSourcePropertyPath(TConstStructView InDescriptor, const FPropertyBindingPath& InSourcePath, FString& OutString); PROPERTYBINDINGUTILSEDITOR_API virtual void UpdatePropertyReferenceTooltip(const FProperty& InProperty, FTextBuilder& InOutTextBuilder) const; [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool CanBindToContextStructInternal(const UStruct* InStruct, int32 InStructIndex); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool CanAcceptPropertyOrChildrenInternal(const FProperty& InProperty, TConstArrayView InBindingChain); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool AddBindingInternal(TConstStructView InDescriptor, FPropertyBindingPath& InOutSourcePath, const FPropertyBindingPath& InTargetPath); PROPERTYBINDINGUTILSEDITOR_API virtual void AddPropertyInfoOverride(const FProperty& InProperty, TArray>& OutPropertyInfoOverrides) const; PROPERTYBINDINGUTILSEDITOR_API virtual void GetSourceDataViewForNewBinding(TNotNull InBindingsOwner,TConstStructView InDescriptor, FPropertyBindingDataView& OutSourceDataView); [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool GetPinTypeAndIconForProperty(const FProperty& InProperty, FPropertyBindingDataView InTargetDataView, FEdGraphPinType& OutPinType, FName& OutIconName) const; [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool GetPropertyFunctionText(FConstStructView InPropertyFunctionStructView, FText& OutText) const; [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool GetPropertyFunctionTooltipText(FConstStructView InPropertyFunctionStructView, FText& OutText) const; [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool GetPropertyFunctionIconColor(FConstStructView InPropertyFunctionStructView, FLinearColor& OutColor) const; [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool GetPropertyFunctionImage(FConstStructView InPropertyFunctionStructView, const FSlateBrush*& OutImage) const; /** @return whether the compatibility has been evaluated. */ [[nodiscard]] PROPERTYBINDINGUTILSEDITOR_API virtual bool DeterminePropertiesCompatibilityInternal( const FProperty* InSourceProperty, const FProperty* InTargetProperty, const void* InSourcePropertyValue, const void* InTargetPropertyValue, bool& bOutAreCompatible) const; private: PROPERTYBINDINGUTILSEDITOR_API void ConditionallyUpdateData(); PROPERTYBINDINGUTILSEDITOR_API void UpdateData(); PROPERTYBINDINGUTILSEDITOR_API bool ArePropertyAndContextStructCompatible(const UStruct* SourceStruct, const FProperty* TargetProperty) const; PROPERTYBINDINGUTILSEDITOR_API bool ArePropertiesCompatible(const FProperty* SourceProperty, const FProperty* TargetProperty, const void* SourcePropertyValue, const void* TargetPropertyValue) const; TWeakInterfacePtr WeakBindingsOwner = nullptr; FPropertyBindingPath CachedSourcePath; FPropertyBindingPath TargetPath; TSharedPtr PropertyHandle; TArray> AccessibleStructs; /* Default name of the source struct. */ FText SourceStructName; /* Binding's display name text. Expects it's source struct name to be injected before use. */ FText FormatableText; /* Binding's tooltip text. Expects it's source struct name to be injected before use. */ FText FormatableTooltipText; FLinearColor Color = FLinearColor::White; const FSlateBrush* Image = nullptr; /** The binding is invalid. The image/color/tooltip/... represents an error state. */ bool bIsCachedDataValid = false; bool bIsDataCached = false; }; inline TConstStructView FCachedBindingData::GetBindableStructDescriptor(const int32 InStructIndex) const { check(InStructIndex >= 0 && InStructIndex < AccessibleStructs.Num()); return AccessibleStructs[InStructIndex]; } inline TStructView FCachedBindingData::GetMutableBindableStructDescriptor(const int32 InStructIndex) { check(InStructIndex >= 0 && InStructIndex < AccessibleStructs.Num()); return AccessibleStructs[InStructIndex]; } inline TWeakObjectPtr<> FCachedBindingData::GetWeakOwner() const { return WeakBindingsOwner.GetWeakObjectPtr(); } inline UObject* FCachedBindingData::GetOwner() const { return WeakBindingsOwner.GetObject(); } inline const IPropertyHandle* FCachedBindingData::GetPropertyHandle() const { return PropertyHandle.Get(); } inline const FPropertyBindingPath& FCachedBindingData::GetSourcePath() const { return CachedSourcePath; } inline const FPropertyBindingPath& FCachedBindingData::GetTargetPath() const { return TargetPath; } inline TConstArrayView> FCachedBindingData::GetAccessibleStructs() const { return AccessibleStructs; } inline FText FCachedBindingData::GetFormatableText() const { return FormatableText; } inline FText FCachedBindingData::GetFormatableTooltipText() const { return FormatableTooltipText; } } // UE::PropertyBinding class FPropertyBindingExtension : public IDetailPropertyExtensionHandler { public: //~ Begin IDetailPropertyExtensionHandler PROPERTYBINDINGUTILSEDITOR_API virtual bool IsPropertyExtendable(const UClass* InObjectClass, const IPropertyHandle& InPropertyHandle) const override; PROPERTYBINDINGUTILSEDITOR_API virtual void ExtendWidgetRow(FDetailWidgetRow& InWidgetRow, const IDetailLayoutBuilder& InDetailBuilder, const UClass* InObjectClass, TSharedPtr InPropertyHandle) override; //~ End IDetailPropertyExtensionHandler protected: PROPERTYBINDINGUTILSEDITOR_API virtual TSharedPtr CreateCachedBindingData(IPropertyBindingBindingCollectionOwner* InBindingsOwner, const FPropertyBindingPath& InTargetPath, const TSharedPtr& InPropertyHandle, TConstArrayView> InAccessibleStructs) const; PROPERTYBINDINGUTILSEDITOR_API virtual bool CanBindToProperty(const FPropertyBindingPath& InTargetPath, const IPropertyHandle& InPropertyHandle) const; PROPERTYBINDINGUTILSEDITOR_API virtual bool GetPromotionToParameterOverrideInternal(const FProperty& InProperty, bool& bOutOverride) const; PROPERTYBINDINGUTILSEDITOR_API virtual void UpdateContextStruct(TConstStructView InStructDesc, FBindingContextStruct& InOutContextStruct, TMap& InOutSectionNames) const; virtual bool CanBindToArrayElements() const { return false; } PROPERTYBINDINGUTILSEDITOR_API static TSharedRef MakeContextStructWidget(const FPropertyBindingBindableStructDescriptor& InContextStruct); private: bool CanPromoteToParameter(const TSharedPtr& InPropertyHandle) const; };