// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Containers/Array.h" #include "CoreMinimal.h" #include "Customizations/MathStructCustomizations.h" #include "Delegates/Delegate.h" #include "IPropertyTypeCustomization.h" #include "Internationalization/Text.h" #include "Math/Color.h" #include "Math/Rotator.h" #include "Math/Vector.h" #include "Misc/Optional.h" #include "PropertyHandle.h" #include "Styling/CoreStyle.h" #include "Styling/ISlateStyle.h" #include "Templates/SharedPointer.h" #include "Types/SlateEnums.h" #include "Widgets/SWidget.h" class FDetailWidgetRow; class IPropertyHandle; class IPropertyTypeCustomization; class IPropertyTypeCustomizationUtils; class IPropertyUtilities; class SWidget; /** * Helper class used to track the dirty state of a proxy value */ template< typename ObjectType > class TProxyValue { public: TProxyValue() : Value() , bIsSet(false) { } TProxyValue(const ObjectType& InValue) : Value(InValue) , bIsSet(false) { } /** * Set the wrapped value * @param InValue The value to set. */ void Set(const ObjectType& InValue) { Value = InValue; bIsSet = true; } /** * Get the wrapped value * @return the wrapped value */ const ObjectType& Get() const { return Value; } /** * Get the wrapped value * @return the wrapped value */ ObjectType& Get() { return Value; } /** * Check to see if the value is set. * @return whether the value is set. */ bool IsSet() const { return bIsSet; } /** * Mark the value as if it was set. */ void MarkAsSet() { bIsSet = true; } private: /** The value we are tracking */ ObjectType Value; /** Whether the value is set */ bool bIsSet; }; /** * Helper class used to track the state of properties of proxy values. */ template< typename ObjectType, typename PropertyType > class TProxyProperty { public: TProxyProperty(const TSharedRef< TProxyValue >& InValue, PropertyType& InPropertyValue) : Value(InValue) , Property(InPropertyValue) , bIsSet(false) { } /** * Set the value of this property * @param InPropertyValue The value of the property to set */ void Set(const PropertyType& InPropertyValue) { Property = InPropertyValue; Value->MarkAsSet(); bIsSet = true; } /** * Get the value of this property * @return The value of the property */ const PropertyType& Get() const { return Property; } /** * Check to see if the value is set. * @return whether the value is set. */ bool IsSet() const { return bIsSet; } private: /** The proxy value we are tracking */ TSharedRef< TProxyValue > Value; /** The property of the value we are tracking */ PropertyType& Property; /** Whether the value is set */ bool bIsSet; }; /** * Helper class to aid representing math structs to the user in an editable form * e.g. representing a quaternion as a set of euler angles */ class DETAILCUSTOMIZATIONS_API FMathStructProxyCustomization : public FMathStructCustomization { public: /** IPropertyTypeCustomization interface */ virtual void CustomizeChildren( TSharedRef StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils ) override; /** FMathStructCustomization interface */ virtual void MakeHeaderRow( TSharedRef& InStructPropertyHandle, FDetailWidgetRow& Row ) override; protected: /** * Cache the values from the property to the proxy. * @param WeakHandlePtr The property handle to get values from. * @return true if values(s) were successfully cached */ virtual bool CacheValues( TWeakPtr WeakHandlePtr ) const = 0; /** * Flush the values from the proxy to the property. * @param WeakHandlePtr The property handle to set values to. * @return true if values(s) were successfully flushed */ virtual bool FlushValues( TWeakPtr WeakHandlePtr ) const = 0; /** * Helper function to make a numeric property widget to edit a proxy value. * @param StructPropertyHandle Property handle to the containing struct * @param ProxyValue The value we will be editing in the proxy data. * @param Label A label to use for this value. * @param bRotationInDegrees Whether this is to be used for a rotation value (configures sliders appropriately). * @return the newly created widget. */ template TSharedRef MakeNumericProxyWidget(TSharedRef& StructPropertyHandle, TSharedRef< TProxyProperty >& ProxyValue, const FText& Label, bool bRotationInDegrees = false, const FLinearColor& LabelColor = FCoreStyle::Get().GetColor("DefaultForeground")); template UE_DEPRECATED(5.6, "OnGetValueToolTip is deprecated and no longer called. Please use the Label in MakeNumericProxyWidget to customize the display name portion of the ToolTip.") FText OnGetValueToolTip(TWeakPtr WeakHandlePtr, TSharedRef> ProxyValue, FText Label) const; TOptional OnGetValueToolTipTextFormat(FText Label) const; private: /** * Gets the value as a float for the provided property handle * * @param WeakHandlePtr Handle to the property to get the value from * @param ProxyValue Proxy value to get value from. * @return The value or unset if it could not be accessed */ template TOptional OnGetValue( TWeakPtr WeakHandlePtr, TSharedRef< TProxyProperty > ProxyValue ) const; /** * Called when the value is committed from the property editor * * @param NewValue The new value of the property as a float * @param CommitType How the value was committed (unused) * @param WeakHandlePtr Handle to the property that the new value is for */ template void OnValueCommitted( NumericType NewValue, ETextCommit::Type CommitType, TWeakPtr WeakHandlePtr, TSharedRef< TProxyProperty > ProxyValue ); /** * Called when the value is changed in the property editor * * @param NewValue The new value of the property as a float * @param WeakHandlePtr Handle to the property that the new value is for */ template void OnValueChanged( NumericType NewValue, TWeakPtr WeakHandlePtr, TSharedRef< TProxyProperty > ProxyValue ); /** Called when a value starts to be changed by a slider */ void OnBeginSliderMovement(); /** Called when a value stops being changed by a slider */ template void OnEndSliderMovement( NumericType NewValue, TWeakPtr WeakHandlePtr, TSharedRef< TProxyProperty > ProxyValue ); protected: /** Cached property utilities */ TSharedPtr PropertyUtilities; }; struct FTransformField { enum Type { Location, Rotation, Scale }; }; /** * Proxy struct customization that displays a matrix as a position, rotation & scale. */ template class DETAILCUSTOMIZATIONS_API FMatrixStructCustomization : public FMathStructProxyCustomization { public: static TSharedRef MakeInstance(); public: FMatrixStructCustomization() : CachedRotation(MakeShareable( new TProxyValue>(UE::Math::TRotator::ZeroRotator))) , CachedRotationYaw(MakeShareable( new TProxyProperty, T>(CachedRotation, CachedRotation->Get().Yaw))) , CachedRotationPitch(MakeShareable( new TProxyProperty, T>(CachedRotation, CachedRotation->Get().Pitch))) , CachedRotationRoll(MakeShareable( new TProxyProperty, T>(CachedRotation, CachedRotation->Get().Roll))) , CachedTranslation(MakeShareable( new TProxyValue>(UE::Math::TVector::ZeroVector))) , CachedTranslationX(MakeShareable( new TProxyProperty, T>(CachedTranslation, CachedTranslation->Get().X))) , CachedTranslationY(MakeShareable( new TProxyProperty, T>(CachedTranslation, CachedTranslation->Get().Y))) , CachedTranslationZ(MakeShareable( new TProxyProperty, T>(CachedTranslation, CachedTranslation->Get().Z))) , CachedScale(MakeShareable( new TProxyValue>(UE::Math::TVector::ZeroVector))) , CachedScaleX(MakeShareable( new TProxyProperty, T>(CachedScale, CachedScale->Get().X))) , CachedScaleY(MakeShareable( new TProxyProperty, T>(CachedScale, CachedScale->Get().Y))) , CachedScaleZ(MakeShareable( new TProxyProperty, T>(CachedScale, CachedScale->Get().Z))) , bUseLeftUpForwardAxisDisplayCoordinateSystem( false ) { } /** IPropertyTypeCustomization interface */ virtual void CustomizeChildren(TSharedRef StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; protected: /** Customization utility functions */ void CustomizeLocation(TSharedRef StructPropertyHandle, FDetailWidgetRow& Row); void CustomizeRotation(TSharedRef StructPropertyHandle, FDetailWidgetRow& Row); void CustomizeScale(TSharedRef StructPropertyHandle, FDetailWidgetRow& Row); /** FMathStructCustomization interface */ virtual void MakeHeaderRow(TSharedRef& InStructPropertyHandle, FDetailWidgetRow& Row) override; /** FMathStructProxyCustomization interface */ virtual bool CacheValues(TWeakPtr PropertyHandlePtr) const override; virtual bool FlushValues(TWeakPtr PropertyHandlePtr) const override; virtual FIntVector4 GetSwizzle() const; void OnCopy(FTransformField::Type Type, TWeakPtr PropertyHandlePtr); void OnPaste(FTransformField::Type Type, TWeakPtr PropertyHandlePtr); void PasteFromText( const FString& InTag, const FString& InText, FTransformField::Type Type, TWeakPtr PropertyHandlePtr); void OnPasteFromText( const FString& InTag, const FString& InText, const TOptional& InOperationId, FTransformField::Type Type, TWeakPtr PropertyHandlePtr); protected: /** Cached rotation values */ mutable TSharedRef< TProxyValue> > CachedRotation; mutable TSharedRef< TProxyProperty, T> > CachedRotationYaw; mutable TSharedRef< TProxyProperty, T> > CachedRotationPitch; mutable TSharedRef< TProxyProperty, T> > CachedRotationRoll; /** Cached translation values */ mutable TSharedRef< TProxyValue> > CachedTranslation; mutable TSharedRef< TProxyProperty, T > > CachedTranslationX; mutable TSharedRef< TProxyProperty, T > > CachedTranslationY; mutable TSharedRef< TProxyProperty, T> > CachedTranslationZ; /** Cached scale values */ mutable TSharedRef< TProxyValue> > CachedScale; mutable TSharedRef< TProxyProperty, T> > CachedScaleX; mutable TSharedRef< TProxyProperty, T> > CachedScaleY; mutable TSharedRef< TProxyProperty, T> > CachedScaleZ; /** Whether or not this customization is using the LeftUpForward axis display coordinate system */ bool bUseLeftUpForwardAxisDisplayCoordinateSystem; }; /** * Proxy struct customization that displays an FTransform as a position, euler rotation & scale. */ template class FTransformStructCustomization : public FMatrixStructCustomization { public: static TSharedRef MakeInstance(); protected: /** FMathStructProxyCustomization interface */ virtual bool CacheValues(TWeakPtr PropertyHandlePtr) const override; virtual bool FlushValues(TWeakPtr PropertyHandlePtr) const override; virtual FIntVector4 GetSwizzle() const override; }; /** * Proxy struct customization that displays an FQuat as an euler rotation */ template class DETAILCUSTOMIZATIONS_API FQuatStructCustomization : public FMatrixStructCustomization { public: static TSharedRef MakeInstance(); /** IPropertyTypeCustomization interface */ virtual void CustomizeChildren(TSharedRef StructPropertyHandle, class IDetailChildrenBuilder& StructBuilder, IPropertyTypeCustomizationUtils& StructCustomizationUtils) override; /** FMathStructCustomization interface */ virtual void MakeHeaderRow(TSharedRef& InStructPropertyHandle, FDetailWidgetRow& Row) override; protected: /** FMathStructProxyCustomization interface */ virtual bool CacheValues(TWeakPtr PropertyHandlePtr) const override; virtual bool FlushValues(TWeakPtr PropertyHandlePtr) const override; };