Files
UnrealEngine/Engine/Source/Editor/SceneDepthPickerMode/Private/EditorModeSceneDepthPicker.cpp
2025-05-18 13:04:45 +08:00

170 lines
4.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "EditorModeSceneDepthPicker.h"
#include "Framework/Application/SlateApplication.h"
#include "Widgets/SToolTip.h"
#include "LevelEditorViewport.h"
#include "EditorModes.h"
#include "Editor/ActorPositioning.h"
#include "Widgets/SWindow.h"
#include "SceneView.h"
#define LOCTEXT_NAMESPACE "SceneDepthPicker"
FEdModeSceneDepthPicker::FEdModeSceneDepthPicker()
{
PickState = ESceneDepthPickState::NotOverViewport;
}
void FEdModeSceneDepthPicker::Initialize()
{
CursorDecoratorWindow = SWindow::MakeCursorDecorator();
FSlateApplication::Get().AddWindow(CursorDecoratorWindow.ToSharedRef(), true);
CursorDecoratorWindow->SetContent(
SNew(SToolTip)
.Text(this, &FEdModeSceneDepthPicker::GetCursorDecoratorText)
);
}
void FEdModeSceneDepthPicker::Tick(FEditorViewportClient* ViewportClient, float DeltaTime)
{
if(CursorDecoratorWindow.IsValid())
{
CursorDecoratorWindow->MoveWindowTo(FSlateApplication::Get().GetCursorPos() + FSlateApplication::Get().GetCursorSize());
}
FEdMode::Tick(ViewportClient, DeltaTime);
}
bool FEdModeSceneDepthPicker::MouseEnter(FEditorViewportClient* ViewportClient, FViewport* Viewport, int32 x, int32 y)
{
PickState = ESceneDepthPickState::OverViewport;
return FEdMode::MouseEnter(ViewportClient, Viewport, x, y);
}
bool FEdModeSceneDepthPicker::MouseLeave(FEditorViewportClient* ViewportClient, FViewport* Viewport)
{
PickState = ESceneDepthPickState::NotOverViewport;
return FEdMode::MouseLeave(ViewportClient, Viewport);
}
bool FEdModeSceneDepthPicker::MouseMove(FEditorViewportClient* ViewportClient, FViewport* Viewport, int32 x, int32 y)
{
if (ViewportClient == GCurrentLevelEditingViewportClient)
{
PickState = ESceneDepthPickState::OverViewport;
}
else
{
PickState = ESceneDepthPickState::NotOverViewport;
}
return true;
}
bool FEdModeSceneDepthPicker::LostFocus(FEditorViewportClient* ViewportClient, FViewport* Viewport)
{
if (ViewportClient == GCurrentLevelEditingViewportClient)
{
// Make sure actor picking mode is disabled once the active viewport loses focus
RequestDeletion();
return true;
}
return false;
}
bool FEdModeSceneDepthPicker::InputKey(FEditorViewportClient* ViewportClient, FViewport* Viewport, FKey Key, EInputEvent Event)
{
if (ViewportClient == GCurrentLevelEditingViewportClient)
{
if (Key == EKeys::LeftMouseButton && Event == IE_Pressed)
{
int32 const HitX = Viewport->GetMouseX();
int32 const HitY = Viewport->GetMouseY();
FSceneViewFamilyContext ViewFamily(FSceneViewFamily::ConstructionValues(
Viewport,
ViewportClient->GetScene(),
ViewportClient->EngineShowFlags)
.SetRealtimeUpdate(true));
FSceneView* View = ViewportClient->CalcSceneView(&ViewFamily);
FViewportCursorLocation Cursor(View, ViewportClient, HitX, HitY);
const FActorPositionTraceResult TraceResult = FActorPositioning::TraceWorldForPosition(Cursor, *View);
FVector WorldPosition = TraceResult.State == FActorPositionTraceResult::HitSuccess ? TraceResult.Location : ViewportClient->GetHitProxyObjectLocation(HitX, HitY);
OnSceneDepthLocationSelected.ExecuteIfBound(WorldPosition);
RequestDeletion();
return true;
}
else if(Key == EKeys::Escape && Event == IE_Pressed)
{
RequestDeletion();
return true;
}
}
else
{
RequestDeletion();
}
return false;
}
bool FEdModeSceneDepthPicker::GetCursor(EMouseCursor::Type& OutCursor) const
{
if (PickState == ESceneDepthPickState::OverViewport)
{
OutCursor = EMouseCursor::EyeDropper;
}
else
{
OutCursor = EMouseCursor::SlashedCircle;
}
return true;
}
bool FEdModeSceneDepthPicker::UsesToolkits() const
{
return false;
}
bool FEdModeSceneDepthPicker::IsCompatibleWith(FEditorModeID OtherModeID) const
{
// We want to be able to perform this action with all the built-in editor modes
return OtherModeID != FBuiltinEditorModes::EM_None;
}
void FEdModeSceneDepthPicker::Exit()
{
OnSceneDepthLocationSelected = FOnSceneDepthLocationSelected();
if (CursorDecoratorWindow.IsValid())
{
CursorDecoratorWindow->RequestDestroyWindow();
CursorDecoratorWindow.Reset();
}
PickState = ESceneDepthPickState::NotOverViewport;
FEdMode::Exit();
}
FText FEdModeSceneDepthPicker::GetCursorDecoratorText() const
{
switch(PickState)
{
default:
case ESceneDepthPickState::NotOverViewport:
return LOCTEXT("PickSceneDepth_NotOverViewport", "Pick an location in an active level viewport to sample the depth");
}
}
#undef LOCTEXT_NAMESPACE