You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
- Renamed the command to access the tool from DrawPrimitiveDebugger.Open to PrimitiveDebugger.Open - Fixed access violations and crashes that occurred when opening and using the tool. - Fixed issue where the debugger table would not populate until filter text was entered when using it in-game. - Fixed an issue causing the server to crash if the console command cheat DrawPrimitiveDebugger.Open is used - Added support for skeletal meshes and other primitives. - Added a details panel for the currently selected row to declutter the table view and provide more in depth information such as the materials and textures used and the number of available LODs. The data displayed will refresh automatically and display the active location, LOD, and triangle count of the primitive. - The details panel can force LOD levels, force disable nanite, display bounds, and show skeletal bones. Bounds and bone displays only work in development or debug builds. - Note that any changes to primitives made by the debugger, as well as pinned and hidden entries, will be reset when the debugger is closed. - Fixed communication between the game and render threads when handling frame captures. - Enhanced search functionality. You can now search by primitive name, primitive class, actor name, actor class, material name, and texture used. #rb daniele.vettorel [FYI] elizabeth.bunner, nicolas.mercier, bryce.lumpkin #tests FNTEST-128602 [CL 32064534 by zach harris in ue5-main branch]
240 lines
7.1 KiB
C++
240 lines
7.1 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "CoreMinimal.h"
|
|
#include "Engine/Engine.h"
|
|
#include "Engine/World.h"
|
|
#include "Modules/ModuleManager.h"
|
|
#include "DrawPrimitiveDebugger.h"
|
|
#include "SDrawPrimitiveDebugger.h"
|
|
#include "ViewDebug.h"
|
|
#include "Widgets/Docking/SDockTab.h"
|
|
|
|
DEFINE_LOG_CATEGORY(LogDrawPrimitiveDebugger)
|
|
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
static FAutoConsoleCommand SummonDebuggerCmd(
|
|
TEXT("PrimitiveDebugger.Open"),
|
|
TEXT("Summons the primitive debugger window."),
|
|
FConsoleCommandDelegate::CreateLambda([]() { IDrawPrimitiveDebugger::Get().OpenDebugWindow(); })
|
|
);
|
|
/*static FAutoConsoleCommand EnableLiveCaptureCmd(
|
|
TEXT("PrimitiveDebugger.EnableLiveCapture"),
|
|
TEXT("Enables live capture for the primitive debugger."),
|
|
FConsoleCommandDelegate::CreateLambda([]() { IDrawPrimitiveDebugger::Get().EnableLiveCapture(); })
|
|
);
|
|
static FAutoConsoleCommand DisableLiveCaptureCmd(
|
|
TEXT("PrimitiveDebugger.DisableLiveCapture"),
|
|
TEXT("Disables live capture for the primitive debugger."),
|
|
FConsoleCommandDelegate::CreateLambda([]() { IDrawPrimitiveDebugger::Get().DisableLiveCapture(); })
|
|
);*/ // TODO: Re-enable these commands once live capture performance has been fixed
|
|
static FAutoConsoleCommand TakeSnapshotCmd(
|
|
TEXT("PrimitiveDebugger.Snapshot"),
|
|
TEXT("Captures the primitives rendered on the next frame for the primitive debugger."),
|
|
FConsoleCommandDelegate::CreateLambda([]() { IDrawPrimitiveDebugger::Get().CaptureSingleFrame(); })
|
|
);
|
|
#endif
|
|
|
|
class FDrawPrimitiveDebuggerModule : public IDrawPrimitiveDebugger
|
|
{
|
|
public:
|
|
virtual void StartupModule() override;
|
|
virtual void ShutdownModule() override;
|
|
|
|
virtual void CaptureSingleFrame() override;
|
|
virtual bool IsLiveCaptureEnabled() const override;
|
|
virtual void EnableLiveCapture() override;
|
|
virtual void DisableLiveCapture() override;
|
|
virtual void DiscardCaptureData() override;
|
|
virtual void OpenDebugWindow() override;
|
|
virtual void CloseDebugWindow() override;
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
static const FViewDebugInfo& GetViewDebugInfo();
|
|
#endif
|
|
|
|
private:
|
|
bool bLiveCaptureEnabled = false;
|
|
FDelegateHandle UpdateDelegateHandle;
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
TSharedPtr<SDrawPrimitiveDebugger> DebuggerWidget;
|
|
TSharedPtr<SDockTab> DebuggerTab;
|
|
FDelegateHandle OnWorldDestroyedHandle;
|
|
FDelegateHandle OnWorldAddedHandle;
|
|
|
|
TSharedRef<SDockTab> MakeDrawPrimitiveDebuggerTab(const FSpawnTabArgs&);
|
|
|
|
void OnTabClosed(TSharedRef<SDockTab> Tab);
|
|
|
|
void OnUpdateViewInformation();
|
|
|
|
void HandleWorldDestroyed(UWorld* World);
|
|
void HandleWorldAdded(UWorld* World);
|
|
#endif
|
|
};
|
|
|
|
IMPLEMENT_MODULE(FDrawPrimitiveDebuggerModule, DrawPrimitiveDebugger)
|
|
|
|
void FDrawPrimitiveDebuggerModule::StartupModule()
|
|
{
|
|
bLiveCaptureEnabled = false;
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
UpdateDelegateHandle = FViewDebugInfo::Instance.AddUpdateHandler(this, &FDrawPrimitiveDebuggerModule::OnUpdateViewInformation);
|
|
FGlobalTabmanager::Get()->RegisterNomadTabSpawner("Primitive Debugger", FOnSpawnTab::CreateRaw(this, &FDrawPrimitiveDebuggerModule::MakeDrawPrimitiveDebuggerTab) );
|
|
#endif
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::ShutdownModule()
|
|
{
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
FViewDebugInfo::Instance.RemoveUpdateHandler(UpdateDelegateHandle);
|
|
#endif
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::CaptureSingleFrame()
|
|
{
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
UE_LOG(LogDrawPrimitiveDebugger, Log, TEXT("Collecting a single frame graphics data capture"));
|
|
FViewDebugInfo::Instance.CaptureNextFrame();
|
|
#endif
|
|
}
|
|
|
|
bool FDrawPrimitiveDebuggerModule::IsLiveCaptureEnabled() const
|
|
{
|
|
return bLiveCaptureEnabled;
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::EnableLiveCapture()
|
|
{
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
if (!bLiveCaptureEnabled)
|
|
{
|
|
UE_LOG(LogDrawPrimitiveDebugger, Log, TEXT("Enabling live graphics data capture"));
|
|
bLiveCaptureEnabled = true;
|
|
FViewDebugInfo::Instance.EnableLiveCapture();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::DisableLiveCapture()
|
|
{
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
if (bLiveCaptureEnabled)
|
|
{
|
|
UE_LOG(LogDrawPrimitiveDebugger, Log, TEXT("Disabling live graphics data capture"));
|
|
bLiveCaptureEnabled = false;
|
|
FViewDebugInfo::Instance.DisableLiveCapture();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::DiscardCaptureData()
|
|
{
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
UE_LOG(LogDrawPrimitiveDebugger, Log, TEXT("Clearing the captured graphics data from the Primitive Debugger"));
|
|
FViewDebugInfo::Instance.ClearCaptureData();
|
|
#endif
|
|
}
|
|
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
const FViewDebugInfo& FDrawPrimitiveDebuggerModule::GetViewDebugInfo()
|
|
{
|
|
return FViewDebugInfo::Get();
|
|
}
|
|
#endif
|
|
|
|
void FDrawPrimitiveDebuggerModule::OpenDebugWindow()
|
|
{
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
if (!DebuggerTab.IsValid())
|
|
{
|
|
UE_LOG(LogDrawPrimitiveDebugger, Log, TEXT("Opening the Primitive Debugger"));
|
|
OnWorldDestroyedHandle = GEngine->OnWorldDestroyed().AddRaw(this, &FDrawPrimitiveDebuggerModule::HandleWorldDestroyed);
|
|
OnWorldAddedHandle = FCoreUObjectDelegates::PostLoadMapWithWorld.AddRaw(this, &FDrawPrimitiveDebuggerModule::HandleWorldAdded);
|
|
if (!FViewDebugInfo::Instance.HasEverUpdated())
|
|
{
|
|
CaptureSingleFrame();
|
|
}
|
|
FGlobalTabmanager::Get()->TryInvokeTab(FTabId("Primitive Debugger"));
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::CloseDebugWindow()
|
|
{
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
if (DebuggerTab.IsValid())
|
|
{
|
|
UE_LOG(LogDrawPrimitiveDebugger, Log, TEXT("Closing the Primitive Debugger"));
|
|
DebuggerTab->RequestCloseTab();
|
|
GEngine->OnWorldDestroyed().Remove(OnWorldDestroyedHandle);
|
|
FCoreUObjectDelegates::PostLoadMapWithWorld.Remove(OnWorldAddedHandle);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#if WITH_PRIMITIVE_DEBUGGER
|
|
TSharedRef<SDockTab> FDrawPrimitiveDebuggerModule::MakeDrawPrimitiveDebuggerTab(const FSpawnTabArgs&)
|
|
{
|
|
DebuggerTab = SNew(SDockTab)
|
|
.TabRole(ETabRole::NomadTab)
|
|
.OnTabClosed(SDockTab::FOnTabClosedCallback::CreateRaw(this, &FDrawPrimitiveDebuggerModule::OnTabClosed));
|
|
|
|
if (!DebuggerWidget.IsValid())
|
|
{
|
|
DebuggerWidget = SNew(SDrawPrimitiveDebugger);
|
|
DebuggerWidget->SetActiveWorld(GEngine->GetCurrentPlayWorld());
|
|
DebuggerTab->SetContent(DebuggerWidget.ToSharedRef());
|
|
}
|
|
return DebuggerTab.ToSharedRef();
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::OnTabClosed(TSharedRef<SDockTab> Tab)
|
|
{
|
|
DebuggerTab.Reset();
|
|
DebuggerTab = nullptr;
|
|
DebuggerWidget.Reset();
|
|
DebuggerWidget = nullptr;
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::OnUpdateViewInformation()
|
|
{
|
|
if (DebuggerWidget && DebuggerWidget.IsValid())
|
|
{
|
|
DebuggerWidget->Refresh();
|
|
}
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::HandleWorldDestroyed(UWorld* World)
|
|
{
|
|
#if WITH_EDITOR
|
|
if (IsValid(World) && !World->IsGameWorld())
|
|
{
|
|
// We should only have to care about the game world, not any editor specific worlds
|
|
return;
|
|
}
|
|
#endif
|
|
if (DebuggerWidget.IsValid())
|
|
{
|
|
// Clear all data bound to the debugger so that it no longer attempts to access them
|
|
DebuggerWidget->ClearAllEntries();
|
|
|
|
DebuggerWidget->SetActiveWorld(nullptr);
|
|
}
|
|
DiscardCaptureData();
|
|
}
|
|
|
|
void FDrawPrimitiveDebuggerModule::HandleWorldAdded(UWorld* World)
|
|
{
|
|
#if WITH_EDITOR
|
|
if (IsValid(World) && !World->IsGameWorld())
|
|
{
|
|
// We should only have to care about the game world, not any editor specific worlds
|
|
return;
|
|
}
|
|
#endif
|
|
if (DebuggerWidget.IsValid())
|
|
{
|
|
DebuggerWidget->SetActiveWorld(World);
|
|
}
|
|
}
|
|
|
|
#endif |