Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added fractional zoom-out support to F4 tilemap viewer (warning, emu.h) #8510

Merged
merged 1 commit into from Aug 31, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions src/emu/inpttype.ipp
Expand Up @@ -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) ) \
Expand Down
1 change: 1 addition & 0 deletions src/emu/ioport.h
Expand Up @@ -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,
Expand Down
151 changes: 103 additions & 48 deletions src/frontend/mame/ui/viewgfx.cpp
Expand Up @@ -18,6 +18,7 @@
#include "tilemap.h"
#include "ui/viewgfx.h"

#include <cmath>


/***************************************************************************
Expand All @@ -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;



Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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]);

Expand All @@ -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));

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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]);

Expand All @@ -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));

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand Down