From a185c11f2397c0296a4b62cc266b4fa00a63c1e2 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 14 May 2008 21:07:10 +0000 Subject: console, camera & interpolation --- src/client/camera.cc | 129 +++++++++--- src/client/chat.cc | 51 ++++- src/client/client.cc | 16 +- src/client/console.cc | 536 ++++++++++++++++++++++++-------------------------- src/client/console.h | 84 ++++---- src/client/input.cc | 20 +- src/client/view.cc | 10 +- 7 files changed, 465 insertions(+), 381 deletions(-) (limited to 'src/client') diff --git a/src/client/camera.cc b/src/client/camera.cc index 29310fc..21bf930 100644 --- a/src/client/camera.cc +++ b/src/client/camera.cc @@ -28,6 +28,7 @@ math::Vector3f target; math::Vector3f eye; math::Axis axis; +const float MIN_DELTA = 10e-10; // current camera mode Mode mode; @@ -86,10 +87,18 @@ void set_mode(Mode newmode) { target_pitch = 0.0f; distance = 0.4f; + axis.clear(); + switch(newmode) { case Track: // switch camera to Track mode mode = Track; + if (core::localcontrol()) { + if (core::localcontrol()->state()) + axis.assign(core::localcontrol()->state()->axis()); + else + axis.assign(core::localcontrol()->axis()); + } break; case Free: @@ -148,7 +157,7 @@ void next_mode() void draw(float seconds) { math::Matrix4f matrix; - + math::Axis target_axis; float d = 0; if (!core::localcontrol()) { @@ -165,37 +174,102 @@ void draw(float seconds) distance = 20.0f; } else { - if (mode == Overview) set_mode(Track); if (core::localcontrol()->state()) { target.assign(core::localcontrol()->state()->location()); - axis.assign(core::localcontrol()->state()->axis()); + target_axis.assign(core::localcontrol()->state()->axis()); } else { target.assign(core::localcontrol()->location()); - axis.assign(core::localcontrol()->axis()); + target_axis.assign(core::localcontrol()->axis()); } - + if (mode == Track) { - if (core::localcontrol()->state() && core::localcontrol()->model()) { - target -= (core::localcontrol()->model()->maxbbox().x + 0.15f) * core::localcontrol()->state()->axis().forward(); - - target += (core::localcontrol()->model()->maxbbox().z + 0.3f ) * - core::localcontrol()->state()->axis().up(); + float cosangle; + float angle; + float side; + float u; + const float cam_speed = seconds * 4 ; + + math::Vector3f n; + math::Vector3f p; + + // camera axis: pitch + + // project target_axis.up() into the plane with axis->left() normal + n = axis.left(); + p = target_axis.up(); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = target_axis.up() + u * n; + + side = axis.forward().x * p.x + + axis.forward().y * p.y + + axis.forward().z * p.z; + + if ((fabs(side) - MIN_DELTA > 0)) { + + cosangle = math::dotproduct(p, axis.up()); + if (fabs(cosangle) + MIN_DELTA < 1 ) { + angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * cam_speed; + axis.change_pitch(-angle); + } } - // make the camera swing while turning - target_direction = core::localcontrol()->target_direction; - target_pitch = core::localcontrol()->target_pitch; + // camera axis: direction + + // project target_axis.forward() into the plane with axis.up() normal + n = axis.up(); + p = target_axis.forward(); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = target_axis.forward() + u * n; + + side = axis.left().x * p.x + + axis.left().y * p.y + + axis.left().z * p.z; + + if ((fabs(side) - MIN_DELTA > 0)) { + + cosangle = math::dotproduct(p, axis.forward()); + if (fabs(cosangle) + MIN_DELTA < 1 ) { + angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * cam_speed; + axis.change_direction(angle); + } + } - yaw_target = - 30 * target_direction; - pitch_target = - 30 * target_pitch; - //pitch_target = pitch_track - 30 * target_pitch; + // camera axis: roll + + // project target_axis.up() into the plane with axis.forward() normal + n = axis.forward(); + p = target_axis.up(); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = target_axis.up() + u * n; + + side = axis.left().x * p.x + + axis.left().y * p.y + + axis.left().z * p.z; + + if ((fabs(side) - MIN_DELTA > 0)) { + + cosangle = math::dotproduct(p, axis.up()); + if (fabs(cosangle) + MIN_DELTA < 1 ) { + angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * cam_speed; + axis.change_roll(angle); + } + } distance = 0.0f; + if (core::localcontrol()->model()) { + target -= (core::localcontrol()->model()->maxbbox().x + 0.1f) * axis.forward(); + target += (core::localcontrol()->model()->maxbbox().z + 0.1f ) * axis.up(); + } + } else if (mode == Free) { + axis.assign(target_axis); yaw_target = yaw_current - 90 * target_direction; pitch_target = pitch_current - 90 * target_pitch; @@ -205,26 +279,25 @@ void draw(float seconds) } else { distance = 1.0f; } - - } else if (mode == Cockpit) { - if (core::localcontrol()->state() && core::localcontrol()->model()) - target += (core::localcontrol()->model()->maxbbox().x+0.05) * - core::localcontrol()->state()->axis().forward(); - - distance = 0.0f; - } - - if (mode != Cockpit) { // adjust direction d = degrees180f(yaw_current - yaw_target); yaw_current = degrees360f( yaw_current - d * seconds); axis.change_direction(yaw_current); - // adjust pitch target + // adjust pitch d = degrees180f(pitch_current - pitch_target); - pitch_current = degrees360f(pitch_current - d *seconds); + pitch_current = degrees360f(pitch_current - d * seconds); axis.change_pitch(pitch_current); + + } else if (mode == Cockpit) { + axis.assign(target_axis); + + if (core::localcontrol()->state() && core::localcontrol()->model()) + target += (core::localcontrol()->model()->maxbbox().x+0.05) * + core::localcontrol()->state()->axis().forward(); + + distance = 0.0f; } } diff --git a/src/client/chat.cc b/src/client/chat.cc index 1953390..9171387 100644 --- a/src/client/chat.cc +++ b/src/client/chat.cc @@ -4,6 +4,7 @@ the terms and conditions of the GNU General Public License version 2 */ +#include "auxiliary/functions.h" #include "core/core.h" #include "client/chat.h" #include "client/console.h" @@ -71,24 +72,54 @@ void draw() { using namespace render; - if (console::visible() || !visible()) + if (console()->visible() || !visible()) return; - size_t width = (size_t) (video::width / Text::fontwidth()) - 7; - size_t draw_pos = 0; - while (input_pos - draw_pos > width) - draw_pos += 2; + size_t width = (size_t) (video::width / Text::fontwidth()) - 8; + float y = video::height*8/10; + Text::draw(4, y, "^BSay^F:^B "); - // draw the chat input - float y = video::height * 8.0 / 10.0; + std::string firstpart((*history_pos).substr(0, input_pos)); + size_t draw_width = 0; + const char *c = firstpart.c_str(); - Text::draw(4 , y, "^Bsay^F:^B"); - Text::draw(4+Text::fontwidth()*5 , y, (*history_pos).substr(draw_pos, width)); + while (*c) { + if (aux::is_color_code(c)) { + c++; + } else { + draw_width++; + } + c++; + } + + c = firstpart.c_str(); + while (*c && draw_width > width - 2) { + if (aux::is_color_code(c)) { + c++; + Text::setcolor(*c); + } else { + draw_width--; + } + c++; + } + + if (*c) { + Text::draw(4+5*Text::fontwidth(), y, c); + } + + if (input_pos < (*history_pos).size()) { + // FIXME limit to width + if (input_pos > 1 && aux::is_color_code((*history_pos).c_str() + input_pos -1)) { + Text::setcolor((*history_pos)[input_pos]); + } + c = (*history_pos).c_str() + input_pos; + Text::draw(4+Text::fontwidth()*(draw_width+5), y, c); + } // draw cursor if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { std::string cursor("^B_"); - Text::draw(4+Text::fontwidth()*(input_pos - draw_pos+5), y, cursor); + Text::draw(4+Text::fontwidth()*(draw_width+5), y , cursor); } } diff --git a/src/client/client.cc b/src/client/client.cc index 97c0128..85dec27 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -25,6 +25,7 @@ namespace client core::Cvar *cl_framerate = 0; //--- private definition ------------------------------------------ + /// client application implementation class Client : public core::Application { @@ -49,10 +50,8 @@ Client app; void func_r_restart(std::stringstream &args) { video::shutdown(); - console::flush(); if (!video::init()) { - console::flush(); app.quit(1); } } @@ -87,6 +86,7 @@ void Client::init(int count, char **arguments) // initialize core core::Cvar::sv_dedicated = core::Cvar::set("sv_private", "0"); core::Application::init(count, arguments); + Console::init(); // client variables core::Cvar *cvar = 0; @@ -104,12 +104,10 @@ void Client::init(int count, char **arguments) // Initialize the video subsystem if (!video::init()) { - console::flush(); quit(1); } // initialize console - console::init(); chat::init(); // initialize input @@ -128,6 +126,9 @@ void Client::run() Uint32 client_framerate = (Uint32)(1000/120); Uint32 elapsed = 0; + console()->flush(); + console()->clear_notify(); + while (true) { Uint32 chrono = SDL_GetTicks(); @@ -155,24 +156,19 @@ void Client::run() void Client::shutdown() { con_print << "^BShutting down client..." << std::endl; - console::flush(); // remove engine functions core::Func::remove("r_restart"); chat::shutdown(); - console::shutdown(); - console::flush(); + Console::shutdown(); input::shutdown(); - console::flush(); video::shutdown(); - console::flush(); core::Application::shutdown(); - console::flush(); quit(0); } diff --git a/src/client/console.cc b/src/client/console.cc index 4c65581..f692db4 100644 --- a/src/client/console.cc +++ b/src/client/console.cc @@ -4,12 +4,12 @@ the terms and conditions of the GNU General Public License version 2 */ +#include "client/console.h" #include "auxiliary/functions.h" #include "core/core.h" #include "filesystem/filesystem.h" #include "render/render.h" #include "render/textures.h" -#include "client/console.h" #include "client/video.h" #include "client/keyboard.h" @@ -19,116 +19,225 @@ namespace client { -namespace console { +Console client_console; -//--- private definition ------------------------------------------ +Console *console() { + return &client_console; +} +//--- engine functions -------------------------------------------- -/// private client console implementation -class Console : public sys::ConsoleInterface { -public: - /// stream to send normal messages too - virtual std::ostream & messagestream(); +void func_con_toggle(std::string const &args) +{ + + console()->toggle(); +} - /// stream to send warning messages too - virtual std::ostream & warningstream(); +//--- public ------------------------------------------------------ - /// stream to send error messages too - virtual std::ostream & errorstream(); - - /// stream to send debug messages too - virtual std::ostream & debugstream(); +void Console::init() +{ + con_print << "^BInitializing console..." << std::endl; - /// flush buffered messages - virtual void flush(); + core::Func *func = core::Func::add("con_toggle", (core::FuncPtr) func_con_toggle); + func->set_info("toggle console on or off"); + console()->load_history(); +} + +void Console::shutdown() +{ + con_print << "^BShutting down console..." << std::endl; - /// console text buffer - std::stringstream buffer; -}; + console()->save_history(); -// private client console object -Console console; + // remove engine functions + core::Func::remove("con_toggle"); +} + +//--- Console ----------------------------------------------------- + +Console::Console() +{ + clear(); +} -// console text data -std::deque text; +Console::~Console() +{ + history.clear(); +} -// input history -std::deque history; -std::deque::reverse_iterator history_pos; -size_t input_pos = 0; +void Console::clear() +{ + console_visible = false; + console_scroll = 0; + history.clear(); + history.push_back(""); + history_pos = history.rbegin(); + input_pos = 0; -// console visibility -bool console_visible = false; -size_t console_scroll = 0; + clear_notify(); -// notifications -size_t notify_pos = 0; -std::string notify_text[MAXNOTIFYLINES]; -float notify_time[MAXNOTIFYLINES]; +} -//--- engine functions -------------------------------------------- +void Console::draw() { + if (visible()) + draw_console(); + else + draw_notify(); +} -void func_con_toggle(std::string const &args) +void Console::toggle() { + console_visible = !console_visible; - std::istringstream argstream(args); - int i; + if (console_visible) { + console_scroll = 0; + input_pos = 0; + + history_pos = history.rbegin(); + (*history_pos).clear(); - if (argstream >> i) { - if (i) console_visible = false; else console_visible = true; + SDL_WM_GrabInput(SDL_GRAB_OFF); + SDL_ShowCursor(SDL_ENABLE); + } else { + SDL_WM_GrabInput(SDL_GRAB_ON); + SDL_ShowCursor(SDL_DISABLE); + clear_notify(); } - toggle(); + + setkeyboardmode(visible()); } -//--- public ------------------------------------------------------ - -void clear_notify() +void Console::keypressed(int key) { - for (size_t i=0; i < MAXNOTIFYLINES; i++) { - notify_text[i].clear(); - notify_time[i] = 0; + std::deque::reverse_iterator upit; + + switch( key ) { + case SDLK_TAB: + core::CommandBuffer::complete( (*history_pos), input_pos); + break; + case SDLK_RETURN: + if ((*history_pos).size()) { + // store input into history + while (history.size() >= MAXHISTOLINES) { + history.pop_front(); + } + + core::cmd() << (*history_pos) << std::endl; + con_print << "^B>" << (*history_pos) << std::endl; + (*history.rbegin()) = (*history_pos); + + history.push_back(""); + history_pos = history.rbegin(); + input_pos = 0; + } + break; + case SDLK_UP: + upit = history_pos; + ++upit; + if (upit != history.rend()) { + history_pos = upit; + input_pos = (*history_pos).size(); + } + break; + case SDLK_DOWN: + if (history_pos != history.rbegin()) { + --history_pos; + input_pos = (*history_pos).size(); + } + break; + case SDLK_HOME: + input_pos = 0; + break; + case SDLK_END: + input_pos = (*history_pos).size(); + break; + case SDLK_LEFT: + if (input_pos > 0) + input_pos--; + break; + case SDLK_RIGHT: + if (input_pos < (*history_pos).size()) + input_pos++; + break; + case SDLK_BACKSPACE: + if ((*history_pos).size() && input_pos) { + (*history_pos).erase(input_pos-1, 1); + input_pos--; + } + break; + case SDLK_PAGEUP: + console_scroll +=5; + if (console_scroll > consoleinterface_text.size()) console_scroll = consoleinterface_text.size(); + break; + case SDLK_PAGEDOWN: + if (console_scroll > 5) console_scroll -=5; + else console_scroll = 0; + break; + default: + if ((key >= 32 ) && (key <175)) { + if (input_pos == (*history_pos).size()) + (*history_pos) += (char)key; + else + (*history_pos).insert(input_pos, 1, (char)key); + input_pos++; + } + break; } + + } -void init() +void Console::save_history() { - con_print << "^BInitializing console..." << std::endl; - - console_visible = false; - - // add engine functions - core::Func *func = core::Func::add("con_toggle", (core::FuncPtr) func_con_toggle); - func->set_info("toggle console on or off"); - clear_notify(); - text.clear(); - console_scroll = 0; + if (history.size() <= 1) + return; - history.clear(); - history.push_back(""); - history_pos = history.rbegin(); - input_pos = 0; + std::string filename(filesystem::writedir); + filename.append("history.txt"); + std::ofstream ofs(filename.c_str()); - load_history(); + if (!ofs.is_open()) { + con_warn << "Could not write " << filename << std::endl; + return; + } + std::deque::iterator it; + size_t l = 1; + for (it = history.begin(); it != history.end(); it++) { + if (l < history.size()) + ofs << (*it) << std::endl; + l++; + } + + ofs.close(); } -void shutdown() +void Console::load_history() { - con_print << "^BShutting down console..." << std::endl; - - save_history(); + std::string filename(filesystem::writedir); + filename.append("history.txt"); + std::ifstream ifs(filename.c_str(), std::ifstream::in); - // remove engine functions - //core::Func::remove("con_toggle"); - - text.clear(); - console_scroll = 0; + if (!ifs.is_open()) { + con_warn << "Could not read " << filename << std::endl; + return; + } history.clear(); + char line[MAXCMDSIZE]; + while (ifs.getline(line, MAXCMDSIZE-1)) { + history.push_back(line); + } + + ifs.close(); + + history.push_back(""); + history_pos = history.rbegin(); input_pos = 0; } -void draw_notify() +void Console::draw_notify() { using namespace render; @@ -150,6 +259,7 @@ void draw_notify() const char *c = linedata.c_str(); char pen = 'N'; + char wordpen = 'N'; while (*c) { @@ -170,7 +280,7 @@ void draw_notify() h += Text::fontheight(); line.clear(); line += '^'; - line += pen; + line += wordpen; line_length = 0; } } @@ -180,6 +290,7 @@ void draw_notify() word.clear(); word_length = 0; + wordpen = pen; // new line if (*c == '\n' ) { @@ -205,7 +316,7 @@ void draw_notify() h += Text::fontheight(); line.clear(); line += '^'; - line += pen; + line += wordpen; line_length = 0; } @@ -214,6 +325,7 @@ void draw_notify() word.clear(); word_length = 0; + wordpen = pen; } } @@ -225,7 +337,7 @@ void draw_notify() } } -void draw_console() +void Console::draw_console() { using namespace render; @@ -251,17 +363,17 @@ void draw_console() gl::color(0.0f, 1.0f, 0.0f, 0.5f); Text::draw(video::width-Text::fontwidth()*(version.size()+1), video::height*con_height-Text::fontheight()-4, version); - // draw the console text - if (console_scroll > text.size()) - console_scroll = text.size(); + // draw the console consoleinterface_text + if (console_scroll > consoleinterface_text.size()) + console_scroll = consoleinterface_text.size(); size_t height = (size_t) (video::height * con_height / Text::fontheight()) -1; size_t width = (size_t) ((video::width-8) / Text::fontwidth()); - size_t bottom = text.size() - console_scroll; + size_t bottom = consoleinterface_text.size() - console_scroll; size_t current_line = 0; std::deque lines; - for (std::deque::iterator it = text.begin(); it != text.end() && current_line < bottom; it++) { + for (std::deque::iterator it = consoleinterface_text.begin(); it != consoleinterface_text.end() && current_line < bottom; it++) { if (current_line >= bottom - height) { std::string linedata(*it); linedata += '\n'; @@ -274,6 +386,7 @@ void draw_console() const char *c = linedata.c_str(); char pen = 'N'; + char wordpen = 'N'; while (*c) { @@ -293,7 +406,7 @@ void draw_console() lines.push_back(line); line.clear(); line += '^'; - line += pen; + line += wordpen; line_length = 0; } } @@ -303,6 +416,7 @@ void draw_console() word.clear(); word_length = 0; + wordpen = pen; // new line if (*c == '\n' ) { @@ -326,7 +440,7 @@ void draw_console() lines.push_back(line); line.clear(); line += '^'; - line += pen; + line += wordpen; line_length = 0; } @@ -335,6 +449,7 @@ void draw_console() word.clear(); word_length = 0; + wordpen = pen; } } @@ -354,233 +469,86 @@ void draw_console() // draw the console input - size_t draw_pos = 0; y = video::height*con_height - Text::fontheight() - 4; - - while (input_pos - draw_pos > width) - draw_pos += 2; - Text::draw(4, y, "^B>"); - Text::draw(4+Text::fontwidth(), y , (*history_pos).substr(draw_pos, width-1)); - // draw cursor - if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { - std::string cursor("^B_"); - Text::draw(4+Text::fontwidth()*(input_pos-draw_pos+1), y , cursor); - } - -} - -void draw(){ - if (visible()) - draw_console(); - else - draw_notify(); -} + std::string firstpart((*history_pos).substr(0, input_pos)); + size_t draw_width = 0; + const char *c = firstpart.c_str(); -void flush() -{ - char line[MAXCMDSIZE]; - while(console.buffer.getline(line, MAXCMDSIZE-1)) { - while (text.size() >= MAXCONLINES) { - text.pop_front(); + while (*c) { + if (aux::is_color_code(c)) { + c++; + } else { + draw_width++; } - text.push_back(std::string(line)); - - // save notification - notify_text[notify_pos] = line; - notify_time[notify_pos] = core::application()->time(); - notify_pos = (notify_pos+1) % MAXNOTIFYLINES; - - // print to stdout - std::cout << line << std::endl; + c++; } - - console.buffer.clear(); -} - -void toggle() -{ - console_visible = !console_visible; - - if (console_visible) { - console_scroll = 0; - input_pos = 0; - history_pos = history.rbegin(); - (*history_pos).clear(); - - SDL_WM_GrabInput(SDL_GRAB_OFF); - SDL_ShowCursor(SDL_ENABLE); - } else { - SDL_WM_GrabInput(SDL_GRAB_ON); - SDL_ShowCursor(SDL_DISABLE); - clear_notify(); + c = firstpart.c_str(); + while (*c && draw_width > width - 2) { + if (aux::is_color_code(c)) { + c++; + Text::setcolor(*c); + } else { + draw_width--; + } + c++; } - - setkeyboardmode(console::visible()); -} - -void keypressed(int key) -{ - std::deque::reverse_iterator upit; - - switch( key ) { - case SDLK_TAB: - core::CommandBuffer::complete( (*history_pos), input_pos); - break; - case SDLK_RETURN: - if ((*history_pos).size()) { - // store input into history - while (history.size() >= MAXHISTOLINES) { - history.pop_front(); - } - core::cmd() << (*history_pos) << std::endl; - con_print << "^B>" << (*history_pos) << std::endl; - (*history.rbegin()) = (*history_pos); + if (*c) { + Text::draw(4+Text::fontwidth(), y, c); + } - history.push_back(""); - history_pos = history.rbegin(); - input_pos = 0; - } - break; - case SDLK_UP: - upit = history_pos; - ++upit; - if (upit != history.rend()) { - history_pos = upit; - input_pos = (*history_pos).size(); - } - break; - case SDLK_DOWN: - if (history_pos != history.rbegin()) { - --history_pos; - input_pos = (*history_pos).size(); + if (input_pos < (*history_pos).size()) { + // FIXME limit to width + if (input_pos > 1 && aux::is_color_code((*history_pos).c_str() + input_pos -1)) { + Text::setcolor((*history_pos)[input_pos]); } - break; - case SDLK_HOME: - input_pos = 0; - break; - case SDLK_END: - input_pos = (*history_pos).size(); - break; - case SDLK_LEFT: - if (input_pos > 0) - input_pos--; - break; - case SDLK_RIGHT: - if (input_pos < (*history_pos).size()) - input_pos++; - break; - case SDLK_BACKSPACE: - if ((*history_pos).size() && input_pos) { - (*history_pos).erase(input_pos-1, 1); - input_pos--; - } - break; - case SDLK_PAGEUP: - console_scroll +=5; - if (console_scroll > text.size()) console_scroll = text.size(); - break; - case SDLK_PAGEDOWN: - if (console_scroll > 5) console_scroll -=5; - else console_scroll = 0; - break; - default: - if ((key >= 32 ) && (key <175)) { - if (input_pos == (*history_pos).size()) - (*history_pos) += (char)key; - else - (*history_pos).insert(input_pos, 1, (char)key); - input_pos++; - } - break; + c = (*history_pos).c_str() + input_pos; + Text::draw(4+Text::fontwidth()*(draw_width+1), y, c); } - -} - -bool visible() -{ - return console_visible; -} - -void save_history() -{ - - if (history.size() <= 1) - return; - - std::string filename(filesystem::writedir); - filename.append("history.txt"); - std::ofstream ofs(filename.c_str()); - - if (!ofs.is_open()) { - con_warn << "Could not write " << filename << std::endl; - return; - } - std::deque::iterator it; - size_t l = 1; - for (it = history.begin(); it != history.end(); it++) { - if (l < history.size()) - ofs << (*it) << std::endl; - l++; + // draw cursor + if ((core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { + std::string cursor("^B_"); + Text::draw(4+Text::fontwidth()*(draw_width+1), y , cursor); } - ofs.close(); } -void load_history() -{ - std::string filename(filesystem::writedir); - filename.append("history.txt"); - std::ifstream ifs(filename.c_str(), std::ifstream::in); - if (!ifs.is_open()) { - con_warn << "Could not read " << filename << std::endl; - return; - } - - history.clear(); - char line[MAXCMDSIZE]; - while (ifs.getline(line, MAXCMDSIZE-1)) { - history.push_back(line); +void Console::clear_notify() +{ + for (size_t i=0; i < MAXNOTIFYLINES; i++) { + notify_text[i].clear(); + notify_time[i] = 0; } - - ifs.close(); - - history.push_back(""); - history_pos = history.rbegin(); - input_pos = 0; + notify_pos = 0; } -//--- private ----------------------------------------------------- void Console::flush() { - console::flush(); -} + char line[MAXCMDSIZE]; -std::ostream & Console::messagestream() -{ - return (buffer << "^N"); -} + while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) { -std::ostream & Console::warningstream() -{ - return (buffer << "^W"); -} + while (consoleinterface_text.size() >= sys::MAXCONLINES) { + consoleinterface_text.pop_front(); + } + consoleinterface_text.push_back(std::string(line)); -std::ostream & Console::errorstream() -{ - return (buffer << "^R"); -} + // save notification + notify_text[notify_pos] = line; + notify_time[notify_pos] = core::application()->time(); + notify_pos = (notify_pos+1) % MAXNOTIFYLINES; -std::ostream & Console::debugstream() -{ - return (buffer << "^D"); + // print to stdout + print_ansi(line); + std::cout << std::endl; + } + + consoleinterface_buffer.clear(); } -} // namespace console - } // namespace client diff --git a/src/client/console.h b/src/client/console.h index dc831b7..2f8d6a0 100644 --- a/src/client/console.h +++ b/src/client/console.h @@ -9,54 +9,70 @@ #include "sys/consoleinterface.h" -#include -#include +namespace client { -const size_t MAXCONLINES = 2048; -const size_t MAXHISTOLINES = 512; const size_t MAXNOTIFYLINES = 3; +const size_t MAXHISTOLINES = 512; -namespace client { +/// client console implementation +class Console : public sys::ConsoleInterface { +public: + Console(); + virtual ~Console(); -/// the client console -namespace console { + virtual void flush(); -/// initialize client console -/** Adds the engine functions for the client console - */ -void init(); + void draw_console(); -/// shutdown the client console -/** Removes the engine functions for the client console - */ -void shutdown(); + void draw_notify(); -/// flush buffer messages and print to stdout -void flush(); - -/// draw the console -void draw(); + /// clear notifications + void clear_notify(); -/// toggle the console on or off -void toggle(); + /// draw client notifications or console text + void draw(); -/// handle keyboard input -void keypressed(int key); + /// toggle the console on or off + void toggle(); -/// true of the console is visible -bool visible(); + /// handle keyboard input + void keypressed(int key); -/// load input history -void load_history(); + /// true of the console is visible + inline bool visible() { return console_visible; } -/// save input history -void save_history(); + /// load input history + void load_history(); -extern size_t notify_pos; -extern std::string notify_text[MAXNOTIFYLINES]; -extern float notify_time[MAXNOTIFYLINES]; + /// save input history + void save_history(); -} + /// clear console + void clear(); + + /// initialize client console + static void init(); + + /// shutdown the client console + static void shutdown(); + +private: + // notifications + size_t notify_pos; + std::string notify_text[MAXNOTIFYLINES]; + float notify_time[MAXNOTIFYLINES]; + + // input history + std::deque history; + std::deque::reverse_iterator history_pos; + size_t input_pos; + + bool console_visible; + size_t console_scroll; + +}; + +Console *console(); } diff --git a/src/client/input.cc b/src/client/input.cc index f40591c..22db6bc 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -221,31 +221,31 @@ void frame(float seconds) mouse_y = event.motion.y; break; case SDL_MOUSEBUTTONDOWN: - if (!console::visible() && core::application()->connected() && core::localcontrol()) + if (!console()->visible() && core::application()->connected() && core::localcontrol()) mousebuttonpressed(event.button); break; case SDL_KEYUP: if (event.key.keysym.sym == SDLK_PRINT) { video::screenshot(); - } else if (!chat::visible() && !console::visible() && + } else if (!chat::visible() && !console()->visible() && core::application()->connected() && core::localcontrol()) // send key events to the game world keyreleased(event.key.keysym); break; case SDL_KEYDOWN: - if (chat::visible() && !console::visible() && (event.key.keysym.sym == SDLK_ESCAPE)) { + if (chat::visible() && !console()->visible() && (event.key.keysym.sym == SDLK_ESCAPE)) { chat::toggle(); } else if (event.key.keysym.sym == '`' || event.key.keysym.sym == '~' || (event.key.keysym.sym == SDLK_ESCAPE)) { //last_control = 0; - console::toggle(); + console()->toggle(); - if (console::visible() && chat::visible()) + if (console()->visible() && chat::visible()) chat::toggle(); - } else if (console::visible()) { + } else if (console()->visible()) { // send key events to the console - console::keypressed(translate_keysym(event.key.keysym)); + console()->keypressed(translate_keysym(event.key.keysym)); } else if (chat::visible()) { if(event.key.keysym.sym == SDLK_ESCAPE) { @@ -270,7 +270,7 @@ void frame(float seconds) } - if (!console::visible() && core::application()->connected() && core::localcontrol()) { + if (!console()->visible() && core::application()->connected() && core::localcontrol()) { if (cl_mousecontrol->value()) { // the mouse will not react if it is in the deadzone @@ -302,8 +302,8 @@ void frame(float seconds) } if ((camera::mode == camera::Track) || (camera::mode == camera::Cockpit)) { - local_direction = mouse_direction; - local_pitch = mouse_pitch; + local_direction = mouse_direction * math::absf(mouse_direction); + local_pitch = mouse_pitch * math::absf(mouse_pitch); } else if (camera::mode == camera::Free) { // squared values to smoothen camera movement camera::set_direction( -mouse_direction * math::absf(mouse_direction)); diff --git a/src/client/view.cc b/src/client/view.cc index 63c373e..e2c8687 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -128,7 +128,7 @@ void draw_status() { using namespace render; - if (console::visible()) + if (console()->visible()) return; // print the status in the upper left corner @@ -171,7 +171,7 @@ void draw_status() void draw_cursor() { - if (!core::localcontrol() || console::visible()) + if (!core::localcontrol() || console()->visible()) return; float crosshair_size = 48.0f; @@ -222,7 +222,7 @@ void frame(float seconds) fps = 9999; // flush console messages - console::flush(); + console()->flush(); // Clear the color and depth buffers. gl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -234,7 +234,7 @@ void frame(float seconds) gl::loadidentity(); // FIXME width must always be one - const float frustumsize = 0.5f; + const float frustumsize = 0.25f; gl::frustum(-frustumsize*video::aspect, frustumsize*video::aspect, -frustumsize, frustumsize, 1.0f, 1024.0f); gl::matrixmode(GL_MODELVIEW); // map world to screen coordinates @@ -263,7 +263,7 @@ void frame(float seconds) // draw text elements Text::setfont("bitmaps/fonts/console", 12, 18); - console::draw(); + console()->draw(); chat::draw(); Text::setfont("bitmaps/fonts/gui", 16, 24); -- cgit v1.2.3