From d7e65e3f42611b3fdd299aff1304dc4b786a571b Mon Sep 17 00:00:00 2001 From: MooglyGuy Date: Tue, 31 Aug 2021 18:17:27 +0200 Subject: -viewgfx: Added fractional zoom-out support to the tilemap viewer. Also added IPT_UI_ZOOM_AUTO for toggling auto-zoom mode without needing to cycle through all zoom levels. [Ryan Holtz] (#8510) --- src/emu/inpttype.ipp | 1 + src/emu/ioport.h | 1 + src/frontend/mame/ui/viewgfx.cpp | 151 ++++++++++++++++++++++++++------------- 3 files changed, 105 insertions(+), 48 deletions(-) diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp index ff7b17f757b..172d206f48c 100644 --- a/src/emu/inpttype.ipp +++ b/src/emu/inpttype.ipp @@ -838,6 +838,7 @@ namespace { INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_CLEAR, "UI Clear", input_seq(KEYCODE_DEL) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_IN, "UI Zoom In", input_seq(KEYCODE_EQUALS) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_OUT, "UI Zoom Out", input_seq(KEYCODE_MINUS) ) \ + INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ZOOM_AUTO, "UI Toggle Auto Zoom", input_seq(KEYCODE_0) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_PREV_GROUP, "UI Previous Group", input_seq(KEYCODE_OPENBRACE) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_NEXT_GROUP, "UI Next Group", input_seq(KEYCODE_CLOSEBRACE) ) \ INPUT_PORT_DIGITAL_TYPE( 0, UI, UI_ROTATE, "UI Rotate", input_seq(KEYCODE_R) ) \ diff --git a/src/emu/ioport.h b/src/emu/ioport.h index fdf859b9afd..53e1e9ad5e8 100644 --- a/src/emu/ioport.h +++ b/src/emu/ioport.h @@ -357,6 +357,7 @@ enum ioport_type IPT_UI_CLEAR, IPT_UI_ZOOM_IN, IPT_UI_ZOOM_OUT, + IPT_UI_ZOOM_AUTO, IPT_UI_PREV_GROUP, IPT_UI_NEXT_GROUP, IPT_UI_ROTATE, diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp index 6816d56bb68..1da14866c57 100644 --- a/src/frontend/mame/ui/viewgfx.cpp +++ b/src/frontend/mame/ui/viewgfx.cpp @@ -18,6 +18,7 @@ #include "tilemap.h" #include "ui/viewgfx.h" +#include /*************************************************************************** @@ -31,7 +32,9 @@ enum ui_gfx_modes UI_GFX_TILEMAP }; -const uint8_t MAX_GFX_DECODERS = 8; +static const uint8_t MAX_GFX_DECODERS = 8; +static const int MAX_ZOOM_LEVEL = 8; +static const int MIN_ZOOM_LEVEL = 8; @@ -87,11 +90,13 @@ struct ui_gfx_state // tilemap-specific data struct { - int which; // which tilemap are we viewing? - int xoffs; // current X offset - int yoffs; // current Y offset - int zoom; // zoom factor - uint8_t rotate; // current rotation (orientation) value + int which; // which tilemap are we viewing? + int xoffs; // current X offset + int yoffs; // current Y offset + int zoom; // zoom factor, either x or 1/x + bool zoom_frac; // zoom via reciprocal fractions + bool auto_zoom; // auto-zoom toggle + uint8_t rotate; // current rotation (orientation) value uint32_t flags; // render flags } tilemap; }; @@ -184,7 +189,9 @@ void ui_gfx_init(running_machine &machine) state.tilemap.which = 0; state.tilemap.xoffs = 0; state.tilemap.yoffs = 0; - state.tilemap.zoom = 0; + state.tilemap.zoom = 1; + state.tilemap.zoom_frac = false; + state.tilemap.auto_zoom = true; state.tilemap.rotate = rotate; state.tilemap.flags = TILEMAP_DRAW_ALL_CATEGORIES; } @@ -473,7 +480,7 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u skip = int(chwidth / cellwidth); for (int x = 0; x < state.palette.columns; x += 1 + skip) { - x0 = boxbounds.x0 + 6.0f * chwidth + (float)x * cellwidth; + x0 = boxbounds.x0 + 6.0f * chwidth + float(x) * cellwidth; y0 = boxbounds.y0 + 2.0f * chheight; container.add_char(x0 + 0.5f * (cellwidth - chwidth), y0, chheight, aspect, rgb_t::white(), *ui_font, "0123456789ABCDEF"[x & 0xf]); @@ -495,7 +502,7 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u // if we're skipping, draw a point between the character and the box to indicate which // one it's referring to x0 = boxbounds.x0 + 5.5f * chwidth; - y0 = boxbounds.y0 + 3.5f * chheight + (float)y * cellheight; + y0 = boxbounds.y0 + 3.5f * chheight + float(y) * cellheight; if (skip != 0) container.add_point(0.5f * (x0 + cellboxbounds.x0), y0 + 0.5f * cellheight, UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); @@ -626,12 +633,12 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui float x0, y0; render_bounds cellboxbounds; render_bounds boxbounds; - int cellboxwidth, cellboxheight; + float cellboxwidth, cellboxheight; int targwidth = mui.machine().render().ui_target().width(); int targheight = mui.machine().render().ui_target().height(); int cellxpix, cellypix; int xcells; - int pixelscale = 0; + float pixelscale = 0.0f; int skip; // add a half character padding for the box @@ -675,24 +682,23 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui } info.columns[set] = xcells; - // worst case, we need a pixel scale of 1 - pixelscale = std::max(1, pixelscale); + if (pixelscale <= 0.0f) + pixelscale = 1.0f; // in the Y direction, we just display as many as we can - const int ycells = cellboxheight / (pixelscale * cellypix); + const int ycells = int(cellboxheight / (pixelscale * cellypix)); // now determine the actual cellbox size cellboxwidth = std::min(cellboxwidth, xcells * pixelscale * cellxpix); cellboxheight = std::min(cellboxheight, ycells * pixelscale * cellypix); - // compute the size of a single cell at this pixel scale factor, as well as the aspect ratio - const float cellwidth = (cellboxwidth / float(xcells)) / float(targwidth); - const float cellheight = (cellboxheight / float(ycells)) / float(targheight); - //cellaspect = cellwidth / cellheight; + // compute the size of a single cell at this pixel scale factor + const float cellwidth = (cellboxwidth / xcells) / targwidth; + const float cellheight = (cellboxheight / ycells) / targheight; // working from the new width/height, recompute the boxbounds - const float fullwidth = float(cellboxwidth) / float(targwidth) + 6.5f * chwidth; - const float fullheight = float(cellboxheight) / float(targheight) + 4.0f * chheight; + const float fullwidth = cellboxwidth / targwidth + 6.5f * chwidth; + const float fullheight = cellboxheight / targheight + 4.0f * chheight; // recompute boxbounds from this boxbounds.x0 = (1.0f - fullwidth) * 0.5f; @@ -702,9 +708,9 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui // recompute cellboxbounds cellboxbounds.x0 = boxbounds.x0 + 6.0f * chwidth; - cellboxbounds.x1 = cellboxbounds.x0 + float(cellboxwidth) / float(targwidth); + cellboxbounds.x1 = cellboxbounds.x0 + cellboxwidth / float(targwidth); cellboxbounds.y0 = boxbounds.y0 + 3.5f * chheight; - cellboxbounds.y1 = cellboxbounds.y0 + float(cellboxheight) / float(targheight); + cellboxbounds.y1 = cellboxbounds.y0 + cellboxheight / float(targheight); // figure out the title std::ostringstream title_buf; @@ -764,7 +770,7 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui skip = int(chwidth / cellwidth); for (int x = 0; x < xcells; x += 1 + skip) { - x0 = boxbounds.x0 + 6.0f * chwidth + (float)x * cellwidth; + x0 = boxbounds.x0 + 6.0f * chwidth + float(x) * cellwidth; y0 = boxbounds.y0 + 2.0f * chheight; container.add_char(x0 + 0.5f * (cellwidth - chwidth), y0, chheight, aspect, rgb_t::white(), *ui_font, "0123456789ABCDEF"[x & 0xf]); @@ -786,7 +792,7 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui // if we're skipping, draw a point between the character and the box to indicate which // one it's referring to x0 = boxbounds.x0 + 5.5f * chwidth; - y0 = boxbounds.y0 + 3.5f * chheight + (float)y * cellheight; + y0 = boxbounds.y0 + 3.5f * chheight + float(y) * cellheight; if (skip != 0) container.add_point(0.5f * (x0 + boxbounds.x0 + 6.0f * chwidth), y0 + 0.5f * cellheight, UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); @@ -1081,28 +1087,28 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u mapboxbounds.y0 += 1.5f * chheight; // convert back to pixels - mapboxwidth = (mapboxbounds.x1 - mapboxbounds.x0) * (float)targwidth; - mapboxheight = (mapboxbounds.y1 - mapboxbounds.y0) * (float)targheight; + mapboxwidth = (mapboxbounds.x1 - mapboxbounds.x0) * float(targwidth); + mapboxheight = (mapboxbounds.y1 - mapboxbounds.y0) * float(targheight); // determine the maximum integral scaling factor - int pixelscale = state.tilemap.zoom; - if (pixelscale == 0) + float pixelscale = state.tilemap.zoom_frac ? (1.0f / state.tilemap.zoom) : float(state.tilemap.zoom); + if (state.tilemap.auto_zoom) { - int maxxscale, maxyscale; + uint32_t maxxscale, maxyscale; for (maxxscale = 1; mapwidth * (maxxscale + 1) < mapboxwidth; maxxscale++) { } for (maxyscale = 1; mapheight * (maxyscale + 1) < mapboxheight; maxyscale++) { } - pixelscale = std::min(maxxscale, maxyscale); + pixelscale = float(std::min(maxxscale, maxyscale)); } // recompute the final box size - mapboxwidth = std::min(mapboxwidth, int(mapwidth * pixelscale)); - mapboxheight = std::min(mapboxheight, int(mapheight * pixelscale)); + mapboxwidth = std::min(mapboxwidth, int(std::round(mapwidth * pixelscale))); + mapboxheight = std::min(mapboxheight, int(std::round(mapheight * pixelscale))); // recompute the bounds, centered within the existing bounds - mapboxbounds.x0 += 0.5f * ((mapboxbounds.x1 - mapboxbounds.x0) - (float)mapboxwidth / (float)targwidth); - mapboxbounds.x1 = mapboxbounds.x0 + (float)mapboxwidth / (float)targwidth; - mapboxbounds.y0 += 0.5f * ((mapboxbounds.y1 - mapboxbounds.y0) - (float)mapboxheight / (float)targheight); - mapboxbounds.y1 = mapboxbounds.y0 + (float)mapboxheight / (float)targheight; + mapboxbounds.x0 += 0.5f * ((mapboxbounds.x1 - mapboxbounds.x0) - float(mapboxwidth) / targwidth); + mapboxbounds.x1 = mapboxbounds.x0 + float(mapboxwidth) / targwidth; + mapboxbounds.y0 += 0.5f * ((mapboxbounds.y1 - mapboxbounds.y0) - float(mapboxheight) / targheight); + mapboxbounds.y1 = mapboxbounds.y0 + float(mapboxheight) / targheight; // now recompute the outer box against this new info boxbounds.x0 = mapboxbounds.x0 - 0.5f * chwidth; @@ -1131,8 +1137,8 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u ypixel = (mapboxheight - 1) - ypixel; if (state.tilemap.rotate & ORIENTATION_SWAP_XY) std::swap(xpixel, ypixel); - uint32_t col = ((xpixel / pixelscale + state.tilemap.xoffs) / tilemap->tilewidth()) % tilemap->cols(); - uint32_t row = ((ypixel / pixelscale + state.tilemap.yoffs) / tilemap->tileheight()) % tilemap->rows(); + uint32_t col = ((int(std::round(xpixel / pixelscale)) + state.tilemap.xoffs) / tilemap->tilewidth()) % tilemap->cols(); + uint32_t row = ((int(std::round(ypixel / pixelscale)) + state.tilemap.yoffs) / tilemap->tileheight()) % tilemap->rows(); uint8_t gfxnum; uint32_t code, color; tilemap->get_info_debug(col, row, gfxnum, code, color); @@ -1168,7 +1174,7 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u } // update the bitmap - tilemap_update_bitmap(mui.machine(), state, mapboxwidth / pixelscale, mapboxheight / pixelscale); + tilemap_update_bitmap(mui.machine(), state, int(std::round(mapboxwidth / pixelscale)), int(std::round(mapboxheight / pixelscale))); // add the final quad container.add_quad(mapboxbounds.x0, mapboxbounds.y0, @@ -1199,21 +1205,70 @@ static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, i uint32_t mapwidth = tilemap->width(); uint32_t mapheight = tilemap->height(); + const bool at_max_zoom = !state.tilemap.auto_zoom && !state.tilemap.zoom_frac && state.tilemap.zoom == MAX_ZOOM_LEVEL; + const bool at_min_zoom = !state.tilemap.auto_zoom && state.tilemap.zoom_frac && state.tilemap.zoom == MIN_ZOOM_LEVEL; + // handle zoom (minus,plus) - if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && state.tilemap.zoom > 0) + if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && !at_min_zoom) { - state.tilemap.zoom--; - state.bitmap_dirty = true; - if (state.tilemap.zoom != 0) - machine.popmessage("Zoom = %d", state.tilemap.zoom); + state.tilemap.auto_zoom = false; + + if (state.tilemap.zoom_frac) + { + // remaining in fractional zoom range + state.tilemap.zoom++; + } + else if (state.tilemap.zoom == 1) + { + // entering fractional zoom range + state.tilemap.zoom++; + state.tilemap.zoom_frac = true; + } else - machine.popmessage("Zoom Auto"); + { + // remaining in integer zoom range + state.tilemap.zoom--; + } + + state.bitmap_dirty = true; + + machine.popmessage(state.tilemap.zoom_frac ? "Zoom = 1/%d" : "Zoom = %d", state.tilemap.zoom); } - if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && state.tilemap.zoom < 8) + + if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && !at_max_zoom) { - state.tilemap.zoom++; + state.tilemap.auto_zoom = false; + + if (!state.tilemap.zoom_frac) + { + // remaining in integer zoom range + state.tilemap.zoom++; + } + else if (state.tilemap.zoom == 2) + { + // entering integer zoom range + state.tilemap.zoom--; + state.tilemap.zoom_frac = false; + } + else + { + // remaining in fractional zoom range + state.tilemap.zoom--; + } + state.bitmap_dirty = true; - machine.popmessage("Zoom = %d", state.tilemap.zoom); + + machine.popmessage(state.tilemap.zoom_frac ? "Zoom = 1/%d" : "Zoom = %d", state.tilemap.zoom); + } + + if (machine.ui_input().pressed(IPT_UI_ZOOM_AUTO)) + { + state.tilemap.auto_zoom = !state.tilemap.auto_zoom; + + if (state.tilemap.auto_zoom) + machine.popmessage("Auto Zoom"); + else + machine.popmessage(state.tilemap.zoom_frac ? "Zoom = 1/%d" : "Zoom = %d", state.tilemap.zoom); } // handle rotation (R) -- cgit v1.2.3