From 02fcd22d8cde355aa898a8c6bb4773d9434b8e9a Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Fri, 10 Oct 2008 16:41:38 +0000 Subject: adds KeyPress, DevInfo and Stats widgets --- src/client/client.cc | 5 +- src/client/console.cc | 4 +- src/client/input.cc | 6 +- src/client/view.cc | 308 ++++++++++++++++++++++++++------------------ src/client/view.h | 69 +++++++++- src/core/application.cc | 8 +- src/core/gameconnection.h | 8 +- src/core/gameinterface.h | 9 +- src/core/gameserver.cc | 37 +++--- src/core/gameserver.h | 11 +- src/filesystem/inifile.cc | 5 + src/filesystem/inifile.h | 3 + src/render/render.cc | 2 +- src/render/textures.cc | 3 - src/sys/consoleinterface.cc | 9 +- src/sys/consoleinterface.h | 20 +-- src/ui/Makefile.am | 4 +- src/ui/button.cc | 14 +- src/ui/button.h | 4 +- src/ui/definitions.h | 28 ++++ src/ui/label.cc | 8 +- src/ui/label.h | 7 + src/ui/menu.cc | 37 +++++- src/ui/paint.cc | 73 +++++++++++ src/ui/paint.h | 8 +- src/ui/ui.cc | 35 +++-- src/ui/ui.h | 23 +++- src/ui/widget.cc | 92 ++++++++----- src/ui/widget.h | 44 ++++--- 29 files changed, 608 insertions(+), 276 deletions(-) create mode 100644 src/ui/definitions.h diff --git a/src/client/client.cc b/src/client/client.cc index e9bfba8..81aba9d 100644 --- a/src/client/client.cc +++ b/src/client/client.cc @@ -108,6 +108,7 @@ void Client::init(int count, char **arguments) // initialize user interface ui::init(); + new View(ui::root()); // Initialize the video subsystem if (!video::init()) { @@ -191,14 +192,14 @@ void Client::frame(float seconds) if (core::application()->load("intro")) { core::application()->connect(""); } - // if all fails, show the console + // show the console if everything fails if (!core::application()->connected() && !console()->visible()) { console()->toggle(); } } else { // show the main menu on non-interactive modules if (!core::game()->interactive() && !ui::root()->active()) { - ui::root()->show_window("main"); + ui::root()->show_window("main"); } } diff --git a/src/client/console.cc b/src/client/console.cc index e3c4288..96da900 100644 --- a/src/client/console.cc +++ b/src/client/console.cc @@ -32,14 +32,12 @@ Console *console() { void Console::init() { con_print << "^BInitializing console..." << std::endl; - console()->load_history(); } void Console::shutdown() { con_print << "^BShutting down console..." << std::endl; - console()->save_history(); } @@ -192,7 +190,6 @@ void Console::keypressed(unsigned int key) void Console::save_history() { - if (history.size() <= 1) return; @@ -539,3 +536,4 @@ void Console::notify(std::string const & message) } } // namespace client + diff --git a/src/client/input.cc b/src/client/input.cc index 0020a1f..31d514f 100644 --- a/src/client/input.cc +++ b/src/client/input.cc @@ -528,7 +528,7 @@ void key_pressed(Key *key) console()->keypressed(translate_keysym(key->sym(), keyboard_modifiers)); } else if (ui::root()->active()) { - ui::root()->event_keypress(key->sym(), keyboard_modifiers); + ui::root()->input_key(true, key->sym(), keyboard_modifiers); } else if (chat::visible()) { // send key events to the chat box @@ -559,7 +559,7 @@ void key_pressed(Key *key) void key_released(Key *key) { if (ui::root()->active()) { - ui::root()->event_keyrelease(key->sym(), keyboard_modifiers); + ui::root()->input_key(false, key->sym(), keyboard_modifiers); } if (core::application()->connected() && core::localcontrol()) { @@ -714,7 +714,7 @@ void frame(float seconds) mouse_x = event.motion.x; mouse_y = event.motion.y; mouse_lastmoved = client()->time(); - ui::root()->event_mousemove((float) mouse_x, (float) mouse_y); + ui::root()->input_mouse((float) mouse_x, (float) mouse_y); break; case SDL_MOUSEBUTTONDOWN: diff --git a/src/client/view.cc b/src/client/view.cc index 50b5b61..38d22d4 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -18,11 +18,14 @@ #include "client/input.h" #include "client/targets.h" #include "client/video.h" +#include "client/view.h" #include "render/render.h" #include "core/core.h" #include "math/mathlib.h" #include "sys/sys.h" +#include "ui/paint.h" #include "ui/ui.h" +#include "ui/widget.h" namespace client { @@ -35,35 +38,196 @@ core::Cvar *draw_keypress = 0; core::Cvar *ui_pointercolor = 0; core::Cvar *ui_pointerhovercolor =0; -namespace view +/* -- DevInfo------------------------------------------------------- */ +DevInfo::DevInfo(ui::Widget *parent) : ui::Widget(parent) { + set_label("devinfo"); + set_border(true); +} -const size_t fps_counter_size = 32; // fps is the average of 32 frames -float fps_counter_time[fps_counter_size]; -size_t fps_counter_index = 0; +void DevInfo::draw() +{ + draw_border(); -const size_t net_counter_size = 128; -float net_counter_time[net_counter_size]; -size_t net_counter_traffic[net_counter_size]; -size_t net_counter_index; + std::stringstream textstream; + core::Entity *target = targets::current(); + float d = 0; -core::Zone *current_zone = 0; + textstream << "^Ntime: ^B" << std::fixed << std::setprecision(4) << client()->time() << '\n'; + if (core::game()) { + textstream << "^Ngame: ^B" << core::game()->time(); + } + textstream << '\n'; -void init() + if (core::localcontrol()) { + textstream << std::fixed << std::setprecision(2) + << "^Nx:^B" << core::localcontrol()->location().x << " " + << "^Ny:^B" << core::localcontrol()->location().y << " " + << "^Nz:^B" << core::localcontrol()->location().z << '\n'; + + textstream << "^Nthurst:^B " << core::localcontrol()->thrust() << " " + << "^Nspeed:^B " << core::localcontrol()->speed() << '\n'; + + if (target) { + d = math::distance(core::localcontrol()->location(), target->state()->location()) - target->radius() - core::localcontrol()->radius(); + textstream << "^Ndist:^B " << d << '\n'; + } + } + + ui::paint::color(palette()->foreground()); + ui::paint::text(global_location(), font(), textstream); +} + +/* -- Stats -------------------------------------------------------- */ + +Stats::Stats(ui::Widget *parent) : ui::Widget(parent) { - draw_stats = core::Cvar::get("draw_stats", "0", core::Cvar::Archive); - draw_stats->set_info("[bool] draw network and render statistics"); + set_label("stats"); + set_border(true); + + // clear counters + for (size_t i =0; i < fps_counter_size; i++) + fps_counter_time[i] = 0.0f; + + for (size_t i = 0; i < net_counter_size; i++) + net_counter_traffic[i] = 0; +} + +void Stats::draw() +{ + draw_border(); + + // average fps + fps_counter_time[fps_counter_index] = core::application()->time(); + fps_counter_index = (fps_counter_index + 1 ) % fps_counter_size; + float min_time = core::application()->time(); + for (size_t i=0; i < fps_counter_size; i++) + if (fps_counter_time[i] < min_time) + min_time = fps_counter_time[i]; + float fps = 0.0f; + float t = (core::application()->time() - min_time); + if (t > 0) { + fps = roundf(((float) fps_counter_size - 1.0f) / t); + } + + std::stringstream textstream; + + if (core::game()) { + int minutes = (int) floorf(core::game()->clientframetime() / 60.0f); + int seconds = (int) floorf( core::game()->clientframetime() - (float) minutes* 60.0f); + + textstream << "^Ntime ^B" << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; + } + + textstream << std::setfill(' ') << "\n"; + textstream << "^Nfps ^B" << std::setw(6) << fps << "\n"; + if (core::application()->connected()) { + textstream << "^Ntris ^B" << std::setw(5) << render::Stats::tris << "\n"; + textstream << "^Nquads ^B" << std::setw(5) << render::Stats::quads << "\n"; + + if (core::Stats::network_bytes_sent + core::Stats::network_bytes_received) { + net_counter_traffic[net_counter_index] = core::Stats::network_bytes_sent + core::Stats::network_bytes_received; + net_counter_time[net_counter_index] = core::application()->time(); + size_t index_max = net_counter_index; + + net_counter_index = (net_counter_index + 1) % net_counter_size; + size_t index_min = net_counter_index; + + float d = net_counter_time[index_max] - net_counter_time[index_min]; + if (d > 0) { + float traffic = net_counter_traffic[index_max] - net_counter_traffic[index_min]; + textstream << "^Nnet ^B" << std::setw(6) << roundf( (float) traffic / d ) << "\n"; + } + } + } + + ui::paint::color(palette()->foreground()); + ui::paint::text(global_location(), font(), textstream); +} + +/* -- KeyPress ----------------------------------------------------- */ + +KeyPress::KeyPress(ui::Widget *parent) : Widget(parent) +{ + set_label("keypress"); + set_border(true); +} + +void KeyPress::draw() +{ + draw_border(); + + if(input::last_key_pressed()) { + ui::paint::color(palette()->highlight()); + ui::paint::text(global_location(), size(), font(), input::last_key_pressed()->name(), ui::AlignCenter); + } +} + +/* -- View --------------------------------------------------------- */ + +View::View(ui::Widget *parent) : ui::Widget(parent) +{ + set_label("view"); + set_border(false); + + // initialize client variables draw_devinfo = core::Cvar::get("draw_devinfo", "0", core::Cvar::Archive); draw_devinfo->set_info("[bool] draw developer information"); - // FIXME integrate with libui - draw_ui = core::Cvar::get("draw_ui", "1", core::Cvar::Archive); - draw_ui->set_info("[bool] draw the user interface"); + draw_stats = core::Cvar::get("draw_stats", "0", core::Cvar::Archive); + draw_stats->set_info("[bool] draw network and render statistics"); draw_keypress = core::Cvar::get("draw_keypress", "0", core::Cvar::Archive); draw_keypress->set_info("[bool] draw keypress key names"); + // add child widgets + view_devinfo = new DevInfo(this); + view_stats = new Stats(this); + view_keypress = new KeyPress(this); + + // make sure the view is at the bottom of the draw stack + lower(); +} + +void View::resize() +{ + set_size(parent()->size()); + + // reposition devinfo widget + view_devinfo->set_size(font()->width()*32, font()->height()*5); + view_devinfo->set_location(font()->width() * 0.5f, font()->height() * 0.5f); + + // reposition stats widget + view_stats->set_size(font()->width()*12, font()->height()*5); + view_stats->set_location(width() - view_stats->width() - font()->width() * 0.5, font()->height() * 0.5f); + + // reposition keypress widget + view_keypress->set_size(font()->width()*12, font()->height()*1); + view_keypress->set_location(width() - view_keypress->width() - font()->width() * 0.5, + height() - view_keypress->height() - font()->height() * 0.5f); +} + +void View::draw() +{ + view_devinfo->set_visible(draw_devinfo->value() ? true : false); + view_stats->set_visible(draw_stats->value() ? true : false); + view_keypress->set_visible(draw_keypress->value() ? true : false); +} + +/* -- namespace view ----------------------------------------------- */ + +namespace view +{ + +core::Zone *current_zone = 0; + +void init() +{ + // FIXME integrate with libui + draw_ui = core::Cvar::get("draw_ui", "1", core::Cvar::Archive); + draw_ui->set_info("[bool] draw the user interface"); + ui_pointercolor = core::Cvar::get("ui_pointercolor", "0 .5 0", core::Cvar::Archive); ui_pointercolor->set_info("[r g b] mouse pointer color"); @@ -71,12 +235,6 @@ void init() ui_pointerhovercolor->set_info("[r g b] mouse pointer hover color"); targets::init(); - - for (size_t i =0; i < fps_counter_size; i++) - fps_counter_time[i] = 0.0f; - - for (size_t i = 0; i < net_counter_size; i++) - net_counter_traffic[i] = 0; } void shutdown() @@ -108,53 +266,7 @@ void clear_zone(core::Zone *zone) zone->set_sky_texture(0); } } -/* -void draw_loader() -{ - using namespace render; - - render::Textures::bind("bitmaps/loader"); - - gl::begin(gl::Quads); - - glTexCoord2f(0.0f, 0.0f); - gl::vertex(0,0, 0); - - glTexCoord2f(1.0f, 0.0f); - gl::vertex(video::width,0,0); - - glTexCoord2f(1.0f, 1.0f); - gl::vertex(video::width,video::height,0); - - glTexCoord2f(0.0f, 1.0f); - gl::vertex(0,video::height,0); - - gl::end(); -} - -void draw_banner() -{ - using namespace render; - render::Textures::bind("bitmaps/banner"); - - gl::begin(gl::Quads); - - glTexCoord2f(0.0f, 0.0f); - gl::vertex(0,0, 0); - - glTexCoord2f(1.0f, 0.0f); - gl::vertex(video::width,0,0); - - glTexCoord2f(1.0f, 1.0f); - gl::vertex(video::width,video::height,0); - - glTexCoord2f(0.0f, 1.0f); - gl::vertex(0,video::height,0); - - gl::end(); -} -*/ /* FIXME should be merged with the render passes and in the bbox pass @@ -168,7 +280,6 @@ void draw_entity_world_target(core::Entity *entity) if (!model) return; - if (!model->docks().size()) return; @@ -375,65 +486,8 @@ void draw_entity_target(core::Entity *entity, bool is_active_target) void draw_status() { using namespace render; - std::stringstream status; - if (core::game() && core::game()->interactive()) { - int minutes = (int) floorf(core::game()->clientframetime() / 60.0f); - int seconds = (int) floorf( core::game()->clientframetime() - (float) minutes* 60.0f); - - status << "^Ntime ^B" << std::setfill(' ') << std::setw(3) << minutes << ":" << std::setfill('0') << std::setw(2) << seconds; - Text::draw(video::width-Text::fontwidth()*12-4, Text::fontheight()+ 4, status); - } - - // print stats if desired - if (draw_stats && draw_stats->value()) { - // average fps - fps_counter_time[fps_counter_index] = core::application()->time(); - fps_counter_index = (fps_counter_index + 1 ) % fps_counter_size; - float min_time = core::application()->time(); - for (size_t i=0; i < fps_counter_size; i++) - if (fps_counter_time[i] < min_time) - min_time = fps_counter_time[i]; - float fps = 0.0f; - float t = (core::application()->time() - min_time); - if (t > 0) { - fps = roundf(((float) fps_counter_size - 1.0f) / t); - } - - std::stringstream stats; - stats << "^Nfps ^B" << std::setw(6) << fps << "\n"; - - if (core::application()->connected()) { - stats << "^Ntris ^B" << std::setw(5) << render::Stats::tris << "\n"; - stats << "^Nquads ^B" << std::setw(5) << render::Stats::quads << "\n"; - - if (core::Stats::network_bytes_sent + core::Stats::network_bytes_received) { - net_counter_traffic[net_counter_index] = core::Stats::network_bytes_sent + core::Stats::network_bytes_received; - net_counter_time[net_counter_index] = core::application()->time(); - size_t index_max = net_counter_index; - - net_counter_index = (net_counter_index + 1) % net_counter_size; - size_t index_min = net_counter_index; - - float d = net_counter_time[index_max] - net_counter_time[index_min]; - if (d > 0) { - float traffic = net_counter_traffic[index_max] - net_counter_traffic[index_min]; - - stats << "^Nnet ^B" << std::setw(6) << roundf( (float) traffic / d ) << "\n"; - } - } - } - - Text::draw(video::width-Text::fontwidth()*12-4, 4 + Text::fontheight()*2, stats); - } - - // draw keypress - if (draw_keypress->value() && input::last_key_pressed()) { - Text::setcolor('F'); //set fancy color - Text::draw(video::width-4-Text::fontwidth()*6, video::height-Text::fontheight()-4, input::last_key_pressed()->name()); - } - // draw a basic HUD if (core::localcontrol() && core::localcontrol()->zone()) { core::Zone *zone = core::localcontrol()->zone(); @@ -477,7 +531,7 @@ void draw_status() if (target) { d = math::distance(core::localcontrol()->location(), target->state()->location()) - target->radius() - core::localcontrol()->radius(); } - +/* if (draw_devinfo->value()) { std::stringstream devinfo; devinfo << std::fixed << std::setprecision(2) @@ -491,7 +545,7 @@ void draw_status() devinfo << "^Ndist:^B " << d << '\n'; Text::draw(4, 4 + Text::fontheight(), devinfo); } - +*/ float y = 1.0f; if (target) { std::stringstream strtarget; diff --git a/src/client/view.h b/src/client/view.h index 1f81597..e5e42bc 100644 --- a/src/client/view.h +++ b/src/client/view.h @@ -7,12 +7,79 @@ #define __INCLUDED_CLIENT_VIEW_H__ #include "core/zone.h" +#include "ui/widget.h" namespace client { +const size_t fps_counter_size = 32; // fps is the average of 32 frames +const size_t net_counter_size = 128; // net is the average of 128 frames + +//// a widget to show developer info +class DevInfo : public ui::Widget +{ +public: + // default constructor + DevInfo(ui::Widget *parent = 0); + +protected: + // draw developer info + void draw(); +}; + +// a widget that shows engine statistics +class Stats : public ui::Widget +{ +public: + // default constructor + Stats(ui::Widget *parent=0); + +protected: + // draw engine statistics + virtual void draw(); + +private: + float fps_counter_time[fps_counter_size]; + size_t fps_counter_index; + + float net_counter_time[net_counter_size]; + size_t net_counter_traffic[net_counter_size]; + size_t net_counter_index; +}; + +/// a widget to show keypress events +class KeyPress : public ui::Widget +{ +public: + // default constructor + KeyPress(ui::Widget *parent=0); + +protected: + // draw keypress events + virtual void draw(); +}; + +/// the client view widget +/** +* the client view renders the world and contains the main user interface widgets +*/ +class View : public ui::Widget +{ +public: + View(ui::Widget *parent=0); + +protected: + virtual void draw(); + virtual void resize(); + +private: + DevInfo *view_devinfo; + Stats *view_stats; + KeyPress *view_keypress; +}; + /// functions to draw the client view -namespace view +namespace view { /// intialize the view void init(); diff --git a/src/core/application.cc b/src/core/application.cc index 3f08a36..3b30962 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -378,15 +378,11 @@ void Application::disconnect() void Application::frame(float seconds) { + application_time += seconds; + // execute commands in the buffer CommandBuffer::exec(); - application_time += seconds; - - // don't run zero lenght time frames - //if (seconds == 0.0f) - // return; - if (!connected()) return; diff --git a/src/core/gameconnection.h b/src/core/gameconnection.h index 973d96f..95df9f3 100644 --- a/src/core/gameconnection.h +++ b/src/core/gameconnection.h @@ -23,14 +23,16 @@ public: /*----- inspectors ------------------------------------------------ */ /// returns true if the game connection can run a time frime - inline bool running() { return connection_running; } + inline bool running() const { return connection_running; } /// returns true if the game connection can not run a time frime - inline bool error() { return !connection_running; } + inline bool error() const { return !connection_running; } /// returns true if the game is running an interactive module - inline bool interactive() { return true; } + inline bool interactive() const { return true; } + /// return the current game time + inline float time() const { return game_clientframetime; } /*----- mutators -------------------------------------------------- */ diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index b6d7cb6..fea86fe 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -26,7 +26,7 @@ public: typedef std::list Players; /*----- inspectors ---------------------------------------------- */ - + /// return the local player inline Player *localplayer() { return &game_localplayer; } @@ -52,10 +52,13 @@ public: /*----- virtual inspectors --------------------------------------- */ /// returns true if the game server can run a time frime - virtual bool running() = 0; + virtual bool running() const = 0; /// returns true if the game is running an interactive module - virtual bool interactive() = 0; + virtual bool interactive() const = 0; + + /// return the current game time + virtual float time() const = 0; /*----- mutators ------------------------------------------------- */ diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 4037c70..b6767ad 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -35,7 +35,18 @@ void func_who(std::string const &args) void func_time(std::string const &args) { - server()->showtime(); + using namespace std; + + int minutes = (int) floorf(server()->time() / 60.0f); + int seconds = (int) floorf(server()->time() - (float) minutes* 60.0f); + + int syshours = sys::time() / 3600; + int sysminutes = (sys::time() - syshours * 3600) / 60; + int sysseconds = sys::time() % 60; + + con_print << + "Uptime " << minutes << ":" << setfill('0') << setw(2) << seconds << + " Local time " << setfill(' ') << setw(2) << syshours << ":" << setfill('0') << setw(2) << sysminutes << ":" << setw(2) << sysseconds << setfill(' ') << std::endl; } void func_mute(std::string const &args) @@ -220,7 +231,7 @@ void GameServer::abort() server_running = false; } -bool GameServer::interactive() +bool GameServer::interactive() const { if (!server_module) { return false; @@ -229,22 +240,6 @@ bool GameServer::interactive() } } -void GameServer::showtime() -{ - using namespace std; - - int minutes = (int) floorf(server_time / 60.0f); - int seconds = (int) floorf(server_time - (float) minutes* 60.0f); - - int syshours = sys::time() / 3600; - int sysminutes = (sys::time() - syshours * 3600) / 60; - int sysseconds = sys::time() % 60; - - con_print << - "Uptime " << minutes << ":" << setfill('0') << setw(2) << seconds << - " Server localtime " << setfill(' ') << setw(2) << syshours << ":" << setfill('0') << setw(2) << sysminutes << ":" << setw(2) << sysseconds << setfill(' ') << std::endl; -} - Player *GameServer::find_player(std::string const search) { using aux::lowercase; @@ -497,20 +492,20 @@ void GameServer::exec(Player *player, std::string const & cmdline) if ((function ->flags() & Func::Game) == Func::Game) { function->exec(player, args); return; + } else if ((function->flags() & Func::Shared) == Func::Shared) { // enable rcon buffering - console()->buffer_rcon(true); + console()->set_rcon(true); function->exec(args); char line[MAXCMDSIZE]; - while(console()->buffer().getline(line, MAXCMDSIZE-1)) { send(player, std::string(line)); } // disable rcon buffering - console()->buffer_rcon(false); + console()->set_rcon(false); return; } } diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 0dfdd9d..550dd99 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -28,19 +28,16 @@ public: /*----- inspectors ------------------------------------------------ */ /// returns true if the game server can run a time frime - inline bool running() { return server_running; } + inline bool running() const { return server_running; } /// returns true if the game server can not run a time frime - inline bool error() { return !server_running; } + inline bool error() const { return !server_running; } /// returns true if the game is running an interactive module - bool interactive(); - - /// show the current time - void showtime(); + virtual bool interactive() const; /// current server game time - inline float time() const { return server_time; } + virtual inline float time() const { return server_time; } /*----- mutators -------------------------------------------------- */ diff --git a/src/filesystem/inifile.cc b/src/filesystem/inifile.cc index 90efa15..ddb1c63 100644 --- a/src/filesystem/inifile.cc +++ b/src/filesystem/inifile.cc @@ -237,6 +237,11 @@ bool IniFile::got_key_bool(const char * keylabel, bool & b) return false; } +void IniFile::unknown_value() const +{ + con_warn << name() << " unknown value '" << value() << "' for key '" << key() << "' at line " << line() << std::endl; +} + void IniFile::unkown_key() const { con_warn << name() << " unknown key '" << key() << "' at line " << line() << std::endl; diff --git a/src/filesystem/inifile.h b/src/filesystem/inifile.h index 765f1af..f118f7b 100644 --- a/src/filesystem/inifile.h +++ b/src/filesystem/inifile.h @@ -81,6 +81,9 @@ public: return line_number; } + /// print a default unkown value error + void unknown_value() const; + /// print a default unkown key error void unkown_key() const; diff --git a/src/render/render.cc b/src/render/render.cc index 8fce251..f018510 100644 --- a/src/render/render.cc +++ b/src/render/render.cc @@ -63,7 +63,7 @@ void init() r_wireframe = core::Cvar::get("r_wireframe", "0", core::Cvar::Archive); r_wireframe->set_info("[bool] render wireframe"); - r_grid = core::Cvar::get("r_grid", "1", core::Cvar::Archive); + r_grid = core::Cvar::get("r_grid", "0", core::Cvar::Archive); r_grid->set_info("[bool] render the space grid"); r_bbox = core::Cvar::get("r_bbox", "0", core::Cvar::Archive); diff --git a/src/render/textures.cc b/src/render/textures.cc index bf0cc84..fd2367d 100644 --- a/src/render/textures.cc +++ b/src/render/textures.cc @@ -40,9 +40,6 @@ void Textures::init() core::application()->shutdown(); } - // loading screen background - load("bitmaps/loader"); - // crosshairs load("bitmaps/pointers/pointer"); load("bitmaps/pointers/aim"); diff --git a/src/sys/consoleinterface.cc b/src/sys/consoleinterface.cc index 45508ee..073f34b 100644 --- a/src/sys/consoleinterface.cc +++ b/src/sys/consoleinterface.cc @@ -72,7 +72,6 @@ void ConsoleInterface::flush() char line[MAXCMDSIZE]; while(consoleinterface_buffer.getline(line, MAXCMDSIZE-1)) { - while (consoleinterface_text.size() >= MAXCONLINES) { consoleinterface_text.pop_front(); } @@ -175,7 +174,12 @@ void ConsoleInterface::print_ansi(const char *line) std::cout << "\033[0;39m"; } -void ConsoleInterface::buffer_rcon(bool enable) +void ConsoleInterface::set_ansi(bool enable) +{ + consoleinterface_ansi = enable; +} + +void ConsoleInterface::set_rcon(bool enable) { if (enable) { flush(); @@ -185,3 +189,4 @@ void ConsoleInterface::buffer_rcon(bool enable) } } // namespace sys + diff --git a/src/sys/consoleinterface.h b/src/sys/consoleinterface.h index 33052cf..5411cb6 100644 --- a/src/sys/consoleinterface.h +++ b/src/sys/consoleinterface.h @@ -60,20 +60,22 @@ public: /// resize the console (ncurses stub) virtual void resize(); - /// turn ANSI color codes on or off - inline void set_ansi(bool ansi) { consoleinterface_ansi = ansi; } - - /// a pointer to the current console instance - static ConsoleInterface *instance(); - - /// enable or disable rcon - void buffer_rcon(bool enable = true); - /// return the console inputbuffer inline std::stringstream & buffer() { return consoleinterface_buffer; } inline bool rcon() { return consoleinterface_rcon; } + inline bool ansi() { return consoleinterface_ansi; } + + /// enable or disable ANSI escape sequences + void set_ansi(bool enable = true); + + /// enable or disable rcon + void set_rcon(bool enable = true); + + /// a pointer to the current console instance + static ConsoleInterface *instance(); + protected: std::deque consoleinterface_text; std::stringstream consoleinterface_buffer; diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am index 5d14589..5c7815b 100644 --- a/src/ui/Makefile.am +++ b/src/ui/Makefile.am @@ -7,8 +7,8 @@ else noinst_LTLIBRARIES = libui.la endif -noinst_HEADERS = bitmap.h button.h font.h label.h menu.h paint.h \ - palette.h ui.h widget.h window.h +noinst_HEADERS = bitmap.h button.h definitions.h font.h label.h \ + menu.h paint.h palette.h ui.h widget.h window.h libui_la_SOURCES = bitmap.cc button.cc font.cc label.cc menu.cc paint.cc \ palette.cc ui.cc widget.cc window.cc diff --git a/src/ui/button.cc b/src/ui/button.cc index d6384c9..1ac5fd8 100644 --- a/src/ui/button.cc +++ b/src/ui/button.cc @@ -17,6 +17,7 @@ Button::Button (Widget *parent, const char *text, const char *command) : Label(p { set_label("button"); set_command(command); + set_alignment(AlignCenter); } Button::~Button() @@ -51,6 +52,7 @@ void Button::draw_border() paint::color(palette()->foreground()); else paint::color(palette()->border()); + paint::border(global_location(), size()); } @@ -64,21 +66,23 @@ void Button::draw_text() else paint::color(palette()->foreground()); - paint::text_centered(global_location(), size(), text(), font()); + paint::text(global_location(), size(), font(), text(), alignment()); } -void Button::keypress(unsigned int key, unsigned int modifier) +bool Button::keypress(unsigned int key, unsigned int modifier) { - + return false; } -void Button::keyrelease(unsigned int key, unsigned int modifier) +bool Button::keyrelease(unsigned int key, unsigned int modifier) { if (key == 512 + SDL_BUTTON_LEFT) { core::cmd() << button_command << std::endl; audio::play("ui/button"); + return true; } -} + return false; } +} diff --git a/src/ui/button.h b/src/ui/button.h index 34c3ba4..c074467 100644 --- a/src/ui/button.h +++ b/src/ui/button.h @@ -26,8 +26,8 @@ public: virtual void print(size_t indent); /// handle keyboard events - virtual void keypress(unsigned int key, unsigned int modifier); - virtual void keyrelease(unsigned int key, unsigned int modifier); + virtual bool keypress(unsigned int key, unsigned int modifier); + virtual bool keyrelease(unsigned int key, unsigned int modifier); protected: /// draw the button border diff --git a/src/ui/definitions.h b/src/ui/definitions.h new file mode 100644 index 0000000..d5d7fe9 --- /dev/null +++ b/src/ui/definitions.h @@ -0,0 +1,28 @@ +/* + ui/definitions.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_UI_DEFINITIONS_H__ +#define __INCLUDED_UI_DEFINITIONS_H__ + +namespace ui { + +enum Alignment { + AlignAuto = 0x0000, + AlignLeft = 0x0001, + AlignHCenter = 0x0002, + AlignRight = 0x0004, + + AlignTop = 0x0010, + AlignVCenter = 0x0020, + AlignBottom = 0x0040, + + AlignCenter = AlignHCenter | AlignVCenter +}; + +} + +#endif // __INCLUDED_UI_DEFINITIONS_H__ + diff --git a/src/ui/label.cc b/src/ui/label.cc index 1b142c4..6f496fc 100644 --- a/src/ui/label.cc +++ b/src/ui/label.cc @@ -16,6 +16,7 @@ Label::Label(Widget *parent, const char *text) : Widget(parent) { set_label("label"); set_text(text); + set_alignment(AlignLeft | AlignTop); } Label::~Label() @@ -41,6 +42,11 @@ void Label::set_text(std::string const &text) label_text.assign(text); } +void Label::set_alignment(unsigned int alignment) +{ + label_alignment = alignment; +} + void Label::draw() { Widget::draw(); @@ -54,7 +60,7 @@ void Label::draw_text() return; paint::color(palette()->foreground()); - paint::text_centered(global_location(), size(), text(), font()); + paint::text(global_location(), size(), font(), text(), alignment()); } } diff --git a/src/ui/label.h b/src/ui/label.h index 460ac8a..45171b2 100644 --- a/src/ui/label.h +++ b/src/ui/label.h @@ -24,9 +24,15 @@ public: /// set the text displayed by the label void set_text(const char *text); + /// set the text alignment + void set_alignment(unsigned int alignment); + /// return the text displayed by the label inline std::string const &text() const { return label_text; } + /// text alignment + inline unsigned int alignment() const { return label_alignment; } + /// print label description virtual void print(size_t indent); @@ -39,6 +45,7 @@ protected: private: std::string label_text; + unsigned int label_alignment; }; } diff --git a/src/ui/menu.cc b/src/ui/menu.cc index 34aa96c..af9929c 100644 --- a/src/ui/menu.cc +++ b/src/ui/menu.cc @@ -23,7 +23,8 @@ Menu::Menu(Window *parent, const char *label) : Window(parent) menu_background = new Bitmap(this); menu_container = new Window(this); - menu_container->set_border(false); + menu_container->set_border(true); + menu_container->set_background(true); menu_container->set_label("container"); } @@ -91,12 +92,34 @@ void Menu::load() } else if (ini.got_key_string("command", strval)) { button->set_command(strval); + } else if (ini.got_key_string("align", strval)) { + aux::to_label(strval); + if (strval.compare("left") == 0) { + button->set_alignment(AlignLeft | AlignVCenter); + } else if (strval.compare("center") == 0) { + button->set_alignment(AlignCenter); + } else if (strval.compare("right") == 0) { + button->set_alignment(AlignRight | AlignVCenter); + } else { + ini.unknown_value(); + } } else { ini.unkown_key(); } } else if (ini.in_section("label")) { if (ini.got_key_string("text", strval)) { label->set_text(strval); + } else if (ini.got_key_string("align", strval)) { + aux::to_label(strval); + if (strval.compare("left") == 0) { + label->set_alignment(AlignLeft | AlignHCenter); + } else if (strval.compare("center") == 0) { + label->set_alignment(AlignCenter); + } else if (strval.compare("right") == 0) { + label->set_alignment(AlignRight | AlignHCenter); + } else { + ini.unknown_value(); + } } else { ini.unkown_key(); } @@ -116,7 +139,11 @@ void Menu::set_background(const char *texture) Label *Menu::add_label(char const * text) { - return new Label(menu_container, text); + Label *label = new Label(menu_container, text); + label->set_alignment(AlignCenter); + label->set_border(false); + label->set_font(ui::root()->font_large()); + return label; } Button *Menu::add_button(char const *text, char const *command) @@ -130,15 +157,15 @@ void Menu::resize() menu_background->size().assign(size()); float n = (float) menu_container->children().size(); - menu_container->set_size(2.0f * menu_element_width, n * (menu_element_height + menu_element_margin) + menu_element_height); - menu_container->set_location(menu_element_margin, (height() - menu_container->height()) / 2.0f); + menu_container->set_size(1.5f * menu_element_width, n * (menu_element_height + menu_element_margin) + menu_element_height); + menu_container->set_location(menu_element_width * 0.25, (height() - menu_container->height()) / 2.0f); // reposition all children within the container size_t i = 0; for (Children::iterator it = menu_container->children().begin(); it != menu_container->children().end(); it++) { Widget *w = (*it); w->set_size(menu_element_width, menu_element_height); - w->set_location(menu_element_width * 0.5f, menu_element_height * 0.5f + i * (menu_element_height + menu_element_margin)); + w->set_location(menu_element_width * 0.25f, menu_element_height * 0.5f + i * (menu_element_height + menu_element_margin)); i++; } } diff --git a/src/ui/paint.cc b/src/ui/paint.cc index 935cf92..ce5a5c2 100644 --- a/src/ui/paint.cc +++ b/src/ui/paint.cc @@ -93,6 +93,79 @@ void text_centered(math::Vector2f const &location, math::Vector2f const &size, s disable(GL_TEXTURE_2D); } +void text(math::Vector2f const &location, Font const *font, std::stringstream & textstream) +{ + using namespace render::gl; + render::Text::setfont(font->name().c_str(), font->width(), font->height()); + + // enable OpenGL textures + enable(GL_TEXTURE_2D); + + render::Text::draw(location.x, location.y, textstream); + + // disable texturing + disable(GL_TEXTURE_2D); +} + +void text(math::Vector2f const &location, math::Vector2f const &size, + Font const *font, + std::string const &text, + unsigned int align) +{ + unsigned int align_horizontal = (align & 0x000F); + if (!align_horizontal) + align_horizontal = AlignLeft; + + unsigned int align_vertical = (align & 0x00F0); + if (!align_vertical) + align_vertical = AlignTop; + + // apply text font + using namespace render::gl; + render::Text::setfont(font->name().c_str(), font->width(), font->height()); + + // enable OpenGL textures + enable(GL_TEXTURE_2D); + + // determine the width and height of the text + // FIXME support multiline text + float text_height = 1.0f * font->height(); + float text_width = (float) aux::text_strip(text).size() * font->width(); + + // calculate drawing position + math::Vector2f v(location); + + switch(align_horizontal) { + case AlignLeft: + v.x += font->width(); + break; + case AlignHCenter: + v.x += (size.x - text_width) / 2.0f; + break; + case AlignRight: + v.x += size.x - text_width - font->width(); + break; + } + + switch(align_vertical) { + case AlignTop: + v.y += font->height()*0.5f; + break; + case AlignVCenter: + v.y += (size.y - text_height) / 2.0f; + break; + case AlignBottom: + v.y += size.y - text_height - font->height()*0.5f; + break; + } + + render::Text::draw(v.x, v.y, text); + + // disable texturing + disable(GL_TEXTURE_2D); + +} + } } diff --git a/src/ui/paint.h b/src/ui/paint.h index b75290d..3128481 100644 --- a/src/ui/paint.h +++ b/src/ui/paint.h @@ -29,8 +29,12 @@ void rectangle(math::Vector2f const &location, math::Vector2f const &size); /// draw a rectangular bitmap void bitmap(math::Vector2f const &location, math::Vector2f const &size, std::string const &texture); -/// draw one line of centered text -void text_centered(math::Vector2f const &location, math::Vector2f const &size, std::string const &text, Font const *font); +/// draw text +void text(math::Vector2f const &location, math::Vector2f const &size, Font const *font, std::string const &text, + unsigned int align = AlignCenter); + +/// draw textstream +void text(math::Vector2f const &location, Font const *font, std::stringstream & textstream); } diff --git a/src/ui/ui.cc b/src/ui/ui.cc index 2b09938..bba9ea6 100644 --- a/src/ui/ui.cc +++ b/src/ui/ui.cc @@ -132,8 +132,15 @@ UI *root() void init() { con_print << "^BInitializing user interface..." << std::endl; - if (!global_ui) + + if (!global_ui) { global_ui = new UI(); + } else { + con_warn << "User interface already initialized!" << std::endl; + return; + } + + global_ui->load(); core::Func *func = core::Func::add("list_ui", func_list_ui); func->set_info("list user interface widgets"); @@ -178,11 +185,8 @@ UI::UI() : Window(0) // default fonts ui_font_small = new Font("gui", 12, 18); - ui_font_medium = new Font("gui", 14, 24); - ui_font_large = new Font("gui", 16, 30); + ui_font_large = new Font("gui", 14, 24); set_font(ui_font_small); - - load(); } UI::~UI() @@ -190,7 +194,6 @@ UI::~UI() delete ui_palette; delete ui_font_small; - delete ui_font_medium; delete ui_font_large; } @@ -315,7 +318,6 @@ void UI::add_window(Window *window) { Window::add_window(window); window->hide(); - window->set_font(ui_font_medium); } void UI::remove_window(Window *window) @@ -347,6 +349,7 @@ void UI::show_window(const char *label) ui_active_window->hide(); ui_active_window = window; ui_active_window->event_resize(); + ui_active_window->raise(); ui_active_window->show(); ui_focus = window; } else { @@ -364,23 +367,29 @@ void UI::hide_window() void UI::frame() { - ui_focus = find_focus(mouse_cursor); + ui_focus = event_focus(mouse_cursor); event_draw(); } -void UI::event_mousemove(float x, float y) +void UI::input_mouse(float x, float y) { mouse_cursor.assign(x, y); } -void UI::event_keypress(unsigned int key, unsigned int modifier) +void UI::input_key(bool pressed, unsigned int key, unsigned int modifier) { - ui_focus->keypress(key, modifier); + ui_focus->event_key(pressed, key, modifier); } -void UI::event_keyrelease(unsigned int key, unsigned int modifier) +bool UI::keypress(unsigned int key, unsigned int modifier) { - ui_focus->keyrelease(key, modifier); + return true; } +bool UI::keyrelease(unsigned int key, unsigned int modifier) +{ + return true; } + +} + diff --git a/src/ui/ui.h b/src/ui/ui.h index b3b2259..3a4ba75 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -40,29 +40,38 @@ public: /// return the active window Window *active() { return ui_active_window; } - /// handle mouse cursor - void event_mousemove(float x, float y); + /// mouse cursor input + void input_mouse(float x, float y); - /// handle keyboard input - void event_keypress(unsigned int key, unsigned int modifier); - void event_keyrelease(unsigned int key, unsigned int modifier); + /// keyboard input + void input_key(bool pressed, unsigned int key, unsigned int modifier); /// run a user interface frame void frame(); - /// return the widget that has the focus + /// return the widget which has the focus inline Widget *focus() { return ui_focus; } + /* -- Fonts ------------------------------------------------ */ + /// default small font + inline Font *font_small() { return ui_font_small; } + + /// default medium font + inline Font *font_large() { return ui_font_large; } + protected: Window *find_window(const char *label); virtual void add_window(Window *window); virtual void remove_window(Window *window); + /// handle keyboard input + virtual bool keypress(unsigned int key, unsigned int modifier); + virtual bool keyrelease(unsigned int key, unsigned int modifier); + private: Palette *ui_palette; Font *ui_font_small; - Font *ui_font_medium; Font *ui_font_large; Window *ui_active_window; diff --git a/src/ui/widget.cc b/src/ui/widget.cc index 4ff577c..b2c436d 100644 --- a/src/ui/widget.cc +++ b/src/ui/widget.cc @@ -71,6 +71,30 @@ Font const *Widget::font() const { } } +void Widget::lower() +{ + if (!parent()) + return; + + Children::iterator it = parent()->find_child(this); + if (it != parent()->children().end()) { + parent()->children().erase(it); + parent()->children().push_front(this); + } +} + +void Widget::raise() +{ + if (!parent()) + return; + + Children::iterator it = parent()->find_child(this); + if (it != parent()->children().end()) { + parent()->children().erase(it); + parent()->children().push_back(this); + } +} + void Widget::show() { widget_visible = true; @@ -81,6 +105,12 @@ void Widget::hide() widget_visible = false; } + +void Widget::set_visible(bool visible) +{ + widget_visible = visible; +} + void Widget::set_border(bool border) { widget_border = border; @@ -122,6 +152,11 @@ void Widget::set_size(float const w, float const h) widget_size.assign(w, h); } +void Widget::set_size(math::Vector2f const &size) +{ + widget_size.assign(size); +} + void Widget::set_width(float const w) { widget_size.x = w; @@ -159,30 +194,6 @@ void Widget::remove_child(Widget *child) } } -void Widget::raise() -{ - if (!parent()) - return; - - Children::iterator it = find_child(this); - if (it != parent()->children().end()) { - parent()->children().erase(it); - parent()->children().push_front(this); - } -} - -void Widget::lower() -{ - if (!parent()) - return; - - Children::iterator it = find_child(this); - if (it != parent()->children().end()) { - parent()->children().erase(it); - parent()->children().push_back(this); - } -} - void Widget::event_resize() { resize(); @@ -231,7 +242,7 @@ void Widget::draw_border() paint::border(global_location(), size()); } -Widget *Widget::find_focus(math::Vector2f const & pos) +Widget *Widget::event_focus(math::Vector2f const & pos) { // this widget is not visible if (!visible()) @@ -245,7 +256,7 @@ Widget *Widget::find_focus(math::Vector2f const & pos) for (Children::reverse_iterator rit = widget_children.rbegin(); rit != widget_children.rend(); ++rit) { Widget *w = (*rit); if (w->visible()) { - Widget *f = w->find_focus(pos - w->location()); + Widget *f = w->event_focus(pos - w->location()); if (f) return f; } @@ -261,13 +272,30 @@ bool Widget::has_focus() const return (root()->focus() == this); } -void Widget::mousemove(float x, float y) -{} +bool Widget::event_key(bool pressed, unsigned int key, unsigned int modifier) +{ + bool handled; + + if (pressed) { + handled = keypress(key, modifier); + } else { + handled = keyrelease(key, modifier); + } -void Widget::keypress(unsigned int key, unsigned int modifier) -{} + if (!handled && parent()) + handled = parent()->event_key(pressed, key, modifier); -void Widget::keyrelease(unsigned int key, unsigned int modifier) -{} + return handled; +} + +bool Widget::keypress(unsigned int key, unsigned int modifier) +{ + return false; +} + +bool Widget::keyrelease(unsigned int key, unsigned int modifier) +{ + return false; +} } diff --git a/src/ui/widget.h b/src/ui/widget.h index 54c8d96..2078134 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -17,6 +17,7 @@ #include "math/vector2f.h" #include "ui/font.h" #include "ui/palette.h" +#include "ui/definitions.h" #include "sys/sys.h" namespace ui { @@ -66,18 +67,30 @@ public: /* -- mutators --------------------------------------------- */ + /// raise the widget to the top of the widget stack + void raise(); + + /// lower the widget to the bottom of the widget stack + void lower(); + /// show the widget void show(); /// hide the widget void hide(); + /// set visibility + void set_visible(bool visible = true); + /// set location of the top-left corner void set_location(float const x, float const y); /// set the widgets width and height void set_size(float const w, float const h); + /// set the widgets width and height + void set_size(math::Vector2f const &size); + /// set the widgets width void set_width(float const w); @@ -106,24 +119,28 @@ public: /// draw event virtual void event_draw(); - /// handle mouse movement - virtual void mousemove(float x, float y); - - /// handle keyboard events - virtual void keypress(unsigned int key, unsigned int modifier); + /// keyboard event + virtual bool event_key(bool pressed, unsigned int key, unsigned int modifier); - virtual void keyrelease(unsigned int key, unsigned int modifier); + /// find the child widget with focus + /** @param pos local position within the widget + */ + Widget *event_focus(math::Vector2f const & pos); /// child widgets inline Children &children() { return widget_children; } - /// raise the widget to the top of the widget stack - void raise(); +protected: + /// handle keyboard events + /** returns true if the event was handled by this widget + */ + virtual bool keypress(unsigned int key, unsigned int modifier); - /// lower the widget to the bottom of the widget stack - void lower(); + /// handle keyboard events + /** returns true if the event was handled by this widget + */ + virtual bool keyrelease(unsigned int key, unsigned int modifier); -protected: /// draw the widget virtual void draw(); @@ -179,11 +196,6 @@ protected: /// remove a child widget void remove_child(Widget *child); - /// find the child widget with focus - /** @param pos local position within the widget - */ - Widget *find_focus(math::Vector2f const & pos); - private: bool widget_visible; bool widget_background; -- cgit v1.2.3