/* ui/ui.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #include #include "audio/audio.h" #include "auxiliary/functions.h" #include "core/core.h" #include "core/application.h" #include "filesystem/filesystem.h" #include "render/gl.h" #include "sys/sys.h" #include "ui/button.h" #include "ui/label.h" #include "ui/menu.h" #include "ui/paint.h" #include "ui/ui.h" #include "ui/widget.h" namespace ui { /* -- static functions --------------------------------------------- */ bool UI::ui_debug = false; float UI::elementmargin = 16; math::Vector2f UI::elementsize(256, 48); UI *global_ui = 0; UI *root() { return global_ui; } void init() { con_print << "^BInitializing user interface..." << std::endl; if (!global_ui) { global_ui = new UI(); } else { con_warn << "User interface already initialized!" << std::endl; return; } global_ui->load_menus(); global_ui->load_settings(); } void shutdown() { con_print << "^BShutting down user interface..." << std::endl; if (global_ui) { delete global_ui; global_ui = 0; } } /* -- class UI ----------------------------------------------------- */ UI::UI() : Window(0) { set_label("root"); set_size(1024, 768); set_border(false); set_background(false); // intialize console ui_console = new Console(this); // default palette ui_palette = new Palette(); set_palette(ui_palette); // default fonts ui_font_small = new Font("gui", 12, 18); ui_font_large = new Font("gui", 14, 24); set_font(ui_font_small); ui_mouse_focus = this; ui_input_focus = this; set_focus(); mouse_pointer_color = Palette::Pointer; mouse_pointer_bitmap.assign("pointer"); } UI::~UI() { delete ui_palette; delete ui_font_small; delete ui_font_large; } void UI::load_menus() { ui_active_menu = 0; Menus::iterator it; for (it = ui_menus.begin(); it != ui_menus.end(); it++) { Window *menu = (*it); remove_child(menu); } ui_menus.clear(); std::string filename("menu"); filesystem::IniFile ini; ini.open(filename); if (!ini.is_open()) { con_error << "Could not open " << ini.name() << std::endl; } else { std::string strval; Button *button = 0; Label *label = 0; Menu *menu = 0; while (ini.getline()) { if (ini.got_section()) { if (ini.got_section("menu")) { menu = new Menu(this); add_menu(menu); continue; } else if (menu) { if (ini.got_section("button")) { button = menu->add_button(); } else if (ini.got_section("label")) { label = menu->add_label(); } else { ini.unknown_section(); } } else { ini.unknown_section(); } } else if (menu && ini.got_key()) { if (ini.in_section("menu")) { if (ini.got_key_string("label", strval)) { aux::to_label(strval); menu->set_label(strval); } else if (ini.got_key_string("background", strval)) { menu->set_background_texture(strval); } else { ini.unkown_key(); } } else if (ini.in_section("button")) { if (ini.got_key_string("text", strval)) { aux::strip_quotes(strval); button->set_text(strval); } else if (ini.got_key_string("command", strval)) { for (size_t i =0; i <= strval.size(); i++) { if (strval[i] == ',') strval[i] = ';'; } aux::strip_quotes(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(); } } } } con_debug << " " << ini.name() << " " << ui_menus.size() << " menus" << std::endl; ini.close(); } // fallback main menu if (!find_menu("main")) { con_warn << "menu 'main' not found, using default" << std::endl; Menu *menu = new Menu(this, "main"); menu->add_label("Main Menu"); menu->add_button("Connect", "connect"); menu->add_button("Quit", "quit"); } // fallback game menu if (!find_menu("game")) { con_warn << "menu 'game' not found, using default" << std::endl; Menu *menu = new Menu(this, "game"); menu->add_label("Game Menu"); menu->add_button("Disconnect", "disconnect"); menu->add_button("Quit", "quit"); } // fallback join menu if (!find_menu("join")) { con_warn << "menu 'join' not found, using default" << std::endl; Menu *menu = new Menu(this, "join"); menu->add_label("Join Menu"); menu->add_button("Join", "join; menu hide"); menu->add_button("Game menu", "menu game"); } } void UI::load_settings() { ui_mouse_focus = this; std::string filename("ui"); filesystem::IniFile ini; ini.open(filename); if (!ini.is_open()) { con_error << "Could not open " << ini.name() << std::endl; return; } std::string strval; math::Color color; float w = elementsize.width(); float h = elementsize.height(); float m = elementmargin; while (ini.getline()) { if (ini.got_section()) { if (ini.got_section("ui")) { continue; } else if (ini.got_section("colors")) { continue; } else if (ini.got_section("hud")) { continue; } else if (ini.got_section("text")) { continue; } else { ini.unknown_section(); continue; } } else if (ini.got_key()) { if (ini.in_section("ui")) { if (ini.got_key_float("elementwidth", w)) { elementsize.assign(w, h); continue; } else if (ini.got_key_float("elementheight", h)) { elementsize.assign(w, h); continue; } else if (ini.got_key_float("elementmargin", m)) { elementmargin = m; continue; } else { ini.unkown_key(); continue; } } else if (ini.in_section("colors")) { if (ini.got_key_color("foreground", color)) { ui_palette->set_foreground(color); continue; } else if (ini.got_key_color("background", color)) { ui_palette->set_background(color); continue; } else if (ini.got_key_color("border", color)) { ui_palette->set_border(color); continue; } else if (ini.got_key_color("text", color)) { ui_palette->set_text(color); continue; } else if (ini.got_key_color("highlight", color)) { ui_palette->set_highlight(color); continue; } else if (ini.got_key_color("disabled", color)) { ui_palette->set_disabled(color); continue; } else if (ini.got_key_color("pointer", color)) { ui_palette->set_pointer(color); continue; } else if (ini.got_key_color("active", color)) { ui_palette->set_active(color); continue; } else if (ini.got_key_color("debug", color)) { ui_palette->set_debug(color); continue; } else { ini.unkown_key(); continue; } } else if (ini.in_section("hud")) { if (ini.got_key_color("mission", color)) { ui_palette->set_mission(color); continue; } else { ini.unkown_key(); continue; } } else if (ini.in_section("text")) { if (ini.got_key_color("bold", color)) { ui_palette->set_bold(color); } else if (ini.got_key_color("fancy", color)) { ui_palette->set_fancy(color); } else if (ini.got_key_color("warning", color)) { ui_palette->set_warning(color); } else if (ini.got_key_color("error", color)) { ui_palette->set_error(color); } } } } ini.close(); } void UI::apply_render_options() { //con_debug << " initializing text colors" << std::endl; // apply palette colors paint::assign_color('N', palette()->text()); paint::assign_color('D', palette()->debug()); paint::assign_color('B', palette()->bold()); paint::assign_color('F', palette()->fancy()); paint::assign_color('W', palette()->warning()); paint::assign_color('E', palette()->error()); } void UI::list() const { size_t n = Widget::list(0); con_print << n << " user interface widgets" << std::endl; } void UI::list_visible() const { size_t n = Widget::list(0, true); con_print << n << " visible user interface widgets" << std::endl; } UI::Menus::iterator UI::find_menu(Window *menu) { Menus::iterator it; for (it = ui_menus.begin(); it != ui_menus.end(); it++) { if ((*it) == menu) return it; } return it; } Window *UI::find_menu(const char *label) { for (Menus::const_iterator it = ui_menus.begin(); it != ui_menus.end(); it++) { if ((*it)->label().compare(label) == 0) { return (*it); } } return 0; } void UI::list_menus() const { for (Menus::const_iterator it = ui_menus.begin(); it != ui_menus.end(); it++) { const Window *menu = (*it); con_print << " " << menu->label() << std::endl; } con_print << ui_menus.size() << " menus" << std::endl; } void UI::add_menu(Window *menu) { Menus::iterator it = find_menu(menu); if (it == ui_menus.end()) { ui_menus.push_back(menu); } } void UI::show_menu(const char *label) { Window *menu = find_menu(label); if (menu) { if (ui_active_menu) { ui_active_menu->hide(); menu->set_previous(ui_active_menu); } else { menu->clear_previous(); } ui_mouse_focus = this; ui_input_focus = this; ui_active_menu = menu; ui_active_menu->event_resize(); ui_active_menu->show(); set_pointer("pointer"); // raise console if it is visible if (ui_console->visible()) ui_console->show(); } else { con_warn << "Unknown window '" << label << "'" << std::endl; } } void UI::hide_menu() { if (ui_active_menu) { ui_active_menu->hide(); ui_active_menu = 0; } } void UI::previous_menu() { if (ui_active_menu) { if (ui_active_menu->previous().size()) { show_menu(ui_active_menu->previous().c_str()); } else { hide_menu(); } } } void UI::frame() { if (ui_active_menu && !ui_active_menu->visible()) { ui_active_menu = 0; } ui_input_focus = find_input_focus(); Widget *f = find_mouse_focus(mouse_cursor); if (f) { f->event_mouse(mouse_cursor); } ui_mouse_focus = f; event_draw(); if (visible()) draw_pointer(); } /* -- global event handlers ---------------------------------------- */ /* These functions receive input events from the client input subsystem and distributes them to the widget hierarchy */ void UI::input_mouse(const float x, const float y) { mouse_cursor.assign(x, y); } bool UI::input_key(const bool pressed, const int key, const unsigned int modifier) { bool handled = false; if (key < 512) { // keyboard keys Widget *f = find_input_focus(); if (f) { handled = f->event_key(pressed, key, modifier); } ui_input_focus = f; } else { // mouse buttons Widget *f = find_mouse_focus(mouse_cursor); if (f) { f->event_mouse(mouse_cursor); } ui_mouse_focus = f; if (ui_mouse_focus) handled = ui_mouse_focus->event_key(pressed, key, modifier); } return handled; } bool UI::on_keypress(const int key, const unsigned int modifier) { switch( key ) { case SDLK_ESCAPE: if (active()) { hide_menu(); audio::play("ui/menu"); } return true; break; default: break; } return false; } bool UI::on_keyrelease(const int key, const unsigned int modifier) { return false; } void UI::set_pointer(const char *pointerbitmap, const Palette::Color color, const bool animated) { if (!pointerbitmap) { mouse_pointer_bitmap.clear(); } else { mouse_pointer_bitmap.assign(pointerbitmap); } mouse_pointer_animated = animated; mouse_pointer_color = color; } void UI::draw_pointer() { if (!mouse_pointer_bitmap.size()) return; math::Color c(palette()->color(mouse_pointer_color)); if (mouse_pointer_animated) { c.a = 1; } else { c.a = 0.5f; } paint::color(c); math::Vector2f pos(mouse_cursor.x() - pointer_size * 0.5f, mouse_cursor.y() - pointer_size * 0.5f); math::Vector2f s(pointer_size, pointer_size); std::string texture("pointers/"); texture.append(mouse_pointer_bitmap); if (mouse_pointer_animated) { gl::push(); gl::translate(mouse_cursor.x(), mouse_cursor.y(), 0); float angle = core::application()->time()* 0.75f - floorf(core::application()->time() * 0.75f); angle *= 360.0f; gl::rotate(angle, math::Vector3f(0, 0, 1.0f)); gl::translate(-mouse_cursor.x(), -mouse_cursor.y(), 0); } paint::bitmap(pos, s, texture); if (mouse_pointer_animated) { gl::pop(); } } }