From 42f25ae23ee34f9ae3a0e31fc0039258deab2bc3 Mon Sep 17 00:00:00 2001 From: ennewalker Date: Thu, 16 Oct 2008 00:09:45 +0000 Subject: Support for inline graphics and mouse input on menus. Menus in the console version should be unchanged. Let me know if this is not the case. git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@7258 c06c8d41-db1a-0410-9941-cceddc491573 --- crawl-ref/source/invent.cc | 21 ++- crawl-ref/source/invent.h | 5 +- crawl-ref/source/makefile_tiles.mgw | 2 +- crawl-ref/source/makefile_tiles.unix | 2 +- crawl-ref/source/menu.cc | 97 ++++++++++--- crawl-ref/source/menu.h | 49 ++++++- crawl-ref/source/stash.cc | 13 +- crawl-ref/source/tilebuf.cc | 266 +++++++++++++++++++++++++++++++++++ crawl-ref/source/tilebuf.h | 141 +++++++++++++++++++ crawl-ref/source/tilefont.cc | 149 ++++++++++++++++---- crawl-ref/source/tilefont.h | 12 ++ crawl-ref/source/tilereg.cc | 263 +++++++++++++++++++++++++++++++++- crawl-ref/source/tilereg.h | 50 +++++++ crawl-ref/source/tilesdl.cc | 59 ++------ crawl-ref/source/tilesdl.h | 7 +- crawl-ref/source/tiletex.cc | 2 +- crawl-ref/source/tiletex.h | 2 +- 17 files changed, 1019 insertions(+), 121 deletions(-) create mode 100644 crawl-ref/source/tilebuf.cc create mode 100644 crawl-ref/source/tilebuf.h diff --git a/crawl-ref/source/invent.cc b/crawl-ref/source/invent.cc index b387d75e20..5c4c7ecad5 100644 --- a/crawl-ref/source/invent.cc +++ b/crawl-ref/source/invent.cc @@ -382,19 +382,18 @@ void InvMenu::load_inv_items(int item_selector, int excluded_slot, set_title(""); } -void InvMenu::draw_stock_item(int index, const MenuEntry *me) const -{ #ifdef USE_TILE - const InvEntry *ie = dynamic_cast(me); - if (ie && me->quantity > 0) - { - char key = ie->hotkeys.size() > 0 ? ie->hotkeys[0] : 0; - tiles.update_menu_inventory(get_entry_index(ie), *ie->item, ie->selected(), key); - } -#endif +bool InvEntry::tile(int &idx, TextureID &tex) const +{ + if (quantity <= 0) + return false; + + idx = tileidx_item(*item); + tex = TEX_DEFAULT; - Menu::draw_stock_item(index, me); + return (idx != 0); } +#endif bool InvMenu::is_selectable(int index) const { @@ -627,7 +626,7 @@ void InvMenu::load_items(const std::vector &mitems, } // Don't make a menu so tall that we recycle hotkeys on the same page. - if (mitems.size() > 52) + if (mitems.size() > 52 && (max_pagesize > 52 || max_pagesize == 0)) set_maxpagesize(52); } diff --git a/crawl-ref/source/invent.h b/crawl-ref/source/invent.h index 8a28bcd942..8cdabe01b1 100644 --- a/crawl-ref/source/invent.h +++ b/crawl-ref/source/invent.h @@ -99,6 +99,10 @@ public: virtual void select( int qty = -1 ); +#ifdef USE_TILE + virtual bool tile(int &tile, TextureID &tex) const; +#endif + private: void add_class_hotkeys(const item_def &i); }; @@ -157,7 +161,6 @@ protected: void sort_menu(std::vector &items, const menu_sort_condition *cond); const menu_sort_condition *find_menu_sort_condition() const; - virtual void draw_stock_item(int index, const MenuEntry *me) const; virtual bool is_selectable(int index) const; protected: diff --git a/crawl-ref/source/makefile_tiles.mgw b/crawl-ref/source/makefile_tiles.mgw index dabf6cec74..0de1ed8843 100644 --- a/crawl-ref/source/makefile_tiles.mgw +++ b/crawl-ref/source/makefile_tiles.mgw @@ -76,7 +76,7 @@ CFOTHERS := -fsigned-char \ CFLAGS := $(INCLUDES) $(CFWARN) $(CFOTHERS) $(SDL_CFLAGS) YCFLAGS := $(INCLUDES) $(CFOTHERS) -OBJECTS := $(OBJECTS) libgui.o tilepick.o tile2.o tilereg.o tilesdl.o tilefont.o tiletex.o tilemcache.o +OBJECTS := $(OBJECTS) libgui.o tilepick.o tile2.o tilereg.o tilesdl.o tilefont.o tiletex.o tilemcache.o tilebuf.o LDFLAGS = diff --git a/crawl-ref/source/makefile_tiles.unix b/crawl-ref/source/makefile_tiles.unix index bd3148a931..8484dd8558 100644 --- a/crawl-ref/source/makefile_tiles.unix +++ b/crawl-ref/source/makefile_tiles.unix @@ -10,7 +10,7 @@ GAME = crawl # it will make a variable called OBJECTS that contains all the libraries include makefile.obj -OBJECTS += libgui.o tilepick.o tile2.o tilereg.o tilesdl.o tilefont.o tiletex.o tilemcache.o +OBJECTS += libgui.o tilepick.o tile2.o tilereg.o tilesdl.o tilefont.o tiletex.o tilemcache.o tilebuf.o SDL_CFLAGS := $(shell sdl-config --cflags) SDL_LDFLAGS := $(shell sdl-config --libs) -lSDLmain diff --git a/crawl-ref/source/menu.cc b/crawl-ref/source/menu.cc index 8d266223f0..a3c7b1e155 100644 --- a/crawl-ref/source/menu.cc +++ b/crawl-ref/source/menu.cc @@ -18,6 +18,59 @@ #include "view.h" #include "initfile.h" +MenuDisplay::MenuDisplay(Menu *menu) : m_menu(menu) +{ +} + +MenuDisplayText::MenuDisplayText(Menu *menu) : MenuDisplay(menu), m_starty(1) +{ +} + +void MenuDisplayText::draw_stock_item(int index, const MenuEntry *me) +{ + textattr(m_menu->item_colour(index, me)); + if (m_menu->get_flags() & MF_ALLOW_FORMATTING) + formatted_string::parse_string(me->get_text()).display(); + else + { + std::string text = me->get_text(); + if ((int) text.length() > get_number_of_cols()) + text = text.substr(0, get_number_of_cols()); + cprintf("%s", text.c_str()); + } +} + +void MenuDisplayText::draw_more() +{ + cgotoxy(1, m_menu->get_y_offset() + m_menu->get_pagesize() - + count_linebreaks(m_menu->get_more())); + m_menu->get_more().display(); +} + +#ifdef USE_TILE +MenuDisplayTile::MenuDisplayTile(Menu *menu) : MenuDisplay(menu) +{ + m_menu->set_maxpagesize(tiles.get_menu()->maxpagesize()); +} + +void MenuDisplayTile::draw_stock_item(int index, const MenuEntry *me) +{ + int colour = m_menu->item_colour(index, me); + std::string text = me->get_text(); + tiles.get_menu()->set_entry(index, text, colour, me); +} + +void MenuDisplayTile::set_offset(int lines) +{ + tiles.get_menu()->set_offset(lines); +} + +void MenuDisplayTile::draw_more() +{ + tiles.get_menu()->set_more(m_menu->get_more()); +} +#endif + Menu::Menu( int _flags, const std::string& tagname ) : f_selitem(NULL), f_drawitem(NULL), f_keyfilter(NULL), title(NULL), flags(_flags), tag(tagname), first_entry(0), y_offset(0), @@ -25,6 +78,11 @@ Menu::Menu( int _flags, const std::string& tagname ) sel(), select_filter(), highlighter(new MenuHighlighter), num(-1), lastch(0), alive(false), last_selected(-1) { +#ifdef USE_TILE + mdisplay = new MenuDisplayTile(this); +#else + mdisplay = new MenuDisplayText(this); +#endif set_flags(flags); } @@ -39,6 +97,12 @@ Menu::Menu( const formatted_string &fs ) select_filter(), highlighter(new MenuHighlighter), num(-1), lastch(0), alive(false), last_selected(-1) { +#ifdef USE_TILE + mdisplay = new MenuDisplayTile(this); +#else + mdisplay = new MenuDisplayText(this); +#endif + int colour = LIGHTGREY; int last_text_colour = LIGHTGREY; std::string line; @@ -122,6 +186,7 @@ Menu::~Menu() delete items[i]; delete title; delete highlighter; + delete mdisplay; } void Menu::clear() @@ -466,14 +531,14 @@ bool Menu::draw_title_suffix( const formatted_string &fs, bool titlefirst ) return (true); } -void Menu::draw_select_count( int count, bool force ) +void Menu::draw_select_count(int count, bool force) { if (!force && !is_set(MF_MULTISELECT)) return; if (f_selitem) { - draw_title_suffix( f_selitem( &sel ) ); + draw_title_suffix(f_selitem(&sel)); } else { @@ -482,7 +547,7 @@ void Menu::draw_select_count( int count, bool force ) snprintf(buf, sizeof buf, " (%d item%s) ", count, (count > 1? "s" : "")); - draw_title_suffix( buf ); + draw_title_suffix(buf); } } @@ -672,6 +737,8 @@ void Menu::draw_menu() draw_select_count( sel.size() ); y_offset = 1 + !!title; + mdisplay->set_offset(y_offset); + int end = first_entry + pagesize; if (end > (int) items.size()) end = items.size(); @@ -679,10 +746,7 @@ void Menu::draw_menu() draw_item( i ); if (end < (int) items.size() || is_set(MF_ALWAYS_SHOW_MORE)) - { - cgotoxy( 1, y_offset + pagesize - count_linebreaks(more) ); - more.display(); - } + mdisplay->draw_more(); } void Menu::update_title() @@ -756,16 +820,7 @@ void Menu::draw_index_item(int index, const MenuEntry *me) const void Menu::draw_stock_item(int index, const MenuEntry *me) const { - textattr( item_colour(index, items[index]) ); - if ( flags & MF_ALLOW_FORMATTING ) - formatted_string::parse_string(items[index]->get_text()).display(); - else - { - std::string text = items[index]->get_text(); - if ((int) text.length() > get_number_of_cols()) - text = text.substr(0, get_number_of_cols()); - cprintf( "%s", text.c_str() ); - } + mdisplay->draw_stock_item(index, me); } bool Menu::page_down() @@ -982,8 +1037,10 @@ int slider_menu::item_colour(int index, const MenuEntry *me) const int colour = Menu::item_colour(index, me); if (index == selected && selected != -1) { -#if defined(WIN32CONSOLE) || defined(DOS) || defined (USE_TILE) +#if defined(WIN32CONSOLE) || defined(DOS) colour = dos_brand(colour, CHATTR_REVERSE); +#elif defined(USE_TILE) + colour = colour == WHITE ? YELLOW : WHITE; #else colour |= COLFLAG_REVERSE; #endif @@ -1010,7 +1067,7 @@ void slider_menu::show_more() const int end = entry_end(); cgotoxy( 1, y_offset + pagesize ); if (end < (int) items.size() || is_set(MF_ALWAYS_SHOW_MORE)) - more.display(); + mdisplay->draw_more(); else textattr(LIGHTGREY); fill_line(); @@ -1043,6 +1100,8 @@ void slider_menu::draw_menu() show_less(); + mdisplay->set_offset(starty + 1); + for (int i = first_entry; i < end; ++i) draw_item( i ); diff --git a/crawl-ref/source/menu.h b/crawl-ref/source/menu.h index 91561b0440..ce2b857ada 100644 --- a/crawl-ref/source/menu.h +++ b/crawl-ref/source/menu.h @@ -137,6 +137,13 @@ struct MenuEntry else if (quantity) selected_qty = (qty == -1? quantity : qty); } + +#ifdef USE_TILE + virtual bool tile(int &idx, TextureID &tex) const + { + return false; + } +#endif }; struct ToggleableMenuEntry : public MenuEntry @@ -181,6 +188,38 @@ enum MenuFlag MF_EASY_EXIT = 0x1000 }; +class MenuDisplay +{ +public: + MenuDisplay(Menu *menu); + virtual ~MenuDisplay() {} + virtual void draw_stock_item(int index, const MenuEntry *me) = 0; + virtual void set_offset(int lines) = 0; + virtual void draw_more() = 0; +protected: + Menu *m_menu; +}; + +class MenuDisplayText : public MenuDisplay +{ +public: + MenuDisplayText(Menu *menu); + virtual void draw_stock_item(int index, const MenuEntry *me); + virtual void draw_more(); + virtual void set_offset(int lines) { m_starty = lines; } +protected: + int m_starty; +}; + +class MenuDisplayTile : public MenuDisplay +{ +public: + MenuDisplayTile(Menu *menu); + virtual void draw_stock_item(int index, const MenuEntry *me); + virtual void set_offset(int lines); + virtual void draw_more(); +}; + /////////////////////////////////////////////////////////////////////// // NOTE // As a general contract, any pointers you pass to Menu methods are OWNED BY @@ -226,6 +265,7 @@ public: // Sets a replacement for the --more-- string. void set_more(const formatted_string &more); + const formatted_string &get_more() const { return more; } void set_highlighter( MenuHighlighter *h ); void set_title( MenuEntry *e ); @@ -233,6 +273,7 @@ public: void get_selected( std::vector *sel ) const; void set_maxpagesize(int max); + int maxpagesize() const { return max_pagesize; } void set_select_filter( std::vector filter ) { @@ -250,6 +291,10 @@ public: // Get entry index, skipping quantity 0 entries. Returns -1 if not found. int get_entry_index( const MenuEntry *e ) const; + virtual int item_colour(int index, const MenuEntry *me) const; + int get_y_offset() const { return y_offset; } + int get_pagesize() const { return pagesize; } + public: typedef std::string (*selitem_tfn)( const std::vector *sel ); typedef void (*drawitem_tfn)(int index, const MenuEntry *me); @@ -284,6 +329,8 @@ protected: int last_selected; + MenuDisplay *mdisplay; + protected: void check_add_formatted_line(int firstcol, int nextcol, std::string &line, bool check_eol); @@ -313,8 +360,6 @@ protected: bool is_hotkey(int index, int key ); virtual bool is_selectable(int index) const; - virtual int item_colour(int index, const MenuEntry *me) const; - virtual bool process_key( int keyin ); }; diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc index 1c9dcf83f3..a9b921f1c8 100644 --- a/crawl-ref/source/stash.cc +++ b/crawl-ref/source/stash.cc @@ -430,13 +430,6 @@ public: protected: void draw_title(); bool process_key(int key); - - void draw_stock_item(int index, const MenuEntry *me) const - { - // Skip inventory draw function, as tiles code can't currently - // handle drawing items that aren't in mitm or in inventory. - Menu::draw_stock_item(index, me); - } }; void StashMenu::draw_title() @@ -1742,6 +1735,7 @@ void StashSearchMenu::draw_title() } } + bool StashSearchMenu::process_key(int key) { if (key == '?') @@ -1781,8 +1775,11 @@ bool StashTracker::display_search_results( stashmenu.set_title(mtitle); // Don't make a menu so tall that we recycle hotkeys on the same page. - if (results.size() > 52) + if (results.size() > 52 + && (stashmenu.maxpagesize() > 52 || stashmenu.maxpagesize() == 0)) + { stashmenu.set_maxpagesize(52); + } menu_letter hotkey; for (unsigned i = 0; i < results.size(); ++i, ++hotkey) diff --git a/crawl-ref/source/tilebuf.cc b/crawl-ref/source/tilebuf.cc new file mode 100644 index 0000000000..6a61de2823 --- /dev/null +++ b/crawl-ref/source/tilebuf.cc @@ -0,0 +1,266 @@ +/* + * File: tilebuf.cc + * Summary: Vertex buffer implementaions + * + * Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC + * + * Modified for Crawl Reference by $Author: ennewalker $ on $Date: 2008-10-11 $ + */ + +#include "tilebuf.h" +#include "tilefont.h" +#include "tilesdl.h" + +#include +#include + +///////////////////////////////////////////////////////////////////////////// +// VColour + +VColour VColour::white(255, 255, 255, 255); +VColour VColour::black(0, 0, 0, 255); +VColour VColour::transparent(0, 0, 0, 0); + +///////////////////////////////////////////////////////////////////////////// +// VertBuffer + +static bool _valid(int num_verts, int prim) +{ + switch (prim) + { + case GL_QUADS: + return (num_verts % 4 == 0); + case GL_TRIANGLES: + return (num_verts % 3 == 0); + case GL_LINES: + return (num_verts % 2 == 0); + case GL_POINTS: + return (true); + default: + return (false); + } +} + +template<> +void VertBuffer::draw() const +{ + if (m_verts.size() == 0) + return; + + ASSERT(_valid(m_verts.size(), m_prim)); + ASSERT(m_tex); + + GLState state; + state.array_vertex = true; + state.array_texcoord = true; + state.blend = true; + state.texture = true; + GLStateManager::set(state); + + m_tex->bind(); + glVertexPointer(2, GL_FLOAT, sizeof(PTVert), &m_verts[0].pos_x); + glTexCoordPointer(2, GL_FLOAT, sizeof(PTVert), &m_verts[0].tex_x); + glDrawArrays(m_prim, 0, m_verts.size()); +} + +template<> +void VertBuffer::draw() const +{ + if (m_verts.size() == 0) + return; + + ASSERT(_valid(m_verts.size(), m_prim)); + ASSERT(!m_tex); + + GLState state; + state.array_vertex = true; + state.array_colour = true; + state.blend = true; + state.texture = true; + GLStateManager::set(state); + + glVertexPointer(2, GL_FLOAT, sizeof(PCVert), &m_verts[0].pos_x); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PCVert), &m_verts[0].col); + glDrawArrays(m_prim, 0, m_verts.size()); +} + +template<> +void VertBuffer::draw() const +{ + if (m_verts.size() == 0) + return; + + ASSERT(_valid(m_verts.size(), m_prim)); + ASSERT(m_tex); + + GLState state; + state.array_vertex = true; + state.array_texcoord = true; + state.array_colour = true; + state.blend = true; + state.texture = true; + GLStateManager::set(state); + + m_tex->bind(); + glVertexPointer(2, GL_FLOAT, sizeof(PTCVert), &m_verts[0].pos_x); + glTexCoordPointer(2, GL_FLOAT, sizeof(PTCVert), &m_verts[0].tex_x); + glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(PTCVert), &m_verts[0].col); + glDrawArrays(m_prim, 0, m_verts.size()); +} + +///////////////////////////////////////////////////////////////////////////// +// FontBuffer + +FontBuffer::FontBuffer(FTFont *font) : + VertBuffer(font->font_tex(), GL_QUADS), m_font(font) +{ + ASSERT(m_font); + ASSERT(m_tex); +} + +void FontBuffer::add(const formatted_string &fs, float x, float y) +{ + m_font->store(*this, x, y, fs); + ASSERT(_valid(m_verts.size(), m_prim)); +} + +void FontBuffer::add(const std::string &s, const VColour &col, float x, float y) +{ + m_font->store(*this, x, y, s, col); + ASSERT(_valid(m_verts.size(), m_prim)); +} + +///////////////////////////////////////////////////////////////////////////// +// TileBuffer + +TileBuffer::TileBuffer(const TilesTexture *t) : VertBuffer(t, GL_QUADS) +{ +} + +void TileBuffer::add(int idx, float x, float y) +{ + const tile_info &inf = ((TilesTexture*)m_tex)->get_info(idx); + + float pos_sx = x + inf.offset_x; + float pos_sy = y + inf.offset_y; + float pos_ex = pos_sx + (inf.ex - inf.sx); + float pos_ey = pos_sy + (inf.ey - inf.sy); + + float fwidth = m_tex->width(); + float fheight = m_tex->height(); + + float tex_sx = inf.sx / fwidth; + float tex_sy = inf.sy / fheight; + float tex_ex = inf.ex / fwidth; + float tex_ey = inf.ey / fheight; + + { + PTVert &v = get_next(); + v.pos_x = pos_sx; + v.pos_y = pos_sy; + v.tex_x = tex_sx; + v.tex_y = tex_sy; + } + { + PTVert &v = get_next(); + v.pos_x = pos_sx; + v.pos_y = pos_ey; + v.tex_x = tex_sx; + v.tex_y = tex_ey; + } + { + PTVert &v = get_next(); + v.pos_x = pos_ex; + v.pos_y = pos_ey; + v.tex_x = tex_ex; + v.tex_y = tex_ey; + } + { + PTVert &v = get_next(); + v.pos_x = pos_ex; + v.pos_y = pos_sy; + v.tex_x = tex_ex; + v.tex_y = tex_sy; + } + + ASSERT(_valid(m_verts.size(), m_prim)); +} + +void TileBuffer::set_tex(const TilesTexture *tex) +{ + ASSERT(tex); + m_tex = tex; +} + +///////////////////////////////////////////////////////////////////////////// +// ShapeBuffer + +ShapeBuffer::ShapeBuffer() : VertBuffer(NULL, GL_QUADS) +{ +} + +void ShapeBuffer::add(float pos_sx, float pos_sy, float pos_ex, float pos_ey, + const VColour &col) +{ + { + PCVert &v = get_next(); + v.pos_x = pos_sx; + v.pos_y = pos_sy; + v.col = col; + } + { + PCVert &v = get_next(); + v.pos_x = pos_sx; + v.pos_y = pos_ey; + v.col = col; + } + { + PCVert &v = get_next(); + v.pos_x = pos_ex; + v.pos_y = pos_ey; + v.col = col; + } + { + PCVert &v = get_next(); + v.pos_x = pos_ex; + v.pos_y = pos_sy; + v.col = col; + } + + ASSERT(_valid(m_verts.size(), m_prim)); +} + +///////////////////////////////////////////////////////////////////////////// +// LineBuffer + +LineBuffer::LineBuffer() : VertBuffer(NULL, GL_LINES) +{ +} + +void LineBuffer::add(float pos_sx, float pos_sy, float pos_ex, float pos_ey, + const VColour &col) +{ + { + PCVert &v = get_next(); + v.pos_x = pos_sx; + v.pos_y = pos_sy; + v.col = col; + } + { + PCVert &v = get_next(); + v.pos_x = pos_ex; + v.pos_y = pos_ey; + v.col = col; + } + + ASSERT(_valid(m_verts.size(), m_prim)); +} + +void LineBuffer::add_square(float sx, float sy, float ex, float ey, + const VColour &col) +{ + add(sx, sy, ex, sy, col); + add(ex, sy, ex, ey, col); + add(ex, ey, sx, ey, col); + add(sx, ey, sx, sy, col); +} diff --git a/crawl-ref/source/tilebuf.h b/crawl-ref/source/tilebuf.h new file mode 100644 index 0000000000..9368f1eb2b --- /dev/null +++ b/crawl-ref/source/tilebuf.h @@ -0,0 +1,141 @@ +/* + * File: tilebuf.h + * Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC + * + * Modified for Crawl Reference by $Author: ennewalker $ on $Date: 2008-03-07 $ + */ + +#ifndef TILEBUF_H +#define TILEBUF_H + +class FTFont; +class formatted_string; +class GenericTexture; +class TilesTexture; + +#include + +struct VColour +{ + VColour() {} + VColour(unsigned char _r, unsigned char _g, unsigned char _b, + unsigned char _a = 255) : r(_r), g(_g), b(_b), a(_a) {} + + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + + static VColour white; + static VColour black; + static VColour transparent; +}; + +struct PTCVert +{ + float pos_x; + float pos_y; + float tex_x; + float tex_y; + VColour col; +}; + +struct PTVert +{ + float pos_x; + float pos_y; + float tex_x; + float tex_y; +}; + +struct PCVert +{ + float pos_x; + float pos_y; + VColour col; +}; + +// V: vertex data +template +class VertBuffer +{ +public: + VertBuffer(const GenericTexture *tex, int prim); + + void add(const V& vert); + V& get_next(); + + void draw() const; + void clear(); +protected: + std::vector m_verts; + const GenericTexture *m_tex; + int m_prim; +}; + +class FontBuffer : public VertBuffer +{ +public: + FontBuffer(FTFont *font); + void add(const formatted_string &fs, float x, float y); + void add(const std::string &s, const VColour &col, float x, float y); +protected: + FTFont *m_font; +}; + +class TileBuffer : public VertBuffer +{ +public: + TileBuffer(const TilesTexture *tex); + void add(int idx, float x, float y); + + // Note: this could invalidate previous additions if they were + // from a different texture. + void set_tex(const TilesTexture *tex); +}; + +class ShapeBuffer : public VertBuffer +{ +public: + ShapeBuffer(); + void add(float sx, float sy, float ex, float ey, const VColour &c); +}; + +class LineBuffer : public VertBuffer +{ +public: + LineBuffer(); + void add(float sx, float sy, float ex, float ey, const VColour &c); + void add_square(float sx, float sy, float ex, float ey, const VColour &c); +}; + +///////////////////////////////////////////////////////////////////////////// +// template implementation + +template +inline VertBuffer::VertBuffer(const GenericTexture *tex, int prim) : + m_tex(tex), m_prim(prim) +{ +} + +template +inline void VertBuffer::add(const V& vert) +{ + m_verts.push_back(vert); +} + +template +inline V& VertBuffer::get_next() +{ + int last = m_verts.size(); + m_verts.resize(last + 1); + return (m_verts[last]); +} + +template +inline void VertBuffer::clear() +{ + m_verts.clear(); +} + +#endif diff --git a/crawl-ref/source/tilefont.cc b/crawl-ref/source/tilefont.cc index 4fb4a841ae..93d14aa9dc 100644 --- a/crawl-ref/source/tilefont.cc +++ b/crawl-ref/source/tilefont.cc @@ -6,6 +6,7 @@ */ #include "AppHdr.h" +#include "tilebuf.h" #include "tilefont.h" #include "defines.h" #include "files.h" @@ -15,24 +16,24 @@ #include #include FT_FREETYPE_H -const unsigned char term_colours[MAX_TERM_COLOUR][3] = +const VColour term_colours[MAX_TERM_COLOUR] = { - { 0, 0, 0}, // BLACK - { 0, 82, 255}, // BLUE - {100, 185, 70}, // GREEN - { 0, 180, 180}, // CYAN - {255, 48, 0}, // RED - {238, 92, 238}, // MAGENTA - {165, 91, 0}, // BROWN - {162, 162, 162}, // LIGHTGREY - { 82, 82, 82}, // DARKGREY - { 82, 102, 255}, // LIGHTBLUE - { 82, 255, 82}, // LIGHTGREEN - { 82, 255, 255}, // LIGHTCYAN - {255, 82, 82}, // LIGHTRED - {255, 82, 255}, // LIGHTMAGENTA - {255, 255, 82}, // YELLOW - {255, 255, 255} // WHITE + VColour( 0, 0, 0), // BLACK + VColour( 0, 82, 255), // BLUE + VColour(100, 185, 70), // GREEN + VColour( 0, 180, 180), // CYAN + VColour(255, 48, 0), // RED + VColour(238, 92, 238), // MAGENTA + VColour(165, 91, 0), // BROWN + VColour(162, 162, 162), // LIGHTGREY + VColour( 82, 82, 82), // DARKGREY + VColour( 82, 102, 255), // LIGHTBLUE + VColour( 82, 255, 82), // LIGHTGREEN + VColour( 82, 255, 255), // LIGHTCYAN + VColour(255, 82, 82), // LIGHTRED + VColour(255, 82, 255), // LIGHTMAGENTA + VColour(255, 255, 82), // YELLOW + VColour(255, 255, 255) // WHITE }; FTFont::FTFont() : @@ -299,9 +300,9 @@ void FTFont::render_textblock(unsigned int x_pos, unsigned int y_pos, { FontVertLayout v; v.tex_x = v.tex_y = 0; - v.r = term_colours[col_bg][0]; - v.g = term_colours[col_bg][1]; - v.b = term_colours[col_bg][2]; + v.r = term_colours[col_bg].r; + v.g = term_colours[col_bg].g; + v.b = term_colours[col_bg].b; v.a = 255; v.pos_x = adv.x; @@ -332,9 +333,9 @@ void FTFont::render_textblock(unsigned int x_pos, unsigned int y_pos, float tex_x2 = tex_x + (float)this_width / (float)m_tex.width(); float tex_y2 = tex_y + texcoord_dy; FontVertLayout v; - v.r = term_colours[col_fg][0]; - v.g = term_colours[col_fg][1]; - v.b = term_colours[col_fg][2]; + v.r = term_colours[col_fg].r; + v.g = term_colours[col_fg].g; + v.b = term_colours[col_fg].b; v.a = 255; v.pos_x = adv.x; @@ -421,9 +422,9 @@ static void _draw_box(int x_pos, int y_pos, float width, float height, box_vert verts[4]; for (unsigned int i = 0; i < 4; i++) { - verts[i].r = term_colours[box_colour][0]; - verts[i].g = term_colours[box_colour][1]; - verts[i].b = term_colours[box_colour][2]; + verts[i].r = term_colours[box_colour].r; + verts[i].g = term_colours[box_colour].g; + verts[i].b = term_colours[box_colour].b; verts[i].a = box_alpha; } verts[0].x = x_pos - box_width; @@ -556,3 +557,99 @@ void FTFont::render_string(unsigned int px, unsigned int py, render_textblock(tx, ty, chars, colours, max_cols, max_rows, drop_shadow); } + +void FTFont::store(FontBuffer &buf, float &x, float &y, + const std::string &str, const VColour &col) +{ + for (unsigned int i = 0; i < str.size(); i++) + { + char c = str[i]; + if (c == '\n') + { + y += m_max_advance.y; + } + else + { + store(buf, x, y, c, col); + } + } +} + +void FTFont::store(FontBuffer &buf, float &x, float &y, + const formatted_string &fs) +{ + int colour = LIGHTGREY; + for (unsigned int i = 0; i < fs.ops.size(); i++) + { + switch (fs.ops[i].type) + { + case FSOP_COLOUR: + // Only foreground colors for now... + colour = fs.ops[i].x & 0xF; + break; + case FSOP_TEXT: + store(buf, x, y, fs.ops[i].text, term_colours[colour]); + break; + default: + case FSOP_CURSOR: + break; + } + } +} + +void FTFont::store(FontBuffer &buf, float &x, float &y, + char c, const VColour &col) +{ + if (!m_glyphs[c].renderable) + { + x += m_glyphs[c].advance; + return; + } + + int this_width = m_glyphs[c].width; + + float pos_sx = x + m_glyphs[c].offset; + float pos_sy = y; + float pos_ex = pos_sx + this_width; + float pos_ey = y + m_max_advance.y; + + float tex_sx = (float)(c % 16) / 16.0f; + float tex_sy = (float)(c / 16) / 16.0f; + float tex_ex = tex_sx + (float)this_width / (float)m_tex.width(); + float tex_ey = tex_sy + (float)m_max_advance.y / (float)m_tex.height(); + + { + PTCVert &v = buf.get_next(); + v.col = col; + v.pos_x = pos_sx; + v.pos_y = pos_sy; + v.tex_x = tex_sx; + v.tex_y = tex_sy; + } + { + PTCVert &v = buf.get_next(); + v.col = col; + v.pos_x = pos_sx; + v.pos_y = pos_ey; + v.tex_x = tex_sx; + v.tex_y = tex_ey; + } + { + PTCVert &v = buf.get_next(); + v.col = col; + v.pos_x = pos_ex; + v.pos_y = pos_ey; + v.tex_x = tex_ex; + v.tex_y = tex_ey; + } + { + PTCVert &v = buf.get_next(); + v.col = col; + v.pos_x = pos_ex; + v.pos_y = pos_sy; + v.tex_x = tex_ex; + v.tex_y = tex_sy; + } + + x += m_glyphs[c].advance; +} diff --git a/crawl-ref/source/tilefont.h b/crawl-ref/source/tilefont.h index 10d1971391..ba4101f167 100644 --- a/crawl-ref/source/tilefont.h +++ b/crawl-ref/source/tilefont.h @@ -22,6 +22,10 @@ // have to link against FreeType2 or be forced do as much processing at // load time. +class FontBuffer; +class VColour; +class formatted_string; + class FTFont { public: @@ -43,11 +47,19 @@ public: unsigned char box_alpha = 0, unsigned char box_colour = 0, unsigned int outline = 0); + // FontBuffer helper functions + void store(FontBuffer &buf, float &x, float &y, + const std::string &s, const VColour &c); + void store(FontBuffer &buf, float &x, float &y, const formatted_string &fs); + void store(FontBuffer &buf, float &x, float &y, char c, const VColour &col); + unsigned int char_width() const { return m_max_advance.x; } unsigned int char_height() const { return m_max_advance.y; } unsigned int string_width(const char *text); + const GenericTexture *font_tex() const { return &m_tex; } + protected: struct GlyphInfo { diff --git a/crawl-ref/source/tilereg.cc b/crawl-ref/source/tilereg.cc index 1648320403..1f35812db5 100644 --- a/crawl-ref/source/tilereg.cc +++ b/crawl-ref/source/tilereg.cc @@ -1,6 +1,6 @@ /* * File: tilereg.cc - * Summary: Region system implementaions + * Summary: Region system implementations * * Created by: ennewalker on Sat Jan 5 01:33:53 2008 UTC * @@ -17,6 +17,7 @@ #include "item_use.h" #include "message.h" #include "misc.h" +#include "menu.h" #include "newgame.h" #include "mon-util.h" #include "player.h" @@ -2351,11 +2352,267 @@ CRTRegion::CRTRegion(FTFont *font) : TextRegion(font) int CRTRegion::handle_mouse(MouseEvent &event) { - // TODO enne - clicking on menu items? We could probably - // determine which items were clicked based on text size. return 0; } +MenuRegion::MenuRegion(ImageManager *im, FTFont *entry) : + m_image(im), m_font_entry(entry), m_mouse_idx(-1), + m_dirty(false), m_font_buf(entry), m_tile_buf(NULL) +{ + ASSERT(m_image); + ASSERT(m_font_entry); + + dx = 1; + dy = 1; + + m_entries.resize(128); +} + +int MenuRegion::mouse_entry(int x, int y) +{ + if (m_dirty) + place_entries(); + + for (unsigned int i = 0; i < m_entries.size(); i++) + { + if (!m_entries[i].valid) + continue; + + if (x >= m_entries[i].sx && x <= m_entries[i].ex + && y >= m_entries[i].sy && y <= m_entries[i].ey) + { + return i; + } + } + + return -1; +} + +int MenuRegion::handle_mouse(MouseEvent &event) +{ + m_mouse_idx = -1; + + int x, y; + if (!mouse_pos(event.px, event.py, x, y)) + return 0; + + if (event.event == MouseEvent::MOVE) + { + int old_idx = m_mouse_idx; + m_mouse_idx = mouse_entry(x, y); + if (old_idx == m_mouse_idx) + return 0; + + const VColour mouse_colour(160, 160, 160, 255); + + m_line_buf.clear(); + if (!m_entries[m_mouse_idx].heading && m_entries[m_mouse_idx].key) + { + m_line_buf.add_square(m_entries[m_mouse_idx].sx-1, + m_entries[m_mouse_idx].sy, + m_entries[m_mouse_idx].ex+1, + m_entries[m_mouse_idx].ey+1, + mouse_colour); + } + + return 0; + } + + if (event.event == MouseEvent::PRESS) + { + switch (event.button) + { + case MouseEvent::LEFT: + { + int entry = mouse_entry(x, y); + if (entry == -1) + return 0; + return m_entries[entry].key; + } +#if 0 + // TODO enne - these events are wonky on OS X. + // TODO enne - fix menus so that mouse wheeling doesn't easy exit + case MouseEvent::SCROLL_UP: + return CK_UP; + case MouseEvent::SCROLL_DOWN: + return CK_DOWN; +#endif + default: + return 0; + } + } + + return 0; +} + +void MenuRegion::place_entries() +{ + m_dirty = false; + + const int heading_indent = 10; + const int tile_ident = 20; + const int text_indent = 58; + const unsigned int max_tile_height = 32; + const int column_width = mx / 2; + const int entry_buffer = 1; + const VColour selected_colour(50, 50, 10, 255); + + m_font_buf.clear(); + m_tile_buf.clear(); + m_shape_buf.clear(); + m_line_buf.clear(); + + TextureID tex = TEX_MAX; + int height = 2; + + bool mouse_selected = false; + + for (unsigned int i = 0; i < m_entries.size(); i++) + { + if (!m_entries[i].valid) + { + m_entries[i].sx = 0; + m_entries[i].sy = 0; + m_entries[i].ex = 0; + m_entries[i].ey = 0; + continue; + } + + m_entries[i].sy = height; + + int text_start = 0; + int text_height = height; + + if (m_entries[i].heading) + { + mouse_selected = false; + m_entries[i].sx = heading_indent; + text_start = heading_indent; + height += m_font_entry->char_height(); + } + else if (m_entries[i].tile) + { + m_entries[i].sx = tile_ident; + text_start = text_indent; + int entry_height = + std::max(max_tile_height, m_font_entry->char_height()); + height += entry_height; + text_height += (entry_height - m_font_entry->char_height()) / 2; + + ASSERT(m_entries[i].texture == tex || tex == TEX_MAX); + tex = m_entries[i].texture; + m_tile_buf.set_tex(&m_image->m_textures[tex]); + + m_tile_buf.add(m_entries[i].tile, m_entries[i].sx, m_entries[i].sy); + } + else + { + m_entries[i].sx = text_start + text_indent; + height += m_font_entry->char_height(); + } + + std::string unfrm = m_entries[i].text.tostring(); + m_entries[i].ex = text_start + m_font_entry->string_width(unfrm.c_str()); + m_entries[i].ex = std::max(m_entries[i].ex, column_width); + m_entries[i].ey = height; + + m_font_buf.add(m_entries[i].text, text_start, text_height); + + if (m_entries[i].selected) + { + m_shape_buf.add(m_entries[i].sx-1, m_entries[i].sy-1, + m_entries[i].ex+1, m_entries[i].ey+1, + selected_colour); + } + + height += entry_buffer; + } + + int lines = count_linebreaks(m_more); + int more_height = (lines + 1) * m_font_entry->char_height(); + m_font_buf.add(m_more, sx + ox, ey - oy - more_height); +} + +void MenuRegion::render() +{ + if (m_dirty) + place_entries(); + + glLoadIdentity(); + glTranslatef(sx + ox, sy + oy, 0); + glScalef(dx, dy, 1); + + m_shape_buf.draw(); + m_line_buf.draw(); + m_tile_buf.draw(); + m_font_buf.draw(); +} + +void MenuRegion::clear() +{ + m_shape_buf.clear(); + m_line_buf.clear(); + m_tile_buf.clear(); + m_font_buf.clear(); + + m_more.clear(); + + for (unsigned int i = 0; i < m_entries.size(); i++) + { + m_entries[i].valid = false; + } + m_mouse_idx = -1; +} + +void MenuRegion::set_entry(int idx, const std::string &str, int colour, + const MenuEntry *me) +{ + if (idx >= (int)m_entries.size()) + { + int new_size = m_entries.size(); + while (idx >= new_size) + new_size *= 2; + m_entries.resize(new_size); + } + + MenuRegionEntry &e = m_entries[idx]; + e.valid = true; + e.text.clear(); + e.text.textcolor(colour); + e.text += formatted_string::parse_string(str); + e.heading = (me->level == MEL_TITLE || me->level == MEL_SUBTITLE); + e.selected = me->selected(); + e.key = me->hotkeys.size() > 0 ? me->hotkeys[0] : 0; + e.sx = e.sy = e.ex = e.ey = 0; + if (!me->tile(e.tile, e.texture)) + e.tile = 0; + + m_dirty = true; +} + +void MenuRegion::on_resize() +{ + m_dirty = true; +} + +int MenuRegion::maxpagesize() const +{ + // TODO enne - this could be much smarter. Also, columns? + return my / 32 - 2; +} + +void MenuRegion::set_offset(int lines) +{ + oy = (lines - 1) * m_font_entry->char_height(); +} + +void MenuRegion::set_more(const formatted_string &more) +{ + m_more.clear(); + m_more += more; + m_dirty = true; +} + ImageManager::ImageManager() { } diff --git a/crawl-ref/source/tilereg.h b/crawl-ref/source/tilereg.h index b46a033945..4111e6152a 100644 --- a/crawl-ref/source/tilereg.h +++ b/crawl-ref/source/tilereg.h @@ -9,9 +9,13 @@ #ifndef TILEREG_H #define TILEREG_H +#include "AppHdr.h" +#include "format.h" +#include "tilebuf.h" #include "tiletex.h" #include "tiles.h" #include + class mcache_entry; class ImageManager @@ -174,6 +178,52 @@ public: virtual int handle_mouse(MouseEvent &event); }; +class MenuEntry; + +class MenuRegion : public Region +{ +public: + MenuRegion(ImageManager *im, FTFont *entry); + + virtual int handle_mouse(MouseEvent &event); + virtual void render(); + virtual void clear(); + + int maxpagesize() const; + void set_entry(int index, const std::string &s, int colour, const MenuEntry *me); + void set_offset(int lines); + void set_more(const formatted_string &more); +protected: + virtual void on_resize(); + virtual void place_entries(); + int mouse_entry(int x, int y); + + struct MenuRegionEntry + { + formatted_string text; + int tile; + TextureID texture; + int sx, ex, sy, ey; + bool selected; + bool heading; + char key; + bool valid; + }; + + ImageManager *m_image; + FTFont *m_font_entry; + formatted_string m_more; + int m_mouse_idx; + bool m_dirty; + + std::vector m_entries; + + ShapeBuffer m_shape_buf; + LineBuffer m_line_buf; + FontBuffer m_font_buf; + TileBuffer m_tile_buf; +}; + class TileRegion : public Region { public: diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc index 27b62eb332..badcfd4656 100644 --- a/crawl-ref/source/tilesdl.cc +++ b/crawl-ref/source/tilesdl.cc @@ -98,7 +98,7 @@ void TilesFramework::shutdown() delete m_region_map; delete m_region_self_inv; delete m_region_crt; - delete m_region_menu_inv; + delete m_region_menu; m_region_tile = NULL; m_region_stat = NULL; @@ -106,7 +106,7 @@ void TilesFramework::shutdown() m_region_map = NULL; m_region_self_inv = NULL; m_region_crt = NULL; - m_region_menu_inv = NULL; + m_region_menu = NULL; for (unsigned int i = 0; i < LAYER_MAX; i++) { @@ -175,7 +175,7 @@ bool TilesFramework::initialise() return false; int crt_font = load_font(Options.tile_font_crt_file.c_str(), - Options.tile_font_crt_size, true, false); + Options.tile_font_crt_size, true, true); int msg_font = load_font(Options.tile_font_msg_file.c_str(), Options.tile_font_msg_size, true, false); int stat_font = load_font(Options.tile_font_stat_file.c_str(), @@ -200,8 +200,7 @@ bool TilesFramework::initialise() m_region_msg = new MessageRegion(m_fonts[msg_font].font); m_region_stat = new StatRegion(m_fonts[stat_font].font); m_region_crt = new CRTRegion(m_fonts[crt_font].font); - m_region_menu_inv = new InventoryRegion(&m_image, m_fonts[lbl_font].font, - TILE_X, TILE_Y); + m_region_menu = new MenuRegion(&m_image, m_fonts[crt_font].font); m_layers[LAYER_NORMAL].m_regions.push_back(m_region_tile); m_layers[LAYER_NORMAL].m_regions.push_back(m_region_map); @@ -210,7 +209,7 @@ bool TilesFramework::initialise() m_layers[LAYER_NORMAL].m_regions.push_back(m_region_stat); m_layers[LAYER_CRT].m_regions.push_back(m_region_crt); - m_layers[LAYER_CRT].m_regions.push_back(m_region_menu_inv); + m_layers[LAYER_CRT].m_regions.push_back(m_region_menu); cgotoxy(1, 1, GOTO_CRT); @@ -229,8 +228,11 @@ int TilesFramework::load_font(const char *font_file, int font_size, for (unsigned int i = 0; i < m_fonts.size(); i++) { font_info &finfo = m_fonts[i]; - if (finfo.name == font_file && finfo.size == font_size) + if (finfo.name == font_file && finfo.size == font_size + && outline == finfo.outline) + { return i; + } } if (!font->load_font(font_file, font_size, outline)) @@ -246,6 +248,7 @@ int TilesFramework::load_font(const char *font_file, int font_size, finfo.name = font_file; finfo.size = font_size; finfo.font = font; + finfo.outline = outline; m_fonts.push_back(finfo); return (m_fonts.size() - 1); @@ -730,7 +733,6 @@ void TilesFramework::do_layout() m_region_stat->resize(crawl_view.hudsz.x, crawl_view.hudsz.y); m_region_msg->resize(crawl_view.msgsz.x, crawl_view.msgsz.y); m_region_map->resize(GXM, GYM); - m_region_menu_inv->resize(24, 1); // Place regions for normal layer const int margin = 4; @@ -861,25 +863,9 @@ void TilesFramework::do_layout() // Place regions for crt layer m_region_crt->place(0, 0, margin); - - while (m_region_crt->ey + m_region_menu_inv->wy > m_windowsz.y) - { - m_region_crt->resize(m_region_crt->mx, m_region_crt->my - 1); - } - while (m_region_crt->ex > m_windowsz.x) - { - m_region_crt->resize(m_region_crt->mx - 1, m_region_crt->my); - } - - m_region_menu_inv->place(0, m_region_crt->ey, margin); - m_region_menu_inv->resize_to_fit(m_windowsz.x, m_windowsz.y - - m_region_menu_inv->sy); - - // Depending on the font, the menu inventory may hold fewer items - // than the crt menu can display. Decrease the lines if necessary. - const int ex = 3; - if (m_region_crt->my - ex > m_region_menu_inv->mx) - m_region_crt->resize(m_region_crt->mx, m_region_menu_inv->mx + ex); + m_region_crt->resize_to_fit(m_windowsz.x, m_windowsz.y); + m_region_menu->place(0, 0, margin); + m_region_menu->resize_to_fit(m_windowsz.x, m_windowsz.y); crawl_view.init_view(); } @@ -894,8 +880,8 @@ void TilesFramework::clrscr() m_region_msg->clear(); if (m_region_crt) m_region_crt->clear(); - if (m_region_menu_inv) - m_region_menu_inv->clear(); + if (m_region_menu) + m_region_menu->clear(); cgotoxy(1,1); } @@ -1217,21 +1203,6 @@ void TilesFramework::update_inventory() m_region_self_inv->update(inv.size(), &inv[0]); } -void TilesFramework::update_menu_inventory(unsigned int slot, - const item_def &item, - bool selected, char key) -{ - InventoryTile desc; - _fill_item_info(desc, item); - desc.key = key; - desc.idx = (desc.flag & TILEI_FLAG_FLOOR) ? item.index() : - letter_to_index(key); - if (selected) - desc.flag |= TILEI_FLAG_SELECT; - - m_region_menu_inv->update_slot(slot, desc); -} - void TilesFramework::place_cursor(cursor_type type, const coord_def &gc) { m_region_tile->place_cursor(type, gc); diff --git a/crawl-ref/source/tilesdl.h b/crawl-ref/source/tilesdl.h index ea4e717284..735189c95b 100644 --- a/crawl-ref/source/tilesdl.h +++ b/crawl-ref/source/tilesdl.h @@ -106,8 +106,6 @@ public: void clear_minimap(); void update_inventory(); - void update_menu_inventory(unsigned int slot, const item_def &item, bool selected, char key); - void redraw(); void place_cursor(cursor_type type, const coord_def &gc); @@ -121,6 +119,8 @@ public: void add_overlay(const coord_def &gc, int idx); void clear_overlays(); + + MenuRegion *get_menu() { return m_region_menu; } protected: int load_font(const char *font_file, int font_size, @@ -161,12 +161,13 @@ protected: // Full-screen CRT layer CRTRegion *m_region_crt; - InventoryRegion *m_region_menu_inv; + MenuRegion *m_region_menu; struct font_info { std::string name; int size; + bool outline; FTFont *font; }; std::vector m_fonts; diff --git a/crawl-ref/source/tiletex.cc b/crawl-ref/source/tiletex.cc index bf0290c2a5..524b37c46b 100644 --- a/crawl-ref/source/tiletex.cc +++ b/crawl-ref/source/tiletex.cc @@ -236,7 +236,7 @@ bool GenericTexture::load_texture(unsigned char *pixels, unsigned int new_width, return true; } -void GenericTexture::bind() +void GenericTexture::bind() const { ASSERT(m_handle); glBindTexture(GL_TEXTURE_2D, m_handle); diff --git a/crawl-ref/source/tiletex.h b/crawl-ref/source/tiletex.h index d5692f9021..63abf4d2f4 100644 --- a/crawl-ref/source/tiletex.h +++ b/crawl-ref/source/tiletex.h @@ -43,7 +43,7 @@ public: unsigned int width() const { return m_width; } unsigned int height() const { return m_height; } - void bind(); + void bind() const; protected: unsigned int m_handle; -- cgit v1.2.3-54-g00ecf