#include "AppHdr.h" #ifdef USE_TILE_LOCAL #include "tilereg-map.h" #include "cio.h" #include "command.h" #include "food.h" #include "libutil.h" #include "misc.h" #include "options.h" #include "tilesdl.h" #include "travel.h" #include "viewgeom.h" MapRegion::MapRegion(int pixsz) : m_buf(NULL), m_dirty(true), m_far_view(false) { ASSERT(pixsz > 0); dx = pixsz; dy = pixsz; clear(); init_colours(); } void MapRegion::on_resize() { delete[] m_buf; int size = mx * my; m_buf = new unsigned char[size]; memset(m_buf, 0, sizeof(unsigned char) * size); } void MapRegion::init_colours() { // TODO enne - the options array for colours should be // tied to the map feature enumeration to avoid this function. m_colours[MF_UNSEEN] = Options.tile_unseen_col; m_colours[MF_FLOOR] = Options.tile_floor_col; m_colours[MF_WALL] = Options.tile_wall_col; m_colours[MF_MAP_FLOOR] = Options.tile_mapped_floor_col; m_colours[MF_MAP_WALL] = Options.tile_mapped_wall_col; m_colours[MF_DOOR] = Options.tile_door_col; m_colours[MF_ITEM] = Options.tile_item_col; m_colours[MF_MONS_FRIENDLY] = Options.tile_friendly_col; m_colours[MF_MONS_PEACEFUL] = Options.tile_peaceful_col; m_colours[MF_MONS_NEUTRAL] = Options.tile_neutral_col; m_colours[MF_MONS_HOSTILE] = Options.tile_monster_col; m_colours[MF_MONS_NO_EXP] = Options.tile_plant_col; m_colours[MF_STAIR_UP] = Options.tile_upstairs_col; m_colours[MF_STAIR_DOWN] = Options.tile_downstairs_col; m_colours[MF_STAIR_BRANCH] = Options.tile_branchstairs_col; m_colours[MF_PORTAL] = Options.tile_portal_col; m_colours[MF_FEATURE] = Options.tile_feature_col; m_colours[MF_WATER] = Options.tile_water_col; m_colours[MF_DEEP_WATER] = Options.tile_deep_water_col; m_colours[MF_LAVA] = Options.tile_lava_col; m_colours[MF_TRAP] = Options.tile_trap_col; m_colours[MF_EXCL_ROOT] = Options.tile_excl_centre_col; m_colours[MF_EXCL] = Options.tile_excluded_col; m_colours[MF_PLAYER] = Options.tile_player_col; } MapRegion::~MapRegion() { delete[] m_buf; } void MapRegion::pack_buffers() { m_buf_map.clear(); m_buf_lines.clear(); for (int x = m_min_gx; x <= m_max_gx; x++) for (int y = m_min_gy; y <= m_max_gy; y++) { map_feature f = (map_feature)m_buf[x + y * mx]; float pos_x = x - m_min_gx; float pos_y = y - m_min_gy; m_buf_map.add(pos_x, pos_y, pos_x + 1, pos_y + 1, m_colours[f]); } // Draw window box. if (m_win_start.x == -1 && m_win_end.x == -1) return; float pos_sx = (m_win_start.x - m_min_gx); float pos_sy = (m_win_start.y - m_min_gy); float pos_ex = (m_win_end.x - m_min_gx) - 1 / (float)dx; float pos_ey = (m_win_end.y - m_min_gy) - 1 / (float)dy; m_buf_lines.add_square(pos_sx, pos_sy, pos_ex, pos_ey, Options.tile_window_col); } void MapRegion::render() { if (m_min_gx > m_max_gx || m_min_gy > m_max_gy) return; #ifdef DEBUG_TILES_REDRAW cprintf("rendering MapRegion\n"); #endif if (m_dirty) { pack_buffers(); m_dirty = false; } set_transform(); m_buf_map.draw(); m_buf_lines.draw(); } void MapRegion::recenter() { // adjust offsets to center map. ox = (wx - dx * (m_max_gx - m_min_gx)) / 2; oy = (wy - dy * (m_max_gy - m_min_gy)) / 2; } void MapRegion::set(const coord_def &gc, map_feature f) { ASSERT((unsigned int)f <= (unsigned char)~0); m_buf[gc.x + gc.y * mx] = f; if (f == MF_UNSEEN) return; // Get map extents m_min_gx = min(m_min_gx, gc.x); m_max_gx = max(m_max_gx, gc.x); m_min_gy = min(m_min_gy, gc.y); m_max_gy = max(m_max_gy, gc.y); recenter(); } void MapRegion::update_bounds() { int min_gx = m_min_gx; int max_gx = m_max_gx; int min_gy = m_min_gy; int max_gy = m_max_gy; m_min_gx = GXM; m_max_gx = 0; m_min_gy = GYM; m_max_gy = 0; for (int x = min_gx; x <= max_gx; x++) for (int y = min_gy; y <= max_gy; y++) { map_feature f = (map_feature)m_buf[x + y * mx]; if (f == MF_UNSEEN) continue; m_min_gx = min(m_min_gx, x); m_max_gx = max(m_max_gx, x); m_min_gy = min(m_min_gy, y); m_max_gy = max(m_max_gy, y); } recenter(); #if 0 // Not needed? (jpeg) m_dirty = true; #endif } void MapRegion::set_window(const coord_def &start, const coord_def &end) { m_win_start = start; m_win_end = end; m_dirty = true; } void MapRegion::clear() { m_min_gx = GXM; m_max_gx = 0; m_min_gy = GYM; m_max_gy = 0; m_win_start.x = -1; m_win_start.y = -1; m_win_end.x = -1; m_win_end.y = -1; recenter(); if (m_buf) memset(m_buf, 0, sizeof(*m_buf) * mx * my); m_buf_map.clear(); m_buf_lines.clear(); } int MapRegion::handle_mouse(MouseEvent &event) { if (mouse_control::current_mode() != MOUSE_MODE_COMMAND && !tiles.get_map_display()) { return 0; } if (!inside(event.px, event.py)) { if (m_far_view) { m_far_view = false; tiles.load_dungeon(crawl_view.vgrdc); return 0; } return 0; } int cx, cy; mouse_pos(event.px, event.py, cx, cy); const coord_def gc(m_min_gx + cx, m_min_gy + cy); tiles.place_cursor(CURSOR_MOUSE, gc); switch (event.event) { case MouseEvent::MOVE: if (m_far_view) tiles.load_dungeon(gc); return 0; case MouseEvent::PRESS: #ifdef TOUCH_UI // ctrl-rolley-wheel on the minimap (this ensures busting out of minimap when zooming in again on very small layouts) if ( (event.mod & MOD_CTRL) && (event.button == MouseEvent::SCROLL_UP || event.button == MouseEvent::SCROLL_DOWN)) { tiles.zoom_dungeon(event.button == MouseEvent::SCROLL_UP); return CK_NO_KEY; // prevents this being handled by the dungeon underneath too(!) } if (event.button == MouseEvent::LEFT) { m_far_view = true; tiles.load_dungeon(gc); if (!tiles.get_map_display()) { process_command(CMD_DISPLAY_MAP); m_far_view = false; return CK_MOUSE_CMD; } } return 0; case MouseEvent::RELEASE: if (event.button == MouseEvent::LEFT && m_far_view) m_far_view = false; return 0; #else if (event.button == MouseEvent::LEFT) { if (event.mod & MOD_SHIFT) { // Start autotravel, or give an appropriate message. do_explore_cmd(); return CK_MOUSE_CMD; } else { const int cmd = click_travel(gc, event.mod & MOD_CTRL); if (cmd != CK_MOUSE_CMD) process_command((command_type) cmd); return CK_MOUSE_CMD; } } else if (event.button == MouseEvent::RIGHT) { m_far_view = true; tiles.load_dungeon(gc); if (!tiles.get_map_display()) { process_command(CMD_DISPLAY_MAP); m_far_view = false; return CK_MOUSE_CMD; } } return 0; case MouseEvent::RELEASE: if (event.button == MouseEvent::RIGHT && m_far_view) m_far_view = false; return 0; #endif default: return 0; } } bool MapRegion::update_tip_text(string& tip) { if (mouse_control::current_mode() != MOUSE_MODE_COMMAND) return false; #ifdef TOUCH_UI tip = "[L-Click] Enable map mode"; #else tip = "[L-Click] Travel / [R-Click] View"; if (!player_in_branch(BRANCH_LABYRINTH) && (you.hunger_state > HS_STARVING || you_min_hunger()) && i_feel_safe()) { tip += "\n[Shift + L-Click] Autoexplore"; } #endif return true; } #endif