Console toggle now on caret key / Started work on Backspace, Autocomplete, Scroll...
authorChristoph Sommer <mail@christoph-sommer.de>
Sat, 8 Apr 2006 14:54:19 +0000 (14:54 +0000)
committerChristoph Sommer <mail@christoph-sommer.de>
Sat, 8 Apr 2006 14:54:19 +0000 (14:54 +0000)
SVN-Revision: 3270

src/console.cpp
src/console.hpp
src/control/joystickkeyboardcontroller.cpp
src/game_session.cpp

index bf7b28e..62d264c 100644 (file)
@@ -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<std::string, ConsoleCommandReceiver*>::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<ConsoleCommandReceiver*>::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<std::string>::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<ConsoleCommandReceiver*>::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<std::string> Console::lines;
-std::list<ConsoleCommandReceiver*> Console::commandReceivers;
+std::map<std::string, ConsoleCommandReceiver*> Console::commands;
 ConsoleStreamBuffer Console::inputBuffer;
 ConsoleStreamBuffer Console::outputBuffer;
 std::ostream Console::input(&Console::inputBuffer);
 std::ostream Console::output(&Console::outputBuffer);
+int Console::offset = 0;
 
index 3238691..4d9ae0d 100644 (file)
@@ -21,6 +21,7 @@
 #define SUPERTUX_CONSOLE_H
 
 #include <list>
+#include <map>
 #include <string>
 #include <sstream>
 #include <iostream>
@@ -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<std::string> lines; /**< backbuffer of lines sent to the console */
-    static std::list<ConsoleCommandReceiver*> commandReceivers; /**< list of instances to notify of new console commands */
-    DrawingContext* context; /**< context to draw to */
+    static std::map<std::string, ConsoleCommandReceiver*> 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 
index 8442664..3a8e279 100644 (file)
@@ -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;
          }
        }
       } 
index 5a8ad88..448ea5e 100644 (file)
 // 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;