// Copyright Epic Games, Inc. All Rights Reserved. #pragma once #include "Chaos/ChaosEngineInterface.h" #include "Containers/Array.h" #include "Containers/UnrealString.h" #include "Customizations/MathStructCustomizations.h" #include "IDetailCustomization.h" #include "Internationalization/Text.h" #include "Math/Color.h" #include "Math/Rotator.h" #include "Math/Transform.h" #include "Math/UnrealMathSSE.h" #include "Math/Vector.h" #include "Misc/Optional.h" #include "Styling/SlateColor.h" #include "Templates/SharedPointer.h" #include "Types/SlateEnums.h" #include "UObject/WeakObjectPtrTemplates.h" class FDetailWidgetRow; class IDetailCategoryBuilder; class IDetailLayoutBuilder; class IPropertyHandle; class IPropertyTypeCustomization; class SWidget; class UObject; class UPhysicsAsset; class UPhysicsConstraintComponent; class UPhysicsConstraintTemplate; struct FConstraintInstance; template class TProxyProperty; template class TProxyValue; enum class ECheckBoxState : uint8; enum class EConstraintTransformComponentFlags : uint8; /** * Proxy class customization that displays a constraint transform in a user friendly way. * * Constraint transforms are described by a position vector and a pair of orthonormal vectors * representing the orientation. This class displays the transform as a position vector and a * rotator in the UI details panel in a way that can be easily read and safely edited by users. */ class FConstraintTransformCustomization : public FMathStructCustomization { public: FConstraintTransformCustomization(); static TSharedRef MakeInstance(); void MakeRotationRow(TSharedRef& InPriAxisPropertyHandle, TSharedRef& InSecAxisPropertyHandle, FDetailWidgetRow& Row, TSharedRef EditSpaceToggleButtonWidget); void MakePositionRow(TSharedRef& InPositionPropertyHandle, FDetailWidgetRow& Row, TSharedRef EditSpaceToggleButtonWidget); template TSharedRef MakeNumericProxyWidget(TSharedRef& PriAxisPropertyHandle, TSharedRef& SecAxisPropertyHandle, TSharedRef< TProxyProperty >& ProxyValue, const FText& Label, bool bRotationInDegrees, const FLinearColor& LabelBackgroundColor); template TSharedRef MakeNumericProxyWidget(TSharedRef& PositionPropertyHandle, TSharedRef< TProxyProperty >& ProxyValue, const FText& Label, const FLinearColor& LabelBackgroundColor); void OnCopy(TWeakPtr PositionPropertyHandlePtr, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); void OnCopyPosition(TWeakPtr PositionPropertyHandlePtr); void OnCopyRotation(TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); void OnPaste(TWeakPtr PositionPropertyHandlePtr, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); void OnPastePosition(TWeakPtr PositionPropertyHandlePtr); void OnPasteRotation(TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); void OnPasteFromText(const FString& InTag, const FString& InText, const TOptional& InOperationId, TWeakPtr PositionPropertyHandlePtr, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); bool IsRotationValueEnabled(TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr) const; template TOptional OnGetRotationValue(TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr, TSharedRef< TProxyProperty > ProxyValue) const; template void OnRotationValueCommitted(NumericType NewValue, ETextCommit::Type CommitType, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr, TSharedRef< TProxyProperty > ProxyValue); template void OnRotationValueChanged(NumericType NewValue, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr, TSharedRef< TProxyProperty > ProxyValue); bool IsPositionValueEnabled(TWeakPtr PositionWeakHandlePtr) const; template TOptional OnGetPositionValue(TWeakPtr PositionWeakHandlePtr, TSharedRef< TProxyProperty > ProxyValue) const; template void OnPositionValueCommitted(NumericType NewValue, ETextCommit::Type CommitType, TWeakPtr PositionWeakHandlePtr, TSharedRef< TProxyProperty > ProxyValue); template void OnPositionValueChanged(NumericType NewValue, TWeakPtr PositionWeakHandlePtr, TSharedRef< TProxyProperty > ProxyValue); void SetFrameLabelText(const FText InText); FText& GetFrameLabelText(); void GetPositionAsFormattedString(FString& OutString); void GetRotationAsFormattedString(FString& OutString); void GetValueAsFormattedString(FString& OutString); bool SetPositionFromFormattedString(const FString& InString); bool SetRotationFromFormattedString(const FString& InString); bool SetValueFromFormattedString(const FString& InString); virtual bool CacheValues(TWeakPtr PositionPropertyHandlePtr) const; virtual bool CacheValues(TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr) const; virtual bool FlushValues(TWeakPtr PositionPropertyHandlePtr) const; virtual bool FlushValues(TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr) const; const FTransform& GetDefaultTransform() const { return DefaultTransform; }; void SetDefaultTransform(const FTransform& InTransform, TWeakPtr PositionPropertyHandlePtr, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); void SetPositionDisplayRelativeToDefault(const bool bValue) { bPositionDisplayRelativeToDefault = bValue; } void SetRotationDisplayRelativeToDefault(const bool bValue) { bRotationDisplayRelativeToDefault = bValue; } protected: void OrthonormalVectorPairToDisplayedRotator(const FVector& PriAxis, const FVector& SecAxis, FRotator& OutRotator) const; void DisplayedRotatorToOrthonormalVectorPair(const FRotator& InRotator, FVector& OutPriAxis, FVector& OutSecAxis) const; void OnPastePositionFromText(const FString& InTag, const FString& InText, const TOptional& InOperationId, TWeakPtr PositionPropertyHandlePtr); void PastePositionFromText(const FString& InTag, const FString& InText, TWeakPtr PositionPropertyHandlePtr); void OnPasteRotationFromText(const FString& InTag, const FString& InText, const TOptional& InOperationId, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); void PasteRotationFromText(const FString& InTag, const FString& InText, TWeakPtr PriAxisPropertyHandlePtr, TWeakPtr SecAxisPropertyHandlePtr); mutable TSharedRef< TProxyValue > CachedRotation; mutable TSharedRef< TProxyProperty > CachedRotationYaw; mutable TSharedRef< TProxyProperty > CachedRotationPitch; mutable TSharedRef< TProxyProperty > CachedRotationRoll; mutable TSharedRef< TProxyValue > CachedPosition; mutable TSharedRef< TProxyProperty > CachedPositionX; mutable TSharedRef< TProxyProperty > CachedPositionY; mutable TSharedRef< TProxyProperty > CachedPositionZ; // Constraint transforms are displayed relative to this default transform when the associated ...DisplayRelativeToDefault flag is true. Otherwise they are displayed in the frame of the associated bone. FTransform DefaultTransform; FTransform InverseDefaultTransform; // When true, the Position/Rotation components are displayed as offsets from the default transforms. bool bPositionDisplayRelativeToDefault; bool bRotationDisplayRelativeToDefault; FText FrameLabelText; }; /** * Detail customizer for PhysicsConstraintComponent and PhysicsConstraintTemplate */ class FPhysicsConstraintComponentDetails : public IDetailCustomization { public: FPhysicsConstraintComponentDetails(); /** Makes a new instance of this detail layout class for a specific detail view requesting it */ static TSharedRef MakeInstance(); /** IDetailCustomization interface */ virtual void CustomizeDetails( IDetailLayoutBuilder& DetailBuilder ) override; private: struct EPropertyType { enum Type { LinearXPositionDrive, LinearYPositionDrive, LinearZPositionDrive, LinearPositionDrive, LinearXVelocityDrive, LinearYVelocityDrive, LinearZVelocityDrive, LinearVelocityDrive, LinearDrive, AngularSwingLimit, AngularSwing1Limit, AngularSwing2Limit, AngularTwistLimit, AngularAnyLimit, }; }; bool IsPropertyEnabled(EPropertyType::Type Type) const; ECheckBoxState IsLimitRadioChecked(TSharedPtr Property, uint8 Value) const ; void OnLimitRadioChanged(ECheckBoxState CheckType, TSharedPtr Property, uint8 Value); void AddConstraintProperties(IDetailLayoutBuilder& DetailBuilder, TSharedPtr ConstraintInstancePropertyHandle, TArray>& Objects); void AddConstraintFrameTransform(const EConstraintFrame::Type ConstraintFrameType, IDetailCategoryBuilder& ConstraintCat, TSharedPtr ConstraintInstancePropertyHandle); void AddConstraintBehaviorProperties(IDetailLayoutBuilder& DetailBuilder, TSharedPtr ConstraintInstancePropertyHandle, TSharedPtr ProfileInstance); void AddLinearLimits(IDetailLayoutBuilder& DetailBuilder, TSharedPtr ConstraintInstancePropertyHandle, TSharedPtr ProfileInstance); void AddAngularLimits(IDetailLayoutBuilder& DetailBuilder, TSharedPtr ConstraintInstancePropertyHandle, TSharedPtr ProfileInstance); void AddLinearDrive(IDetailLayoutBuilder& DetailBuilder, TSharedPtr ConstraintInstancePropertyHandle, TSharedPtr ProfileInstance); void AddAngularDrive(IDetailLayoutBuilder& DetailBuilder, TSharedPtr ConstraintInstancePropertyHandle, TSharedPtr ProfileInstance); void OnCopyConstraintTransform(TSharedPtr PositionPropertyHandle, TSharedPtr PriAxisPropertyHandle, TSharedPtr SecAxisPropertyHandle, TSharedPtr RotationProxy); void OnPasteConstraintTransform(TSharedPtr PositionPropertyHandle, TSharedPtr PriAxisPropertyHandle, TSharedPtr SecAxisPropertyHandle, TSharedPtr RotationProxy); bool IsSnapConstraintTransformComponentVisible(TSharedPtr ConstraintInstancePropertyHandle, const EConstraintTransformComponentFlags SnapFlags); void ToggleDisplayConstraintTransformComponentRelativeToDefault(TSharedPtr ConstraintInstance, const EConstraintTransformComponentFlags ComponentFlags); bool IsDisplayingConstraintTransformComponentRelativeToDefault(const EConstraintTransformComponentFlags ComponentFlags); bool IsConstraintTransformComponentEnabled(const EConstraintTransformComponentFlags ComponentFlags) const; FSlateColor GetConstraintTransformColorAndOpacity(const EConstraintTransformComponentFlags ComponentFlags) const; private: void OnPasteConstraintTransformFromText( const FString& InTag, const FString& InText, const TOptional& InOperationId, TSharedPtr PositionPropertyHandle, TSharedPtr PriAxisPropertyHandle, TSharedPtr SecAxisPropertyHandle, TSharedPtr TransformProxy); void PasteConstraintTransformFromText( const FString& InTag, const FString& InText, TSharedPtr PositionPropertyHandle, TSharedPtr PriAxisPropertyHandle, TSharedPtr SecAxisPropertyHandle, TSharedPtr TransformProxy); TSharedRef MakeEditSpaceToggleButtonWidget(TSharedPtr ConstraintInstancePropertyHandle, const EConstraintTransformComponentFlags ComponentFlags); // TODO - get this in the right place in src void SnapConstraintTransformComponentsToDefault(TSharedPtr ConstraintInstancePropertyHandle, const EConstraintTransformComponentFlags SnapFlags); void UpdateTransformProxyDisplayRelativeToDefault(TSharedPtr ConstraintInstancePropertyHandle); FConstraintInstance* GetConstraintInstance(); TSharedRef ChildTransformProxy; // Creates a user friendly representation of the constraint's transform in the frame of the child bone in the UI details panel. TSharedRef ParentTransformProxy;// Creates a user friendly representation of the constraint's transform in the frame of the parent bone in the UI details panel. TSharedPtr LinearXPositionDriveProperty; TSharedPtr LinearYPositionDriveProperty; TSharedPtr LinearZPositionDriveProperty; TSharedPtr LinearXVelocityDriveProperty; TSharedPtr LinearYVelocityDriveProperty; TSharedPtr LinearZVelocityDriveProperty; TSharedPtr AngularSwing1MotionProperty; TSharedPtr AngularSwing2MotionProperty; TSharedPtr AngularTwistMotionProperty; TSharedPtr ChildPositionPropertyHandle; TSharedPtr ChildPriAxisPropertyHandle; TSharedPtr ChildSecAxisPropertyHandle; TSharedPtr ParentPositionPropertyHandle; TSharedPtr ParentPriAxisPropertyHandle; TSharedPtr ParentSecAxisPropertyHandle; UPhysicsConstraintComponent* ConstraintComp; UPhysicsConstraintTemplate* ConstraintTemplate; UPhysicsAsset* ParentPhysicsAsset; bool bInPhat; };