A Demo Project for the UnrealEngineSDK
Loading...
Searching...
No Matches
INYLogger.cpp
Go to the documentation of this file.
1// Copyright Csaba Molnar, Daniel Butum. All Rights Reserved.
2#include "Logging/INYLogger.h"
3#include "CoreGlobals.h"
4#include "Misc/OutputDevice.h"
5#include "Misc/UObjectToken.h"
6#include "Misc/FeedbackContext.h"
7#include "GameFramework/PlayerController.h"
8#include "Engine/Engine.h"
9#include "Logging/MessageLog.h"
10
11#if WITH_UNREAL_DEVELOPER_TOOLS
12#include "MessageLogInitializationOptions.h"
13#include "MessageLogModule.h"
14#endif // WITH_UNREAL_DEVELOPER_TOOLS
15
16#include "Modules/ModuleManager.h"
17
18#if ENGINE_MINOR_VERSION >= 24
19 #define NY_ARRAY_COUNT UE_ARRAY_COUNT
20#else
21 #define NY_ARRAY_COUNT ARRAY_COUNT
22#endif
23
24
25// Pulled the two FOutputDevice::Logf functions into shared code. Needs to be a #define
26// since it uses GET_VARARGS_RESULT which uses the va_list stuff which operates on the
27// current function, so we can't easily call a function
28#define NY_GROWABLE_LOGF(SerializeFunc) \
29 int32 BufferSize = 1024; \
30 TCHAR* Buffer = NULL; \
31 int32 Result = -1; \
32 /* allocate some stack space to use on the first pass, which matches most strings */ \
33 TCHAR StackBuffer[512]; \
34 TCHAR* AllocatedBuffer = NULL; \
35\
36 /* first, try using the stack buffer */ \
37 Buffer = StackBuffer; \
38 GET_VARARGS_RESULT( Buffer, NY_ARRAY_COUNT(StackBuffer), NY_ARRAY_COUNT(StackBuffer) - 1, Fmt, Fmt, Result ); \
39\
40 /* if that fails, then use heap allocation to make enough space */ \
41 while(Result == -1) \
42 { \
43 FMemory::SystemFree(AllocatedBuffer); \
44 /* We need to use malloc here directly as GMalloc might not be safe. */ \
45 Buffer = AllocatedBuffer = (TCHAR*) FMemory::SystemMalloc( BufferSize * sizeof(TCHAR) ); \
46 GET_VARARGS_RESULT( Buffer, BufferSize, BufferSize-1, Fmt, Fmt, Result ); \
47 BufferSize *= 2; \
48 }; \
49 Buffer[Result] = 0; \
50 ; \
51\
52 SerializeFunc; \
53 FMemory::SystemFree(AllocatedBuffer);
54
55
61
63{
64#if NO_LOGGING
65 return nullptr;
66#endif
67
68 switch (Level)
69 {
71 return nullptr;
72
75 return GWarn;
76
77 default:
78 return GLog;
79 }
80}
81
82#if WITH_UNREAL_DEVELOPER_TOOLS
83FMessageLogModule* INYLogger::GetMessageLogModule()
84{
85 return FModuleManager::LoadModulePtr<FMessageLogModule>("MessageLog");
86}
87#endif // WITH_UNREAL_DEVELOPER_TOOLS
88
90{
91#if WITH_UNREAL_DEVELOPER_TOOLS
92 FMessageLogModule* MessageLogModule = GetMessageLogModule();
93 if (!MessageLogModule)
94 {
95 return false;
96 }
97
98 return MessageLogModule->IsRegisteredLogListing(LogName);
99#else
100 return false;
101#endif // WITH_UNREAL_DEVELOPER_TOOLS
102}
103
104void INYLogger::MessageLogRegisterLogName(FName LogName, const FText& LogLabel, const FNYMessageLogInitializationOptions& InitOptions)
105{
106#if WITH_UNREAL_DEVELOPER_TOOLS
107 FMessageLogModule* MessageLogModule = GetMessageLogModule();
108 if (!MessageLogModule)
109 {
110 return;
111 }
112
113 FMessageLogInitializationOptions UnrealInitOptions;
114 UnrealInitOptions.bShowFilters = InitOptions.bShowFilters;
115 UnrealInitOptions.bShowPages = InitOptions.bShowPages;
116 UnrealInitOptions.bAllowClear = InitOptions.bAllowClear;
117 UnrealInitOptions.bDiscardDuplicates = InitOptions.bDiscardDuplicates;
118 UnrealInitOptions.MaxPageCount = InitOptions.MaxPageCount;
119 UnrealInitOptions.bShowInLogWindow = InitOptions.bShowInLogWindow;
120
121 MessageLogModule->RegisterLogListing(LogName, LogLabel, UnrealInitOptions);
122#endif // WITH_UNREAL_DEVELOPER_TOOLS
123}
124
126{
127#if WITH_UNREAL_DEVELOPER_TOOLS
128 FMessageLogModule* MessageLogModule = GetMessageLogModule();
129 if (!MessageLogModule)
130 {
131 return false;
132 }
133
134 return MessageLogModule->UnregisterLogListing(LogName);
135#else
136 return false;
137#endif // WITH_UNREAL_DEVELOPER_TOOLS
138}
139
140#if WITH_UNREAL_DEVELOPER_TOOLS
141TSharedPtr<IMessageLogListing> INYLogger::MessageLogGetLogNameListing(FName LogName)
142{
143 FMessageLogModule* MessageLogModule = GetMessageLogModule();
144 if (!MessageLogModule)
145 {
146 return nullptr;
147 }
148
149 return MessageLogModule->GetLogListing(LogName);
150}
151#endif // WITH_UNREAL_DEVELOPER_TOOLS
152
154{
155#if WITH_UNREAL_DEVELOPER_TOOLS
156 FMessageLogModule* MessageLogModule = GetMessageLogModule();
157 if (!MessageLogModule)
158 {
159 return;
160 }
161
162 MessageLogModule->OpenMessageLog(LogName);
163#endif // WITH_UNREAL_DEVELOPER_TOOLS
164}
165
166void INYLogger::LogfImplementation(ENYLoggerLogLevel Level, const TCHAR* Fmt, ...)
167{
168#if !NO_LOGGING
169 NY_GROWABLE_LOGF(Log(Level, Buffer))
170#endif // !NO_LOGGING
171}
172
173// void INYLogger::Fatal(const ANSICHAR* File, int32 Line, const FString& Message)
174// {
175// #if NO_LOGGING
176// LowLevelFatalErrorHandler(File, Line, *Message);
177// _DebugBreakAndPromptForRemote();
178// FDebug::AssertFailed("", File, Line, *Message);
179// #else
180// LowLevelFatalErrorHandler(File, Line, *Message);
181// _DebugBreakAndPromptForRemote();
182// FDebug::AssertFailed("", File, Line, *Message);
183// #endif // NO_LOGGING
184// }
185
186void INYLogger::Log(ENYLoggerLogLevel Level, const FString& Message)
187{
188 // Should not happen but just in case redirect to the fatal function
189 // if (Level == ENYLoggerLogLevel::Fatal)
190 // {
191 // Fatal(__FILE__, __LINE__, Message);
192 // return;
193 // }
194
195 // No logging, abort
196#if !NO_LOGGING
198 {
199 LogClientConsole(Level, Message);
200 }
201 if (IsOnScreenEnabled())
202 {
203 LogScreen(Level, Message);
204 }
205 if (IsOutputLogEnabled())
206 {
207 LogOutputLog(Level, Message);
208 }
210 {
211 LogMessageLog(Level, Message);
212 }
213#endif // !NO_LOGGING
214}
215
216void INYLogger::LogScreen(ENYLoggerLogLevel Level, const FString& Message)
217{
218 if (!GEngine)
219 {
220 return;
221 }
222
223 const bool bPreviousValue = AreAllOnScreenMessagesEnabled();
225 {
227 }
228
229 const uint64 Key = INDEX_NONE;
230 const FColor Color = GetColorForLogLevel(Level);
231 GEngine->AddOnScreenDebugMessage(Key, ScreenLogDisplayTimeSeconds, Color, Message, bScreenNewerOnTop, ScreenTextScale);
232
234 {
235 SetAreAllOnScreenMessagesEnabled(bPreviousValue);
236 }
237}
238
239void INYLogger::LogClientConsole(ENYLoggerLogLevel Level, const FString& Message)
240{
241 if (!IsValid(PlayerController) || !PlayerController->IsValidLowLevelFast())
242 {
243 return;
244 }
245
246 // These arguments seem to not be used
247 const FName Type = NAME_None;
248 const float LifetimeSeconds = 0.f;
249 PlayerController->ClientMessage(Message, Type, LifetimeSeconds);
250}
251
252void INYLogger::LogMessageLog(ENYLoggerLogLevel Level, const FString& Message)
253{
254 // Should we be redirecting this message log because
257 {
258 // Redirect to the output log if not enabled
259 if (!IsOutputLogEnabled())
260 {
261 LogOutputLog(Level, Message);
262 }
263 return;
264 }
265
266 // TSharedRef<FTokenizedMessage> NewMessage = FTokenizedMessage::Create(Severity);
267 const EMessageSeverity::Type Severity = GetMessageSeverityForLogLevel(Level);
268 auto MessageLog = FMessageLog(MessageLogName);
269 MessageLog.SuppressLoggingToOutputLog(!bMessageLogMirrorToOutputLog);
270 MessageLog.Message(Severity, FText::FromString(Message));
271
272 // Open message log
274 {
275 MessageLog.Open(Severity, false);
276 }
277}
278
279void INYLogger::LogOutputLog(ENYLoggerLogLevel Level, const FString& Message)
280{
281 FOutputDevice* LogDevice = GetOutputDeviceFromLogLevel(Level);
282 if (!LogDevice)
283 {
284 return;
285 }
286
287 const ELogVerbosity::Type UnrealLogType = GetUnrealLogTypeForLogLevel(Level);
288 LogDevice->Log(OutputLogCategory, UnrealLogType, Message);
289}
290
291
293{
294 if (!GEngine)
295 {
296 return;
297 }
298
299 GEngine->ClearOnScreenDebugMessages();
300}
301
302#undef NY_ARRAY_COUNT
#define NY_GROWABLE_LOGF(SerializeFunc)
Definition INYLogger.cpp:28
ENYLoggerLogLevel
UENUM()
Definition INYLogger.h:47
ENYLoggerLogLevel OpenMessageLogLevelsHigherThan
Definition INYLogger.h:468
FORCEINLINE bool IsOnScreenEnabled() const
Definition INYLogger.h:292
float ScreenLogDisplayTimeSeconds
Definition INYLogger.h:418
virtual void LogOutputLog(ENYLoggerLogLevel Level, const FString &Message)
static FOutputDevice * GetOutputDeviceFromLogLevel(ENYLoggerLogLevel Level)
Definition INYLogger.cpp:62
static bool IsMessageLogNameRegistered(FName LogName)
Definition INYLogger.cpp:89
FORCEINLINE bool IsMessageLogEnabled() const
Definition INYLogger.h:294
bool bScreenNewerOnTop
Definition INYLogger.h:424
FORCEINLINE bool IsClientConsoleEnabled() const
Definition INYLogger.h:291
FColor GetColorForLogLevel(ENYLoggerLogLevel Level) const
Definition INYLogger.h:384
FVector2D ScreenTextScale
Definition INYLogger.h:421
virtual void LogScreen(ENYLoggerLogLevel Level, const FString &Message)
static FORCEINLINE void EnableAllOnScreenMessages()
Definition INYLogger.h:186
FName OutputLogCategory
Definition INYLogger.h:437
ENYLoggerLogLevel RedirectMessageLogLevelsHigherThan
Definition INYLogger.h:460
void Log(ENYLoggerLogLevel Level, const FString &Message)
virtual void LogClientConsole(ENYLoggerLogLevel Level, const FString &Message)
bool bMessageLogOpen
Definition INYLogger.h:464
Self & SetClientConsolePlayerController(APlayerController *PC)
Definition INYLogger.cpp:56
static void MessageLogOpenLogName(FName LogName)
bool bForceEnableScreenMessages
Definition INYLogger.h:427
static EMessageSeverity::Type GetMessageSeverityForLogLevel(ENYLoggerLogLevel Level)
Definition INYLogger.h:366
static FORCEINLINE void SetAreAllOnScreenMessagesEnabled(bool bValue)
Definition INYLogger.h:181
static void MessageLogRegisterLogName(FName LogName, const FText &LogLabel, const FNYMessageLogInitializationOptions &InitOptions={})
void VARARGS LogfImplementation(ENYLoggerLogLevel Level, const TCHAR *Fmt,...)
static void ClearAllOnScreenLogs()
static FORCEINLINE bool AreAllOnScreenMessagesEnabled()
Definition INYLogger.h:180
APlayerController * PlayerController
Definition INYLogger.h:478
virtual void LogMessageLog(ENYLoggerLogLevel Level, const FString &Message)
bool bMessageLogMirrorToOutputLog
Definition INYLogger.h:453
FORCEINLINE bool IsOutputLogEnabled() const
Definition INYLogger.h:293
static bool MessageLogUnregisterLogName(FName LogName)
FName MessageLogName
Definition INYLogger.h:450
static ELogVerbosity::Type GetUnrealLogTypeForLogLevel(ENYLoggerLogLevel Level)
Definition INYLogger.h:343
bool bDiscardDuplicates
Whether to check for duplicate messages & discard them.
Definition INYLogger.h:33