From 1a28393dabf4f4696bf433ddde52e7a25253c955 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Thu, 16 Oct 2008 16:34:15 +0000 Subject: various user interface related updates --- src/ui/Makefile.am | 4 +- src/ui/button.cc | 14 ++-- src/ui/container.cc | 17 ++++- src/ui/container.h | 2 + src/ui/definitions.h | 2 + src/ui/input.cc | 184 --------------------------------------------------- src/ui/input.h | 55 --------------- src/ui/inputbox.cc | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ui/inputbox.h | 55 +++++++++++++++ src/ui/menu.h | 2 +- src/ui/palette.cc | 27 ++++++++ src/ui/palette.h | 16 +++-- src/ui/ui.cc | 68 +++++++++++++++++-- src/ui/ui.h | 16 ++++- src/ui/widget.cc | 4 +- src/ui/widget.h | 2 +- src/ui/window.cc | 8 +-- src/ui/window.h | 3 +- 18 files changed, 386 insertions(+), 277 deletions(-) delete mode 100644 src/ui/input.cc delete mode 100644 src/ui/input.h create mode 100644 src/ui/inputbox.cc create mode 100644 src/ui/inputbox.h (limited to 'src/ui') diff --git a/src/ui/Makefile.am b/src/ui/Makefile.am index a68c307..4bfad3d 100644 --- a/src/ui/Makefile.am +++ b/src/ui/Makefile.am @@ -7,9 +7,9 @@ else noinst_LTLIBRARIES = libui.la endif -noinst_HEADERS = bitmap.h button.h container.h definitions.h font.h input.h label.h \ +noinst_HEADERS = bitmap.h button.h container.h definitions.h font.h inputbox.h label.h \ menu.h paint.h palette.h ui.h widget.h window.h -libui_la_SOURCES = bitmap.cc button.cc container.cc font.cc input.cc label.cc \ +libui_la_SOURCES = bitmap.cc button.cc container.cc font.cc inputbox.cc label.cc \ menu.cc paint.cc palette.cc ui.cc widget.cc window.cc libui_la_LDFLAGS = -avoid-version -no-undefined diff --git a/src/ui/button.cc b/src/ui/button.cc index 08fd0e9..e36d036 100644 --- a/src/ui/button.cc +++ b/src/ui/button.cc @@ -71,18 +71,18 @@ void Button::draw_text() } bool Button::on_keypress(const int key, const unsigned int modifier) -{ - return false; -} - -bool Button::on_keyrelease(const int key, const unsigned int modifier) -{ +{ if (key == 512 + SDL_BUTTON_LEFT) { core::cmd() << button_command << std::endl; audio::play("ui/button"); return true; } - + + return false; +} + +bool Button::on_keyrelease(const int key, const unsigned int modifier) +{ return false; } diff --git a/src/ui/container.cc b/src/ui/container.cc index 5a12e8e..37fbea8 100644 --- a/src/ui/container.cc +++ b/src/ui/container.cc @@ -6,6 +6,7 @@ #include "ui/container.h" +#include "ui/paint.h" namespace ui { @@ -31,9 +32,8 @@ void Container::resize() { float w = container_childsize.width() * 1.5f; float h = children().size() * (container_childsize.height() + margin()) + container_childsize.height(); - set_size(w, h); - + const float x = container_childsize.width() * 0.25f; float y = container_childsize.height() * 0.5f; @@ -56,4 +56,17 @@ void Container::set_margin(const float margin) container_margin = margin; } +void Container::draw_border() +{ + if (!border()) + return; + + if(focus()) { + paint::color(palette()->foreground()); + } else { + paint::color(palette()->border()); + } + paint::border(global_location(), size()); +} + } diff --git a/src/ui/container.h b/src/ui/container.h index ae97bdf..5556759 100644 --- a/src/ui/container.h +++ b/src/ui/container.h @@ -27,6 +27,8 @@ public: inline float margin() const { return container_margin; } protected: + virtual void draw_border(); + virtual void resize(); private: diff --git a/src/ui/definitions.h b/src/ui/definitions.h index b9b4e3c..ea3e040 100644 --- a/src/ui/definitions.h +++ b/src/ui/definitions.h @@ -23,6 +23,8 @@ enum Alignment { AlignCenter = AlignHCenter | AlignVCenter }; +const float pointer_size = 48.0f; + } #endif // __INCLUDED_UI_DEFINITIONS_H__ diff --git a/src/ui/input.cc b/src/ui/input.cc deleted file mode 100644 index 8113354..0000000 --- a/src/ui/input.cc +++ /dev/null @@ -1,184 +0,0 @@ -/* - ui/input.cc - This file is part of the Osirion project and is distributed under - the terms of the GNU General Public License version 2 -*/ - -#include "ui/input.h" -#include "ui/paint.h" -#include "auxiliary/functions.h" -#include "core/core.h" - -namespace ui -{ - -Input::Input(Widget *parent) : Widget(parent) -{ - input_text.clear(); - input_pos = 0; - - set_label("input"); - set_background(false); - set_border(false); -} - -Input::~Input() -{ -} - -void Input::clear() -{ - input_text.clear(); - input_pos = 0; -} -void Input::set_text(std::string const &text) -{ - input_text.assign(text); - input_pos = input_text.size(); -} - -void Input::set_text(const char *text) -{ - if (text) - input_text.assign(text); - else - input_text.clear(); - input_pos = input_text.size(); -} - -void Input::draw() -{ - draw_background(); - draw_border(); - - size_t text_width = (size_t) floorf(width() / font()->width()); - math::Vector2f v(global_location()); - paint::color(palette()->foreground()); - - // draw the part before the cursor - std::string firstpart(input_text.substr(0, input_pos)); - size_t draw_width = 0; - const char *c = firstpart.c_str(); - - while (*c) { - if (aux::is_color_code(c)) { - c++; - } else { - draw_width++; - } - c++; - } - - c = firstpart.c_str(); - while (*c && draw_width > text_width - 2) { - if (aux::is_color_code(c)) { - c++; - paint::color_code(*c); - } else { - draw_width--; - } - c++; - } - - if (*c) { - paint::text(v, size(), font(), std::string(c), AlignLeft | AlignVCenter); - } - - // draw the part behind the cursor - v.x += draw_width * font()->width(); - if (input_pos < input_text.size()) { - if (input_pos > 1 && aux::is_color_code(input_text.c_str() + input_pos -1)) { - paint::color_code(input_text[input_pos]); - } - // limit to width - std::string secondpart; - c = &input_text.c_str()[input_pos]; - while (*c && (draw_width <= (text_width - 2))) { - if (aux::is_color_code(c)) { - c++; - } else { - draw_width++; - secondpart += *c; - } - c++; - } - - paint::text(v, size(), font(), secondpart, AlignLeft | AlignVCenter); - } - - // draw the cursor - if (has_input_focus() && (core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { - std::string cursor("^B"); - cursor += (char) 11; - paint::text(v, size(), font(), cursor, AlignLeft | AlignVCenter); - } -} - -bool Input::on_keypress(const int key, const unsigned int modifier) -{ - switch (key) { - case SDLK_TAB: - // FIXME should not be here - core::CommandBuffer::complete(input_text, input_pos); - return true; - break; - - case SDLK_HOME: - input_pos = 0; - return true; - break; - - case SDLK_END: - input_pos = input_text.size(); - return true; - break; - - case SDLK_LEFT: - if (input_pos > 0) - input_pos--; - return true; - break; - - case SDLK_RIGHT: - if (input_pos < input_text.size()) - input_pos++; - return true; - break; - - case SDLK_DELETE: - if (input_text.size() && input_pos < input_text.size()) { - input_text.erase(input_pos, 1); - } - return true; - break; - - case SDLK_BACKSPACE: - if (input_text.size() && input_pos) { - input_text.erase(input_pos-1, 1); - input_pos--; - } - return true; - break; - - default: - if ((key >= 32) && (key <175)) { - if (input_pos == input_text.size()) - input_text += (char)key; - else - input_text.insert(input_pos, 1, (char)key); - input_pos++; - return true; - } - break; - } - - return false; -} -bool Input::on_keyrelease(const int key, const unsigned int modifier) -{ - return false; -} - -} - - diff --git a/src/ui/input.h b/src/ui/input.h deleted file mode 100644 index 214f63e..0000000 --- a/src/ui/input.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - ui/input.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_INPUT_H__ -#define __INCLUDED_UI_INPUT_H__ - -#include "ui/widget.h" - -namespace ui -{ - -/// text input widget -class Input : public Widget -{ -public: - Input(Widget *parent); - ~Input(); - - /// set the text displayed by the label - void set_text(std::string const &text); - - /// set the text displayed by the label - void set_text(const char *text); - - /// return the text displayed by the label - inline std::string const &text() const { - return input_text; - } - - /// clear the text - void clear(); - -protected: - /// draw the widget - virtual void draw(); - - /// called when the widget receives a key press - virtual bool on_keypress(const int key, const unsigned int modifier); - - /// called when the widget receives a key release - virtual bool on_keyrelease(const int key, const unsigned int modifier); - -private: - - std::string input_text; - size_t input_pos; -}; - -} - -#endif // __INCLUDED_UI_INPUT_H__ - diff --git a/src/ui/inputbox.cc b/src/ui/inputbox.cc new file mode 100644 index 0000000..30cae3b --- /dev/null +++ b/src/ui/inputbox.cc @@ -0,0 +1,184 @@ +/* + ui/inputbox.cc + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#include "ui/inputbox.h" +#include "ui/paint.h" +#include "auxiliary/functions.h" +#include "core/core.h" + +namespace ui +{ + +InputBox::InputBox(Widget *parent) : Widget(parent) +{ + input_text.clear(); + input_pos = 0; + + set_label("input"); + set_background(false); + set_border(false); +} + +InputBox::~InputBox() +{ +} + +void InputBox::clear() +{ + input_text.clear(); + input_pos = 0; +} +void InputBox::set_text(std::string const &text) +{ + input_text.assign(text); + input_pos = input_text.size(); +} + +void InputBox::set_text(const char *text) +{ + if (text) + input_text.assign(text); + else + input_text.clear(); + input_pos = input_text.size(); +} + +void InputBox::draw() +{ + draw_background(); + draw_border(); + + size_t text_width = (size_t) floorf(width() / font()->width()); + math::Vector2f v(global_location()); + paint::color(palette()->foreground()); + + // draw the part before the cursor + std::string firstpart(input_text.substr(0, input_pos)); + size_t draw_width = 0; + const char *c = firstpart.c_str(); + + while (*c) { + if (aux::is_color_code(c)) { + c++; + } else { + draw_width++; + } + c++; + } + + c = firstpart.c_str(); + while (*c && draw_width > text_width - 2) { + if (aux::is_color_code(c)) { + c++; + paint::color_code(*c); + } else { + draw_width--; + } + c++; + } + + if (*c) { + paint::text(v, size(), font(), std::string(c), AlignLeft | AlignVCenter); + } + + // draw the part behind the cursor + v.x += draw_width * font()->width(); + if (input_pos < input_text.size()) { + if (input_pos > 1 && aux::is_color_code(input_text.c_str() + input_pos -1)) { + paint::color_code(input_text[input_pos]); + } + // limit to width + std::string secondpart; + c = &input_text.c_str()[input_pos]; + while (*c && (draw_width <= (text_width - 2))) { + if (aux::is_color_code(c)) { + c++; + } else { + draw_width++; + secondpart += *c; + } + c++; + } + + paint::text(v, size(), font(), secondpart, AlignLeft | AlignVCenter); + } + + // draw the cursor + if (has_input_focus() && (core::application()->time() - ::floorf(core::application()->time())) < 0.5f) { + std::string cursor("^B"); + cursor += (char) 11; + paint::text(v, size(), font(), cursor, AlignLeft | AlignVCenter); + } +} + +bool InputBox::on_keypress(const int key, const unsigned int modifier) +{ + switch (key) { + case SDLK_TAB: + // FIXME should not be here + core::CommandBuffer::complete(input_text, input_pos); + return true; + break; + + case SDLK_HOME: + input_pos = 0; + return true; + break; + + case SDLK_END: + input_pos = input_text.size(); + return true; + break; + + case SDLK_LEFT: + if (input_pos > 0) + input_pos--; + return true; + break; + + case SDLK_RIGHT: + if (input_pos < input_text.size()) + input_pos++; + return true; + break; + + case SDLK_DELETE: + if (input_text.size() && input_pos < input_text.size()) { + input_text.erase(input_pos, 1); + } + return true; + break; + + case SDLK_BACKSPACE: + if (input_text.size() && input_pos) { + input_text.erase(input_pos-1, 1); + input_pos--; + } + return true; + break; + + default: + if ((key >= 32) && (key <175)) { + if (input_pos == input_text.size()) + input_text += (char)key; + else + input_text.insert(input_pos, 1, (char)key); + input_pos++; + return true; + } + break; + } + + return false; +} +bool InputBox::on_keyrelease(const int key, const unsigned int modifier) +{ + return false; +} + +} + + diff --git a/src/ui/inputbox.h b/src/ui/inputbox.h new file mode 100644 index 0000000..557ca6c --- /dev/null +++ b/src/ui/inputbox.h @@ -0,0 +1,55 @@ +/* + ui/inputbox.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_INPUTBOX_H__ +#define __INCLUDED_UI_INPUTBOX_H__ + +#include "ui/widget.h" + +namespace ui +{ + +/// text input widget +class InputBox : public Widget +{ +public: + InputBox(Widget *parent); + ~InputBox(); + + /// set the text displayed by the label + void set_text(std::string const &text); + + /// set the text displayed by the label + void set_text(const char *text); + + /// return the text displayed by the label + inline std::string const &text() const { + return input_text; + } + + /// clear the text + void clear(); + +protected: + /// draw the widget + virtual void draw(); + + /// called when the widget receives a key press + virtual bool on_keypress(const int key, const unsigned int modifier); + + /// called when the widget receives a key release + virtual bool on_keyrelease(const int key, const unsigned int modifier); + +private: + + std::string input_text; + size_t input_pos; +}; + +} + +#endif // __INCLUDED_UI_INPUTBOX_H__ + diff --git a/src/ui/menu.h b/src/ui/menu.h index a909e20..e3a853a 100644 --- a/src/ui/menu.h +++ b/src/ui/menu.h @@ -36,7 +36,7 @@ public: /// add a button with a command Button *add_button(char const *text=0, char const *command=0); - + protected: /// resize event virtual void resize(); diff --git a/src/ui/palette.cc b/src/ui/palette.cc index 20d1e93..3a9dc78 100644 --- a/src/ui/palette.cc +++ b/src/ui/palette.cc @@ -24,6 +24,33 @@ Palette::~Palette() { } +const math::Color &Palette::color(Color palettecolor) const +{ + switch(palettecolor) { + case Foreground: + return foreground(); + break; + case Background: + return background(); + break; + case Highlight: + return highlight(); + break; + case Border: + return border(); + break; + case Pointer: + return pointer(); + break; + case Active: + return active(); + break; + default: + return foreground(); + break; + } +} + void Palette::set_foreground(math::Color const &color) { palette_foreground.assign(color); diff --git a/src/ui/palette.h b/src/ui/palette.h index 9d27f95..41eee03 100644 --- a/src/ui/palette.h +++ b/src/ui/palette.h @@ -19,6 +19,8 @@ public: Palette(); ~Palette(); + enum Color { Foreground=0, Background=1, Highlight=2, Border=3, Pointer=4, Active=5 }; + void set_foreground(math::Color const &color); void set_highlight(math::Color const &color); @@ -31,29 +33,31 @@ public: void set_active(math::Color const &color); - inline math::Color const &foreground() const { + inline const math::Color &foreground() const { return palette_foreground; } - inline math::Color const &highlight() const { + inline const math::Color &highlight() const { return palette_highlight; } - inline math::Color const &background() const { + inline const math::Color &background() const { return palette_background; } - inline math::Color const &border() const { + inline const math::Color &border() const { return palette_border; } - inline math::Color const &pointer() const { + inline const math::Color &pointer() const { return palette_pointer; } - inline math::Color const &active() const { + inline const math::Color &active() const { return palette_active; } + + const math::Color &color(Palette::Color palettecolor) const; private: diff --git a/src/ui/ui.cc b/src/ui/ui.cc index baedd38..1ecfbb1 100644 --- a/src/ui/ui.cc +++ b/src/ui/ui.cc @@ -7,13 +7,16 @@ #include #include +#include "audio/audio.h" #include "auxiliary/functions.h" #include "core/core.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" @@ -204,6 +207,9 @@ UI::UI() : Window(0) ui_mouse_focus = this; ui_input_focus = this; set_focus(); + + mouse_pointer_color = Palette::Pointer; + mouse_pointer_bitmap.assign("pointer"); } UI::~UI() @@ -386,7 +392,9 @@ void UI::show_menu(const char *label) ui_active_menu = menu; ui_active_menu->event_resize(); - ui_active_menu->show(); + ui_active_menu->show(); + + set_pointer("pointer"); } else { con_warn << "Unknown window '" << label << "'" << std::endl; } @@ -418,6 +426,9 @@ void UI::frame() } event_draw(); + + if (visible()) + draw_pointer(); } /* -- global event handlers ---------------------------------------- */ @@ -453,21 +464,18 @@ bool UI::input_key(const bool pressed, const int key, const unsigned int modifie return handled; } -/* -- event handlers ----------------------------------------------- */ -/* - These functions handle events for this widget only. They are - the fallback input handlers -*/ bool UI::on_keypress(const int key, const unsigned int modifier) { switch( key ) { case SDLK_ESCAPE: if (active()) { - previous_menu(); + hide_menu(); + audio::play("ui/menu"); } else { if (core::application()->connected()) { show_menu("game"); + audio::play("ui/menu"); } } return true; @@ -484,5 +492,51 @@ 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) { + render::gl::push(); + render::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; + render::gl::rotate(angle, math::Vector3f(0, 0, 1.0f)); + render::gl::translate(-mouse_cursor.x, -mouse_cursor.y, 0); + } + + paint::bitmap(pos, s, texture); + + if (mouse_pointer_animated) { + render::gl::pop(); + } +} + } diff --git a/src/ui/ui.h b/src/ui/ui.h index 8fa32c2..24f9793 100644 --- a/src/ui/ui.h +++ b/src/ui/ui.h @@ -62,7 +62,7 @@ public: /// receive global key input bool input_key(const bool pressed, const int key, const unsigned int modifier); - + /// run a user interface frame void frame(); @@ -77,7 +77,12 @@ public: inline const Font *font_large() const { return ui_font_large; } - + + /* -- mouse pointer ---------------------------------------- */ + + /// set mouse pointer bitmap + void set_pointer(const char *pointerbitmap=0, const Palette::Color color = Palette::Highlight,const bool animated = false); + protected: typedef std::list Menus; @@ -95,6 +100,8 @@ protected: virtual bool on_keyrelease(const int key, const unsigned int modifier); private: + void draw_pointer(); + Palette *ui_palette; Font *ui_font_small; Font *ui_font_large; @@ -106,7 +113,10 @@ private: Menus ui_menus; /// TODO move to separate object to handle mouse cursor drawing - math::Vector2f mouse_cursor; + math::Vector2f mouse_cursor; + std::string mouse_pointer_bitmap; + Palette::Color mouse_pointer_color; + bool mouse_pointer_animated; }; /// initialize the user interface diff --git a/src/ui/widget.cc b/src/ui/widget.cc index 24dfe5c..606c4ab 100644 --- a/src/ui/widget.cc +++ b/src/ui/widget.cc @@ -209,6 +209,7 @@ void Widget::set_width(float const w) { widget_size.x = w; } + void Widget::set_height(float const h) { widget_size.y = h; @@ -339,10 +340,11 @@ void Widget::event_draw() void Widget::event_resize() { + resize(); + for (Children::iterator it = widget_children.begin(); it != widget_children.end(); it++) { (*it)->event_resize(); } - resize(); } /* -- event handlers ----------------------------------------------- */ diff --git a/src/ui/widget.h b/src/ui/widget.h index 41ad795..ef386c0 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h @@ -200,7 +200,7 @@ protected: /// find the widget that has input focus virtual Widget *find_input_focus(); - + /// find widget that has mosue focus /** @param cursor mouse cursor position relative to this widget's location */ diff --git a/src/ui/window.cc b/src/ui/window.cc index 3015a10..9ae9ec5 100644 --- a/src/ui/window.cc +++ b/src/ui/window.cc @@ -50,12 +50,8 @@ void Window::draw_border() if (!border()) return; - if(focus()) { - paint::color(palette()->foreground()); - } else { - paint::color(palette()->border()); - } - paint::border(global_location(), size()); + paint::color(palette()->border()); + paint::border(global_location(), size()); } } diff --git a/src/ui/window.h b/src/ui/window.h index 412d1f1..2a077ff 100644 --- a/src/ui/window.h +++ b/src/ui/window.h @@ -20,8 +20,6 @@ public: Window(Widget *parent=0); ~Window(); - virtual void draw_border(); - /// set the label of the previous window void set_previous(Window *previous); @@ -38,6 +36,7 @@ public: } protected: + virtual void draw_border(); std::string window_previous; }; -- cgit v1.2.3