Commit c98bec5f authored by NTAuthority's avatar NTAuthority

'clean' console printfs, console input (for win32 only, though)

parent b3858a82
Pipeline #48 skipped
#pragma once
namespace krt
{
namespace console
{
void Printf(const char* format, ...);
void DPrintf(const char* format, ...);
void PrintWarning(const char* format, ...);
void PrintError(const char* format, ...);
// NOT thread-safe!
void AddPrintListener(void(*function)(const char*));
}
namespace sys
{
void InitializeConsole();
const char* GetConsoleInput();
}
}
\ No newline at end of file
......@@ -31,13 +31,13 @@ struct Constraints<T, std::enable_if_t<std::is_arithmetic<T>::value>>
{
if (ConsoleArgumentTraits<T>::Greater()(value, maxValue))
{
printf("Value out of range (%s) - should be at most %s\n", UnparseArgument(value).c_str(), UnparseArgument(maxValue).c_str());
console::Printf("Value out of range (%s) - should be at most %s\n", UnparseArgument(value).c_str(), UnparseArgument(maxValue).c_str());
return false;
}
if (ConsoleArgumentTraits<T>::Less()(value, minValue))
{
printf("Value out of range (%s) - should be at least %s\n", UnparseArgument(value).c_str(), UnparseArgument(minValue).c_str());
console::Printf("Value out of range (%s) - should be at least %s\n", UnparseArgument(value).c_str(), UnparseArgument(minValue).c_str());
return false;
}
......@@ -56,7 +56,7 @@ public:
{
m_getCommand = std::make_unique<ConsoleCommand>(manager->GetParentContext(), name, [=] ()
{
printf(" \"%s\" is \"%s\"\n default: \"%s\"\n type: %s\n", name.c_str(), GetValue().c_str(), UnparseArgument(m_defaultValue).c_str(), ConsoleArgumentName<T>::Get());
console::Printf(" \"%s\" is \"%s\"\n default: \"%s\"\n type: %s\n", name.c_str(), GetValue().c_str(), UnparseArgument(m_defaultValue).c_str(), ConsoleArgumentName<T>::Get());
});
m_setCommand = std::make_unique<ConsoleCommand>(manager->GetParentContext(), name, [=] (const T& newValue)
......
......@@ -32,4 +32,6 @@
#include <utils/LockUtil.h>
#include <rw.h>
#include <RwHelpers.h>
\ No newline at end of file
#include <RwHelpers.h>
#include <Console.Base.h>
\ No newline at end of file
#include <StdInc.h>
#include <Console.Base.h>
#include <Console.VariableHelpers.h>
#include <stdarg.h>
namespace krt
{
namespace console
{
static std::vector<void(*)(const char*)> g_printListeners;
static int g_useDeveloper;
void Printf(const char* format, ...)
{
// this'll only initialize the buffer if needed
static thread_local std::vector<char> buffer(32768);
va_list ap;
va_start(ap, format);
vsnprintf(&buffer[0], buffer.size(), format, ap);
va_end(ap);
// always zero-terminate
buffer[buffer.size() - 1] = '\0';
// print to all interested listeners
for (auto& listener : g_printListeners)
{
listener(buffer.data());
}
}
void DPrintf(const char* format, ...)
{
if (g_useDeveloper > 0)
{
// this'll only initialize the buffer if needed
static thread_local std::vector<char> buffer(32768);
va_list ap;
va_start(ap, format);
vsnprintf(&buffer[0], buffer.size(), format, ap);
va_end(ap);
// always zero-terminate
buffer[buffer.size() - 1] = '\0';
// do print
Printf("%s", buffer.data());
}
}
void PrintWarning(const char* format, ...)
{
// this'll only initialize the buffer if needed
static thread_local std::vector<char> buffer(32768);
va_list ap;
va_start(ap, format);
vsnprintf(&buffer[0], buffer.size(), format, ap);
va_end(ap);
// always zero-terminate
buffer[buffer.size() - 1] = '\0';
// print the string directly
Printf("^3Warning: %s^7", buffer.data());
}
void PrintError(const char* format, ...)
{
// this'll only initialize the buffer if needed
static thread_local std::vector<char> buffer(32768);
va_list ap;
va_start(ap, format);
vsnprintf(&buffer[0], buffer.size(), format, ap);
va_end(ap);
// always zero-terminate
buffer[buffer.size() - 1] = '\0';
// print the string directly
Printf("^1Error: %s^7", buffer.data());
}
void AddPrintListener(void(*function)(const char*))
{
g_printListeners.push_back(function);
}
static ConVar<int> developerVariable("developer", ConVar_Archive, 0, &g_useDeveloper);
}
}
\ No newline at end of file
......@@ -72,7 +72,7 @@ void ConsoleCommandManager::Invoke(const std::string& commandName, const Program
}
// TODO: replace with console stream output
printf("No such command %s.\n", commandName.c_str());
console::Printf("No such command %s.\n", commandName.c_str());
return;
}
......@@ -102,7 +102,7 @@ void ConsoleCommandManager::Invoke(const std::string& commandName, const Program
if (!result)
{
printf("%s", context.errorBuffer.str().c_str());
console::Printf("%s", context.errorBuffer.str().c_str());
}
}
......
......@@ -11,7 +11,7 @@ static ConsoleCommand execCommand("exec", [] (const std::string& path)
if (!stream)
{
printf("No such config file: %s\n", path.c_str());
console::Printf("No such config file: %s\n", path.c_str());
return;
}
......
......@@ -37,7 +37,7 @@ ConsoleVariableManager::ConsoleVariableManager(console::Context* parentContext)
}
}
int flags = ConVar_None;
int flags = ConVar_Modified;
if (archive)
{
......
......@@ -158,6 +158,8 @@ void Context::SaveConfigurationIfNeeded(const std::string& path)
if (numModifiedVars > 0)
{
console::DPrintf("Saving ^1c^2o^3n^4f^5i^6g^7uration to %s...\n", path.c_str());
SaveConfiguration(path, GetVariableManager());
wasSavedBefore = true;
......
#include <StdInc.h>
#include <Console.Base.h>
#include <windows.h>
#include <conio.h>
#include <fcntl.h>
#include <io.h>
#include <thread>
#include <concurrent_queue.h>
namespace krt
{
namespace sys
{
static const int g_colors[] = {
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY, // black, but actually bright white
FOREGROUND_RED | FOREGROUND_INTENSITY, // red
FOREGROUND_GREEN | FOREGROUND_INTENSITY, // green
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, // yellow
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // blue
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, // cyan
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, // magenta
FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED, // neutral
FOREGROUND_RED, // dark red
FOREGROUND_BLUE, // dark blue
};
static int MapColorCode(char color)
{
return g_colors[color - '0'];
}
static void PrintConsole(const char* string)
{
for (const char* p = string; *p; p++)
{
if (*p == '^' && isdigit(p[1]))
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), MapColorCode(p[1]));
++p;
}
else
{
DWORD dummy;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), p, 1, &dummy, nullptr);
}
}
}
void InitializeConsole()
{
console::AddPrintListener(PrintConsole);
}
// we're assuming we're using VC
concurrency::concurrent_queue<std::string> commandQueue;
const char* GetConsoleInput()
{
static bool inputInited;
if (!inputInited)
{
std::thread([] ()
{
static char text[2048];
static int len;
int c;
DWORD mode = 0;
GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode);
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode & (~ENABLE_ECHO_INPUT) & (~ENABLE_LINE_INPUT));
_setmode(_fileno(stdin), _O_BINARY);
// read a line out
while ((c = getchar()) != EOF)
{
//c = _getch();
printf("%c", c);
if (c == '\r')
{
text[len] = '\n';
text[len + 1] = 0;
printf("%c", '\n');
len = 0;
commandQueue.push(text);
}
if (c == 8)
{
if (len)
{
printf(" %c", c);
len--;
text[len] = 0;
}
continue;
}
text[len] = c;
len++;
text[len] = 0;
if (len == (sizeof(text) - 1))
len = 0;
}
}).detach();
inputInited = true;
}
if (commandQueue.empty())
{
return nullptr;
}
std::string entry;
if (commandQueue.try_pop(entry))
{
static std::string entryText;
entryText = entry;
return entryText.c_str();
}
return nullptr;
}
}
}
\ No newline at end of file
......@@ -3,6 +3,8 @@
#include <sys/Timer.h>
#include <Console.h>
namespace krt
{
class NullEvent : public Event
......@@ -14,10 +16,40 @@ class NullEvent : public Event
}
};
class ConsoleInputEvent : public Event
{
private:
std::string m_text;
public:
ConsoleInputEvent(const std::string& input)
: m_text(input)
{
SetTime(sys::Milliseconds());
}
void Handle() override
{
console::AddToBuffer(m_text);
}
};
static void ProcessConsoleInput(EventSystem* eventSystem)
{
const char* consoleBuffer = sys::GetConsoleInput();
if (consoleBuffer)
{
eventSystem->QueueEvent(std::make_unique<ConsoleInputEvent>(consoleBuffer));
}
}
uint64_t EventSystem::HandleEvents()
{
while (true)
{
ProcessConsoleInput(this);
std::unique_ptr<Event> event = GetEvent();
if (dynamic_cast<NullEvent*>(event.get()) != nullptr)
......
......@@ -9,6 +9,8 @@
#include "CdImageDevice.h"
#include <Console.VariableHelpers.h>
namespace krt
{
static void make_lower(std::string& str)
......@@ -56,8 +58,15 @@ inline std::string get_file_name(std::string path, std::string* extOut = NULL)
return std::string(fileNameStart, pathIter);
}
static bool g_fileloaderDebug;
void FileLoader::ScanIMG(const vfs::DevicePtr& imgDevice, const std::string& pathPrefix, const GameUniversePtr& universe)
{
if (g_fileloaderDebug)
{
console::Printf("Scanning CD image %s\n", pathPrefix.c_str());
}
// We now have to parse the contents of the IMG archive. :)
{
vfs::FindData findData;
......@@ -471,6 +480,12 @@ void FileLoader::LoadIDEFile(const std::string& relPath, const GameUniversePtr&
// set the universe we parse into
g_currentParseUniverse = universe;
// debug print
if (g_fileloaderDebug)
{
console::Printf("Loading IDE file %s into universe %s\n", relPath.c_str(), g_currentParseUniverse->GetConfiguration().gameName.c_str());
}
// load the section file
ProcessSectionedFile(ideSections, ideFile);
......@@ -802,10 +817,18 @@ void FileLoader::LoadIPLFile(const std::string& absPath, const GameUniversePtr&
// set the universe we parse into
g_currentParseUniverse = universe;
// debug print
if (g_fileloaderDebug)
{
console::Printf("Loading IPL file %s into universe %s\n", absPath.c_str(), g_currentParseUniverse->GetConfiguration().gameName.c_str());
}
// load the section file
ProcessSectionedFile(iplSections, iplFileData);
// unset the universe
g_currentParseUniverse.reset();
}
static ConVar<bool> g_fileloaderDebugVar("fileLoader_debug", ConVar_Archive, false, &g_fileloaderDebug);
}
\ No newline at end of file
......@@ -28,6 +28,8 @@ Game::Game(void) : streaming(GAME_NUM_STREAMING_CHANNELS), texManager(streaming)
{
assert(theGame == NULL);
sys::InitializeConsole();
// Initialize console variables.
maxFPSVariable = std::make_unique<ConVar<int>>("maxFPS", ConVar_Archive, 60, &maxFPS);
timescaleVariable = std::make_unique<ConVar<float>>("timescale", ConVar_None, 1.0f, &timescale);
......@@ -147,7 +149,7 @@ void Game::Run()
if (millis > 500)
{
printf("long frame: %d millis\n", millis);
console::Printf("long frame: %d millis\n", millis);
}
// store timing values for this frame
......
......@@ -37,9 +37,7 @@ static std::mutex safety_lock;
static void DebugMessage(const std::string& msg)
{
std::unique_lock<std::mutex> msgLock;
std::cout << msg << std::endl;
console::Printf("%s\n", msg.c_str());
}
class TestInterface : public streaming::StreamingTypeInterface
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment