erebus
changeset 37:db8a90307386
implemented console and rudimentary commandline parser
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 09 Jun 2014 16:01:00 +0300 |
parents | 6eab83024d28 |
children | 5e27c85e79ca |
files | .clang_complete data/mono.glyphmap liberebus/src/erebus.cc liberebus/src/erebus.h src/console.cc src/console.h src/main.cc |
diffstat | 7 files changed, 547 insertions(+), 11 deletions(-) [+] |
line diff
1.1 --- a/.clang_complete Mon Jun 09 07:28:03 2014 +0300 1.2 +++ b/.clang_complete Mon Jun 09 16:01:00 2014 +0300 1.3 @@ -1,2 +1,3 @@ 1.4 -std=c++11 1.5 -Iliberebus/src 1.6 +-I/usr/local/include
2.1 Binary file data/mono.glyphmap has changed
3.1 --- a/liberebus/src/erebus.cc Mon Jun 09 07:28:03 2014 +0300 3.2 +++ b/liberebus/src/erebus.cc Mon Jun 09 16:01:00 2014 +0300 3.3 @@ -3,6 +3,11 @@ 3.4 #include <algorithm> 3.5 #include <chrono> 3.6 #include <random> 3.7 +#ifndef _MSC_VER 3.8 +#include <alloca.h> 3.9 +#else 3.10 +#include <malloc.h> 3.11 +#endif 3.12 #include "erebus.h" 3.13 #include "erebus_impl.h" 3.14 #include "scene.h" 3.15 @@ -248,8 +253,9 @@ 3.16 3.17 int erb_load_scene(struct erebus *ctx, const char *fname) 3.18 { 3.19 - delete ctx->scn; 3.20 - ctx->scn = new Scene; 3.21 + if(!ctx->scn) { 3.22 + ctx->scn = new Scene; 3.23 + } 3.24 3.25 if(!ctx->scn->load(fname)) { 3.26 return -1; 3.27 @@ -257,6 +263,29 @@ 3.28 return 0; 3.29 } 3.30 3.31 +int erb_proc_cmd(struct erebus *ctx, const char *cmd) 3.32 +{ 3.33 + if(!ctx->scn) { 3.34 + ctx->scn = new Scene; 3.35 + } 3.36 + 3.37 + char *buf = (char*)alloca(strlen(cmd) + 1); 3.38 + strcpy(buf, cmd); 3.39 + 3.40 + std::vector<char*> args; 3.41 + char *tok; 3.42 + while((tok = strtok(buf, " \t\v\n\r"))) { 3.43 + buf = 0; 3.44 + args.push_back(tok); 3.45 + } 3.46 + args.push_back(0); 3.47 + 3.48 + if(!ctx->scn->proc_cmd(args.size() - 1, &args[0])) { 3.49 + return -1; 3.50 + } 3.51 + return 0; 3.52 +} 3.53 + 3.54 bool erb_input_keyboard(struct erebus *ctx, int key, bool pressed) 3.55 { 3.56 if(!ctx) return false;
4.1 --- a/liberebus/src/erebus.h Mon Jun 09 07:28:03 2014 +0300 4.2 +++ b/liberebus/src/erebus.h Mon Jun 09 16:01:00 2014 +0300 4.3 @@ -46,6 +46,7 @@ 4.4 int erb_get_status(struct erebus *ctx, struct erb_render_status *stat); 4.5 4.6 int erb_load_scene(struct erebus *ctx, const char *fname); 4.7 +int erb_proc_cmd(struct erebus *ctx, const char *cmd); 4.8 4.9 bool erb_input_keyboard(struct erebus *ctx, int key, bool pressed); 4.10 bool erb_input_mouse_button(struct erebus *ctx, int bn, bool pressed, int x, int y);
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/console.cc Mon Jun 09 16:01:00 2014 +0300 5.3 @@ -0,0 +1,324 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <string.h> 5.7 +#include <stdarg.h> 5.8 +#include <assert.h> 5.9 +#include <algorithm> 5.10 +#include "opengl.h" 5.11 +#include "console.h" 5.12 + 5.13 +Console::Console() 5.14 +{ 5.15 + visible = false; 5.16 + nlines = 16; 5.17 + ncolumns = 80; 5.18 + 5.19 + inpq_front = inpq_back = 0; 5.20 + 5.21 + max_hist_lines = 64; 5.22 + max_output_lines = 128; 5.23 + 5.24 + echo = true; 5.25 + font = 0; 5.26 + font_size = 0; 5.27 + 5.28 + cursor = 0; 5.29 +} 5.30 + 5.31 +void Console::set_font(dtx_font *font, int sz) 5.32 +{ 5.33 + this->font = font; 5.34 + font_size = sz; 5.35 +} 5.36 + 5.37 +void Console::set_history_size(int hsz) 5.38 +{ 5.39 + max_hist_lines = hsz; 5.40 + 5.41 + int drop = hist.size() - hsz; 5.42 + if(drop > 0) { 5.43 + auto it = hist.begin(); 5.44 + for(int i=0; i<drop; i++) { 5.45 + ++it; 5.46 + } 5.47 + hist.erase(hist.begin(), it); 5.48 + } 5.49 +} 5.50 + 5.51 +void Console::set_output_buffer_size(int sz) 5.52 +{ 5.53 + max_output_lines = sz; 5.54 + 5.55 + int drop = output.size() - sz; 5.56 + if(drop > 0) { 5.57 + output.erase(output.begin(), output.begin() + drop); 5.58 + } 5.59 +} 5.60 + 5.61 +void Console::set_command_func(std::function<void (const char*)> func) 5.62 +{ 5.63 + cmd_handler = func; 5.64 +} 5.65 + 5.66 +void Console::set_echo(bool echo) 5.67 +{ 5.68 + this->echo = echo; 5.69 +} 5.70 + 5.71 +bool Console::get_echo() const 5.72 +{ 5.73 + return echo; 5.74 +} 5.75 + 5.76 +void Console::set_visible(bool v) 5.77 +{ 5.78 + visible = v; 5.79 +} 5.80 + 5.81 +bool Console::is_visible() const 5.82 +{ 5.83 + return visible; 5.84 +} 5.85 + 5.86 +void Console::set_size(int lines, int columns) 5.87 +{ 5.88 + nlines = lines; 5.89 + ncolumns = columns; 5.90 +} 5.91 + 5.92 +int Console::get_size_lines() const 5.93 +{ 5.94 + return nlines; 5.95 +} 5.96 + 5.97 +int Console::get_size_columns() const 5.98 +{ 5.99 + return ncolumns; 5.100 +} 5.101 + 5.102 +bool Console::update() 5.103 +{ 5.104 + bool must_redraw = false; 5.105 + 5.106 + while(inpq_front != inpq_back) { 5.107 + int c = keybuf[inpq_front]; 5.108 + inpq_front = (inpq_front + 1) % INPUTQ_SIZE; 5.109 + 5.110 + switch(c) { 5.111 + case '\n': 5.112 + case '\r': 5.113 + if(cmd_handler) { 5.114 + cmd_handler(input.c_str()); 5.115 + } 5.116 + 5.117 + if(echo) { 5.118 + puts(input.c_str()); 5.119 + putchar('\n'); 5.120 + } 5.121 + 5.122 + hist.push_back(std::move(input)); // move the input string into the history buffer 5.123 + if((int)hist.size() > max_hist_lines) { 5.124 + hist.pop_front(); 5.125 + } 5.126 + cursor = 0; 5.127 + must_redraw = true; 5.128 + break; 5.129 + 5.130 + case '\t': 5.131 + // TODO: completion 5.132 + break; 5.133 + 5.134 + case '\b': 5.135 + if(!input.empty()) { 5.136 + if(cursor == (int)input.size()) { 5.137 + input.pop_back(); 5.138 + --cursor; 5.139 + must_redraw = true; 5.140 + } else if(cursor > 0) { 5.141 + input.erase(cursor - 1); 5.142 + --cursor; 5.143 + must_redraw = true; 5.144 + } 5.145 + } 5.146 + break; 5.147 + 5.148 + case KEY_LEFT: 5.149 + if(cursor > 0) { 5.150 + --cursor; 5.151 + must_redraw = true; 5.152 + } 5.153 + break; 5.154 + 5.155 + case KEY_RIGHT: 5.156 + if(cursor < (int)input.size()) { 5.157 + ++cursor; 5.158 + must_redraw = true; 5.159 + } 5.160 + break; 5.161 + 5.162 + case KEY_HOME: 5.163 + cursor = 0; 5.164 + must_redraw = true; 5.165 + break; 5.166 + 5.167 + case KEY_END: 5.168 + cursor = input.size(); 5.169 + must_redraw = true; 5.170 + break; 5.171 + 5.172 + case KEY_PGUP: 5.173 + case KEY_PGDOWN: 5.174 + // TODO history 5.175 + break; 5.176 + 5.177 + default: 5.178 + if(c < 256 && isprint(c)) { 5.179 + input.push_back(c); 5.180 + ++cursor; 5.181 + must_redraw = true; 5.182 + } 5.183 + } 5.184 + } 5.185 + return must_redraw; 5.186 +} 5.187 + 5.188 +void Console::draw() const 5.189 +{ 5.190 + if(!font || !visible) return; 5.191 + dtx_use_font(font, font_size); 5.192 + 5.193 + int vp[4]; 5.194 + glGetIntegerv(GL_VIEWPORT, vp); 5.195 + 5.196 + glMatrixMode(GL_PROJECTION); 5.197 + glPushMatrix(); 5.198 + glLoadIdentity(); 5.199 + glOrtho(vp[0], vp[0] + vp[2], vp[1], vp[1] + vp[3], -1, 1); 5.200 + 5.201 + glMatrixMode(GL_MODELVIEW); 5.202 + glPushMatrix(); 5.203 + glLoadIdentity(); 5.204 + glTranslatef(0, vp[3] - vp[1], 0); 5.205 + 5.206 + std::string buflines; 5.207 + 5.208 + int num_lines = std::min(nlines, (int)output.size()); 5.209 + auto it = output.cbegin() + (output.size() - num_lines); 5.210 + 5.211 + float max_width = dtx_glyph_width('Q') * ncolumns; 5.212 + 5.213 + while(it != output.cend()) { 5.214 + const std::string &line = *it++; 5.215 + buflines += line + std::string("\n"); 5.216 + 5.217 + max_width = std::max(max_width, dtx_string_width(line.c_str())); 5.218 + } 5.219 + 5.220 + // draw the output box 5.221 + float outbox_height = nlines * dtx_line_height(); 5.222 + 5.223 + glPushAttrib(GL_ENABLE_BIT); 5.224 + glEnable(GL_BLEND); 5.225 + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 5.226 + 5.227 + glBegin(GL_QUADS); 5.228 + glColor4f(0.1, 0.2, 0.5, 0.7); 5.229 + glVertex2f(0, -outbox_height); 5.230 + glVertex2f(max_width, -outbox_height); 5.231 + glVertex2f(max_width, 0); 5.232 + glVertex2f(0, 0); 5.233 + 5.234 + glColor4f(0.5, 0.2, 0.1, 0.7); 5.235 + glVertex2f(0, -(outbox_height + dtx_line_height())); 5.236 + glVertex2f(max_width, -(outbox_height + dtx_line_height())); 5.237 + glVertex2f(max_width, -outbox_height); 5.238 + glVertex2f(0, -outbox_height); 5.239 + glEnd(); 5.240 + 5.241 + // draw the output text 5.242 + glPushMatrix(); 5.243 + glTranslatef(0, -dtx_line_height(), 0); 5.244 + glColor4f(1, 1, 1, 0.7); 5.245 + dtx_string(buflines.c_str()); 5.246 + glPopMatrix(); 5.247 + 5.248 + // draw the input line 5.249 + glTranslatef(0, -outbox_height - dtx_line_height(), 0); 5.250 + dtx_string((std::string("> ") + input).c_str()); 5.251 + 5.252 + glPopAttrib(); 5.253 + 5.254 + glMatrixMode(GL_PROJECTION); 5.255 + glPopMatrix(); 5.256 + glMatrixMode(GL_MODELVIEW); 5.257 + glPopMatrix(); 5.258 +} 5.259 + 5.260 +void Console::input_key(int key) 5.261 +{ 5.262 + keybuf[inpq_back] = key; 5.263 + inpq_back = (inpq_back + 1) % INPUTQ_SIZE; 5.264 +} 5.265 + 5.266 +void Console::putchar(char c) 5.267 +{ 5.268 + if(output.empty()) { 5.269 + output.push_back(std::string("")); 5.270 + } 5.271 + 5.272 + if(c == '\n' || c == '\r') { 5.273 + output.push_back(std::string("")); 5.274 + if((int)output.size() > max_output_lines) { 5.275 + output.erase(output.begin()); 5.276 + } 5.277 + } else { 5.278 + output.back().push_back(c); 5.279 + } 5.280 +} 5.281 + 5.282 +void Console::puts(const char *str) 5.283 +{ 5.284 + while(*str) { 5.285 + putchar(*str++); 5.286 + } 5.287 +} 5.288 + 5.289 +void Console::printf(const char *fmt, ...) 5.290 +{ 5.291 + static char buf[1024]; 5.292 + va_list ap; 5.293 + 5.294 + va_start(ap, fmt); 5.295 + vsnprintf(buf, sizeof buf, fmt, ap); 5.296 + va_end(ap); 5.297 + 5.298 + puts(buf); 5.299 +} 5.300 + 5.301 +void Console::debug() 5.302 +{ 5.303 + fprintf(stderr, "visible: %s\n", visible ? "true" : "false"); 5.304 + fprintf(stderr, "size: %d lines x %d columns\n", nlines, ncolumns); 5.305 + fprintf(stderr, "cursor: %d\n", cursor); 5.306 + 5.307 + int qsize = 0; 5.308 + int qidx = inpq_front; 5.309 + while(qidx != inpq_back) { 5.310 + qsize++; 5.311 + qidx = (qidx + 1) % INPUTQ_SIZE; 5.312 + } 5.313 + 5.314 + fprintf(stderr, "input queue size: %d\n", qsize); 5.315 + fprintf(stderr, "current input line: \"%s\"\n", input.c_str()); 5.316 + fprintf(stderr, "%d saved inputs in the history (max %d)\n", (int)hist.size(), max_hist_lines); 5.317 + auto it = hist.begin(); 5.318 + int idx = 0; 5.319 + while(it != hist.end()) { 5.320 + fprintf(stderr, " h(%d): \"%s\"\n", idx++, it++->c_str()); 5.321 + } 5.322 + 5.323 + fprintf(stderr, "output buffer (lines: %d/%d):\n", (int)output.size(), max_output_lines); 5.324 + for(size_t i=0; i<output.size(); i++) { 5.325 + fprintf(stderr, "o(%d): \"%s\"\n", (int)i, output[i].c_str()); 5.326 + } 5.327 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/console.h Mon Jun 09 16:01:00 2014 +0300 6.3 @@ -0,0 +1,82 @@ 6.4 +#ifndef CONSOLE_H_ 6.5 +#define CONSOLE_H_ 6.6 + 6.7 +#include <vector> 6.8 +#include <list> 6.9 +#include <string> 6.10 +#include <functional> 6.11 +#include <drawtext.h> 6.12 + 6.13 +#define INPUTQ_SIZE 64 6.14 + 6.15 +class Console { 6.16 +private: 6.17 + bool visible; 6.18 + int nlines, ncolumns; 6.19 + 6.20 + int inpq_front, inpq_back; 6.21 + int keybuf[INPUTQ_SIZE]; 6.22 + 6.23 + std::string input; // current input line 6.24 + int cursor; 6.25 + 6.26 + // input history 6.27 + int max_hist_lines; 6.28 + std::list<std::string> hist; 6.29 + 6.30 + // console output 6.31 + int max_output_lines; 6.32 + std::vector<std::string> output; 6.33 + bool echo; 6.34 + 6.35 + std::function<void (const char*)> cmd_handler; 6.36 + 6.37 + int font_size; 6.38 + dtx_font *font; 6.39 + 6.40 +public: 6.41 + enum { 6.42 + KEY_LEFT = 256, 6.43 + KEY_RIGHT, 6.44 + KEY_UP, KEY_DOWN, 6.45 + KEY_INS, 6.46 + KEY_DEL, 6.47 + KEY_HOME, 6.48 + KEY_END, 6.49 + KEY_PGUP, 6.50 + KEY_PGDOWN 6.51 + }; 6.52 + 6.53 + Console(); 6.54 + 6.55 + void set_font(dtx_font *font, int sz); 6.56 + void set_history_size(int hsz); 6.57 + void set_output_buffer_size(int sz); 6.58 + void set_command_func(std::function<void (const char*)> func); 6.59 + 6.60 + void set_echo(bool echo); 6.61 + bool get_echo() const; 6.62 + 6.63 + void show() { set_visible(true); } 6.64 + void hide() { set_visible(false); } 6.65 + void set_visible(bool v); 6.66 + bool is_visible() const; 6.67 + 6.68 + void set_size(int lines, int columns = 80); 6.69 + int get_size_lines() const; 6.70 + int get_size_columns() const; 6.71 + 6.72 + // update returns true if what it did makes a redraw necessary 6.73 + bool update(); 6.74 + void draw() const; 6.75 + 6.76 + void input_key(int key); // send a keystroke to the console 6.77 + 6.78 + void putchar(char c); 6.79 + void puts(const char *str); 6.80 + void printf(const char *fmt, ...); 6.81 + 6.82 + void debug(); 6.83 +}; 6.84 + 6.85 +#endif // CONSOLE_H_
7.1 --- a/src/main.cc Mon Jun 09 07:28:03 2014 +0300 7.2 +++ b/src/main.cc Mon Jun 09 16:01:00 2014 +0300 7.3 @@ -9,6 +9,7 @@ 7.4 #include <drawtext.h> 7.5 #include "opengl.h" 7.6 #include "erebus.h" 7.7 +#include "console.h" 7.8 7.9 using namespace std::chrono; 7.10 7.11 @@ -25,6 +26,7 @@ 7.12 static void reshape(int x, int y); 7.13 static void keyb(unsigned char key, int x, int y); 7.14 static void keyb_up(unsigned char key, int x, int y); 7.15 +static void skeyb(int key, int x, int y); 7.16 static void mouse(int bn, int st, int x, int y); 7.17 static void motion(int x, int y); 7.18 static void sball_button(int bn, int st); 7.19 @@ -32,6 +34,7 @@ 7.20 static int next_pow2(int x); 7.21 static void sighandler(int s); 7.22 static bool parse_args(int argc, char **argv); 7.23 +static void con_parse(const char *line); 7.24 7.25 static int win_width, win_height, width, height, rtex_width, rtex_height; 7.26 static unsigned int rtex; 7.27 @@ -48,7 +51,9 @@ 7.28 7.29 static std::vector<char*> sfiles; 7.30 7.31 +#define FONTSZ 22 7.32 static dtx_font *font; 7.33 +static Console con; 7.34 7.35 int main(int argc, char **argv) 7.36 { 7.37 @@ -66,6 +71,7 @@ 7.38 glutReshapeFunc(reshape); 7.39 glutKeyboardFunc(keyb); 7.40 glutKeyboardUpFunc(keyb_up); 7.41 + glutSpecialFunc(skeyb); 7.42 glutMouseFunc(mouse); 7.43 glutMotionFunc(motion); 7.44 glutSpaceballButtonFunc(sball_button); 7.45 @@ -89,11 +95,20 @@ 7.46 width = glutGet(GLUT_WINDOW_WIDTH) / opt_imgscale; 7.47 height = glutGet(GLUT_WINDOW_HEIGHT) / opt_imgscale; 7.48 7.49 - //if(!(font = dtx_open_font("/usr/share/fonts/opentype/linux-libertine/LinLibertine_R.otf", 22))) { 7.50 + //if(!(font = dtx_open_font("/usr/share/fonts/opentype/linux-libertine/LinLibertine_R.otf", FONTSZ))) { 7.51 if(!(font = dtx_open_font_glyphmap("data/serif.glyphmap"))) { 7.52 fprintf(stderr, "warning: failed to load font!\n"); 7.53 } 7.54 7.55 + //dtx_font *confont = dtx_open_font("/usr/share/fonts/truetype/droid/DroidSansMono.ttf", 14); 7.56 + dtx_font *confont = dtx_open_font_glyphmap("data/mono.glyphmap"); 7.57 + if(confont) { 7.58 + con.set_font(confont, 14); 7.59 + } else { 7.60 + con.set_font(font, FONTSZ); 7.61 + } 7.62 + con.set_command_func(con_parse); 7.63 + 7.64 if(!(erb = erb_init())) { 7.65 return false; 7.66 } 7.67 @@ -256,6 +271,10 @@ 7.68 glTexCoord2f(0, 0); glVertex2f(-1, 1); 7.69 glEnd(); 7.70 7.71 + // draw the console 7.72 + con.update(); 7.73 + con.draw(); 7.74 + 7.75 // draw progress information etc... 7.76 if(show_status) { 7.77 display_statusbar(status); 7.78 @@ -268,6 +287,7 @@ 7.79 static void display_statusbar(const erb_render_status &status) 7.80 { 7.81 if(!font) return; 7.82 + dtx_use_font(font, FONTSZ); 7.83 7.84 bool show_progress = opt_samples > 0; 7.85 7.86 @@ -368,22 +388,41 @@ 7.87 { 7.88 switch(key) { 7.89 case 27: 7.90 - end_frame(); 7.91 - exit(0); 7.92 + if(con.is_visible()) { 7.93 + con.hide(); 7.94 + glutPostRedisplay(); 7.95 + } else { 7.96 + end_frame(); 7.97 + exit(0); 7.98 + } 7.99 + break; 7.100 7.101 case ' ': 7.102 - begin_frame(0); 7.103 - break; 7.104 - 7.105 - case '\b': 7.106 - printf("saving image.\n"); 7.107 - save_image(); 7.108 + if(!con.is_visible()) { 7.109 + begin_frame(0); 7.110 + } else { 7.111 + con.input_key(' '); 7.112 + glutPostRedisplay(); 7.113 + } 7.114 break; 7.115 7.116 case '`': 7.117 + con.set_visible(!con.is_visible()); 7.118 + glutPostRedisplay(); 7.119 + break; 7.120 + 7.121 + case '~': 7.122 show_status = !show_status; 7.123 glutPostRedisplay(); 7.124 break; 7.125 + 7.126 + default: 7.127 + // otherwise if the console is visible, let them through 7.128 + if(con.is_visible()) { 7.129 + con.input_key(key); 7.130 + glutPostRedisplay(); 7.131 + return; // don't pass anything to the erb input handler 7.132 + } 7.133 } 7.134 7.135 if(erb_input_keyboard(erb, key, true)) { 7.136 @@ -398,6 +437,55 @@ 7.137 } 7.138 } 7.139 7.140 +static void skeyb(int key, int x, int y) 7.141 +{ 7.142 + if(key == GLUT_KEY_F12) { 7.143 + printf("saving image...\n"); 7.144 + save_image(); 7.145 + return; 7.146 + } 7.147 + 7.148 + if(con.is_visible()) { 7.149 + switch(key) { 7.150 + case GLUT_KEY_F8: 7.151 + con.debug(); 7.152 + return; 7.153 + 7.154 + case GLUT_KEY_LEFT: 7.155 + con.input_key(Console::KEY_LEFT); 7.156 + break; 7.157 + case GLUT_KEY_RIGHT: 7.158 + con.input_key(Console::KEY_RIGHT); 7.159 + break; 7.160 + case GLUT_KEY_UP: 7.161 + con.input_key(Console::KEY_UP); 7.162 + break; 7.163 + case GLUT_KEY_DOWN: 7.164 + con.input_key(Console::KEY_DOWN); 7.165 + break; 7.166 + case GLUT_KEY_HOME: 7.167 + con.input_key(Console::KEY_HOME); 7.168 + break; 7.169 + case GLUT_KEY_END: 7.170 + con.input_key(Console::KEY_END); 7.171 + break; 7.172 + case GLUT_KEY_INSERT: 7.173 + con.input_key(Console::KEY_INS); 7.174 + break; 7.175 + case GLUT_KEY_PAGE_UP: 7.176 + con.input_key(Console::KEY_PGUP); 7.177 + break; 7.178 + case GLUT_KEY_PAGE_DOWN: 7.179 + con.input_key(Console::KEY_PGDOWN); 7.180 + break; 7.181 + 7.182 + default: 7.183 + return; 7.184 + } 7.185 + glutPostRedisplay(); 7.186 + } 7.187 +} 7.188 + 7.189 static void mouse(int bn, int st, int x, int y) 7.190 { 7.191 if(erb_input_mouse_button(erb, bn - GLUT_LEFT_BUTTON, st == GLUT_DOWN, x, y)) { 7.192 @@ -483,3 +571,14 @@ 7.193 7.194 return true; 7.195 } 7.196 + 7.197 +static void con_parse(const char *line) 7.198 +{ 7.199 + printf("got line: %s\n", line); 7.200 + 7.201 + if(erb_proc_cmd(erb, line) == -1) { 7.202 + con.puts("invalid command\n"); 7.203 + } else { 7.204 + begin_frame(0); 7.205 + } 7.206 +}