#include "CStdConsole.h" #include "CEngine.h" #include "U_Platform.h" #include "U_ConsoleColors.h" #include "CConVarManager.h" #include "CCommandProcessor.h" #include "CWrapable.h" #include void CStdConsole::V_Init() { auto mgr = CEngine::GetInstance()->Components.GetComponentTyped(); mgr->AddConVar("con.time.maxfps", new CWrapable(20)); mgr->AddConVar("con.time.yield", new CWrapable(true)); mgr->AddConVar("con.time.adaptive_sleep", new CWrapable(true)); mgr->AddConVar("con.time.strict_sleep", new CWrapable(false)); COMPONENT_CALL(CConVarManager, AddConVar("con.max_msg", new CWrapable(100))); //std::ios::sync_with_stdio(false); //std::cin.tie(nullptr); Crossplatform::CreateConsole(); m_consoleThread = std::make_unique(&CStdConsole::m_threadedWorker, this); } void CStdConsole::V_DeInit() { AsyncState.Set(1); //while (AsyncState.Get() != 2) { std::this_thread::yield(); } if (m_consoleThread->joinable()) { m_consoleThread->join(); } Crossplatform::DestroyConsole(); //COMPONENT_CALL(CConVarManager, DeleteConVar("con.max_msg")); TODO segmentation fault } void CStdConsole::Print(const std::wstring& text) { std::wcout << text; } void CStdConsole::Error(const std::wstring& err) { auto oldcolors = GetColor(); SetColor(CColor::Red, oldcolors.second); //TODO don't hardcode the error color std::wcerr << err; SetColor(oldcolors.first, oldcolors.second); } void CStdConsole::SetColor(const CColor& text, const CColor& bg) { CConsoleColor txt = ConsoleColors::RGBToConsoleColor(text); CConsoleColor bag = ConsoleColors::RGBToConsoleColor(bg); Crossplatform::SetConsoleColors(txt, bag); bgCol = bg; txCol = text; } std::pair CStdConsole::GetColor() const { return { txCol, bgCol }; } void CStdConsole::m_threadedWorker() { while (true) { if(CEngine::GetInstance()->GetStopFlag()) { return; } auto mgr = CEngine::GetInstance()->Components.GetComponentTyped(); auto maxfps = mgr->GetConVarValue("con.time.maxfps"); Sleeper.Start(maxfps); auto yield = mgr->GetConVarValue("con.time.yield"); auto adaptive_sleep = mgr->GetConVarValue("con.time.adaptive_sleep"); auto strict_sleep = mgr->GetConVarValue("con.time.strict_sleep"); unsigned int maxmsg = 100; COMPONENT_CALL_GET(maxmsg, CConVarManager, GetConVarValue("con.max_msg", 100)); for (size_t i = 0U; i < maxmsg; i++) { if (!_kbhit()) { continue; } constexpr int key_backspace = 8; constexpr int key_enter = 13; constexpr int key_del = 127; constexpr int key_special = 224; constexpr int key_up = 72; constexpr int key_down = 80; constexpr int key_left = 75; constexpr int key_right = 77; constexpr int key_delete = 83; constexpr int key_insert = 82; constexpr int key_home = 71; constexpr int key_end = 79; constexpr int key_pgup = 73; constexpr int key_pgdn = 81; int key = _getch(); if (key == key_backspace) { if (!m_Input.empty()) { m_Input.pop_back(); COMPONENT_CALL(CCommandProcessor, History.EditedCommand(m_Input)); std::wcout << L'\b' << L' ' << L'\b'; } } else if (key == key_special) { key = _getch(); //TODO create method ReplaceText instead of fors if (key == key_up) { for (size_t i = 0U; i < m_Input.size(); i++) { std::wcout << L'\b'; } //HACK HACK HACK for (size_t i = 0U; i < m_Input.size(); i++) { std::wcout << L' '; } for (size_t i = 0U; i < m_Input.size(); i++) { std::wcout << L'\b'; } COMPONENT_CALL_GET(m_Input, CCommandProcessor, History.GetNext()); std::wcout << m_Input; } else if (key == key_down) { for (size_t i = 0U; i < m_Input.size(); i++) { std::wcout << L'\b'; } //HACK HACK HACK for (size_t i = 0U; i < m_Input.size(); i++) { std::wcout << L' '; } for (size_t i = 0U; i < m_Input.size(); i++) { std::wcout << L'\b'; } COMPONENT_CALL_GET(m_Input, CCommandProcessor, History.GetPrev()); std::wcout << m_Input; } } else if (key > 31 && key != 127) { m_Input.push_back(key); COMPONENT_CALL(CCommandProcessor, History.EditedCommand(m_Input)); std::wcout << wchar_t(key); } if (!m_Input.empty() && key == key_enter) { std::wcout << '\n'; SendCommand(m_Input); m_Input.clear(); } } if(AsyncState.Get() == 1) { AsyncState.Set(2); break; } Sleeper.End(yield, adaptive_sleep, strict_sleep); } } CStdConsole::~CStdConsole() { } LINK_CONSOLE_TO_CLASS(CStdConsole, stdconsole);