summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/viewgfx.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/viewgfx.cpp')
-rw-r--r--src/frontend/mame/ui/viewgfx.cpp2211
1 files changed, 1238 insertions, 973 deletions
diff --git a/src/frontend/mame/ui/viewgfx.cpp b/src/frontend/mame/ui/viewgfx.cpp
index bc6dee9cd47..cbb104d5460 100644
--- a/src/frontend/mame/ui/viewgfx.cpp
+++ b/src/frontend/mame/ui/viewgfx.cpp
@@ -9,408 +9,1003 @@
*********************************************************************/
#include "emu.h"
+#include "ui/viewgfx.h"
+
#include "emupal.h"
-#include "ui/ui.h"
-#include "uiinput.h"
#include "render.h"
#include "rendfont.h"
#include "rendutil.h"
+#include "screen.h"
#include "tilemap.h"
-#include "ui/viewgfx.h"
+#include "uiinput.h"
+#include "util/unicode.h"
+#include "osdepend.h"
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
+#include <cmath>
+#include <vector>
+
+
+namespace {
-enum ui_gfx_modes
+class gfx_viewer
{
- UI_GFX_PALETTE = 0,
- UI_GFX_GFXSET,
- UI_GFX_TILEMAP
-};
+public:
+ gfx_viewer(running_machine &machine) :
+ m_machine(machine),
+ m_palette(machine),
+ m_gfxset(machine),
+ m_tilemap(machine)
+ {
+ }
-const uint8_t MAX_GFX_DECODERS = 8;
+ // copy constructor needed to make std::any happy
+ gfx_viewer(gfx_viewer const &that) :
+ gfx_viewer(that.m_machine)
+ {
+ }
+ ~gfx_viewer()
+ {
+ if (m_texture)
+ m_machine.render().texture_free(m_texture);
+ }
+ uint32_t handle(mame_ui_manager &mui, render_container &container, bool uistate)
+ {
+ // implicitly cancel if there's nothing to display
+ if (!is_relevant())
+ return cancel(uistate);
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
+ // let the OSD do its thing
+ mui.machine().osd().check_osd_inputs();
-// information about a single gfx device
-struct ui_gfx_info
-{
- device_gfx_interface *interface; // pointer to device's gfx interface
- uint8_t setcount; // how many gfx sets device has
- uint8_t rotate[MAX_GFX_ELEMENTS]; // current rotation (orientation) value
- uint8_t columns[MAX_GFX_ELEMENTS]; // number of items per row
- int offset[MAX_GFX_ELEMENTS]; // current offset of top,left item
- int color[MAX_GFX_ELEMENTS]; // current color selected
- device_palette_interface *palette[MAX_GFX_ELEMENTS]; // associated palette (maybe multiple choice one day?)
- int color_count[MAX_GFX_ELEMENTS]; // Range of color values
-};
+ // always mark the bitmap dirty if not paused
+ if (!m_machine.paused())
+ m_bitmap_dirty = true;
-struct ui_gfx_state
-{
- bool started; // have we called ui_gfx_count_devices() yet?
- uint8_t mode; // which mode are we in?
+ // handle pointer events to show hover info
+ ui_event event;
+ while (m_machine.ui_input().pop_event(&event))
+ {
+ switch (event.event_type)
+ {
+ case ui_event::type::POINTER_UPDATE:
+ {
+ // ignore pointer input in windows other than the one that displays the UI
+ render_target &target(m_machine.render().ui_target());
+ if (&target != event.target)
+ break;
+
+ // don't change if the current pointer has buttons pressed and this one doesn't
+ if (event.pointer_id == m_current_pointer)
+ {
+ assert(m_pointer_type == event.pointer_type);
+ m_pointer_buttons = event.pointer_buttons;
+ m_pointer_inside = target.map_point_container(
+ event.pointer_x,
+ event.pointer_y,
+ container,
+ m_pointer_x,
+ m_pointer_y);
+ }
+ else if ((0 > m_current_pointer) || (!m_pointer_buttons && (!m_pointer_inside || event.pointer_buttons)))
+ {
+ float x, y;
+ bool const inside(target.map_point_container(event.pointer_x, event.pointer_y, container, x, y));
+ if ((0 > m_current_pointer) || event.pointer_buttons || (!m_pointer_inside && inside))
+ {
+ m_current_pointer = event.pointer_id;
+ m_pointer_type = event.pointer_type;
+ m_pointer_buttons = event.pointer_buttons;
+ m_pointer_x = x;
+ m_pointer_y = y;
+ m_pointer_inside = inside;
+ }
+ }
+ }
+ break;
+
+ case ui_event::type::POINTER_LEAVE:
+ case ui_event::type::POINTER_ABORT:
+ {
+ // if this was our pointer, we've lost it
+ render_target &target(m_machine.render().ui_target());
+ if ((&target == event.target) && (event.pointer_id == m_current_pointer))
+ {
+ // keep the pointer position and type so we can show touch locations after release
+ m_current_pointer = -1;
+ m_pointer_buttons = 0U;
+ m_pointer_inside = target.map_point_container(
+ event.pointer_x,
+ event.pointer_y,
+ container,
+ m_pointer_x,
+ m_pointer_y);
+ }
+ }
+ break;
+
+ // ignore anything that isn't pointer-related
+ default:
+ break;
+ }
+ }
+
+ // always draw non-touch pointer
+ mame_ui_manager::display_pointer pointers[1]{ { m_machine.render().ui_target(), m_pointer_type, m_pointer_x, m_pointer_y } };
+ if (m_pointer_inside && (0 <= m_current_pointer) && (ui_event::pointer::TOUCH != m_pointer_type))
+ mui.set_pointers(std::begin(pointers), std::end(pointers));
+ else
+ mui.set_pointers(std::begin(pointers), std::begin(pointers));
+
+ // try to display the selected view
+ while (true)
+ {
+ switch (m_mode)
+ {
+ case view::PALETTE:
+ if (m_palette.interface())
+ return handle_palette(mui, container, uistate);
+ m_mode = view::GFXSET;
+ break;
+
+ case view::GFXSET:
+ if (m_gfxset.has_gfx())
+ return handle_gfxset(mui, container, uistate);
+ m_mode = view::TILEMAP;
+ break;
- // intermediate bitmaps
- bool bitmap_dirty; // is the bitmap dirty?
- bitmap_rgb32 bitmap; // bitmap for drawing gfx and tilemaps
- render_texture *texture; // texture for rendering the above bitmap
+ case view::TILEMAP:
+ if (m_machine.tilemap().count())
+ return handle_tilemap(mui, container, uistate);
+ m_mode = view::PALETTE;
+ break;
+ }
+ }
+ }
- // palette-specific data
- struct
+private:
+ enum class view
{
- device_palette_interface *interface; // pointer to current palette
- int devcount; // how many palette devices exist
- int devindex; // which palette device is visible
- uint8_t which; // which subset (pens or indirect colors)?
- uint8_t columns; // number of items per row
- int offset; // current offset of top left item
- } palette;
-
- // graphics-specific data
- struct
+ PALETTE = 0,
+ GFXSET,
+ TILEMAP
+ };
+
+ class palette
{
- uint8_t devcount; // how many gfx devices exist
- uint8_t devindex; // which device is visible
- uint8_t set; // which set is visible
- } gfxset;
+ public:
+ enum class subset
+ {
+ PENS,
+ INDIRECT
+ };
+
+ palette(running_machine &machine) :
+ m_count(palette_interface_enumerator(machine.root_device()).count())
+ {
+ if (m_count)
+ set_device(machine);
+ }
+
+ device_palette_interface *interface() const noexcept
+ {
+ return m_interface;
+ }
+
+ bool indirect() const noexcept
+ {
+ return subset::INDIRECT == m_which;
+ }
+
+ unsigned columns() const noexcept
+ {
+ return m_columns;
+ }
+
+ unsigned index(unsigned x, unsigned y) const noexcept
+ {
+ return m_offset + (y * m_columns) + x;
+ }
+
+ void handle_keys(running_machine &machine);
+
+ private:
+ void set_device(running_machine &machine)
+ {
+ m_interface = palette_interface_enumerator(machine.root_device()).byindex(m_index);
+ }
- // information about each gfx device
- ui_gfx_info gfxdev[MAX_GFX_DECODERS];
+ void next_group(running_machine &machine) noexcept
+ {
+ if ((subset::PENS == m_which) && m_interface->indirect_entries())
+ {
+ m_which = subset::INDIRECT;
+ }
+ else if ((m_count - 1) > m_index)
+ {
+ ++m_index;
+ set_device(machine);
+ m_which = subset::PENS;
+ }
+ }
- // tilemap-specific data
- struct
+ void prev_group(running_machine &machine) noexcept
+ {
+ if (subset::INDIRECT == m_which)
+ {
+ m_which = subset::PENS;
+ }
+ else if (0 < m_index)
+ {
+ --m_index;
+ set_device(machine);
+ m_which = m_interface->indirect_entries() ? subset::INDIRECT : subset::PENS;
+ }
+ }
+
+ device_palette_interface *m_interface = nullptr;
+ unsigned const m_count;
+ unsigned m_index = 0U;
+ subset m_which = subset::PENS;
+ unsigned m_columns = 16U;
+ int m_offset = 0;
+ };
+
+ class gfxset
{
- 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
- uint32_t flags; // render flags
- } tilemap;
-};
+ public:
+ struct setinfo
+ {
+ void next_color() noexcept
+ {
+ if ((m_color_count - 1) > m_color)
+ ++m_color;
+ else
+ m_color = 0U;
+ }
+ void prev_color() noexcept
+ {
+ if (m_color)
+ --m_color;
+ else
+ m_color = m_color_count - 1;
+ }
+ device_palette_interface *m_palette = nullptr;
+ int m_offset = 0;
+ unsigned m_color = 0;
+ unsigned m_color_count = 0U;
+ uint8_t m_rotate = 0U;
+ uint8_t m_columns = 16U;
+ bool m_integer_scale = false;
+ };
-/***************************************************************************
- GLOBAL VARIABLES
-***************************************************************************/
+ class devinfo
+ {
+ public:
+ devinfo(device_gfx_interface &interface, device_palette_interface *first_palette, u8 rotate) :
+ m_interface(&interface),
+ m_setcount(0U)
+ {
+ for (gfx_element *gfx; (MAX_GFX_ELEMENTS > m_setcount) && ((gfx = interface.gfx(m_setcount)) != nullptr); ++m_setcount)
+ {
+ auto &set = m_sets[m_setcount];
+ if (gfx->has_palette())
+ {
+ set.m_palette = &gfx->palette();
+ set.m_color_count = gfx->colors();
+ }
+ else
+ {
+ set.m_palette = first_palette;
+ set.m_color_count = first_palette->entries() / gfx->granularity();
+ if (!set.m_color_count)
+ set.m_color_count = 1U;
+ }
+ set.m_rotate = rotate;
+ }
+ }
-static ui_gfx_state ui_gfx;
+ device_gfx_interface &interface() const noexcept
+ {
+ return *m_interface;
+ }
+ unsigned setcount() const noexcept
+ {
+ return m_setcount;
+ }
+ setinfo const &set(unsigned index) const noexcept
+ {
+ return m_sets[index];
+ }
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
+ setinfo &set(unsigned index) noexcept
+ {
+ return m_sets[index];
+ }
-static void ui_gfx_count_devices(running_machine &machine, ui_gfx_state &state);
-static void ui_gfx_exit(running_machine &machine);
+ private:
+ device_gfx_interface *m_interface;
+ unsigned m_setcount;
+ setinfo m_sets[MAX_GFX_ELEMENTS];
+ };
-// palette handling
-static void palette_set_device(running_machine &machine, ui_gfx_state &state);
-static void palette_handle_keys(running_machine &machine, ui_gfx_state &state);
-static void palette_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state);
+ gfxset(running_machine &machine)
+ {
+ // get useful defaults
+ uint8_t const rotate = machine.system().flags & machine_flags::MASK_ORIENTATION;
+ device_palette_interface *const first_palette = palette_interface_enumerator(machine.root_device()).first();
-// graphics set handling
-static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, int xcells, int ycells);
-static void gfxset_draw_item(running_machine &machine, gfx_element &gfx, int index, bitmap_rgb32 &bitmap, int dstx, int dsty, int color, int rotate, device_palette_interface *dpalette);
-static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, int xcells, int ycells, gfx_element &gfx);
-static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state);
+ // iterate over graphics decoders
+ for (device_gfx_interface &interface : gfx_interface_enumerator(machine.root_device()))
+ {
+ // if there are any exposed graphics sets, add the device
+ if (interface.gfx(0U))
+ m_devices.emplace_back(interface, first_palette, rotate);
+ }
+ }
-// tilemap handling
-static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, int viswidth, int visheight);
-static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, int width, int height);
-static void tilemap_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state);
+ bool has_gfx() const noexcept
+ {
+ return !m_devices.empty();
+ }
+ bool handle_keys(running_machine &machine, int xcells, int ycells);
+ std::vector<devinfo> m_devices;
+ unsigned m_device = 0U;
+ unsigned m_set = 0U;
-/***************************************************************************
- CORE IMPLEMENTATION
-***************************************************************************/
+ private:
+ bool next_group() noexcept
+ {
+ if ((m_devices[m_device].setcount() - 1) > m_set)
+ {
+ ++m_set;
+ return true;
+ }
+ else if ((m_devices.size() - 1) > m_device)
+ {
+ ++m_device;
+ m_set = 0U;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
-//-------------------------------------------------
-// ui_gfx_init - initialize the graphics viewer
-//-------------------------------------------------
+ bool prev_group() noexcept
+ {
+ if (m_set)
+ {
+ --m_set;
+ return true;
+ }
+ else if (m_device)
+ {
+ --m_device;
+ m_set = m_devices[m_device].setcount() - 1;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ };
-void ui_gfx_init(running_machine &machine)
-{
- ui_gfx_state &state = ui_gfx;
- uint8_t rotate = machine.system().flags & machine_flags::MASK_ORIENTATION;
-
- // make sure we clean up after ourselves
- machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&ui_gfx_exit, &machine));
-
- // initialize our global state
- state.started = false;
- state.mode = 0;
- state.bitmap_dirty = false;
- state.bitmap.reset();
- state.texture = nullptr;
- state.gfxset.devcount = 0;
- state.gfxset.devindex = 0;
- state.gfxset.set = 0;
-
- // set up the palette state
- state.palette.interface = nullptr;
- state.palette.devcount = 0;
- state.palette.devindex = 0;
- state.palette.which = 0;
- state.palette.columns = 16;
-
- // set up the graphics state
- for (uint8_t i = 0; i < MAX_GFX_DECODERS; i++)
+ class tilemap
{
- state.gfxdev[i].interface = nullptr;
- state.gfxdev[i].setcount = 0;
- for (uint8_t j = 0; j < MAX_GFX_ELEMENTS; j++)
+ public:
+ tilemap(running_machine &machine)
{
- state.gfxdev[i].rotate[j] = rotate;
- state.gfxdev[i].columns[j] = 16;
- state.gfxdev[i].offset[j] = 0;
- state.gfxdev[i].color[j] = 0;
- state.gfxdev[i].palette[j] = nullptr;
- state.gfxdev[i].color_count[j] = 0;
+ uint8_t const rotate = machine.system().flags & machine_flags::MASK_ORIENTATION;
+ m_info.resize(machine.tilemap().count());
+ for (auto &info : m_info)
+ info.m_rotate = rotate;
}
- }
- // set up the tilemap state
- state.tilemap.which = 0;
- state.tilemap.xoffs = 0;
- state.tilemap.yoffs = 0;
- state.tilemap.zoom = 0;
- state.tilemap.rotate = rotate;
- state.tilemap.flags = TILEMAP_DRAW_ALL_CATEGORIES;
-}
+ unsigned index() const noexcept
+ {
+ return m_index;
+ }
+ float zoom_scale() const noexcept
+ {
+ auto const &info = m_info[m_index];
+ return info.m_zoom_frac ? (1.0f / float(info.m_zoom)) : float(info.m_zoom);
+ }
-//-------------------------------------------------
-// ui_gfx_count_devices - count the palettes,
-// gfx decoders and gfx sets in the machine
-//-------------------------------------------------
+ bool auto_zoom() const noexcept
+ {
+ return m_info[m_index].m_auto_zoom;
+ }
-static void ui_gfx_count_devices(running_machine &machine, ui_gfx_state &state)
-{
- // count the palette devices
- state.palette.devcount = palette_interface_iterator(machine.root_device()).count();
+ uint8_t rotate() const noexcept
+ {
+ return m_info[m_index].m_rotate;
+ }
+
+ uint32_t flags() const noexcept
+ {
+ return m_info[m_index].m_flags;
+ }
- // set the pointer to the first palette
- if (state.palette.devcount > 0)
- palette_set_device(machine, state);
+ int xoffs() const noexcept
+ {
+ return m_info[m_index].m_xoffs;
+ }
- // count the gfx devices
- state.gfxset.devcount = 0;
- for (device_gfx_interface &interface : gfx_interface_iterator(machine.root_device()))
- {
- // count the gfx sets in each device, skipping devices with none
- uint8_t count = 0;
- while (count < MAX_GFX_ELEMENTS && interface.gfx(count) != nullptr)
- count++;
+ int yoffs() const noexcept
+ {
+ return m_info[m_index].m_yoffs;
+ }
+
+ bool handle_keys(running_machine &machine, float pixelscale);
+
+ private:
+ static constexpr int MAX_ZOOM_LEVEL = 8; // maximum tilemap zoom ratio screen:native
+ static constexpr int MIN_ZOOM_LEVEL = 8; // minimum tilemap zoom ratio native:screen
- // count = index of first nullptr
- if (count > 0)
+ struct info
{
- state.gfxdev[state.gfxset.devcount].interface = &interface;
- state.gfxdev[state.gfxset.devcount].setcount = count;
- for (uint8_t slot = 0; slot != count; slot++) {
- auto gfx = interface.gfx(slot);
- if (gfx->has_palette())
+ bool zoom_in(float pixelscale) noexcept
+ {
+ if (m_auto_zoom)
+ {
+ // auto zoom never uses fractional factors
+ m_zoom = std::min<int>(std::lround(pixelscale) + 1, MAX_ZOOM_LEVEL);
+ m_zoom_frac = false;
+ m_auto_zoom = false;
+ return true;
+ }
+ else if (m_zoom_frac)
+ {
+ m_zoom--;
+ if (m_zoom == 1)
+ m_zoom_frac = false; // entering integer zoom range
+ return true;
+ }
+ else if (MAX_ZOOM_LEVEL > m_zoom)
{
- state.gfxdev[state.gfxset.devcount].palette[slot] = &gfx->palette();
- state.gfxdev[state.gfxset.devcount].color_count[slot] = gfx->colors();
+ m_zoom++; // remaining in integer zoom range
+ return true;
}
else
{
- state.gfxdev[state.gfxset.devcount].palette[slot] = state.palette.interface;
- state.gfxdev[state.gfxset.devcount].color_count[slot] = state.palette.interface->entries() / gfx->granularity();
- if (!state.gfxdev[state.gfxset.devcount].color_count[slot])
- state.gfxdev[state.gfxset.devcount].color_count[slot] = 1;
+ return false;
}
}
- if (++state.gfxset.devcount == MAX_GFX_DECODERS)
- break;
+
+ bool zoom_out(float pixelscale) noexcept
+ {
+ if (m_auto_zoom)
+ {
+ // auto zoom never uses fractional factors
+ m_zoom = std::lround(pixelscale) - 1;
+ m_zoom_frac = !m_zoom;
+ if (m_zoom_frac)
+ m_zoom = 2;
+ m_auto_zoom = false;
+ return true;
+ }
+ else if (!m_zoom_frac)
+ {
+ if (m_zoom == 1)
+ {
+ m_zoom++;
+ m_zoom_frac = true; // entering fractional zoom range
+ }
+ else
+ {
+ m_zoom--; // remaining in integer zoom range
+ }
+ return true;
+ }
+ else if (MIN_ZOOM_LEVEL > m_zoom)
+ {
+ m_zoom++; // remaining in fractional zoom range
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool next_category() noexcept
+ {
+ if (TILEMAP_DRAW_ALL_CATEGORIES == m_flags)
+ {
+ m_flags = 0U;
+ return true;
+ }
+ else if (TILEMAP_DRAW_CATEGORY_MASK > m_flags)
+ {
+ ++m_flags;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool prev_catagory() noexcept
+ {
+ if (!m_flags)
+ {
+ m_flags = TILEMAP_DRAW_ALL_CATEGORIES;
+ return true;
+ }
+ else if (TILEMAP_DRAW_ALL_CATEGORIES != m_flags)
+ {
+ --m_flags;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ int m_xoffs = 0;
+ int m_yoffs = 0;
+ unsigned m_zoom = 1U;
+ bool m_zoom_frac = false;
+ bool m_auto_zoom = true;
+ uint8_t m_rotate = 0U;
+ uint32_t m_flags = TILEMAP_DRAW_ALL_CATEGORIES;
+ };
+
+ static int scroll_step(running_machine &machine)
+ {
+ auto &input = machine.input();
+ if (input.code_pressed(KEYCODE_LCONTROL) || input.code_pressed(KEYCODE_RCONTROL))
+ return 64;
+ else if (input.code_pressed(KEYCODE_LSHIFT) || input.code_pressed(KEYCODE_RSHIFT))
+ return 1;
+ else
+ return 8;
}
+
+ std::vector<info> m_info;
+ unsigned m_index = 0U;
+ };
+
+ bool is_relevant() const noexcept
+ {
+ return m_palette.interface() || m_gfxset.has_gfx() || m_machine.tilemap().count();
}
- state.started = true;
-}
+ uint32_t handle_general_keys(bool uistate)
+ {
+ auto &input = m_machine.ui_input();
+
+ // UI select cycles through views
+ if (input.pressed(IPT_UI_SELECT))
+ {
+ m_mode = view((int(m_mode) + 1) % 3);
+ if (0 > m_current_pointer)
+ {
+ m_pointer_type = ui_event::pointer::UNKNOWN;
+ m_pointer_x = -1.0F;
+ m_pointer_x = -1.0F;
+ m_pointer_inside = false;
+ }
+ m_bitmap_dirty = true;
+ }
+ // pause does what you'd expect
+ if (input.pressed(IPT_UI_PAUSE))
+ {
+ if (m_machine.paused())
+ m_machine.resume();
+ else
+ m_machine.pause();
+ }
-//-------------------------------------------------
-// ui_gfx_exit - clean up after ourselves
-//-------------------------------------------------
+ // cancel or graphics viewer dismisses the viewer
+ if (input.pressed(IPT_UI_BACK) || input.pressed(IPT_UI_SHOW_GFX))
+ return cancel(uistate);
-static void ui_gfx_exit(running_machine &machine)
-{
- // free the texture
- machine.render().texture_free(ui_gfx.texture);
- ui_gfx.texture = nullptr;
+ return uistate;
+ }
- // free the bitmap
- ui_gfx.bitmap.reset();
-}
+ uint32_t cancel(bool uistate)
+ {
+ if (!uistate)
+ m_machine.resume();
+ m_machine.ui_input().reset();
+ m_current_pointer = -1;
+ m_pointer_type = ui_event::pointer::UNKNOWN;
+ m_pointer_buttons = 0U;
+ m_pointer_x = -1.0F;
+ m_pointer_y = -1.0F;
+ m_pointer_inside = false;
+ m_bitmap_dirty = true;
+ return mame_ui_manager::HANDLER_CANCEL;
+ }
+ uint32_t handle_palette(mame_ui_manager &mui, render_container &container, bool uistate);
+ uint32_t handle_gfxset(mame_ui_manager &mui, render_container &container, bool uistate);
+ uint32_t handle_tilemap(mame_ui_manager &mui, render_container &container, bool uistate);
-//-------------------------------------------------
-// ui_gfx_is_relevant - returns 'true' if the
-// internal graphics viewer has relevance
-//
-// NOTE: this must not be called before machine
-// initialization is complete, as some drivers
-// create or modify gfx sets in VIDEO_START
-//-------------------------------------------------
+ void update_gfxset_bitmap(int xcells, int ycells, gfx_element &gfx);
+ void update_tilemap_bitmap(int width, int height);
-bool ui_gfx_is_relevant(running_machine &machine)
-{
- ui_gfx_state &state = ui_gfx;
+ void gfxset_draw_item(gfx_element &gfx, int index, int dstx, int dsty, gfxset::setinfo const &info);
- if (!state.started)
- ui_gfx_count_devices(machine, state);
+ void draw_text(mame_ui_manager &mui, render_container &container, std::string_view str, float x, float y)
+ {
+ render_font *const font = mui.get_font();
+ float const height = mui.get_line_height();
+ float const aspect = m_machine.render().ui_aspect(&container);
+ rgb_t const color = mui.colors().text_color();
+
+ int n;
+ char32_t ch;
+ while ((n = uchar_from_utf8(&ch, str)) != 0)
+ {
+ if (0 > n)
+ ch = 0xfffd;
+ str.remove_prefix((0 > n) ? 1 : n);
+ container.add_char(x, y, height, aspect, color, *font, ch);
+ x += font->char_width(height, aspect, ch);
+ }
+ }
- return state.palette.devcount > 0
- || state.gfxset.devcount > 0
- || machine.tilemap().count() > 0;
-}
+ void resize_bitmap(int32_t width, int32_t height)
+ {
+ if (!m_bitmap.valid() || !m_texture || (m_bitmap.width() != width) || (m_bitmap.height() != height))
+ {
+ // free the old stuff
+ if (m_texture)
+ m_machine.render().texture_free(m_texture);
+ // allocate new stuff
+ m_bitmap.resize(width, height);
+ m_texture = m_machine.render().texture_alloc();
+ m_texture->set_bitmap(m_bitmap, m_bitmap.cliprect(), TEXFORMAT_ARGB32);
-//-------------------------------------------------
-// ui_gfx_ui_handler - primary UI handler
-//-------------------------------------------------
+ // force a redraw
+ m_bitmap_dirty = true;
+ }
+ }
-uint32_t ui_gfx_ui_handler(render_container &container, mame_ui_manager &mui, bool uistate)
+ bool map_mouse(render_container &container, render_bounds const &clip, float &x, float &y) const
+ {
+ if (((0 > m_current_pointer) && (m_pointer_type != ui_event::pointer::TOUCH)) || !m_pointer_inside)
+ return false;
+
+ x = m_pointer_x;
+ y = m_pointer_y;
+ return clip.includes(x, y);
+ }
+
+ running_machine &m_machine;
+ view m_mode = view::PALETTE;
+
+ s32 m_current_pointer = -1;
+ ui_event::pointer m_pointer_type = ui_event::pointer::UNKNOWN;
+ u32 m_pointer_buttons = 0U;
+ float m_pointer_x = -1.0F;
+ float m_pointer_y = -1.0F;
+ bool m_pointer_inside = false;
+
+ bitmap_rgb32 m_bitmap;
+ render_texture *m_texture = nullptr;
+ bool m_bitmap_dirty = false;
+
+ palette m_palette;
+ gfxset m_gfxset;
+ tilemap m_tilemap;
+};
+
+
+void gfx_viewer::palette::handle_keys(running_machine &machine)
{
- ui_gfx_state &state = ui_gfx;
+ auto &input = machine.ui_input();
- // if we have nothing, implicitly cancel
- if (!ui_gfx_is_relevant(mui.machine()))
- goto cancel;
+ // handle zoom (minus,plus)
+ if (input.pressed(IPT_UI_ZOOM_OUT))
+ m_columns = std::min<unsigned>(m_columns * 2, 64);
+ if (input.pressed(IPT_UI_ZOOM_IN))
+ m_columns = std::max<unsigned>(m_columns / 2, 4);
+ if (input.pressed(IPT_UI_ZOOM_DEFAULT))
+ m_columns = 16;
- // if we're not paused, mark the bitmap dirty
- if (!mui.machine().paused())
- state.bitmap_dirty = true;
+ // handle colormap selection (open bracket,close bracket)
+ if (input.pressed(IPT_UI_PREV_GROUP))
+ prev_group(machine);
+ if (input.pressed(IPT_UI_NEXT_GROUP))
+ next_group(machine);
- // switch off the state to display something
-again:
- switch (state.mode)
- {
- case UI_GFX_PALETTE:
- // if we have a palette, display it
- if (state.palette.devcount > 0)
- {
- palette_handler(mui, container, state);
- break;
- }
+ // cache some info in locals
+ int const total = (subset::INDIRECT == m_which) ? m_interface->indirect_entries() : m_interface->entries();
- // fall through...
- state.mode++;
+ // determine number of entries per row and total
+ int const rowcount = m_columns;
+ int const screencount = rowcount * rowcount;
- case UI_GFX_GFXSET:
- // if we have graphics sets, display them
- if (state.gfxset.devcount > 0)
- {
- gfxset_handler(mui, container, state);
- break;
- }
+ // handle keyboard navigation
+ if (input.pressed_repeat(IPT_UI_UP, 4))
+ m_offset -= rowcount;
+ if (input.pressed_repeat(IPT_UI_DOWN, 4))
+ m_offset += rowcount;
+ if (input.pressed_repeat(IPT_UI_PAGE_UP, 6))
+ m_offset -= screencount;
+ if (input.pressed_repeat(IPT_UI_PAGE_DOWN, 6))
+ m_offset += screencount;
+ if (input.pressed_repeat(IPT_UI_HOME, 4))
+ m_offset = 0;
+ if (input.pressed_repeat(IPT_UI_END, 4))
+ m_offset = total;
- // fall through...
- state.mode++;
+ // clamp within range
+ if (m_offset + screencount > ((total + rowcount - 1) / rowcount) * rowcount)
+ m_offset = ((total + rowcount - 1) / rowcount) * rowcount - screencount;
+ if (m_offset < 0)
+ m_offset = 0;
+}
- case UI_GFX_TILEMAP:
- // if we have tilemaps, display them
- if (mui.machine().tilemap().count() > 0)
- {
- tilemap_handler(mui, container, state);
- break;
- }
- state.mode = UI_GFX_PALETTE;
- goto again;
+bool gfx_viewer::gfxset::handle_keys(running_machine &machine, int xcells, int ycells)
+{
+ auto &input = machine.ui_input();
+ bool const shift_pressed = machine.input().code_pressed(KEYCODE_LSHIFT) || machine.input().code_pressed(KEYCODE_RSHIFT);
+ bool result = false;
+
+ // handle previous/next group
+ if (input.pressed(IPT_UI_PREV_GROUP) && prev_group())
+ result = true;
+ if (input.pressed(IPT_UI_NEXT_GROUP) && next_group())
+ result = true;
+
+ auto &info = m_devices[m_device];
+ auto &set = info.set(m_set);
+ auto &gfx = *info.interface().gfx(m_set);
+
+ // handle cells per line (0/-/=)
+ if (input.pressed(IPT_UI_ZOOM_OUT) && (xcells < 128))
+ {
+ set.m_columns = xcells + 1;
+ set.m_integer_scale = shift_pressed;
+ result = true;
+ }
+ if (input.pressed(IPT_UI_ZOOM_IN) && (xcells > 2))
+ {
+ set.m_columns = xcells - 1;
+ set.m_integer_scale = shift_pressed;
+ result = true;
+ }
+ if (input.pressed(IPT_UI_ZOOM_DEFAULT) && ((xcells != 16) || (set.m_integer_scale != shift_pressed)))
+ {
+ set.m_columns = 16;
+ set.m_integer_scale = shift_pressed;
+ result = true;
}
- // handle keys
- if (mui.machine().ui_input().pressed(IPT_UI_SELECT))
+ // handle rotation (R)
+ if (input.pressed(IPT_UI_ROTATE))
{
- state.mode = (state.mode + 1) % 3;
- state.bitmap_dirty = true;
+ set.m_rotate = orientation_add(ROT90, set.m_rotate);
+ result = true;
}
- if (mui.machine().ui_input().pressed(IPT_UI_PAUSE))
+ // handle navigation within the cells (up,down,pgup,pgdown)
+ if (input.pressed_repeat(IPT_UI_UP, 4))
{
- if (mui.machine().paused())
- mui.machine().resume();
- else
- mui.machine().pause();
+ set.m_offset -= xcells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_DOWN, 4))
+ {
+ set.m_offset += xcells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_PAGE_UP, 6))
+ {
+ set.m_offset -= xcells * ycells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_PAGE_DOWN, 6))
+ {
+ set.m_offset += xcells * ycells;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_HOME, 4))
+ {
+ set.m_offset = 0;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_END, 4))
+ {
+ set.m_offset = gfx.elements();
+ result = true;
}
- if (mui.machine().ui_input().pressed(IPT_UI_CANCEL) || mui.machine().ui_input().pressed(IPT_UI_SHOW_GFX))
- goto cancel;
+ // clamp within range
+ if (set.m_offset + xcells * ycells > ((gfx.elements() + xcells - 1) / xcells) * xcells)
+ {
+ set.m_offset = ((gfx.elements() + xcells - 1) / xcells) * xcells - xcells * ycells;
+ result = true;
+ }
+ if (set.m_offset < 0)
+ {
+ set.m_offset = 0;
+ result = true;
+ }
- return uistate;
+ // handle color selection (left,right)
+ if (input.pressed_repeat(IPT_UI_LEFT, 4))
+ {
+ set.prev_color();
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_RIGHT, 4))
+ {
+ set.next_color();
+ result = true;
+ }
-cancel:
- if (!uistate)
- mui.machine().resume();
- state.bitmap_dirty = true;
- return UI_HANDLER_CANCEL;
+ return result;
}
+bool gfx_viewer::tilemap::handle_keys(running_machine &machine, float pixelscale)
+{
+ auto &input = machine.ui_input();
+ bool result = false;
-/***************************************************************************
- PALETTE VIEWER
-***************************************************************************/
+ // handle tilemap selection (open bracket,close bracket)
+ if (input.pressed(IPT_UI_PREV_GROUP) && m_index > 0)
+ {
+ m_index--;
+ result = true;
+ }
+ if (input.pressed(IPT_UI_NEXT_GROUP) && ((m_info.size() - 1) > m_index))
+ {
+ m_index++;
+ result = true;
+ }
-//-------------------------------------------------
-// palette_set_device - set the pointer to the
-// current palette device
-//-------------------------------------------------
+ auto &info = m_info[m_index];
-static void palette_set_device(running_machine &machine, ui_gfx_state &state)
-{
- palette_interface_iterator pal_iter(machine.root_device());
- state.palette.interface = pal_iter.byindex(state.palette.devindex);
-}
+ // handle zoom (minus,plus)
+ if (input.pressed(IPT_UI_ZOOM_OUT) && info.zoom_out(pixelscale))
+ {
+ result = true;
+ machine.popmessage(info.m_zoom_frac ? _("gfxview", "Zoom = 1/%1$d") : _("gfxview", "Zoom = %1$d"), info.m_zoom);
+ }
+ if (input.pressed(IPT_UI_ZOOM_IN) && info.zoom_in(pixelscale))
+ {
+ result = true;
+ machine.popmessage(info.m_zoom_frac ? _("gfxview", "Zoom = 1/%1$d") : _("gfxview", "Zoom = %1$d"), info.m_zoom);
+ }
+ if (input.pressed(IPT_UI_ZOOM_DEFAULT) && !info.m_auto_zoom)
+ {
+ info.m_auto_zoom = true;
+ machine.popmessage(_("gfxview", "Expand to fit"));
+ }
+ // handle rotation (R)
+ if (input.pressed(IPT_UI_ROTATE))
+ {
+ info.m_rotate = orientation_add(ROT90, info.m_rotate);
+ result = true;
+ }
-//-------------------------------------------------
-// palette_handler - handler for the palette
-// viewer
-//-------------------------------------------------
+ // return to (0,0) (HOME)
+ if (input.pressed(IPT_UI_HOME))
+ {
+ info.m_xoffs = 0;
+ info.m_yoffs = 0;
+ result = true;
+ }
+
+ // handle flags (category)
+ if (input.pressed(IPT_UI_PAGE_UP) && info.prev_catagory())
+ {
+ result = true;
+ if (TILEMAP_DRAW_ALL_CATEGORIES == info.m_flags)
+ machine.popmessage(_("gfxview", "All categories"));
+ else
+ machine.popmessage(_("gfxview", "Category %1$d"), info.m_flags);
+ }
+ if (input.pressed(IPT_UI_PAGE_DOWN) && info.next_category())
+ {
+ result = true;
+ machine.popmessage(_("gfxview", "Category %1$d"), info.m_flags);
+ }
-static void palette_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state)
+ // handle navigation (up,down,left,right), taking orientation into account
+ int const step = scroll_step(machine); // this may be applied more than once if multiple directions are pressed
+ if (input.pressed_repeat(IPT_UI_UP, 4))
+ {
+ if (info.m_rotate & ORIENTATION_SWAP_XY)
+ info.m_xoffs -= (info.m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ else
+ info.m_yoffs -= (info.m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_DOWN, 4))
+ {
+ if (info.m_rotate & ORIENTATION_SWAP_XY)
+ info.m_xoffs += (info.m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ else
+ info.m_yoffs += (info.m_rotate & ORIENTATION_FLIP_Y) ? -step : step;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_LEFT, 6))
+ {
+ if (info.m_rotate & ORIENTATION_SWAP_XY)
+ info.m_yoffs -= (info.m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ else
+ info.m_xoffs -= (info.m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ result = true;
+ }
+ if (input.pressed_repeat(IPT_UI_RIGHT, 6))
+ {
+ if (info.m_rotate & ORIENTATION_SWAP_XY)
+ info.m_yoffs += (info.m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ else
+ info.m_xoffs += (info.m_rotate & ORIENTATION_FLIP_X) ? -step : step;
+ result = true;
+ }
+
+ // cache some info in locals
+ tilemap_t *const tilemap = machine.tilemap().find(m_index);
+ uint32_t const mapwidth = tilemap->width();
+ uint32_t const mapheight = tilemap->height();
+
+ // clamp within range
+ while (info.m_xoffs < 0)
+ info.m_xoffs += mapwidth;
+ while (info.m_xoffs >= mapwidth)
+ info.m_xoffs -= mapwidth;
+ while (info.m_yoffs < 0)
+ info.m_yoffs += mapheight;
+ while (info.m_yoffs >= mapheight)
+ info.m_yoffs -= mapheight;
+
+ return result;
+}
+
+
+uint32_t gfx_viewer::handle_palette(mame_ui_manager &mui, render_container &container, bool uistate)
{
- device_palette_interface *palette = state.palette.interface;
- palette_device *paldev = dynamic_cast<palette_device *>(&palette->device());
+ device_palette_interface &palette = *m_palette.interface();
+ palette_device *const paldev = dynamic_cast<palette_device *>(&palette.device());
- int total = state.palette.which ? palette->indirect_entries() : palette->entries();
- const rgb_t *raw_color = palette->palette()->entry_list_raw();
- render_font *ui_font = mui.get_font();
- float titlewidth;
- float x0, y0;
- render_bounds cellboxbounds;
- render_bounds boxbounds;
- int skip;
+ bool const indirect = m_palette.indirect();
+ unsigned const total = indirect ? palette.indirect_entries() : palette.entries();
+ rgb_t const *const raw_color = palette.palette()->entry_list_raw();
// add a half character padding for the box
- const float aspect = mui.machine().render().ui_aspect(&container);
- const float chheight = mui.get_line_height();
- const float chwidth = ui_font->char_width(chheight, aspect, '0');
- boxbounds.x0 = 0.0f + 0.5f * chwidth;
- boxbounds.x1 = 1.0f - 0.5f * chwidth;
- boxbounds.y0 = 0.0f + 0.5f * chheight;
- boxbounds.y1 = 1.0f - 0.5f * chheight;
+ render_font *const ui_font = mui.get_font();
+ float const aspect = m_machine.render().ui_aspect(&container);
+ float const chheight = mui.get_line_height();
+ float const chwidth = ui_font->char_width(chheight, aspect, '0');
+ render_bounds const boxbounds{
+ 0.0f + (0.5f * chwidth),
+ 0.0f + (0.5f * chheight),
+ 1.0f - (0.5f * chwidth),
+ 1.0f - (0.5f * chheight) };
// the character cell box bounds starts a half character in from the box
- cellboxbounds = boxbounds;
+ render_bounds cellboxbounds = boxbounds;
cellboxbounds.x0 += 0.5f * chwidth;
- cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y0 += 0.5f * chheight;
+ cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y1 -= 0.5f * chheight;
// add space on the left for 5 characters of text, plus a half character of padding
@@ -420,41 +1015,57 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u
cellboxbounds.y0 += 3.0f * chheight;
// compute the cell size
- const float cellwidth = (cellboxbounds.x1 - cellboxbounds.x0) / float(state.palette.columns);
- const float cellheight = (cellboxbounds.y1 - cellboxbounds.y0) / float(state.palette.columns);
+ float const cellwidth = (cellboxbounds.x1 - cellboxbounds.x0) / float(m_palette.columns());
+ float const cellheight = (cellboxbounds.y1 - cellboxbounds.y0) / float(m_palette.columns());
// figure out the title
std::ostringstream title_buf;
- util::stream_format(title_buf, "'%s'", palette->device().tag());
- if (palette->indirect_entries() > 0)
- title_buf << (state.palette.which ? _(" COLORS") : _(" PENS"));
+ util::stream_format(title_buf,
+ !palette.indirect_entries() ? _("gfxview", "[root%1$s]") : indirect ? _("gfxview", "[root%1$s] colors") : _("gfxview", "[root%1$s] pens"),
+ palette.device().tag());
// if the mouse pointer is over one of our cells, add some info about the corresponding palette entry
- int32_t mouse_target_x, mouse_target_y;
float mouse_x, mouse_y;
- bool mouse_button;
- render_target *const mouse_target = mui.machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target != nullptr && mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)
- && cellboxbounds.x0 <= mouse_x && cellboxbounds.x1 > mouse_x
- && cellboxbounds.y0 <= mouse_y && cellboxbounds.y1 > mouse_y)
+ if (map_mouse(container, cellboxbounds, mouse_x, mouse_y))
{
- int index = state.palette.offset + int((mouse_x - cellboxbounds.x0) / cellwidth) + int((mouse_y - cellboxbounds.y0) / cellheight) * state.palette.columns;
+ int const index = m_palette.index(int((mouse_x - cellboxbounds.x0) / cellwidth), int((mouse_y - cellboxbounds.y0) / cellheight));
if (index < total)
{
- util::stream_format(title_buf, " #%X", index);
- if (palette->indirect_entries() > 0 && !state.palette.which)
- util::stream_format(title_buf, " => %X", palette->pen_indirect(index));
- else if (paldev != nullptr && paldev->basemem().base() != nullptr)
- util::stream_format(title_buf, " = %X", paldev->read_entry(index));
-
- rgb_t col = state.palette.which ? palette->indirect_color(index) : raw_color[index];
- util::stream_format(title_buf, " (A:%X R:%X G:%X B:%X)", col.a(), col.r(), col.g(), col.b());
+ rgb_t const col = indirect ? palette.indirect_color(index) : raw_color[index];
+ if (palette.indirect_entries() && indirect)
+ {
+ util::stream_format(title_buf,
+ _("gfxview", u8" #%1$X \u2192 %2$X (A:%3$02X R:%4$02X G:%5$02X B:%6$02X)"),
+ index, palette.pen_indirect(index),
+ col.a(), col.r(), col.g(), col.b());
+ }
+ else if (paldev && paldev->basemem().base())
+ {
+ util::stream_format(title_buf,
+ _("gfxview", " #%1$X = %2$X (A:%3$02X R:%4$02X G:%5$02X B:%6$02X)"),
+ index, paldev->read_entry(index),
+ col.a(), col.r(), col.g(), col.b());
+ }
+ else
+ {
+ util::stream_format(title_buf,
+ _("gfxview", " #%1$X (A:%2$02X R:%3$02X G:%4$02X B:%5$02X)"),
+ index,
+ col.a(), col.r(), col.g(), col.b());
+ }
+
+ // keep touch pointer displayed after release so they know what it's pointing at
+ mame_ui_manager::display_pointer pointers[1]{ { m_machine.render().ui_target(), m_pointer_type, m_pointer_x, m_pointer_y } };
+ if (ui_event::pointer::TOUCH == m_pointer_type)
+ mui.set_pointers(std::begin(pointers), std::end(pointers));
}
}
+ float x0, y0;
+
// expand the outer box to fit the title
- const std::string title = title_buf.str();
- titlewidth = ui_font->string_width(chheight, aspect, title.c_str());
+ std::string const title = std::move(title_buf).str();
+ float const titlewidth = ui_font->string_width(chheight, aspect, title);
x0 = 0.0f;
if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));
@@ -463,193 +1074,97 @@ static void palette_handler(mame_ui_manager &mui, render_container &container, u
mui.draw_outlined_box(container, boxbounds.x0 - x0, boxbounds.y0, boxbounds.x1 + x0, boxbounds.y1, mui.colors().gfxviewer_bg_color());
// draw the title
- x0 = 0.5f - 0.5f * titlewidth;
- y0 = boxbounds.y0 + 0.5f * chheight;
- for (auto ch : title)
- {
- container.add_char(x0, y0, chheight, aspect, rgb_t::white(), *ui_font, ch);
- x0 += ui_font->char_width(chheight, aspect, ch);
- }
+ draw_text(mui, container, title, 0.5f - 0.5f * titlewidth, boxbounds.y0 + 0.5f * chheight);
// draw the top column headers
- skip = int(chwidth / cellwidth);
- for (int x = 0; x < state.palette.columns; x += 1 + skip)
+ int const rowskip = int(chwidth / cellwidth);
+ for (int x = 0; x < m_palette.columns(); x += 1 + rowskip)
{
- 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]);
- // if we're skipping, draw a point between the character and the box to indicate which
- // one it's referring to
- if (skip != 0)
+ // if we're skipping, draw a point between the character and the box to indicate which one it's referring to
+ if (rowskip)
container.add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + cellboxbounds.y0), UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
// draw the side column headers
- skip = int(chheight / cellheight);
- for (int y = 0; y < state.palette.columns; y += 1 + skip)
-
+ int const colskip = int(chheight / cellheight);
+ for (int y = 0; y < m_palette.columns(); y += 1 + colskip)
+ {
// only display if there is data to show
- if (state.palette.offset + y * state.palette.columns < total)
+ unsigned const index = m_palette.index(0, y);
+ if (index < total)
{
- char buffer[10];
-
// 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;
- if (skip != 0)
+ y0 = boxbounds.y0 + 3.5f * chheight + float(y) * cellheight;
+ if (colskip != 0)
container.add_point(0.5f * (x0 + cellboxbounds.x0), y0 + 0.5f * cellheight, UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
// draw the row header
- sprintf(buffer, "%5X", state.palette.offset + y * state.palette.columns);
+ auto buffer = util::string_format("%5X", index);
for (int x = 4; x >= 0; x--)
{
x0 -= ui_font->char_width(chheight, aspect, buffer[x]);
container.add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, aspect, rgb_t::white(), *ui_font, buffer[x]);
}
}
+ }
// now add the rectangles for the colors
- for (int y = 0; y < state.palette.columns; y++)
- for (int x = 0; x < state.palette.columns; x++)
+ for (int y = 0; y < m_palette.columns(); y++)
+ {
+ for (int x = 0; x < m_palette.columns(); x++)
{
- int index = state.palette.offset + y * state.palette.columns + x;
+ int const index = m_palette.index(x, y);
if (index < total)
{
- const pen_t pen = state.palette.which ? palette->indirect_color(index) : raw_color[index];
- container.add_rect(cellboxbounds.x0 + x * cellwidth, cellboxbounds.y0 + y * cellheight,
- cellboxbounds.x0 + (x + 1) * cellwidth, cellboxbounds.y0 + (y + 1) * cellheight,
- 0xff000000 | pen, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ pen_t const pen = indirect ? palette.indirect_color(index) : raw_color[index];
+ container.add_rect(
+ cellboxbounds.x0 + x * cellwidth, cellboxbounds.y0 + y * cellheight,
+ cellboxbounds.x0 + (x + 1) * cellwidth, cellboxbounds.y0 + (y + 1) * cellheight,
+ 0xff000000 | pen, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
}
-
- // handle keys
- palette_handle_keys(mui.machine(), state);
-}
-
-
-//-------------------------------------------------
-// palette_handle_keys - handle key inputs for
-// the palette viewer
-//-------------------------------------------------
-
-static void palette_handle_keys(running_machine &machine, ui_gfx_state &state)
-{
- device_palette_interface *palette = state.palette.interface;
- int rowcount, screencount;
- int total;
-
- // handle zoom (minus,plus)
- if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT))
- state.palette.columns /= 2;
- if (machine.ui_input().pressed(IPT_UI_ZOOM_IN))
- state.palette.columns *= 2;
-
- // clamp within range
- if (state.palette.columns <= 4)
- state.palette.columns = 4;
- if (state.palette.columns > 64)
- state.palette.columns = 64;
-
- // handle colormap selection (open bracket,close bracket)
- if (machine.ui_input().pressed(IPT_UI_PREV_GROUP))
- {
- if (state.palette.which)
- state.palette.which = 0;
- else if (state.palette.devindex > 0)
- {
- state.palette.devindex--;
- palette_set_device(machine, state);
- palette = state.palette.interface;
- state.palette.which = (palette->indirect_entries() > 0);
- }
- }
- if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP))
- {
- if (!state.palette.which && palette->indirect_entries() > 0)
- state.palette.which = 1;
- else if (state.palette.devindex < state.palette.devcount - 1)
- {
- state.palette.devindex++;
- palette_set_device(machine, state);
- palette = state.palette.interface;
- state.palette.which = 0;
- }
}
- // cache some info in locals
- total = state.palette.which ? palette->indirect_entries() : palette->entries();
-
- // determine number of entries per row and total
- rowcount = state.palette.columns;
- screencount = rowcount * rowcount;
-
- // handle keyboard navigation
- if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
- state.palette.offset -= rowcount;
- if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
- state.palette.offset += rowcount;
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_UP, 6))
- state.palette.offset -= screencount;
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_DOWN, 6))
- state.palette.offset += screencount;
- if (machine.ui_input().pressed_repeat(IPT_UI_HOME, 4))
- state.palette.offset = 0;
- if (machine.ui_input().pressed_repeat(IPT_UI_END, 4))
- state.palette.offset = total;
-
- // clamp within range
- if (state.palette.offset + screencount > ((total + rowcount - 1) / rowcount) * rowcount)
- state.palette.offset = ((total + rowcount - 1) / rowcount) * rowcount - screencount;
- if (state.palette.offset < 0)
- state.palette.offset = 0;
+ // handle keys
+ m_palette.handle_keys(m_machine);
+ return handle_general_keys(uistate);
}
-
-/***************************************************************************
- GRAPHICS VIEWER
-***************************************************************************/
-
-//-------------------------------------------------
-// gfxset_handler - handler for the graphics
-// viewer
-//-------------------------------------------------
-
-static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state)
+uint32_t gfx_viewer::handle_gfxset(mame_ui_manager &mui, render_container &container, bool uistate)
{
- render_font *ui_font = mui.get_font();
- int dev = state.gfxset.devindex;
- int set = state.gfxset.set;
- ui_gfx_info &info = state.gfxdev[dev];
- device_gfx_interface &interface = *info.interface;
- gfx_element &gfx = *interface.gfx(set);
- float x0, y0;
- render_bounds cellboxbounds;
- render_bounds boxbounds;
- int 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;
- int skip;
+ // get graphics info
+ auto &info = m_gfxset.m_devices[m_gfxset.m_device];
+ auto &set = info.set(m_gfxset.m_set);
+ device_gfx_interface &interface = info.interface();
+ gfx_element &gfx = *interface.gfx(m_gfxset.m_set);
+
+ // get some UI metrics
+ render_font *const ui_font = mui.get_font();
+ int const targwidth = m_machine.render().ui_target().width();
+ int const targheight = m_machine.render().ui_target().height();
+ float const aspect = m_machine.render().ui_aspect(&container);
+ float const chheight = mui.get_line_height();
+ float const chwidth = ui_font->char_width(chheight, aspect, '0');
// add a half character padding for the box
- const float aspect = mui.machine().render().ui_aspect(&container);
- const float chheight = mui.get_line_height();
- const float chwidth = ui_font->char_width(chheight, aspect, '0');
- boxbounds.x0 = 0.0f + 0.5f * chwidth;
- boxbounds.x1 = 1.0f - 0.5f * chwidth;
- boxbounds.y0 = 0.0f + 0.5f * chheight;
- boxbounds.y1 = 1.0f - 0.5f * chheight;
+ render_bounds boxbounds{
+ 0.0f + (0.5f * chwidth),
+ 0.0f + (0.5f * chheight),
+ 1.0f - (0.5f * chwidth),
+ 1.0f - (0.5f * chheight) };
// the character cell box bounds starts a half character in from the box
- cellboxbounds = boxbounds;
+ render_bounds cellboxbounds = boxbounds;
cellboxbounds.x0 += 0.5f * chwidth;
- cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y0 += 0.5f * chheight;
+ cellboxbounds.x1 -= 0.5f * chwidth;
cellboxbounds.y1 -= 0.5f * chheight;
// add space on the left for 5 characters of text, plus a half character of padding
@@ -659,93 +1174,110 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui
cellboxbounds.y0 += 3.0f * chheight;
// convert back to pixels
- cellboxwidth = (cellboxbounds.x1 - cellboxbounds.x0) * float(targwidth);
- cellboxheight = (cellboxbounds.y1 - cellboxbounds.y0) * float(targheight);
+ float cellboxwidth = cellboxbounds.width() * float(targwidth);
+ float cellboxheight = cellboxbounds.height() * float(targheight);
// compute the number of source pixels in a cell
- cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
- cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
+ int const cellxpix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
+ int const cellypix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
// compute the largest pixel scale factor that still fits
- xcells = info.columns[set];
+ int xcells = set.m_columns;
+ float pixelscale = 0.0f;
while (xcells > 1)
{
- pixelscale = (cellboxwidth / xcells) / cellxpix;
- if (pixelscale != 0)
+ pixelscale = cellboxwidth / (xcells * cellxpix);
+ if (set.m_integer_scale)
+ pixelscale = std::floor(pixelscale);
+ if (0.25f <= pixelscale)
break;
xcells--;
}
- info.columns[set] = xcells;
-
- // worst case, we need a pixel scale of 1
- pixelscale = std::max(1, pixelscale);
+ if (0.0f == pixelscale)
+ pixelscale = cellboxwidth / (xcells * cellxpix);
// in the Y direction, we just display as many as we can
- const int ycells = cellboxheight / (pixelscale * cellypix);
+ int ycells = int(cellboxheight / (pixelscale * cellypix));
+ if (!ycells)
+ {
+ ycells = 1;
+ pixelscale = cellboxheight / cellypix;
+ xcells = int(cellboxwidth / (pixelscale * cellxpix));
+ }
// now determine the actual cellbox size
+ set.m_columns = xcells;
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
+ float const cellwidth = (cellboxwidth / xcells) / targwidth;
+ float const 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;
+ float const fullwidth = cellboxwidth / targwidth + 6.5f * chwidth;
+ float const fullheight = cellboxheight / targheight + 4.0f * chheight;
// recompute boxbounds from this
boxbounds.x0 = (1.0f - fullwidth) * 0.5f;
- boxbounds.x1 = boxbounds.x0 + fullwidth;
boxbounds.y0 = (1.0f - fullheight) * 0.5f;
+ boxbounds.x1 = boxbounds.x0 + fullwidth;
boxbounds.y1 = boxbounds.y0 + fullheight;
// recompute cellboxbounds
cellboxbounds.x0 = boxbounds.x0 + 6.0f * chwidth;
- cellboxbounds.x1 = cellboxbounds.x0 + float(cellboxwidth) / float(targwidth);
cellboxbounds.y0 = boxbounds.y0 + 3.5f * chheight;
- cellboxbounds.y1 = cellboxbounds.y0 + float(cellboxheight) / float(targheight);
+ cellboxbounds.x1 = cellboxbounds.x0 + cellboxwidth / float(targwidth);
+ cellboxbounds.y1 = cellboxbounds.y0 + cellboxheight / float(targheight);
// figure out the title
std::ostringstream title_buf;
- util::stream_format(title_buf, "'%s' %d/%d", interface.device().tag(), set, info.setcount - 1);
+ util::stream_format(title_buf,
+ _("gfxview", "[root%1$s] %2$d/%3$d"),
+ interface.device().tag(),
+ m_gfxset.m_set, info.setcount() - 1);
// if the mouse pointer is over a pixel in a tile, add some info about the tile and pixel
bool found_pixel = false;
- int32_t mouse_target_x, mouse_target_y;
float mouse_x, mouse_y;
- bool mouse_button;
- render_target *const mouse_target = mui.machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target != nullptr && mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)
- && cellboxbounds.x0 <= mouse_x && cellboxbounds.x1 > mouse_x
- && cellboxbounds.y0 <= mouse_y && cellboxbounds.y1 > mouse_y)
+ if (map_mouse(container, cellboxbounds, mouse_x, mouse_y))
{
- int code = info.offset[set] + int((mouse_x - cellboxbounds.x0) / cellwidth) + int((mouse_y - cellboxbounds.y0) / cellheight) * xcells;
+ int const code = set.m_offset + int((mouse_x - cellboxbounds.x0) / cellwidth) + int((mouse_y - cellboxbounds.y0) / cellheight) * xcells;
int xpixel = int((mouse_x - cellboxbounds.x0) / (cellwidth / cellxpix)) % cellxpix;
int ypixel = int((mouse_y - cellboxbounds.y0) / (cellheight / cellypix)) % cellypix;
- if (code < gfx.elements() && xpixel < (cellxpix - 1) && ypixel < (cellypix - 1))
+ if ((code < gfx.elements()) && (xpixel < (cellxpix - 1)) && (ypixel < (cellypix - 1)))
{
found_pixel = true;
- if (info.rotate[set] & ORIENTATION_FLIP_X)
+ if (set.m_rotate & ORIENTATION_FLIP_X)
xpixel = (cellxpix - 2) - xpixel;
- if (info.rotate[set] & ORIENTATION_FLIP_Y)
+ if (set.m_rotate & ORIENTATION_FLIP_Y)
ypixel = (cellypix - 2) - ypixel;
- if (info.rotate[set] & ORIENTATION_SWAP_XY)
+ if (set.m_rotate & ORIENTATION_SWAP_XY)
std::swap(xpixel, ypixel);
- uint8_t pixdata = gfx.get_data(code)[xpixel + ypixel * gfx.rowbytes()];
- util::stream_format(title_buf, " #%X:%X @ %d,%d = %X",
- code, info.color[set], xpixel, ypixel,
- gfx.colorbase() + info.color[set] * gfx.granularity() + pixdata);
+ uint8_t const pixdata = gfx.get_data(code)[xpixel + ypixel * gfx.rowbytes()];
+ util::stream_format(title_buf,
+ _("gfxview", " #%1$X:%2$X (%3$d %4$d) = %5$X"),
+ code, set.m_color,
+ xpixel, ypixel,
+ gfx.colorbase() + (set.m_color * gfx.granularity()) + pixdata);
+
+ // keep touch pointer displayed after release so they know what it's pointing at
+ mame_ui_manager::display_pointer pointers[1]{ { m_machine.render().ui_target(), m_pointer_type, m_pointer_x, m_pointer_y } };
+ if (ui_event::pointer::TOUCH == m_pointer_type)
+ mui.set_pointers(std::begin(pointers), std::end(pointers));
}
}
if (!found_pixel)
- util::stream_format(title_buf, " %dx%d COLOR %X/%X", gfx.width(), gfx.height(), info.color[set], info.color_count[set]);
+ util::stream_format(title_buf,
+ _("gfxview", u8" %1$d\u00d7%2$d color %3$X/%4$X"),
+ gfx.width(), gfx.height(),
+ set.m_color, set.m_color_count);
+
+ float x0, y0;
// expand the outer box to fit the title
- const std::string title = title_buf.str();
- const float titlewidth = ui_font->string_width(chheight, aspect, title.c_str());
+ std::string const title = std::move(title_buf).str();
+ float const titlewidth = ui_font->string_width(chheight, aspect, title);
x0 = 0.0f;
if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
x0 = boxbounds.x0 - (0.5f - 0.5f * (titlewidth + chwidth));
@@ -754,326 +1286,85 @@ static void gfxset_handler(mame_ui_manager &mui, render_container &container, ui
mui.draw_outlined_box(container, boxbounds.x0 - x0, boxbounds.y0, boxbounds.x1 + x0, boxbounds.y1, mui.colors().gfxviewer_bg_color());
// draw the title
- x0 = 0.5f - 0.5f * titlewidth;
- y0 = boxbounds.y0 + 0.5f * chheight;
- for (auto ch : title)
- {
- container.add_char(x0, y0, chheight, aspect, rgb_t::white(), *ui_font, ch);
- x0 += ui_font->char_width(chheight, aspect, ch);
- }
+ draw_text(mui, container, title, 0.5f - 0.5f * titlewidth, boxbounds.y0 + 0.5f * chheight);
// draw the top column headers
- skip = int(chwidth / cellwidth);
- for (int x = 0; x < xcells; x += 1 + skip)
+ int const colskip = int(chwidth / cellwidth);
+ for (int x = 0; x < xcells; x += 1 + colskip)
{
- 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]);
- // if we're skipping, draw a point between the character and the box to indicate which
- // one it's referring to
- if (skip != 0)
+ // if we're skipping, draw a point between the character and the box to indicate which one it's referring to
+ if (colskip)
container.add_point(x0 + 0.5f * cellwidth, 0.5f * (y0 + chheight + boxbounds.y0 + 3.5f * chheight), UI_LINE_WIDTH, rgb_t::white(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
}
// draw the side column headers
- skip = int(chheight / cellheight);
- for (int y = 0; y < ycells; y += 1 + skip)
-
+ int const rowskip = int(chheight / cellheight);
+ for (int y = 0; y < ycells; y += 1 + rowskip)
+ {
// only display if there is data to show
- if (info.offset[set] + y * xcells < gfx.elements())
+ if (set.m_offset + (y * xcells) < gfx.elements())
{
- char buffer[10];
-
- // if we're skipping, draw a point between the character and the box to indicate which
- // one it's referring to
+ // 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;
- if (skip != 0)
+ y0 = boxbounds.y0 + 3.5f * chheight + float(y) * cellheight;
+ if (rowskip)
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));
// draw the row header
- sprintf(buffer, "%5X", info.offset[set] + y * xcells);
+ auto buffer = util::string_format("%5X", set.m_offset + (y * xcells));
for (int x = 4; x >= 0; x--)
{
x0 -= ui_font->char_width(chheight, aspect, buffer[x]);
container.add_char(x0, y0 + 0.5f * (cellheight - chheight), chheight, aspect, rgb_t::white(), *ui_font, buffer[x]);
}
}
+ }
// update the bitmap
- gfxset_update_bitmap(mui.machine(), state, xcells, ycells, gfx);
+ update_gfxset_bitmap(xcells, ycells, gfx);
// add the final quad
- container.add_quad(cellboxbounds.x0, cellboxbounds.y0, cellboxbounds.x1, cellboxbounds.y1,
- rgb_t::white(), state.texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+ container.add_quad(
+ cellboxbounds.x0, cellboxbounds.y0, cellboxbounds.x1, cellboxbounds.y1,
+ rgb_t::white(), m_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
// handle keyboard navigation before drawing
- gfxset_handle_keys(mui.machine(), state, xcells, ycells);
+ if (m_gfxset.handle_keys(m_machine, xcells, ycells))
+ m_bitmap_dirty = true;
+ return handle_general_keys(uistate);
}
-//-------------------------------------------------
-// gfxset_handle_keys - handle keys for the
-// graphics viewer
-//-------------------------------------------------
-
-static void gfxset_handle_keys(running_machine &machine, ui_gfx_state &state, int xcells, int ycells)
+uint32_t gfx_viewer::handle_tilemap(mame_ui_manager &mui, render_container &container, bool uistate)
{
- // handle gfxset selection (open bracket,close bracket)
- if (machine.ui_input().pressed(IPT_UI_PREV_GROUP))
- {
- if (state.gfxset.set > 0)
- state.gfxset.set--;
- else if (state.gfxset.devindex > 0)
- {
- state.gfxset.devindex--;
- state.gfxset.set = state.gfxdev[state.gfxset.devindex].setcount - 1;
- }
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP))
- {
- if (state.gfxset.set < state.gfxdev[state.gfxset.devindex].setcount - 1)
- state.gfxset.set++;
- else if (state.gfxset.devindex < state.gfxset.devcount - 1)
- {
- state.gfxset.devindex++;
- state.gfxset.set = 0;
- }
- state.bitmap_dirty = true;
- }
-
- // cache some info in locals
- int dev = state.gfxset.devindex;
- int set = state.gfxset.set;
- ui_gfx_info &info = state.gfxdev[dev];
- gfx_element &gfx = *info.interface->gfx(set);
-
- // handle cells per line (minus,plus)
- if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT))
- { info.columns[set] = xcells - 1; state.bitmap_dirty = true; }
-
- if (machine.ui_input().pressed(IPT_UI_ZOOM_IN))
- { info.columns[set] = xcells + 1; state.bitmap_dirty = true; }
-
- // clamp within range
- if (info.columns[set] < 2)
- { info.columns[set] = 2; state.bitmap_dirty = true; }
- if (info.columns[set] > 128)
- { info.columns[set] = 128; state.bitmap_dirty = true; }
-
- // handle rotation (R)
- if (machine.ui_input().pressed(IPT_UI_ROTATE))
- {
- info.rotate[set] = orientation_add(ROT90, info.rotate[set]);
- state.bitmap_dirty = true;
- }
-
- // handle navigation within the cells (up,down,pgup,pgdown)
- if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
- { info.offset[set] -= xcells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
- { info.offset[set] += xcells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_UP, 6))
- { info.offset[set] -= xcells * ycells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_PAGE_DOWN, 6))
- { info.offset[set] += xcells * ycells; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_HOME, 4))
- { info.offset[set] = 0; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_END, 4))
- { info.offset[set] = gfx.elements(); state.bitmap_dirty = true; }
-
- // clamp within range
- if (info.offset[set] + xcells * ycells > ((gfx.elements() + xcells - 1) / xcells) * xcells)
- {
- info.offset[set] = ((gfx.elements() + xcells - 1) / xcells) * xcells - xcells * ycells;
- state.bitmap_dirty = true;
- }
- if (info.offset[set] < 0)
- { info.offset[set] = 0; state.bitmap_dirty = true; }
-
- // handle color selection (left,right)
- if (machine.ui_input().pressed_repeat(IPT_UI_LEFT, 4))
- { info.color[set] -= 1; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed_repeat(IPT_UI_RIGHT, 4))
- { info.color[set] += 1; state.bitmap_dirty = true; }
-
- // clamp within range
- if (info.color[set] >= info.color_count[set])
- { info.color[set] = info.color_count[set] - 1; state.bitmap_dirty = true; }
- if (info.color[set] < 0)
- { info.color[set] = 0; state.bitmap_dirty = true; }
-}
-
-
-//-------------------------------------------------
-// gfxset_update_bitmap - redraw the current
-// graphics view bitmap
-//-------------------------------------------------
-
-static void gfxset_update_bitmap(running_machine &machine, ui_gfx_state &state, int xcells, int ycells, gfx_element &gfx)
-{
- int dev = state.gfxset.devindex;
- int set = state.gfxset.set;
- ui_gfx_info &info = state.gfxdev[dev];
- int cellxpix, cellypix;
- int x, y;
-
- // compute the number of source pixels in a cell
- cellxpix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
- cellypix = 1 + ((info.rotate[set] & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
-
- // realloc the bitmap if it is too small
- if (!state.bitmap.valid() || state.texture == nullptr || state.bitmap.width() != cellxpix * xcells || state.bitmap.height() != cellypix * ycells)
- {
- // free the old stuff
- machine.render().texture_free(state.texture);
- state.bitmap.reset();
-
- // allocate new stuff
- state.bitmap.allocate(cellxpix * xcells, cellypix * ycells);
- state.texture = machine.render().texture_alloc();
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_ARGB32);
-
- // force a redraw
- state.bitmap_dirty = true;
- }
-
- // handle the redraw
- if (state.bitmap_dirty)
- {
- // loop over rows
- for (y = 0; y < ycells; y++)
- {
- rectangle cellbounds;
-
- // make a rect that covers this row
- cellbounds.set(0, state.bitmap.width() - 1, y * cellypix, (y + 1) * cellypix - 1);
-
- // only display if there is data to show
- if (info.offset[set] + y * xcells < gfx.elements())
- {
- // draw the individual cells
- for (x = 0; x < xcells; x++)
- {
- int index = info.offset[set] + y * xcells + x;
-
- // update the bounds for this cell
- cellbounds.min_x = x * cellxpix;
- cellbounds.max_x = (x + 1) * cellxpix - 1;
-
- // only render if there is data
- if (index < gfx.elements())
- gfxset_draw_item(machine, gfx, index, state.bitmap, cellbounds.min_x, cellbounds.min_y, info.color[set], info.rotate[set], info.palette[set]);
-
- // otherwise, fill with transparency
- else
- state.bitmap.fill(0, cellbounds);
- }
- }
-
- // otherwise, fill with transparency
- else
- state.bitmap.fill(0, cellbounds);
- }
-
- // reset the texture to force an update
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_ARGB32);
- state.bitmap_dirty = false;
- }
-}
-
-
-//-------------------------------------------------
-// gfxset_draw_item - draw a single item into
-// the view
-//-------------------------------------------------
-
-static void gfxset_draw_item(running_machine &machine, gfx_element &gfx, int index, bitmap_rgb32 &bitmap, int dstx, int dsty, int color, int rotate, device_palette_interface *dpalette)
-{
- int width = (rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width();
- int height = (rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height();
- rgb_t const *const palette = dpalette->palette()->entry_list_raw() + gfx.colorbase() + color * gfx.granularity();
-
- // loop over rows in the cell
- for (int y = 0; y < height; y++)
- {
- uint32_t *dest = &bitmap.pix(dsty + y, dstx);
- const uint8_t *src = gfx.get_data(index);
-
- // loop over columns in the cell
- for (int x = 0; x < width; x++)
- {
- int effx = x, effy = y;
- const uint8_t *s;
-
- // compute effective x,y values after rotation
- if (!(rotate & ORIENTATION_SWAP_XY))
- {
- if (rotate & ORIENTATION_FLIP_X)
- effx = gfx.width() - 1 - effx;
- if (rotate & ORIENTATION_FLIP_Y)
- effy = gfx.height() - 1 - effy;
- }
- else
- {
- if (rotate & ORIENTATION_FLIP_X)
- effx = gfx.height() - 1 - effx;
- if (rotate & ORIENTATION_FLIP_Y)
- effy = gfx.width() - 1 - effy;
- std::swap(effx, effy);
- }
-
- // get a pointer to the start of this source row
- s = src + effy * gfx.rowbytes();
-
- // extract the pixel
- *dest++ = 0xff000000 | palette[s[effx]];
- }
- }
-}
-
-
-
-/***************************************************************************
- TILEMAP VIEWER
-***************************************************************************/
-
-//-------------------------------------------------
-// tilemap_handler - handler for the tilemap
-// viewer
-//-------------------------------------------------
-
-static void tilemap_handler(mame_ui_manager &mui, render_container &container, ui_gfx_state &state)
-{
- render_font *ui_font = mui.get_font();
- render_bounds mapboxbounds;
- render_bounds boxbounds;
- const int targwidth = mui.machine().render().ui_target().width();
- const int targheight = mui.machine().render().ui_target().height();
- float titlewidth;
- float x0, y0;
- int mapboxwidth, mapboxheight;
+ // get some UI metrics
+ render_font *const ui_font = mui.get_font();
+ int const targwidth = m_machine.render().ui_target().width();
+ int const targheight = m_machine.render().ui_target().height();
+ float const aspect = m_machine.render().ui_aspect(&container);
+ float const chheight = mui.get_line_height();
+ float const chwidth = ui_font->char_width(chheight, aspect, '0');
// get the size of the tilemap itself
- tilemap_t *tilemap = mui.machine().tilemap().find(state.tilemap.which);
- uint32_t mapwidth = tilemap->width();
- uint32_t mapheight = tilemap->height();
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
+ tilemap_t &tilemap = *m_machine.tilemap().find(m_tilemap.index());
+ uint32_t mapwidth = tilemap.width();
+ uint32_t mapheight = tilemap.height();
+ if (m_tilemap.rotate() & ORIENTATION_SWAP_XY)
std::swap(mapwidth, mapheight);
// add a half character padding for the box
- const float aspect = mui.machine().render().ui_aspect(&container);
- const float chheight = mui.get_line_height();
- const float chwidth = ui_font->char_width(chheight, aspect, '0');
- boxbounds.x0 = 0.0f + 0.5f * chwidth;
- boxbounds.x1 = 1.0f - 0.5f * chwidth;
- boxbounds.y0 = 0.0f + 0.5f * chheight;
- boxbounds.y1 = 1.0f - 0.5f * chheight;
+ render_bounds boxbounds{
+ 0.0f + (0.5f * chwidth),
+ 0.0f + (0.5f * chheight),
+ 1.0f - (0.5f * chwidth),
+ 1.0f - (0.5f * chheight) };
// the tilemap box bounds starts a half character in from the box
- mapboxbounds = boxbounds;
+ render_bounds mapboxbounds = boxbounds;
mapboxbounds.x0 += 0.5f * chwidth;
mapboxbounds.x1 -= 0.5f * chwidth;
mapboxbounds.y0 += 0.5f * chheight;
@@ -1083,28 +1374,30 @@ 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;
+ int mapboxwidth = mapboxbounds.width() * float(targwidth);
+ int mapboxheight = mapboxbounds.height() * float(targheight);
- // determine the maximum integral scaling factor
- int pixelscale = state.tilemap.zoom;
- if (pixelscale == 0)
+ float pixelscale;
+ if (m_tilemap.auto_zoom())
{
- int maxxscale, maxyscale;
- for (maxxscale = 1; mapwidth * (maxxscale + 1) < mapboxwidth; maxxscale++) { }
- for (maxyscale = 1; mapheight * (maxyscale + 1) < mapboxheight; maxyscale++) { }
- pixelscale = std::min(maxxscale, maxyscale);
+ // determine the maximum integral scaling factor
+ pixelscale = std::min(std::floor(mapboxwidth / mapwidth), std::floor(mapboxheight / mapheight));
+ pixelscale = std::max(pixelscale, 1.0f);
+ }
+ else
+ {
+ pixelscale = m_tilemap.zoom_scale();
}
// recompute the final box size
- mapboxwidth = std::min(mapboxwidth, int(mapwidth * pixelscale));
- mapboxheight = std::min(mapboxheight, int(mapheight * pixelscale));
+ mapboxwidth = std::min<int>(mapboxwidth, std::lround(mapwidth * pixelscale));
+ mapboxheight = std::min<int>(mapboxheight, std::lround(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;
@@ -1114,43 +1407,49 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u
// figure out the title
std::ostringstream title_buf;
- util::stream_format(title_buf, "TILEMAP %d/%d", state.tilemap.which + 1, mui.machine().tilemap().count());
+ util::stream_format(title_buf,
+ (m_tilemap.flags() != TILEMAP_DRAW_ALL_CATEGORIES) ? _("gfxview", "Tilemap %1$d/%2$d category %3$u") : _("gfxview", "Tilemap %1$d/%2$d "),
+ m_tilemap.index() + 1, m_machine.tilemap().count(),
+ m_tilemap.flags());
// if the mouse pointer is over a tile, add some info about its coordinates and color
- int32_t mouse_target_x, mouse_target_y;
float mouse_x, mouse_y;
- bool mouse_button;
- render_target *const mouse_target = mui.machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button);
- if (mouse_target != nullptr && mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)
- && mapboxbounds.x0 <= mouse_x && mapboxbounds.x1 > mouse_x
- && mapboxbounds.y0 <= mouse_y && mapboxbounds.y1 > mouse_y)
+ if (map_mouse(container, mapboxbounds, mouse_x, mouse_y))
{
int xpixel = (mouse_x - mapboxbounds.x0) * targwidth;
int ypixel = (mouse_y - mapboxbounds.y0) * targheight;
- if (state.tilemap.rotate & ORIENTATION_FLIP_X)
+ if (m_tilemap.rotate() & ORIENTATION_FLIP_X)
xpixel = (mapboxwidth - 1) - xpixel;
- if (state.tilemap.rotate & ORIENTATION_FLIP_Y)
+ if (m_tilemap.rotate() & ORIENTATION_FLIP_Y)
ypixel = (mapboxheight - 1) - ypixel;
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
+ if (m_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 const col = ((std::lround(xpixel / pixelscale) + m_tilemap.xoffs()) / tilemap.tilewidth()) % tilemap.cols();
+ uint32_t const row = ((std::lround(ypixel / pixelscale) + m_tilemap.yoffs()) / tilemap.tileheight()) % tilemap.rows();
uint8_t gfxnum;
uint32_t code, color;
- tilemap->get_info_debug(col, row, gfxnum, code, color);
- util::stream_format(title_buf, " @ %d,%d = GFX%d #%X:%X",
- col * tilemap->tilewidth(), row * tilemap->tileheight(),
- int(gfxnum), code, color);
+ tilemap.get_info_debug(col, row, gfxnum, code, color);
+ util::stream_format(title_buf,
+ _("gfxview", " (%1$u %2$u) = GFX%3$u #%4$X:%5$X"),
+ col * tilemap.tilewidth(), row * tilemap.tileheight(),
+ gfxnum, code, color);
+
+ // keep touch pointer displayed after release so they know what it's pointing at
+ mame_ui_manager::display_pointer pointers[1]{ { m_machine.render().ui_target(), m_pointer_type, m_pointer_x, m_pointer_y } };
+ if (ui_event::pointer::TOUCH == m_pointer_type)
+ mui.set_pointers(std::begin(pointers), std::end(pointers));
}
else
- util::stream_format(title_buf, " %dx%d OFFS %d,%d", tilemap->width(), tilemap->height(), state.tilemap.xoffs, state.tilemap.yoffs);
-
- if (state.tilemap.flags != TILEMAP_DRAW_ALL_CATEGORIES)
- util::stream_format(title_buf, " CAT %d", state.tilemap.flags);
+ {
+ util::stream_format(title_buf,
+ _("gfxview", u8" %1$d\u00d7%2$d origin (%3$d %4$d)"),
+ tilemap.width(), tilemap.height(),
+ m_tilemap.xoffs(), m_tilemap.yoffs());
+ }
// expand the outer box to fit the title
- const std::string title = title_buf.str();
- titlewidth = ui_font->string_width(chheight, aspect, title.c_str());
+ std::string const title = std::move(title_buf).str();
+ float const titlewidth = ui_font->string_width(chheight, aspect, title);
if (boxbounds.x1 - boxbounds.x0 < titlewidth + chwidth)
{
boxbounds.x0 = 0.5f - 0.5f * (titlewidth + chwidth);
@@ -1161,192 +1460,158 @@ static void tilemap_handler(mame_ui_manager &mui, render_container &container, u
mui.draw_outlined_box(container, boxbounds.x0, boxbounds.y0, boxbounds.x1, boxbounds.y1, mui.colors().gfxviewer_bg_color());
// draw the title
- x0 = 0.5f - 0.5f * titlewidth;
- y0 = boxbounds.y0 + 0.5f * chheight;
- for (auto ch : title)
- {
- container.add_char(x0, y0, chheight, aspect, rgb_t::white(), *ui_font, ch);
- x0 += ui_font->char_width(chheight, aspect, ch);
- }
+ draw_text(mui, container, title, 0.5f - 0.5f * titlewidth, boxbounds.y0 + 0.5f * chheight);
// update the bitmap
- tilemap_update_bitmap(mui.machine(), state, mapboxwidth / pixelscale, mapboxheight / pixelscale);
+ update_tilemap_bitmap(std::lround(mapboxwidth / pixelscale), std::lround(mapboxheight / pixelscale));
// add the final quad
- container.add_quad(mapboxbounds.x0, mapboxbounds.y0,
- mapboxbounds.x1, mapboxbounds.y1,
- rgb_t::white(), state.texture,
- PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(state.tilemap.rotate));
+ container.add_quad(
+ mapboxbounds.x0, mapboxbounds.y0,
+ mapboxbounds.x1, mapboxbounds.y1,
+ rgb_t::white(), m_texture,
+ PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(m_tilemap.rotate()));
// handle keyboard input
- tilemap_handle_keys(mui.machine(), state, mapboxwidth, mapboxheight);
+ if (m_tilemap.handle_keys(m_machine, pixelscale))
+ m_bitmap_dirty = true;
+ return handle_general_keys(uistate);
}
-//-------------------------------------------------
-// tilemap_handle_keys - handle keys for the
-// tilemap view
-//-------------------------------------------------
-
-static void tilemap_handle_keys(running_machine &machine, ui_gfx_state &state, int viswidth, int visheight)
+void gfx_viewer::update_gfxset_bitmap(int xcells, int ycells, gfx_element &gfx)
{
- // handle tilemap selection (open bracket,close bracket)
- if (machine.ui_input().pressed(IPT_UI_PREV_GROUP) && state.tilemap.which > 0)
- { state.tilemap.which--; state.bitmap_dirty = true; }
- if (machine.ui_input().pressed(IPT_UI_NEXT_GROUP) && state.tilemap.which < machine.tilemap().count() - 1)
- { state.tilemap.which++; state.bitmap_dirty = true; }
-
- // cache some info in locals
- tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
- uint32_t mapwidth = tilemap->width();
- uint32_t mapheight = tilemap->height();
+ auto const &info = m_gfxset.m_devices[m_gfxset.m_device];
+ auto const &set = info.set(m_gfxset.m_set);
- // handle zoom (minus,plus)
- if (machine.ui_input().pressed(IPT_UI_ZOOM_OUT) && state.tilemap.zoom > 0)
- {
- state.tilemap.zoom--;
- state.bitmap_dirty = true;
- if (state.tilemap.zoom != 0)
- machine.popmessage("Zoom = %d", state.tilemap.zoom);
- else
- machine.popmessage("Zoom Auto");
- }
- if (machine.ui_input().pressed(IPT_UI_ZOOM_IN) && state.tilemap.zoom < 8)
- {
- state.tilemap.zoom++;
- state.bitmap_dirty = true;
- machine.popmessage("Zoom = %d", state.tilemap.zoom);
- }
+ // compute the number of source pixels in a cell
+ int const cellxpix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width());
+ int const cellypix = 1 + ((set.m_rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height());
- // handle rotation (R)
- if (machine.ui_input().pressed(IPT_UI_ROTATE))
- {
- state.tilemap.rotate = orientation_add(ROT90, state.tilemap.rotate);
- state.bitmap_dirty = true;
- }
+ // reallocate the bitmap if it is too small
+ resize_bitmap(cellxpix * xcells, cellypix * ycells);
- // return to (0,0) (HOME)
- if (machine.ui_input().pressed(IPT_UI_HOME))
+ // handle the redraw
+ if (m_bitmap_dirty)
{
- state.tilemap.xoffs = 0;
- state.tilemap.yoffs = 0;
- state.bitmap_dirty = true;
- }
+ // pre-fill with transparency
+ m_bitmap.fill(0);
- // handle flags (category)
- if (machine.ui_input().pressed(IPT_UI_PAGE_UP) && state.tilemap.flags != TILEMAP_DRAW_ALL_CATEGORIES)
- {
- if (state.tilemap.flags > 0)
- {
- state.tilemap.flags--;
- machine.popmessage("Category = %d", state.tilemap.flags);
- }
- else
+ // loop over rows
+ for (int y = 0, index = set.m_offset; y < ycells; y++)
{
- state.tilemap.flags = TILEMAP_DRAW_ALL_CATEGORIES;
- machine.popmessage("Category All");
+ // make a rectangle that covers this row
+ rectangle cellbounds(0, m_bitmap.width() - 1, y * cellypix, (y + 1) * cellypix - 1);
+
+ // only display if there is data to show
+ if (index < gfx.elements())
+ {
+ // draw the individual cells
+ for (int x = 0; x < xcells; x++, index++)
+ {
+ // update the bounds for this cell
+ cellbounds.min_x = x * cellxpix;
+ cellbounds.max_x = (x + 1) * cellxpix - 1;
+
+ if (index < gfx.elements()) // only render if there is data
+ gfxset_draw_item(gfx, index, cellbounds.min_x, cellbounds.min_y, set);
+ else // otherwise, fill with transparency
+ m_bitmap.fill(0, cellbounds);
+ }
+ }
}
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed(IPT_UI_PAGE_DOWN) && (state.tilemap.flags < TILEMAP_DRAW_CATEGORY_MASK || (state.tilemap.flags == TILEMAP_DRAW_ALL_CATEGORIES)))
- {
- if (state.tilemap.flags == TILEMAP_DRAW_ALL_CATEGORIES)
- state.tilemap.flags = 0;
- else
- state.tilemap.flags++;
- state.bitmap_dirty = true;
- machine.popmessage("Category = %d", state.tilemap.flags);
- }
- // handle navigation (up,down,left,right), taking orientation into account
- int step = 8; // this may be applied more than once if multiple directions are pressed
- if (machine.input().code_pressed(KEYCODE_LSHIFT)) step = 1;
- if (machine.input().code_pressed(KEYCODE_LCONTROL)) step = 64;
- if (machine.ui_input().pressed_repeat(IPT_UI_UP, 4))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.xoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- else
- state.tilemap.yoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed_repeat(IPT_UI_DOWN, 4))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.xoffs += (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- else
- state.tilemap.yoffs += (state.tilemap.rotate & ORIENTATION_FLIP_Y) ? -step : step;
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed_repeat(IPT_UI_LEFT, 6))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.yoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- else
- state.tilemap.xoffs -= (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- state.bitmap_dirty = true;
- }
- if (machine.ui_input().pressed_repeat(IPT_UI_RIGHT, 6))
- {
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
- state.tilemap.yoffs += (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- else
- state.tilemap.xoffs += (state.tilemap.rotate & ORIENTATION_FLIP_X) ? -step : step;
- state.bitmap_dirty = true;
+ // reset the texture to force an update
+ m_texture->set_bitmap(m_bitmap, m_bitmap.cliprect(), TEXFORMAT_ARGB32);
+ m_bitmap_dirty = false;
}
-
- // clamp within range
- while (state.tilemap.xoffs < 0)
- state.tilemap.xoffs += mapwidth;
- while (state.tilemap.xoffs >= mapwidth)
- state.tilemap.xoffs -= mapwidth;
- while (state.tilemap.yoffs < 0)
- state.tilemap.yoffs += mapheight;
- while (state.tilemap.yoffs >= mapheight)
- state.tilemap.yoffs -= mapheight;
}
-//-------------------------------------------------
-// tilemap_update_bitmap - update the bitmap
-// for the tilemap view
-//-------------------------------------------------
-
-static void tilemap_update_bitmap(running_machine &machine, ui_gfx_state &state, int width, int height)
+void gfx_viewer::update_tilemap_bitmap(int width, int height)
{
// swap the coordinates back if they were talking about a rotated surface
- if (state.tilemap.rotate & ORIENTATION_SWAP_XY)
+ if (m_tilemap.rotate() & ORIENTATION_SWAP_XY)
std::swap(width, height);
- // realloc the bitmap if it is too small
- if (!state.bitmap.valid() || state.texture == nullptr || state.bitmap.width() != width || state.bitmap.height() != height)
- {
- // free the old stuff
- machine.render().texture_free(state.texture);
- state.bitmap.reset();
+ // reallocate the bitmap if it is too small
+ resize_bitmap(width, height);
- // allocate new stuff
- state.bitmap.allocate(width, height);
- state.texture = machine.render().texture_alloc();
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_RGB32);
+ // handle the redraw
+ if (m_bitmap_dirty)
+ {
+ m_bitmap.fill(0);
+ tilemap_t &tilemap = *m_machine.tilemap().find(m_tilemap.index());
+ screen_device *const first_screen = screen_device_enumerator(m_machine.root_device()).first();
+ if (first_screen)
+ tilemap.draw_debug(*first_screen, m_bitmap, m_tilemap.xoffs(), m_tilemap.yoffs(), m_tilemap.flags());
- // force a redraw
- state.bitmap_dirty = true;
+ // reset the texture to force an update
+ m_texture->set_bitmap(m_bitmap, m_bitmap.cliprect(), TEXFORMAT_RGB32);
+ m_bitmap_dirty = false;
}
+}
- // handle the redraw
- if (state.bitmap_dirty)
+
+void gfx_viewer::gfxset_draw_item(gfx_element &gfx, int index, int dstx, int dsty, gfxset::setinfo const &info)
+{
+ int const width = (info.m_rotate & ORIENTATION_SWAP_XY) ? gfx.height() : gfx.width();
+ int const height = (info.m_rotate & ORIENTATION_SWAP_XY) ? gfx.width() : gfx.height();
+ rgb_t const *const palette = info.m_palette->palette()->entry_list_raw() + gfx.colorbase() + info.m_color * gfx.granularity();
+ uint8_t const *const src = gfx.get_data(index);
+
+ // loop over rows in the cell
+ for (int y = 0; y < height; y++)
{
- state.bitmap.fill(0);
- tilemap_t *tilemap = machine.tilemap().find(state.tilemap.which);
- screen_device *first_screen = screen_device_iterator(machine.root_device()).first();
- if (first_screen)
+ uint32_t *dest = &m_bitmap.pix(dsty + y, dstx);
+
+ // loop over columns in the cell
+ for (int x = 0; x < width; x++)
{
- tilemap->draw_debug(*first_screen, state.bitmap, state.tilemap.xoffs, state.tilemap.yoffs, state.tilemap.flags);
- }
+ // compute effective x,y values after rotation
+ int effx = x, effy = y;
+ if (!(info.m_rotate & ORIENTATION_SWAP_XY))
+ {
+ if (info.m_rotate & ORIENTATION_FLIP_X)
+ effx = gfx.width() - 1 - effx;
+ if (info.m_rotate & ORIENTATION_FLIP_Y)
+ effy = gfx.height() - 1 - effy;
+ }
+ else
+ {
+ if (info.m_rotate & ORIENTATION_FLIP_X)
+ effx = gfx.height() - 1 - effx;
+ if (info.m_rotate & ORIENTATION_FLIP_Y)
+ effy = gfx.width() - 1 - effy;
+ std::swap(effx, effy);
+ }
- // reset the texture to force an update
- state.texture->set_bitmap(state.bitmap, state.bitmap.cliprect(), TEXFORMAT_RGB32);
- state.bitmap_dirty = false;
+ // get a pointer to the start of this source row
+ uint8_t const *const s = src + (effy * gfx.rowbytes());
+
+ // extract the pixel
+ *dest++ = 0xff000000 | palette[s[effx]];
+ }
}
}
+
+} // anonymous namespace
+
+
+
+/***************************************************************************
+ MAIN ENTRY POINT
+***************************************************************************/
+
+//-------------------------------------------------
+// ui_gfx_ui_handler - primary UI handler
+//
+// NOTE: this must not be called before machine
+// initialization is complete, as some drivers
+// create or modify gfx sets in VIDEO_START
+//-------------------------------------------------
+
+uint32_t ui_gfx_ui_handler(render_container &container, mame_ui_manager &mui, bool uistate)
+{
+ return mui.get_session_data<gfx_viewer, gfx_viewer>(mui.machine()).handle(mui, container, uistate);
+}