mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 22:29:39 -06:00
Remove the embedded Console from the possible logging options.
Note I do not mean the Logging window, but the console window. It's literally rarely, if at all used, and offers less advantages over the built-in logging window (ie. it breaks on different locales: http://i.imgur.com/Cs92tQE.png) This commit should remove all of the console logging.
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
@ -54,7 +54,6 @@
|
||||
<ClInclude Include="CommonFuncs.h" />
|
||||
<ClInclude Include="CommonPaths.h" />
|
||||
<ClInclude Include="CommonTypes.h" />
|
||||
<ClInclude Include="ConsoleListener.h" />
|
||||
<ClInclude Include="CPUDetect.h" />
|
||||
<ClInclude Include="Crypto\tools.h" />
|
||||
<ClInclude Include="DebugInterface.h" />
|
||||
@ -93,7 +92,6 @@
|
||||
<ClCompile Include="BreakPoints.cpp" />
|
||||
<ClCompile Include="CDUtils.cpp" />
|
||||
<ClCompile Include="ColorUtil.cpp" />
|
||||
<ClCompile Include="ConsoleListener.cpp" />
|
||||
<ClCompile Include="Crypto\bn.cpp" />
|
||||
<ClCompile Include="Crypto\ec.cpp" />
|
||||
<ClCompile Include="ExtendedTrace.cpp" />
|
||||
@ -139,4 +137,4 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Crypto">
|
||||
@ -52,9 +52,6 @@
|
||||
<ClInclude Include="Crypto\tools.h">
|
||||
<Filter>Crypto</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ConsoleListener.h">
|
||||
<Filter>Logging</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Log.h">
|
||||
<Filter>Logging</Filter>
|
||||
</ClInclude>
|
||||
@ -97,9 +94,6 @@
|
||||
<ClCompile Include="Crypto\ec.cpp">
|
||||
<Filter>Crypto</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ConsoleListener.cpp">
|
||||
<Filter>Logging</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LogManager.cpp">
|
||||
<Filter>Logging</Filter>
|
||||
</ClCompile>
|
||||
@ -108,4 +102,4 @@
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
@ -1,334 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm> // min
|
||||
#include <cstdlib>
|
||||
#include <string> // System: To be able to add strings with "+"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <array>
|
||||
#endif
|
||||
|
||||
#include "ConsoleListener.h" // Common
|
||||
|
||||
ConsoleListener::ConsoleListener()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
hConsole = NULL;
|
||||
bUseColor = true;
|
||||
#else
|
||||
bUseColor = isatty(fileno(stdout));
|
||||
#endif
|
||||
}
|
||||
|
||||
ConsoleListener::~ConsoleListener()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
// 100, 100, "Dolphin Log Console"
|
||||
// Open console window - width and height is the size of console window
|
||||
// Name is the window title
|
||||
void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!GetConsoleWindow())
|
||||
{
|
||||
// Open the console window and create the window handle for GetStdHandle()
|
||||
AllocConsole();
|
||||
// Hide
|
||||
if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE);
|
||||
// Save the window handle that AllocConsole() created
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
// Set the console window title
|
||||
SetConsoleTitle(UTF8ToTStr(Title).c_str());
|
||||
// Set letter space
|
||||
LetterSpace(80, 4000);
|
||||
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConsoleListener::UpdateHandle()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Close the console window and close the eventual file handle
|
||||
void ConsoleListener::Close()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (hConsole == NULL)
|
||||
return;
|
||||
FreeConsole();
|
||||
hConsole = NULL;
|
||||
#else
|
||||
fflush(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ConsoleListener::IsOpen()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return (hConsole != NULL);
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are
|
||||
dependent on each other, that's the reason for the additional checks.
|
||||
*/
|
||||
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
BOOL SB, SW;
|
||||
if (BufferFirst)
|
||||
{
|
||||
// Change screen buffer size
|
||||
COORD Co = {BufferWidth, BufferHeight};
|
||||
SB = SetConsoleScreenBufferSize(hConsole, Co);
|
||||
// Change the screen buffer window size
|
||||
SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
||||
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Change the screen buffer window size
|
||||
SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
|
||||
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
|
||||
// Change screen buffer size
|
||||
COORD Co = {BufferWidth, BufferHeight};
|
||||
SB = SetConsoleScreenBufferSize(hConsole, Co);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
void ConsoleListener::LetterSpace(int Width, int Height)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Get console info
|
||||
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
|
||||
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
|
||||
|
||||
//
|
||||
int OldBufferWidth = ConInfo.dwSize.X;
|
||||
int OldBufferHeight = ConInfo.dwSize.Y;
|
||||
int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left);
|
||||
int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top);
|
||||
//
|
||||
int NewBufferWidth = Width;
|
||||
int NewBufferHeight = Height;
|
||||
int NewScreenWidth = NewBufferWidth - 1;
|
||||
int NewScreenHeight = OldScreenHeight;
|
||||
|
||||
// Width
|
||||
BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1));
|
||||
// Height
|
||||
BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1));
|
||||
|
||||
// Resize the window too
|
||||
//MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
|
||||
#endif
|
||||
}
|
||||
#ifdef _WIN32
|
||||
COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
|
||||
{
|
||||
COORD Ret = {0, 0};
|
||||
// Full rows
|
||||
int Step = (int)floor((float)BytesRead / (float)BufferWidth);
|
||||
Ret.Y += Step;
|
||||
// Partial row
|
||||
Ret.X = BytesRead - (BufferWidth * Step);
|
||||
return Ret;
|
||||
}
|
||||
#endif
|
||||
void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
// Check size
|
||||
if (Width < 8 || Height < 12) return;
|
||||
|
||||
bool DBef = true;
|
||||
bool DAft = true;
|
||||
std::string SLog = "";
|
||||
|
||||
const HWND hWnd = GetConsoleWindow();
|
||||
const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
// Get console info
|
||||
CONSOLE_SCREEN_BUFFER_INFO ConInfo;
|
||||
GetConsoleScreenBufferInfo(hConsole, &ConInfo);
|
||||
DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Save the current text
|
||||
// ------------------------
|
||||
DWORD cCharsRead = 0;
|
||||
COORD coordScreen = { 0, 0 };
|
||||
|
||||
static const int MAX_BYTES = 1024 * 16;
|
||||
|
||||
std::vector<std::array<TCHAR, MAX_BYTES>> Str;
|
||||
std::vector<std::array<WORD, MAX_BYTES>> Attr;
|
||||
|
||||
// ReadConsoleOutputAttribute seems to have a limit at this level
|
||||
static const int ReadBufferSize = MAX_BYTES - 32;
|
||||
|
||||
DWORD cAttrRead = ReadBufferSize;
|
||||
DWORD BytesRead = 0;
|
||||
while (BytesRead < BufferSize)
|
||||
{
|
||||
Str.resize(Str.size() + 1);
|
||||
if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead))
|
||||
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
|
||||
|
||||
Attr.resize(Attr.size() + 1);
|
||||
if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead))
|
||||
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
|
||||
|
||||
// Break on error
|
||||
if (cAttrRead == 0) break;
|
||||
BytesRead += cAttrRead;
|
||||
coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X);
|
||||
}
|
||||
// Letter space
|
||||
int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f);
|
||||
int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f);
|
||||
int LBufWidth = LWidth + 1;
|
||||
int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth);
|
||||
// Change screen buffer size
|
||||
LetterSpace(LBufWidth, LBufHeight);
|
||||
|
||||
|
||||
ClearScreen(true);
|
||||
coordScreen.Y = 0;
|
||||
coordScreen.X = 0;
|
||||
DWORD cCharsWritten = 0;
|
||||
|
||||
int BytesWritten = 0;
|
||||
DWORD cAttrWritten = 0;
|
||||
for (size_t i = 0; i < Attr.size(); i++)
|
||||
{
|
||||
if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten))
|
||||
SLog += StringFromFormat("WriteConsoleOutputCharacter error");
|
||||
if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten))
|
||||
SLog += StringFromFormat("WriteConsoleOutputAttribute error");
|
||||
|
||||
BytesWritten += cAttrWritten;
|
||||
coordScreen = GetCoordinates(BytesWritten, LBufWidth);
|
||||
}
|
||||
|
||||
const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
|
||||
COORD Coo = GetCoordinates(OldCursor, LBufWidth);
|
||||
SetConsoleCursorPosition(hConsole, Coo);
|
||||
|
||||
if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str());
|
||||
|
||||
// Resize the window too
|
||||
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
/*
|
||||
const int MAX_BYTES = 1024*10;
|
||||
char Str[MAX_BYTES];
|
||||
va_list ArgPtr;
|
||||
int Cnt;
|
||||
va_start(ArgPtr, Text);
|
||||
Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr);
|
||||
va_end(ArgPtr);
|
||||
*/
|
||||
DWORD cCharsWritten;
|
||||
WORD Color;
|
||||
|
||||
switch (Level)
|
||||
{
|
||||
case NOTICE_LEVEL: // light green
|
||||
Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case ERROR_LEVEL: // light red
|
||||
Color = FOREGROUND_RED | FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case WARNING_LEVEL: // light yellow
|
||||
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case INFO_LEVEL: // cyan
|
||||
Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
|
||||
break;
|
||||
case DEBUG_LEVEL: // gray
|
||||
Color = FOREGROUND_INTENSITY;
|
||||
break;
|
||||
default: // off-white
|
||||
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
break;
|
||||
}
|
||||
if (strlen(Text) > 10)
|
||||
{
|
||||
// First 10 chars white
|
||||
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
|
||||
WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL);
|
||||
Text += 10;
|
||||
}
|
||||
SetConsoleTextAttribute(hConsole, Color);
|
||||
WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL);
|
||||
#else
|
||||
char ColorAttr[16] = "";
|
||||
char ResetAttr[16] = "";
|
||||
|
||||
if (bUseColor)
|
||||
{
|
||||
strcpy(ResetAttr, "\033[0m");
|
||||
switch (Level)
|
||||
{
|
||||
case NOTICE_LEVEL: // light green
|
||||
strcpy(ColorAttr, "\033[92m");
|
||||
break;
|
||||
case ERROR_LEVEL: // light red
|
||||
strcpy(ColorAttr, "\033[91m");
|
||||
break;
|
||||
case WARNING_LEVEL: // light yellow
|
||||
strcpy(ColorAttr, "\033[93m");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr);
|
||||
#endif
|
||||
}
|
||||
// Clear console screen
|
||||
void ConsoleListener::ClearScreen(bool Cursor)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
COORD coordScreen = { 0, 0 };
|
||||
DWORD cCharsWritten;
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
DWORD dwConSize;
|
||||
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||
dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
|
||||
// Write space to the entire console
|
||||
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
|
||||
GetConsoleScreenBufferInfo(hConsole, &csbi);
|
||||
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
|
||||
// Reset cursor
|
||||
if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1,38 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "LogManager.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
class ConsoleListener : public LogListener
|
||||
{
|
||||
public:
|
||||
ConsoleListener();
|
||||
~ConsoleListener();
|
||||
|
||||
void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console");
|
||||
void UpdateHandle();
|
||||
void Close();
|
||||
bool IsOpen();
|
||||
void LetterSpace(int Width, int Height);
|
||||
void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst);
|
||||
void PixelSpace(int Left, int Top, int Width, int Height, bool);
|
||||
#ifdef _WIN32
|
||||
COORD GetCoordinates(int BytesRead, int BufferWidth);
|
||||
#endif
|
||||
void Log(LogTypes::LOG_LEVELS, const char *Text);
|
||||
void ClearScreen(bool Cursor = true);
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
HWND GetHwnd(void);
|
||||
HANDLE hConsole;
|
||||
#endif
|
||||
bool bUseColor;
|
||||
};
|
@ -8,7 +8,6 @@
|
||||
#include "Host.h"
|
||||
#endif
|
||||
#include "LogManager.h"
|
||||
#include "ConsoleListener.h"
|
||||
#include "Timer.h"
|
||||
#include "Thread.h"
|
||||
#include "FileUtil.h"
|
||||
@ -77,18 +76,11 @@ LogManager::LogManager()
|
||||
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
|
||||
|
||||
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
|
||||
m_consoleLog = new ConsoleListener();
|
||||
m_debuggerLog = new DebuggerLogListener();
|
||||
|
||||
for (LogContainer* container : m_Log)
|
||||
{
|
||||
container->SetEnable(true);
|
||||
container->AddListener(m_fileLog);
|
||||
container->AddListener(m_consoleLog);
|
||||
#ifdef _MSC_VER
|
||||
if (IsDebuggerPresent())
|
||||
container->AddListener(m_debuggerLog);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -97,16 +89,12 @@ LogManager::~LogManager()
|
||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
||||
{
|
||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
|
||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
|
||||
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
|
||||
}
|
||||
|
||||
for (LogContainer* container : m_Log)
|
||||
delete container;
|
||||
|
||||
delete m_fileLog;
|
||||
delete m_consoleLog;
|
||||
delete m_debuggerLog;
|
||||
}
|
||||
|
||||
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
|
||||
@ -187,10 +175,3 @@ void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
||||
std::lock_guard<std::mutex> lk(m_log_lock);
|
||||
m_logfile << msg << std::flush;
|
||||
}
|
||||
|
||||
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
|
||||
{
|
||||
#if _MSC_VER
|
||||
::OutputDebugStringA(msg);
|
||||
#endif
|
||||
}
|
||||
|
@ -44,12 +44,6 @@ private:
|
||||
bool m_enable;
|
||||
};
|
||||
|
||||
class DebuggerLogListener : public LogListener
|
||||
{
|
||||
public:
|
||||
void Log(LogTypes::LOG_LEVELS, const char *msg);
|
||||
};
|
||||
|
||||
class LogContainer
|
||||
{
|
||||
public:
|
||||
@ -81,15 +75,11 @@ private:
|
||||
std::set<LogListener*> m_listeners;
|
||||
};
|
||||
|
||||
class ConsoleListener;
|
||||
|
||||
class LogManager : NonCopyable
|
||||
{
|
||||
private:
|
||||
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
|
||||
FileLogListener *m_fileLog;
|
||||
ConsoleListener *m_consoleLog;
|
||||
DebuggerLogListener *m_debuggerLog;
|
||||
static LogManager *m_logManager; // Singleton. Ugh.
|
||||
|
||||
LogManager();
|
||||
@ -141,16 +131,6 @@ public:
|
||||
return m_fileLog;
|
||||
}
|
||||
|
||||
ConsoleListener *GetConsoleListener() const
|
||||
{
|
||||
return m_consoleLog;
|
||||
}
|
||||
|
||||
DebuggerLogListener *GetDebuggerListener() const
|
||||
{
|
||||
return m_debuggerLog;
|
||||
}
|
||||
|
||||
static LogManager* GetInstance()
|
||||
{
|
||||
return m_logManager;
|
||||
|
Reference in New Issue
Block a user