Lots of refactors related to BreakToDebugger and FormatLogMessage
This commit is contained in:
113
Source/Integration/BreakToDebugger.h
Normal file
113
Source/Integration/BreakToDebugger.h
Normal file
@@ -0,0 +1,113 @@
|
||||
////////////////////////////////////////////////////////////
|
||||
//
|
||||
// BreakToDebugger
|
||||
//
|
||||
// When an error message gets written to UE_LOG, we can
|
||||
// optionally trigger the blueprint debugger.
|
||||
//
|
||||
// This only affects UE_LOG messages that are generated
|
||||
// during blueprint execution. Log messages from other
|
||||
// threads do not trigger the debugger.
|
||||
//
|
||||
// The following explains how we trigger the blueprint
|
||||
// debugger on UE_LOG messages. Log messages are sent to a
|
||||
// long list of output devices, including: the visual studio
|
||||
// output window, the unreal editor output window, the log
|
||||
// file, and so forth. We add another pseudo output device.
|
||||
// This output device doesn't actually send the log message
|
||||
// anywhere, instead, it just activates the blueprint
|
||||
// debugger.
|
||||
//
|
||||
// UE_LOG messages can be generated from any thread. The
|
||||
// pseudo output device checks what thread it is running in,
|
||||
// and if it's not the blueprint thread, it does nothing at
|
||||
// all. If it is the blueprint thread, it's safe to trigger
|
||||
// the blueprint debugger.
|
||||
//
|
||||
// One annoying limitation of this design is that our output
|
||||
// device ends up early in the list, so the debugger runs
|
||||
// *before* the message shows up in visual studio or the
|
||||
// unreal editor. As a result, when you are in the
|
||||
// debugger, the message won't be in your output window.
|
||||
// Pressing 'single step' always reveals the message.
|
||||
//
|
||||
// The blueprint node "Format Log Message" uses UE_LOG
|
||||
// internally, so therefore, that too can trigger the
|
||||
// blueprint debugger.
|
||||
//
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "HAL/Platform.h"
|
||||
#include "Misc/OutputDeviceError.h"
|
||||
#include "UObject/NameTypes.h"
|
||||
#include "UObject/ObjectMacros.h"
|
||||
#include "UObject/UObjectGlobals.h"
|
||||
#include "BreakToDebugger.generated.h"
|
||||
|
||||
// ElxBreakToDebuggerThreshold:
|
||||
//
|
||||
// Controls the sensitivity level at which UE_LOG messages
|
||||
// trigger the blueprint debugger.
|
||||
//
|
||||
UENUM(BlueprintType)
|
||||
enum class ElxBreakToDebuggerThreshold : uint8 {
|
||||
|
||||
/* Break on errors. */
|
||||
Error,
|
||||
|
||||
/* Break on warnings and above. */
|
||||
Warning,
|
||||
|
||||
/* Break on display messages and above. */
|
||||
Display,
|
||||
|
||||
/* Break on log messages and above. */
|
||||
Log,
|
||||
|
||||
/* Break on verbose messages and above. */
|
||||
Verbose,
|
||||
|
||||
/* Break on all messages. */
|
||||
VeryVerbose,
|
||||
|
||||
/* Break on fatal errors only (ie, never break -- the process crashes instead). */
|
||||
Fatal,
|
||||
};
|
||||
|
||||
|
||||
struct FlxBreakToDebuggerOutputDevice : public FOutputDevice
|
||||
{
|
||||
public:
|
||||
// The constructor and destructor automatically register
|
||||
// this output device with GLog.
|
||||
//
|
||||
// This struct doesn't store the sensitivity threshold.
|
||||
// It relies on the LuprexGameMode class to do that, so
|
||||
// that the threshold can be easily edited with the
|
||||
// blueprint editor. This struct must be initialized
|
||||
// with a reference to the threshold variable.
|
||||
//
|
||||
FlxBreakToDebuggerOutputDevice(const ElxBreakToDebuggerThreshold &SensitivityRef);
|
||||
~FlxBreakToDebuggerOutputDevice();
|
||||
|
||||
// Inspect a log message.
|
||||
//
|
||||
INTEGRATION_API virtual void Serialize(const TCHAR* V, ELogVerbosity::Type Verbosity, const FName& Category) override;
|
||||
|
||||
// If the device is marked 'CanBeUsedOnMultipleThreads,'
|
||||
// then UE_LOG will call Serialize from the current
|
||||
// thread, otherwise, it will call Serialize from the
|
||||
// logging thread. Using the logging thread would
|
||||
// defeat the purpose of this device, so it's imperative
|
||||
// that we set this flag.
|
||||
//
|
||||
INTEGRATION_API virtual bool CanBeUsedOnMultipleThreads() const override { return true; }
|
||||
|
||||
private:
|
||||
static ELogVerbosity::Type ConvertThreshold(ElxBreakToDebuggerThreshold Verbosity);
|
||||
const ElxBreakToDebuggerThreshold &Sensitivity;
|
||||
};
|
||||
Reference in New Issue
Block a user