diff options
author | ennewalker <ennewalker@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-07-15 04:07:07 +0000 |
---|---|---|
committer | ennewalker <ennewalker@c06c8d41-db1a-0410-9941-cceddc491573> | 2008-07-15 04:07:07 +0000 |
commit | af3cd3ff34ef5da884b2c673afe1321f0cf372e7 (patch) | |
tree | a574c2155f571f216f29c44b29e333ea320322a6 /crawl-ref/source/tilesdl.cc | |
parent | 71ed1a7fd6819916d79d194126c061ac1f087b11 (diff) | |
download | crawl-ref-af3cd3ff34ef5da884b2c673afe1321f0cf372e7.tar.gz crawl-ref-af3cd3ff34ef5da884b2c673afe1321f0cf372e7.zip |
Large tiles-related changes. Platform-specific rendering removed and replaced with SDL/OpenGL.
git-svn-id: https://crawl-ref.svn.sourceforge.net/svnroot/crawl-ref/trunk@6550 c06c8d41-db1a-0410-9941-cceddc491573
Diffstat (limited to 'crawl-ref/source/tilesdl.cc')
-rw-r--r-- | crawl-ref/source/tilesdl.cc | 937 |
1 files changed, 937 insertions, 0 deletions
diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc new file mode 100644 index 0000000000..7a375ea046 --- /dev/null +++ b/crawl-ref/source/tilesdl.cc @@ -0,0 +1,937 @@ +#include "cio.h" +#include "itemname.h" +#include "items.h" +#include "itemprop.h" +#include "mon-util.h" +#include "player.h" +#include "stuff.h" +#include "tiles.h" +#include "tilesdl.h" +#include "travel.h" +#include "version.h" + +#include "tiledef-dngn.h" +#include "tilefont.h" + +#include <SDL.h> +#include <SDL_opengl.h> +#include <SDL_image.h> + +// Note: these defaults should match the OpenGL defaults +GLState::GLState() : + array_vertex(false), + array_texcoord(false), + array_colour(false), + blend(false), + texture(false) +{ +} + +void GLStateManager::init() +{ + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glClearColor(0.0, 0.0, 0.0, 1.0f); +} + +void GLStateManager::set(const GLState& state) +{ + if (state.array_vertex) + glEnableClientState(GL_VERTEX_ARRAY); + else + glDisableClientState(GL_VERTEX_ARRAY); + + if (state.array_texcoord) + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + else + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + + if (state.array_colour) + { + glEnableClientState(GL_COLOR_ARRAY); + } + else + { + glDisableClientState(GL_COLOR_ARRAY); + + // [enne] This should *not* be necessary, but the Linux OpenGL + // drive that I'm using sets this to the last colour of the + // colour array. So, we need to unset it here. + glColor3f(1.0f, 1.0f, 1.0f); + } + + if (state.texture) + glEnable(GL_TEXTURE_2D); + else + glDisable(GL_TEXTURE_2D); + + if (state.blend) + glEnable(GL_BLEND); + else + glDisable(GL_BLEND); +} + +TilesFramework tiles; + +TilesFramework::TilesFramework() : + m_windowsz(1024, 768), + m_viewsc(0, 0), + m_context(NULL), + m_fullscreen(false), + m_active_layer(LAYER_CRT), + m_font(NULL), + m_buttons_held(0), + m_key_mod(0), + m_mouse(-1, -1), + m_last_tick_moved(0) +{ +} + +TilesFramework::~TilesFramework() +{ +} + +void TilesFramework::shutdown() +{ + delete m_region_tile; + delete m_region_stat; + delete m_region_msg; + delete m_region_map; + delete m_region_self_inv; + delete m_region_crt; + delete m_region_menu_inv; + + m_region_tile = NULL; + m_region_stat = NULL; + m_region_msg = NULL; + m_region_map = NULL; + m_region_self_inv = NULL; + m_region_crt = NULL; + m_region_menu_inv = NULL; + + for (unsigned int i = 0; i < LAYER_MAX; i++) + { + m_layers[i].m_regions.clear(); + } + + SDL_Quit(); +} + +bool TilesFramework::initialise() +{ + if (SDL_Init(SDL_INIT_VIDEO) != 0) + { + printf ("Failed to initialise SDL: %s\n", SDL_GetError()); + return false; + } + + SDL_EnableUNICODE(true); + + SDL_WM_SetCaption(CRAWL " " VERSION, CRAWL); + SDL_Surface *icon = IMG_Load("dat/tiles/stone_soup_icon-32x32.png"); + if (!icon) + { + printf ("Failed to load icon: %s\n", SDL_GetError()); + return false; + } + SDL_WM_SetIcon(icon, NULL); + + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); + + unsigned int flags = SDL_OPENGL; + if (m_fullscreen) + flags |= SDL_FULLSCREEN; + + // TODO enne - add options for screen size and fullscreen + m_context = SDL_SetVideoMode(m_windowsz.x, m_windowsz.y, 0, flags); + if (!m_context) + { + printf ("Failed to set video mode: %s\n", SDL_GetError()); + return false; + } + + if (!m_image.load_textures()) + return false; + + // TODO enne - make this configurable (and fall back on default if fails) + // TODO enne - use Crawl's dat file loading utilities + const char *font_file = "dat/tiles/VeraMono.ttf"; + const int font_size = 14; + if (!load_font(font_file, font_size)) + return false; + + ASSERT(m_font); + + // TODO enne - grab these from options + unsigned int map_pixsz = 4; + + // TODO enne - different font for tooltip and for dungeon tags + m_region_tile = new DungeonRegion(&m_image, m_font, TILE_X, TILE_Y); + m_region_map = new MapRegion(map_pixsz); + m_region_self_inv = new InventoryRegion(&m_image, TILE_X, TILE_Y); + m_region_msg = new MessageRegion(m_font); + m_region_stat = new StatRegion(m_font); + m_region_crt = new CRTRegion(m_font); + m_region_menu_inv = new InventoryRegion(&m_image, TILE_X, TILE_Y); + + m_layers[LAYER_NORMAL].m_regions.push_back(m_region_tile); + m_layers[LAYER_NORMAL].m_regions.push_back(m_region_map); + m_layers[LAYER_NORMAL].m_regions.push_back(m_region_self_inv); + m_layers[LAYER_NORMAL].m_regions.push_back(m_region_msg); + 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); + + cgotoxy(1, 1, GOTO_CRT); + + GLStateManager::init(); + + resize(); + + return true; +} + +bool TilesFramework::load_font(const char *font_file, int font_size) +{ + m_font = new FTFont(); + + if (!m_font->load_font(font_file, font_size)) + { + delete m_font; + m_font = NULL; + + printf("Failed to open font '%s'\n", font_file); + return false; + } + + return true; +} + +void TilesFramework::load_dungeon(unsigned int *tileb, int gx, int gy) +{ + unsigned int ox = m_region_tile->mx/2; + unsigned int oy = m_region_tile->my/2; + m_region_tile->load_dungeon(tileb, gx - ox, gy - oy); + + coord_def win_start(gx - ox, gy - oy); + coord_def win_end(gx + ox + 1, gy + oy + 1); + + m_region_map->set_window(win_start, win_end); +} + +void TilesFramework::load_dungeon(int cx, int cy) +{ + int wx = m_region_tile->mx; + int wy = m_region_tile->my; + unsigned int *tb = (unsigned int*)alloca(sizeof(unsigned int) * + wy * wx * 2); + + int count = 0; + for (int y = 0; y < wy; y++) + { + for (int x = 0; x < wx; x++) + { + int fg; + int bg; + + const coord_def gc(cx + x - wx/2, + cy + y - wy/2); + const coord_def ep = view2show(grid2view(gc)); + + // mini "viewwindow" routine + if (!map_bounds(gc)) + { + fg = 0; + bg = TILE_DNGN_UNSEEN; + } + else if (!crawl_view.in_grid_los(gc) || !env.show(ep)) + { + fg = env.tile_bk_fg[gc.x][gc.y]; + bg = env.tile_bk_bg[gc.x][gc.y]; + if (bg == 0) + bg |= TILE_DNGN_UNSEEN; + bg |= tile_unseen_flag(gc); + } + else + { + fg = env.tile_fg[ep.x-1][ep.y-1]; + bg = env.tile_bg[ep.x-1][ep.y-1]; + } + + if (gc.x == cx && gc.y == cy) + bg |= TILE_FLAG_CURSOR1; + + tb[count++] = fg; + tb[count++] = bg; + } + } + + load_dungeon(tb, cx, cy); + tiles.redraw(); +} + +void TilesFramework::resize() +{ + do_layout(); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // TODO enne - need better resizing + // View size in pixels is (m_viewsc * crawl_view.viewsz) + m_viewsc.x = 32; + m_viewsc.y = 32; + + // For ease, vertex positions are pixel positions. + glOrtho(0, m_windowsz.x, m_windowsz.y, 0, 0, 100); +} + +static unsigned char _get_modifiers(SDL_keysym &keysym) +{ + // keysym.mod can't be used to keep track of the modifier state. + // If shift is hit by itself, this will not include KMOD_SHIFT. + // Instead, look for the key itself as a separate event. + switch (keysym.sym) + { + case SDLK_LSHIFT: + case SDLK_RSHIFT: + return MOD_SHIFT; + case SDLK_LCTRL: + case SDLK_RCTRL: + return MOD_CTRL; + case SDLK_LALT: + case SDLK_RALT: + return MOD_ALT; + default: + return 0; + } +} + +static int _translate_keysym(SDL_keysym &keysym) +{ + // This function returns the key that was hit. Returning zero implies that + // the keypress (e.g. hitting shift on its own) should be eaten and not + // handled. + + const int shift_offset = CK_SHIFT_UP - CK_UP; + const int ctrl_offset = CK_CTRL_UP - CK_UP; + + int offset = 0; + if (keysym.mod & KMOD_CTRL) + offset = ctrl_offset; + else if (keysym.mod & KMOD_SHIFT) + offset = shift_offset; + + switch (keysym.sym) + { + case SDLK_RETURN: + return CK_ENTER; + case SDLK_BACKSPACE: + return CK_BKSP; + case SDLK_ESCAPE: + return CK_ESCAPE; + case SDLK_DELETE: + return CK_DELETE; + + case SDLK_UP: + return CK_UP + offset; + case SDLK_DOWN: + return CK_DOWN + offset; + case SDLK_LEFT: + return CK_LEFT + offset; + case SDLK_RIGHT: + return CK_RIGHT + offset; + case SDLK_INSERT: + return CK_INSERT + offset; + case SDLK_HOME: + return CK_HOME + offset; + case SDLK_END: + return CK_END + offset; + case SDLK_CLEAR: + return CK_CLEAR + offset; + case SDLK_PAGEUP: + return CK_PGUP + offset; + case SDLK_PAGEDOWN: + return CK_PGDN + offset; + default: + break; + } + + bool is_ascii = ((keysym.unicode & 0xFF80) == 0); + return is_ascii ? keysym.unicode & 0x7F : 0; +} + +int TilesFramework::getch() +{ + // TODO enne - is there really a difference between these two functions?? + return getch_ck(); +} + +int TilesFramework::handle_mouse(MouseEvent &event) +{ + m_region_tile->place_cursor(CURSOR_MOUSE, Region::NO_CURSOR); + + // Note: the mouse event goes to all regions in the active layer because + // we want to be able to start some GUI event (e.g. far viewing) and + // stop if it moves to another region. + int return_key = 0; + for (unsigned int i = 0; i < m_layers[m_active_layer].m_regions.size(); i++) + { + // TODO enne - what if two regions give a key? + int key = 0; + key = m_layers[m_active_layer].m_regions[i]->handle_mouse(event); + if (key) + return_key = key; + } + + // Let regions take priority in any mouse mode. + if (return_key) + return return_key; + + // Handle "more" mode globally here, rather than duplicate across regions. + if (mouse_control::current_mode() == MOUSE_MODE_MORE + && event.button == MouseEvent::LEFT + && event.event == MouseEvent::PRESS) + { + return '\r'; + } + + // TODO enne - in what cases should the buttons be returned? +#if 0 + // If nothing else, return the mouse button that was pressed. + switch (event.button) + { + case MouseEvent::LEFT: + return CK_MOUSE_B1; + case MouseEvent::RIGHT: + return CK_MOUSE_B2; + case MouseEvent::MIDDLE: + return CK_MOUSE_B3; + case MouseEvent::SCROLL_UP: + return CK_MOUSE_B4; + case MouseEvent::SCROLL_DOWN: + return CK_MOUSE_B5; + default: + case MouseEvent::NONE: + return 0; + } +#endif + + return 0; +} + +static void _translate_event(const SDL_MouseMotionEvent &sdl_event, + MouseEvent &tile_event) +{ + tile_event.held = MouseEvent::NONE; + tile_event.event = MouseEvent::MOVE; + tile_event.button = MouseEvent::NONE; + tile_event.px = sdl_event.x; + tile_event.py = sdl_event.y; + + // TODO enne - do we want the relative motion? +} + +static void _translate_event(const SDL_MouseButtonEvent &sdl_event, + MouseEvent &tile_event) +{ + tile_event.held = MouseEvent::NONE; + tile_event.event = (sdl_event.type == SDL_MOUSEBUTTONDOWN) ? + MouseEvent::PRESS : MouseEvent::RELEASE; + switch (sdl_event.button) + { + case SDL_BUTTON_LEFT: + tile_event.button = MouseEvent::LEFT; + break; + case SDL_BUTTON_RIGHT: + tile_event.button = MouseEvent::RIGHT; + break; + case SDL_BUTTON_MIDDLE: + tile_event.button = MouseEvent::MIDDLE; + break; + case SDL_BUTTON_WHEELUP: + tile_event.button = MouseEvent::SCROLL_UP; + break; + case SDL_BUTTON_WHEELDOWN: + tile_event.button = MouseEvent::SCROLL_DOWN; + break; + default: + ASSERT(!"Unhandled button"); + tile_event.button = MouseEvent::NONE; + break; + } + tile_event.px = sdl_event.x; + tile_event.py = sdl_event.y; +} + +int TilesFramework::getch_ck() +{ + SDL_Event event; + + int key = 0; + + while (!key) + { + unsigned int ticks = SDL_GetTicks(); + + if (SDL_PollEvent(&event)) + { + switch(event.type) + { + case SDL_KEYDOWN: + m_key_mod |= _get_modifiers(event.key.keysym); + key = _translate_keysym(event.key.keysym); + + // If you hit a key, disable tooltips until the mouse + // is moved again. + m_last_tick_moved = ~0; + break; + + case SDL_KEYUP: + m_key_mod &= ~_get_modifiers(event.key.keysym); + m_last_tick_moved = ~0; + break; + + case SDL_MOUSEMOTION: + { + // Record mouse pos for tooltip timer + if (m_mouse.x != event.motion.x + || m_mouse.y != event.motion.y) + { + m_last_tick_moved = ticks; + } + m_mouse.x = event.motion.x; + m_mouse.y = event.motion.y; + + MouseEvent mouse_event; + _translate_event(event.motion, mouse_event); + mouse_event.held = m_buttons_held; + mouse_event.mod = m_key_mod; + key = handle_mouse(mouse_event); + } + break; + + case SDL_MOUSEBUTTONUP: + { + MouseEvent mouse_event; + _translate_event(event.button, mouse_event); + m_buttons_held &= ~(mouse_event.button); + mouse_event.held = m_buttons_held; + mouse_event.mod = m_key_mod; + key = handle_mouse(mouse_event); + m_last_tick_moved = ticks; + } + break; + + case SDL_MOUSEBUTTONDOWN: + { + MouseEvent mouse_event; + _translate_event(event.button, mouse_event); + m_buttons_held |= mouse_event.button; + mouse_event.held = m_buttons_held; + mouse_event.mod = m_key_mod; + key = handle_mouse(mouse_event); + m_last_tick_moved = ticks; + } + break; + + case SDL_QUIT: + // TODO enne + exit(0); + + case SDL_USEREVENT: + default: + break; + } + } + + // TODO enne - outsource this value + unsigned int tooltip_ticks = 1000; + bool show_tooltip = ((ticks - m_last_tick_moved > tooltip_ticks) + && ticks > m_last_tick_moved); + + if (show_tooltip) + { + if (m_tooltip.empty()) + { + for (unsigned int i = 0; + i < m_layers[m_active_layer].m_regions.size(); i++) + { + Region *reg = m_layers[m_active_layer].m_regions[i]; + if (!reg->inside(m_mouse.x, m_mouse.y)) + continue; + if (reg->update_tip_text(m_tooltip)) + break; + } + } + } + else + { + m_tooltip.clear(); + } + + redraw(); + } + + return key; +} + +void TilesFramework::do_layout() +{ + const int map_stat_buffer = 5; + + // TODO enne - use options + const int crt_width = 80; + const int crt_height = 30; + const int map_margin = 2; + + // Size regions that we know about + m_region_tile->resize(crawl_view.viewsz.x, crawl_view.viewsz.y); + m_region_crt->resize(crt_width, crt_height); + 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); + + + // Place regions for normal layer + const int margin = 4; + m_region_tile->place(0, 0, margin); + m_region_msg->place(0, m_region_tile->ey, margin); + + int stat_col = m_region_tile->ex + map_stat_buffer; + + m_region_stat->place(stat_col, 0, 0); + m_region_map->place(stat_col, m_region_stat->ey, map_margin); + + int inv_col = std::max(m_region_tile->ex, m_region_msg->ex); + + m_region_self_inv->place(inv_col, m_region_map->ey, 0); + m_region_self_inv->resize_to_fit(m_windowsz.x - + m_region_self_inv->sx, + m_windowsz.y - + m_region_self_inv->sy); + + // Place regions for crt layer + m_region_crt->place(0, 0, margin); + 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); +} + +void TilesFramework::clrscr() +{ + TextRegion::cursor_region = NULL; + + if (m_region_stat) + m_region_stat->clear(); + if (m_region_msg) + m_region_msg->clear(); + if (m_region_crt) + m_region_crt->clear(); + if (m_region_menu_inv) + m_region_menu_inv->clear(); + + cgotoxy(1,1); +} + +void TilesFramework::message_out(int which_line, int colour, const char *s, int firstcol, bool newline) +{ + if (!firstcol) + firstcol = Options.delay_message_clear ? 2 : 1; + + cgotoxy(firstcol, which_line + 1, GOTO_MSG); + textcolor(colour); + + cprintf("%s", s); + + if (newline && which_line == crawl_view.msgsz.y - 1) + m_region_msg->scroll(); +} + +void TilesFramework::clear_message_window() +{ + m_region_msg->clear(); + m_active_layer = LAYER_NORMAL; +} + +void TilesFramework::cgotoxy(int x, int y, int region) +{ + if (region == GOTO_LAST) + { + // nothing + } + else if (region == GOTO_CRT) + { + m_active_layer = LAYER_CRT; + TextRegion::text_mode = m_region_crt; + } + else if (region == GOTO_MSG) + { + m_active_layer = LAYER_NORMAL; + TextRegion::text_mode = m_region_msg; + } + else if (region == GOTO_STAT) + { + m_active_layer = LAYER_NORMAL; + TextRegion::text_mode = m_region_stat; + } + + TextRegion::cgotoxy(x, y); +} + +void TilesFramework::redraw() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glScalef(m_viewsc.x, m_viewsc.y, 1.0f); + + for (unsigned int i = 0; i < m_layers[m_active_layer].m_regions.size(); i++) + { + m_layers[m_active_layer].m_regions[i]->render(); + } + + // Draw tooltip + if (!m_tooltip.empty()) + { + const coord_def min_pos(0, 0); + m_font->render_string(m_mouse.x, m_mouse.y - 2, m_tooltip.c_str(), + min_pos, m_windowsz, WHITE, false, 150, + BLUE, 5); + } + + SDL_GL_SwapBuffers(); +} + +void TilesFramework::update_minimap(int gx, int gy, map_feature f) +{ + if (!player_in_mappable_area()) + return; + + coord_def gc(gx, gy); + + if (you.pos() == gc) + { + f = MF_PLAYER; + } + else if (f == MF_MONS_HOSTILE && mgrd[gx][gy] != NON_MONSTER) + { + const int grid = mgrd[gx][gy]; + if (mons_friendly(&menv[grid])) + f = MF_MONS_FRIENDLY; + else if (mons_neutral(&menv[grid])) + f = MF_MONS_NEUTRAL; + else if (mons_class_flag(menv[grid].type, M_NO_EXP_GAIN)) + f = MF_MONS_NO_EXP; + } + else if (f == MF_FLOOR || f == MF_MAP_FLOOR) + { + if (is_exclude_root(gc)) + f = MF_EXCL_ROOT; + else if (is_excluded(gc)) + f = MF_EXCL; + } + + m_region_map->set(gx, gy, f); +} + +void TilesFramework::clear_minimap() +{ + m_region_map->clear(); +} + +static void _fill_item_info(InventoryTile &desc, const item_def &item) +{ + desc.tile = tileidx_item(item); + + int type = item.base_type; + if (type == OBJ_FOOD || type == OBJ_SCROLLS + || type == OBJ_POTIONS || type == OBJ_MISSILES) + { + // -1 specifies don't display anything + desc.quantity = item.quantity == 1 ? -1 : item.quantity; + } + else if (type == OBJ_WANDS + && ((item.flags & ISFLAG_KNOW_PLUSES) + || item.plus2 == ZAPCOUNT_EMPTY)) + { + desc.quantity = item.plus; + } + else + { + desc.quantity = -1; + } + + desc.flag = 0; + if (item_cursed(item) && item_ident(item, ISFLAG_KNOW_CURSE)) + desc.flag |= TILEI_FLAG_CURSE; + if (item_type_tried(item)) + desc.flag |= TILEI_FLAG_TRIED; + if (item.x != -1) + desc.flag |= TILEI_FLAG_FLOOR; +} + +void TilesFramework::update_inventory() +{ + std::vector<InventoryTile> inv; + + if (!Options.tile_show_items) + return; + + unsigned int max_pack_row = (ENDOFPACK-1) / m_region_self_inv->mx + 1; + max_pack_row = std::min(m_region_self_inv->my - 1, max_pack_row); + unsigned int max_pack_items = max_pack_row * m_region_self_inv->mx; + + // TODO enne - document that '.' and '_' no longer work + + // TODO enne - if all inventory and ground can't fit, allow ground + // and inventory items on the same row. + + // item.base_type <-> char conversion table + const static char *obj_syms = ")([/%#?=!#+\\0}x"; + + for (unsigned int c = 0; c < strlen(Options.tile_show_items); c++) + { + if (inv.size() >= max_pack_items) + break; + + const char *find = strchr(obj_syms, Options.tile_show_items[c]); + if (!find) + continue; + object_class_type type = (object_class_type)(find - obj_syms); + + // First, normal inventory + for (int i = 0; i < ENDOFPACK; i++) + { + if (!is_valid_item(you.inv[i]) || you.inv[i].quantity == 0) + continue; + + if (you.inv[i].base_type != type) + continue; + + InventoryTile desc; + _fill_item_info(desc, you.inv[i]); + desc.idx = i; + + for (int eq = 0; eq < NUM_EQUIP; eq++) + { + if (you.equip[eq] == i) + { + desc.flag |= TILEI_FLAG_EQUIP; + break; + } + } + + inv.push_back(desc); + } + } + + // Finish out this row + while (inv.size() % m_region_self_inv->mx != 0) + { + InventoryTile desc; + inv.push_back(desc); + } + + // How many ground items do we have? + unsigned int num_ground = 0; + for (int i = igrd[you.x_pos][you.y_pos]; i != NON_ITEM; i = mitm[i].link) + num_ground++; + + // Add extra rows, if needed. + unsigned int ground_rows = + std::max(((int)num_ground-1) / (int)m_region_self_inv->mx + 1, 1); + + while (inv.size() / m_region_self_inv->mx + ground_rows < m_region_self_inv->my) + { + for (unsigned int i = 0; i < m_region_self_inv->mx; i++) + { + InventoryTile desc; + inv.push_back(desc); + } + } + + // Then, ground items... + for (unsigned int c = 0; c < strlen(Options.tile_show_items); c++) + { + if (inv.size() >= m_region_self_inv->mx * m_region_self_inv->my) + break; + + const char *find = strchr(obj_syms, Options.tile_show_items[c]); + if (!find) + continue; + object_class_type type = (object_class_type)(find - obj_syms); + + for (int i = igrd[you.x_pos][you.y_pos]; i != NON_ITEM; i = mitm[i].link) + { + if (inv.size() >= m_region_self_inv->mx * m_region_self_inv->my) + break; + + if (mitm[i].base_type != type) + continue; + + InventoryTile desc; + _fill_item_info(desc, mitm[i]); + desc.idx = i; + + inv.push_back(desc); + } + } + + // Finish out ground inventory + while (inv.size() < m_region_self_inv->mx * m_region_self_inv->my) + { + InventoryTile desc; + desc.flag = TILEI_FLAG_FLOOR; + inv.push_back(desc); + } + + 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); +} + +void TilesFramework::clear_text_tags(text_tag_type type) +{ + m_region_tile->clear_text_tags(type); +} + +void TilesFramework::add_text_tag(text_tag_type type, const std::string &tag, + const coord_def &gc) +{ + m_region_tile->add_text_tag(type, tag, gc); +} + +bool TilesFramework::initialise_items() +{ + return (m_image.load_item_texture()); +} + +const coord_def &TilesFramework::get_cursor() const +{ + return (m_region_tile->get_cursor()); +} |