Files
UnrealEngine/Engine/Source/Editor/UnrealEd/Public/ComponentVisualizer.h
2025-05-18 13:04:45 +08:00

229 lines
8.2 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Components/ActorComponent.h"
#include "Containers/Array.h"
#include "ConvexVolume.h"
#include "CoreMinimal.h"
#include "CoreTypes.h"
#include "Engine/EngineBaseTypes.h"
#include "GameFramework/Actor.h"
#include "GenericPlatform/ICursor.h"
#include "HitProxies.h"
#include "InputCoreTypes.h"
#include "Math/Box.h"
#include "Math/MathFwd.h"
#include "Math/Matrix.h"
#include "Math/Rotator.h"
#include "Templates/SharedPointer.h"
#include "UObject/NameTypes.h"
#include "UObject/ObjectMacros.h"
#include "UObject/UnrealNames.h"
#include "UObject/UnrealType.h"
#include "UObject/WeakObjectPtr.h"
#include "UObject/WeakObjectPtrTemplates.h"
#include "Elements/Framework/EngineElementsLibrary.h"
#include "Elements/Framework/TypedElementHandle.h"
#include "ComponentVisualizer.generated.h"
class AActor;
class FCanvas;
class FEditorViewportClient;
class FPrimitiveDrawInterface;
class FSceneView;
class FViewport;
class SWidget;
struct FViewportClick;
struct HComponentVisProxy : public HHitProxy
{
DECLARE_HIT_PROXY(UNREALED_API);
HComponentVisProxy(const UActorComponent* InComponent, EHitProxyPriority InPriority = HPP_Wireframe)
: HHitProxy(InPriority)
, Component(InComponent)
{}
virtual EMouseCursor::Type GetMouseCursor() override
{
return EMouseCursor::Crosshairs;
}
virtual FTypedElementHandle GetElementHandle() const override
{
return UEngineElementsLibrary::AcquireEditorComponentElementHandle(Component.Get());
}
TWeakObjectPtr<const UActorComponent> Component;
};
USTRUCT()
struct FPropertyNameAndIndex
{
public:
GENERATED_USTRUCT_BODY()
FPropertyNameAndIndex()
: Name(NAME_None)
, Index(INDEX_NONE)
{}
explicit FPropertyNameAndIndex(FName InName, int32 InIndex = 0)
: Name(InName)
, Index(InIndex)
{}
bool IsValid() const { return Name != NAME_None && Index != INDEX_NONE; }
void Clear()
{
Name = NAME_None;
Index = INDEX_NONE;
}
bool operator ==(const FPropertyNameAndIndex& InRHS) const
{
return (Name == InRHS.Name && Index == InRHS.Index);
}
UPROPERTY()
FName Name;
UPROPERTY()
int32 Index;
};
/**
* Describes a chain of properties from the parent actor of a given component, to the component itself.
*/
USTRUCT()
struct FComponentPropertyPath
{
public:
GENERATED_USTRUCT_BODY()
FComponentPropertyPath() = default;
explicit FComponentPropertyPath(const UActorComponent* Component) { Set(Component); }
/** Resets the property path */
void Reset()
{
ParentOwningActor = nullptr;
LastResortComponentPtr = nullptr;
PropertyChain.Reset();
}
/** Gets the parent owning actor for the component, or nullptr if it is not valid */
AActor* GetParentOwningActor() const { return ParentOwningActor.Get(); }
/** Gets a pointer to the component, or nullptr if it is not valid */
UNREALED_API UActorComponent* GetComponent() const;
/** Determines whether the property path is valid or not */
UNREALED_API bool IsValid() const;
bool operator ==(const FComponentPropertyPath& InRHS) const
{
return (ParentOwningActor == InRHS.ParentOwningActor && LastResortComponentPtr == InRHS.LastResortComponentPtr && PropertyChain == InRHS.PropertyChain);
}
bool operator !=(const FComponentPropertyPath& InRHS) const
{
return (ParentOwningActor != InRHS.ParentOwningActor || LastResortComponentPtr != InRHS.LastResortComponentPtr || PropertyChain != InRHS.PropertyChain);
}
private:
/** Sets the component referred to by the object */
UNREALED_API void Set(const UActorComponent* Component);
UPROPERTY()
TWeakObjectPtr<AActor> ParentOwningActor;
UPROPERTY()
TWeakObjectPtr<UActorComponent> LastResortComponentPtr;
UPROPERTY()
TArray<FPropertyNameAndIndex> PropertyChain;
};
/** Base class for a component visualizer, that draw editor information for a particular component class */
class FComponentVisualizer : public TSharedFromThis<FComponentVisualizer>
{
public:
FComponentVisualizer() {}
virtual ~FComponentVisualizer() {}
/** */
virtual void OnRegister() {}
/** Show this visualizer if the component is indirectly selected */
virtual bool ShouldShowForSelectedSubcomponents(const UActorComponent* Component) { return true; }
/** Draw visualization for the supplied component */
virtual void DrawVisualization(const UActorComponent* Component, const FSceneView* View, FPrimitiveDrawInterface* PDI) {}
/** Draw HUD on viewport for the supplied component */
virtual void DrawVisualizationHUD(const UActorComponent* Component, const FViewport* Viewport, const FSceneView* View, FCanvas* Canvas) {}
/** */
virtual bool VisProxyHandleClick(FEditorViewportClient* InViewportClient, HComponentVisProxy* VisProxy, const FViewportClick& Click) { return false; }
/**
* Determines whether, if the visualizer returns true from VisProxyHandleClick, the hitproxy element should
* be automatically selected. By default, uses the value of Editor.ComponentVisualizer.AutoSelectComponent.
*/
UNREALED_API virtual bool ShouldAutoSelectElementOnHandleClick() const;
/** */
virtual void EndEditing() {}
/** */
virtual bool GetWidgetLocation(const FEditorViewportClient* ViewportClient, FVector& OutLocation) const { return false; }
/** */
virtual bool GetCustomInputCoordinateSystem(const FEditorViewportClient* ViewportClient, FMatrix& OutMatrix) const { return false; }
/** */
virtual bool HandleInputDelta(FEditorViewportClient* ViewportClient, FViewport* Viewport, FVector& DeltaTranslate, FRotator& DeltaRotate, FVector& DeltaScale) { return false; }
/** */
virtual bool HandleInputKey(FEditorViewportClient* ViewportClient,FViewport* Viewport,FKey Key,EInputEvent Event) { return false; }
/** Handle click modified by Alt, Ctrl and/or Shift. The input HitProxy may not be on this component. */
virtual bool HandleModifiedClick(FEditorViewportClient* InViewportClient, HHitProxy* HitProxy, const FViewportClick& Click) { return false; }
/** Handle box select input */
virtual bool HandleBoxSelect(const FBox& InBox, FEditorViewportClient* InViewportClient,FViewport* InViewport) { return false; }
/** Handle frustum select input */
virtual bool HandleFrustumSelect(const FConvexVolume& InFrustum, FEditorViewportClient* InViewportClient, FViewport* InViewport) { return false; }
/** Return whether focus on selection should focus on bounding box defined by active visualizer */
virtual bool HasFocusOnSelectionBoundingBox(FBox& OutBoundingBox) { return false; }
/** Pass snap input to active visualizer */
virtual bool HandleSnapTo(const bool bInAlign, const bool bInUseLineTrace, const bool bInUseBounds, const bool bInUsePivot, AActor* InDestination) { return false; }
/** Gets called when the mouse tracking has started (dragging behavior) */
virtual void TrackingStarted(FEditorViewportClient* InViewportClient) {}
/** Gets called when the mouse tracking has stopped (dragging behavior) */
virtual void TrackingStopped(FEditorViewportClient* InViewportClient, bool bInDidMove) {}
/** Get currently edited component, this is needed to reset the active visualizer after undo/redo */
virtual UActorComponent* GetEditedComponent() const { return nullptr; }
/** */
virtual TSharedPtr<SWidget> GenerateContextMenu() const { return TSharedPtr<SWidget>(); }
/** */
virtual bool IsVisualizingArchetype() const { return false; }
// So deprecated code expecting this as an inner class still works
using FPropertyNameAndIndex UE_DEPRECATED(5.6, "Please update to use the external class instead of internal identifier") = ::FPropertyNameAndIndex;
/** Notify that a component property has been modified */
static UNREALED_API void NotifyPropertyModified(UActorComponent* Component, FProperty* Property, EPropertyChangeType::Type PropertyChangeType = EPropertyChangeType::Unspecified);
/** Notify that many component properties have been modified */
static UNREALED_API void NotifyPropertiesModified(UActorComponent* Component, const TArray<FProperty*>& Properties, EPropertyChangeType::Type PropertyChangeType = EPropertyChangeType::Unspecified);
};
struct FCachedComponentVisualizer
{
FComponentPropertyPath ComponentPropertyPath;
TSharedPtr<FComponentVisualizer> Visualizer;
FCachedComponentVisualizer(UActorComponent* InComponent, TSharedPtr<FComponentVisualizer>& InVisualizer)
: ComponentPropertyPath(InComponent)
, Visualizer(InVisualizer)
{}
};