No, THIS is the major overhaul of DebugPrint
This commit is contained in:
180
Source/Integration/DebugPrint.cpp
Normal file
180
Source/Integration/DebugPrint.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
#include "DebugPrint.h"
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
using DPrintCallback = DebugPrintControl::DPrintCallback;
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DPrintState
|
||||
//
|
||||
// The global state of the DPrint routine. There is only
|
||||
// ever one of these, and it is owned by DPrintAccess below.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
struct DPrintState {
|
||||
// True if buffering is enabled.
|
||||
bool Collect;
|
||||
|
||||
// The array of buffered messages.
|
||||
TArray<FString> Messages;
|
||||
|
||||
// The array of callback functions.
|
||||
TArray<DPrintCallback> Callbacks;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// DPrintAccess
|
||||
//
|
||||
// This class grants you safe access to the global state
|
||||
// of the DPrint routine. Constructing an object of
|
||||
// class DPrintAccess will lock the global mutex and make
|
||||
// sure that the DPrintState is initialized. Then it will
|
||||
// give you unrestricted access to the DPrintState through
|
||||
// operator right arrow.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
class DPrintAccess {
|
||||
private:
|
||||
// The Mutex that protects the global state.
|
||||
static FCriticalSection Mutex;
|
||||
|
||||
// The Global State. A pointer, to avoid static init issues.
|
||||
static DPrintState* State;
|
||||
|
||||
public:
|
||||
// Constructor. Locks mutex and initializes state if necessary.
|
||||
DPrintAccess() {
|
||||
Mutex.Lock();
|
||||
if (State == nullptr) {
|
||||
State = new DPrintState;
|
||||
State->Collect = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Destructor. Releases mutex.
|
||||
~DPrintAccess() {
|
||||
Mutex.Unlock();
|
||||
}
|
||||
|
||||
// Access the DPrintState.
|
||||
DPrintState* operator ->() {
|
||||
return State;
|
||||
}
|
||||
};
|
||||
|
||||
FCriticalSection DPrintAccess::Mutex;
|
||||
DPrintState* DPrintAccess::State;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Namespace DebugPrint.
|
||||
//
|
||||
// This contains all the various versions of the DPrint routine.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
namespace DebugPrint {
|
||||
|
||||
// DPrint. Invoke all the callbacks, and store the message.
|
||||
void DPrint(const FString& fs) {
|
||||
DPrintAccess state;
|
||||
for (DPrintCallback cb : state->Callbacks) {
|
||||
cb(fs);
|
||||
}
|
||||
if (state->Collect) {
|
||||
state->Messages.Emplace(fs);
|
||||
}
|
||||
}
|
||||
|
||||
// Alternative interface to the dispatcher.
|
||||
void DPrint(const char* msg) {
|
||||
DPrint(FString(msg));
|
||||
}
|
||||
|
||||
// Alternative interface to the dispatcher.
|
||||
void DPrint(const char* msg, size_t len) {
|
||||
DPrint(FString(len, (const UTF8CHAR*)msg));
|
||||
}
|
||||
|
||||
} // namespace DebugPrint
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Namespace DebugPrintControl.
|
||||
//
|
||||
// Configuration and control for the DPrint routine.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
namespace DebugPrintControl {
|
||||
|
||||
// Register a callback. Check for duplication.
|
||||
void RegisterCallback(DPrintCallback cb) {
|
||||
DPrintAccess state;
|
||||
for (DPrintCallback old : state->Callbacks) {
|
||||
if (cb == old) return;
|
||||
}
|
||||
state->Callbacks.Add(cb);
|
||||
}
|
||||
|
||||
// Set the collection bit in the global state.
|
||||
void EnableCollection() {
|
||||
DPrintAccess state;
|
||||
state->Collect = true;
|
||||
}
|
||||
|
||||
// Get the array of collected messages, if any.
|
||||
TArray<FString> GetStored() {
|
||||
DPrintAccess state;
|
||||
TArray<FString> result = std::move(state->Messages);
|
||||
state->Messages.Empty();
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
// ConsoleOutput
|
||||
//
|
||||
// Storing the text that goes in the unreal console.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void FConsoleOutput::Append(const FString& text) {
|
||||
if (!text.IsEmpty()) {
|
||||
Content += text;
|
||||
Truncate();
|
||||
Dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FConsoleOutput::AppendLine(const FString& text) {
|
||||
int csize = Content.Len();
|
||||
if ((csize > 0) && (Content[csize - 1] != '\n')) {
|
||||
Content += TEXT("\n");
|
||||
}
|
||||
Content += text;
|
||||
Content += TEXT("\n");
|
||||
Truncate();
|
||||
Dirty = true;
|
||||
}
|
||||
|
||||
void FConsoleOutput::Truncate() {
|
||||
int lines = 50;
|
||||
int csize = Content.Len();
|
||||
int total = 0;
|
||||
for (int i = csize - 1; i >= 0; i--) {
|
||||
if (Content[i] == '\n') {
|
||||
total += 1;
|
||||
if (total == lines) {
|
||||
Content = Content.RightChop(i + 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user