/*! * \file src/Console.cpp * \brief Console 'overlay' * * \author xythobuz */ #include #include "global.h" #include "commands/Command.h" #include "Font.h" #include "Log.h" #include "utf8-cpp/utf8.h" #include "utils/strings.h" #include "utils/time.h" #include "Window.h" #include "Console.h" Console::Console() { zPos = -1; mHistoryPointer = 0; mLineOffset = 0; UI::addWindow(this); } Console::~Console() { UI::removeWindow(this); } void Console::moveToTop() { if (!getWindow().getTextInput()) getWindow().setTextInput(true); UI::moveToTop(); } void Console::makeInvisible() { if (getWindow().getTextInput()) getWindow().setTextInput(false); UI::makeInvisible(); } void Console::display() { // Calculate line drawing geometry // Depends on window height, so recalculate every time unsigned int firstLine = 35; unsigned int lastLine = (::getWindow().getHeight() / 2) - 55; unsigned int inputLine = (::getWindow().getHeight() / 2) - 30; unsigned int lineSteps = 20; unsigned int lineCount = (lastLine - firstLine + lineSteps) / lineSteps; while (((lineCount * lineSteps) + firstLine) < inputLine) { lineSteps++; lineCount = (lastLine - firstLine + lineSteps) / lineSteps; } ::getWindow().glEnter2D(); // Draw half-transparent *overlay* glColor4f(0.0f, 0.0f, 0.0f, 0.75f); glDisable(GL_TEXTURE_2D); glRecti(0, 0, ::getWindow().getWidth(), ::getWindow().getHeight() / 2); glEnable(GL_TEXTURE_2D); unsigned long scrollIndicator; if (getLog().size() > lineCount) { scrollIndicator = (getLog().size() - lineCount - mLineOffset) * 100 / (getLog().size() - lineCount); } else { scrollIndicator = 100; mLineOffset = 0; } // Draw status line std::ostringstream status; status << VERSION << " uptime " << (systemTimerGet() / 1000) << "s scroll " << scrollIndicator << "%"; getFont().drawText(10, 10, 0.70f, BLUE, status.str()); // Draw output log long end = lineCount; long drawOffset = 0; long historyOffset = 0; if (getLog().size() < lineCount) { end = getLog().size(); drawOffset = lineCount - getLog().size(); } else if (lineCount < getLog().size()) { historyOffset = getLog().size() - lineCount; } for (int i = 0; i < end; i++) { getFont().drawText(10, (unsigned int)((i + drawOffset) * lineSteps) + firstLine, 0.75f, BLUE, getLog().get(i + historyOffset - mLineOffset)); } // Draw current input getFont().drawText(10, inputLine, 0.75f, BLUE, "> " + mInputBuffer + mPartialInput); ::getWindow().glExit2D(); } void Console::handleKeyboard(KeyboardButton key, bool pressed) { if (pressed && (key == enterKey)) { // Execute entered command if (mInputBuffer.length() > 0) { getLog() << "> " << mInputBuffer.c_str() << Log::endl; mCommandHistory.push_back(mInputBuffer.c_str()); int error = Command::command(mInputBuffer); if (error != 0) { getLog() << "Error Code: " << error << Log::endl; } } else { getLog() << "> " << Log::endl; } // Clear partial and input buffer mInputBuffer = ""; mPartialInput = ""; mHistoryPointer = 0; } // Delete last character if (pressed && (key == backspaceKey)) { if ((mPartialInput.length() == 0) && (mInputBuffer.length() > 0)) { utf8::iterator it(mInputBuffer.end(), mInputBuffer.begin(), mInputBuffer.end()); mInputBuffer.erase((--it).base(), mInputBuffer.end()); } } if (pressed && ((key == upKey) || (key == downKey))) { moveInHistory(key == upKey); } } void Console::moveInHistory(bool up) { if (mCommandHistory.size() == 0) return; if (up) { if (mHistoryPointer < mCommandHistory.size()) { mHistoryPointer++; if (mHistoryPointer == 1) { mUnfinishedInput = mInputBuffer; } } else { return; } } else { if (mHistoryPointer > 0) mHistoryPointer--; else return; } if ((mHistoryPointer > 0) && (mHistoryPointer <= mCommandHistory.size())) { mInputBuffer = mCommandHistory[mCommandHistory.size() - mHistoryPointer]; } else { if (mUnfinishedInput.length() > 0) { mInputBuffer = mUnfinishedInput; mUnfinishedInput = ""; } else { mInputBuffer = ""; } } } void Console::handleText(char *text, bool notFinished) { // Always scroll to bottom when text input is received mLineOffset = 0; if (!notFinished) { // Finished entering character // delete previous partial character, if present mPartialInput = ""; //! \fixme Temporary hack filtering the console activation key if (text[0] == '`') return; // Append new input to buffer mInputBuffer += text; } else { // Partial character received mPartialInput = text; } } void Console::handleMouseScroll(int xrel, int yrel) { assert((xrel != 0) || (yrel != 0)); // Calculate line drawing geometry // Depends on window height, so recalculate every time unsigned int firstLine = 35; unsigned int lastLine = (::getWindow().getHeight() / 2) - 55; unsigned int inputLine = (::getWindow().getHeight() / 2) - 30; unsigned int lineSteps = 20; unsigned int lineCount = (lastLine - firstLine + lineSteps) / lineSteps; while (((lineCount * lineSteps) + firstLine) < inputLine) { lineSteps++; lineCount = (lastLine - firstLine + lineSteps) / lineSteps; } if (getLog().size() > lineCount) { if (yrel > 0) { if (mLineOffset < (getLog().size() - lineCount)) { mLineOffset++; } } else if (yrel < 0) { if (mLineOffset > 0) { mLineOffset--; } } } }