From: Christoph Sommer Date: Sat, 8 Apr 2006 14:54:19 +0000 (+0000) Subject: Console toggle now on caret key / Started work on Backspace, Autocomplete, Scroll... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=c0e46f337d5febb5dffeb08494db4df5f176f8d8;p=supertux.git Console toggle now on caret key / Started work on Backspace, Autocomplete, Scroll features SVN-Revision: 3270 --- diff --git a/src/console.cpp b/src/console.cpp index bf7b28e5a..62d264cd4 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -62,6 +62,49 @@ Console::flush(ConsoleStreamBuffer* buffer) } } +void +Console::backspace() +{ + std::string s = inputBuffer.str(); + if (s.length() > 0) { + s.erase(s.length()-1); + inputBuffer.str(s); + inputBuffer.pubseekoff(0, std::ios_base::end, std::ios_base::out); + } +} + +void +Console::scroll(int numLines) +{ + offset += numLines; + if (offset > 0) offset = 0; +} + +void +Console::autocomplete() +{ + std::string cmdPart = inputBuffer.str(); + addLine("> "+cmdPart); + + std::string cmdList = ""; + int cmdListLen = 0; + for (std::map::iterator i = commands.begin(); i != commands.end(); i++) { + std::string cmdKnown = i->first; + if (cmdKnown.substr(0, cmdPart.length()) == cmdPart) { + if (cmdListLen == 0) { + inputBuffer.str(cmdKnown); + inputBuffer.pubseekoff(0, std::ios_base::end, std::ios_base::out); + } else { + cmdList = cmdList + ", "; + } + cmdList = cmdList + cmdKnown; + cmdListLen++; + } + } + if (cmdListLen == 0) addLine("No known command starts with \""+cmdPart+"\""); + if (cmdListLen > 1) addLine(cmdList); +} + void Console::addLine(std::string s) { @@ -71,18 +114,19 @@ Console::addLine(std::string s) if (height < 4+9) height=4+9; height+=9; } - ticks=120; + ticks=60; std::cerr << s << std::endl; } void Console::parse(std::string s) { - for (std::list::iterator i = commandReceivers.begin(); i != commandReceivers.end(); i++) { - ConsoleCommandReceiver* ccr = *i; - if (ccr->consoleCommand(s) == true) return; + if (commands.find(s) == commands.end()) { + addLine("unknown command: \"" + s + "\""); + return; } - addLine("unknown command: \"" + s + "\""); + ConsoleCommandReceiver* ccr = commands[s]; + if (ccr->consoleCommand(s) != true) msg_warning("Sent command to registered ccr, but command was unhandled"); } bool @@ -95,7 +139,7 @@ void Console::show() { focused = true; - height = 128; + height = 256; } void @@ -111,7 +155,7 @@ Console::draw(DrawingContext& context) if (height == 0) return; if (!focused) { if (ticks-- < 0) { - height-=1; + height-=10; ticks=0; if (height < 0) height=0; } @@ -125,10 +169,12 @@ Console::draw(DrawingContext& context) if (focused) { lineNo++; float py = height-4-1*9; - context.draw_text(white_small_text, "> "+inputBuffer.str(), Vector(4, py), LEFT_ALLIGN, LAYER_FOREGROUND1+1); + context.draw_text(white_small_text, "> "+inputBuffer.str()+"_", Vector(4, py), LEFT_ALLIGN, LAYER_FOREGROUND1+1); } + int skipLines = -offset; for (std::list::iterator i = lines.begin(); i != lines.end(); i++) { + if (skipLines-- > 0) continue; lineNo++; float py = height-4-lineNo*9; if (py < -9) break; @@ -137,24 +183,36 @@ Console::draw(DrawingContext& context) } void -Console::registerCommandReceiver(ConsoleCommandReceiver* ccr) +Console::registerCommand(std::string command, ConsoleCommandReceiver* ccr) { - commandReceivers.push_front(ccr); + if (commands.find(command) != commands.end()) { + msg_warning("Command \"" << command << "\" already associated with a command receiver. Not associated."); + return; + } + commands[command] = ccr; } void -Console::unregisterCommandReceiver(ConsoleCommandReceiver* ccr) +Console::unregisterCommand(std::string command, ConsoleCommandReceiver* ccr) { - std::list::iterator i = find(commandReceivers.begin(), commandReceivers.end(), ccr); - if (i != commandReceivers.end()) commandReceivers.erase(i); + if (commands.find(command) == commands.end()) { + msg_warning("Command \"" << command << "\" not associated with a command receiver. Not dissociated."); + return; + } + if (commands[command] != ccr) { + msg_warning("Command \"" << command << "\" associated with another command receiver. Not dissociated."); + return; + } + commands.erase(command); } int Console::height = 0; bool Console::focused = false; std::list Console::lines; -std::list Console::commandReceivers; +std::map Console::commands; ConsoleStreamBuffer Console::inputBuffer; ConsoleStreamBuffer Console::outputBuffer; std::ostream Console::input(&Console::inputBuffer); std::ostream Console::output(&Console::outputBuffer); +int Console::offset = 0; diff --git a/src/console.hpp b/src/console.hpp index 323869141..4d9ae0d39 100644 --- a/src/console.hpp +++ b/src/console.hpp @@ -21,6 +21,7 @@ #define SUPERTUX_CONSOLE_H #include +#include #include #include #include @@ -40,21 +41,23 @@ class Console static std::ostream input; /**< stream of keyboard input to send to the console. Do not forget to send std::endl or to flush the stream. */ static std::ostream output; /**< stream of characters to output to the console. Do not forget to send std::endl or to flush the stream. */ - static void flush(ConsoleStreamBuffer* buffer); /**< act upon changes in a stream, normally called by the stream itself */ + static void backspace(); /**< delete last character sent to the input stream */ + static void scroll(int offset); /**< scroll console text up or down by @c offset lines */ + static void autocomplete(); /**< autocomplete current command */ - void draw(DrawingContext& context); /**< draw the console to its */ + void draw(DrawingContext& context); /**< draw the console in a DrawingContext */ static void show(); /**< display the console */ static void hide(); /**< hide the console */ static bool hasFocus(); /**< true if characters should be sent to the console instead of their normal target */ - static void registerCommandReceiver(ConsoleCommandReceiver* ccr); /**< register instance to notify of commands entered in the console */ - static void unregisterCommandReceiver(ConsoleCommandReceiver* ccr); /**< new commands should no longer be sent to this ccr */ + static void registerCommand(std::string command, ConsoleCommandReceiver* ccr); /**< associate command with the given CCR */ + static void unregisterCommand(std::string command, ConsoleCommandReceiver* ccr); /**< dissociate command and CCR */ protected: static std::list lines; /**< backbuffer of lines sent to the console */ - static std::list commandReceivers; /**< list of instances to notify of new console commands */ - DrawingContext* context; /**< context to draw to */ + static std::map commands; /**< map of console commands and their associated ConsoleCommandReceivers */ Surface* background; /**< console background image */ static int height; /**< height of the console in px */ + static int offset; /**< decrease to scroll text up */ static bool focused; /**< true if console has input focus */ static ConsoleStreamBuffer inputBuffer; /**< stream buffer used by input stream */ @@ -62,6 +65,9 @@ class Console static void addLine(std::string s); /**< display a line in the console */ static void parse(std::string s); /**< react to a given command */ + + friend class ConsoleStreamBuffer; + static void flush(ConsoleStreamBuffer* buffer); /**< act upon changes in a ConsoleStreamBuffer */ }; class ConsoleStreamBuffer : public std::stringbuf diff --git a/src/control/joystickkeyboardcontroller.cpp b/src/control/joystickkeyboardcontroller.cpp index 84426649e..3a8e279ac 100644 --- a/src/control/joystickkeyboardcontroller.cpp +++ b/src/control/joystickkeyboardcontroller.cpp @@ -246,7 +246,7 @@ JoystickKeyboardController::process_event(const SDL_Event& event) switch(event.type) { case SDL_KEYUP: case SDL_KEYDOWN: - if (event.key.keysym.unicode == '\t') { + if (event.key.keysym.sym == SDLK_CARET) { // console key was pressed - toggle console if (event.type == SDL_KEYDOWN) { if (Console::hasFocus()) { @@ -257,13 +257,29 @@ JoystickKeyboardController::process_event(const SDL_Event& event) } } else if (Console::hasFocus()) { // console is open - send key there - int c = event.key.keysym.unicode; if (event.type == SDL_KEYDOWN) { + int c = event.key.keysym.unicode; if ((c >= 32) && (c <= 126)) { Console::input << (char)c; } - if ((c == '\n') || (c == '\r')) { - Console::input << std::endl; + switch (event.key.keysym.sym) { + case SDLK_RETURN: + Console::input << std::endl; + break; + case SDLK_BACKSPACE: + Console::backspace(); + break; + case SDLK_TAB: + Console::autocomplete(); + break; + case SDLK_PAGEUP: + Console::scroll(-1); + break; + case SDLK_PAGEDOWN: + Console::scroll(+1); + break; + default: + break; } } } diff --git a/src/game_session.cpp b/src/game_session.cpp index 5a8ad88b0..448ea5ea3 100644 --- a/src/game_session.cpp +++ b/src/game_session.cpp @@ -75,6 +75,28 @@ // binary fraction... static const float LOGICAL_FPS = 64.0; +namespace { + const char* consoleCommands[] = { + "foo", + "whereami", + "camera", + "grow", + "fire", + "ice", + "lifeup", + "numberofthebeast", + "lifedown", + "grease", + "invincible", + "mortal", + "shrink", + "kill", + "gotoend", + "flip", + "finish" + }; +} + using namespace WorldMapNS; GameSession* GameSession::current_ = 0; @@ -92,7 +114,9 @@ GameSession::GameSession(const std::string& levelfile_, GameSessionMode mode, game_pause = false; fps_fps = 0; - Console::registerCommandReceiver(this); + for (uint16_t i=0; i < sizeof(::consoleCommands)/sizeof(typeof(consoleCommands[0])); i++) { + Console::registerCommand(consoleCommands[i], this); + } restart_level(true); } @@ -166,7 +190,9 @@ GameSession::~GameSession() delete end_sequence_controller; delete level; - Console::unregisterCommandReceiver(this); + for (uint16_t i=0; i < sizeof(::consoleCommands)/sizeof(typeof(consoleCommands[0])); i++) { + Console::unregisterCommand(consoleCommands[i], this); + } current_ = NULL; } @@ -327,17 +353,6 @@ GameSession::consoleCommand(std::string command) return true; } - //TODO: Build command list automatically - if (command == "cmdlist") { - msg_info("foo, cmdlist, cheats, whereami, camera"); - return true; - } - //TODO: remove (or at least hide) this before release - if (command == "cheats") { - msg_info("grow, fire, ice, lifeup, numberofthebeast, lifedown, grease, invincible, mortal, shrink, kill, gotoend, flip, finish"); - return true; - } - if (currentsector == 0) return false; Player& tux = *currentsector->player;