diff options
Diffstat (limited to 'src/frontend/mame/ui/ui.cpp')
-rw-r--r-- | src/frontend/mame/ui/ui.cpp | 904 |
1 files changed, 673 insertions, 231 deletions
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 663354420d2..e697f861da2 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -33,33 +33,26 @@ #include "emuopts.h" #include "mameopts.h" #include "drivenum.h" +#include "fileio.h" #include "natkeyboard.h" #include "render.h" #include "cheat.h" #include "rendfont.h" +#include "rendlay.h" #include "romload.h" +#include "screen.h" +#include "speaker.h" #include "uiinput.h" +// FIXME: allow OSD module headers to be included in a less ugly way +#include "../osd/modules/lib/osdlib.h" #include "../osd/modules/lib/osdobj_common.h" -#include <chrono> #include <functional> #include <type_traits> /*************************************************************************** - CONSTANTS -***************************************************************************/ - -enum -{ - LOADSAVE_NONE, - LOADSAVE_LOAD, - LOADSAVE_SAVE -}; - - -/*************************************************************************** LOCAL VARIABLES ***************************************************************************/ @@ -160,6 +153,63 @@ static uint32_t const mouse_bitmap[32*32] = }; +enum class mame_ui_manager::ui_callback_type : int +{ + NOINPUT, + GENERAL, + MODAL, + MENU, + CUSTOM +}; + + +struct mame_ui_manager::active_pointer +{ + active_pointer(ui_event const &event) + : target(event.target) + , updated(std::chrono::steady_clock::time_point::min()) + , type(event.pointer_type) + , ptrid(event.pointer_id) + , x(-1.0F) + , y(-1.0F) + { + } + + bool operator<(std::pair<render_target *, u16> const &val) const noexcept + { + return std::make_pair(target, ptrid) < val; + } + + render_target *target; + std::chrono::steady_clock::time_point updated; + osd::ui_event_handler::pointer type; + u16 ptrid; + float x, y; +}; + + +struct mame_ui_manager::pointer_options +{ + pointer_options() + : timeout(std::chrono::seconds(3)) + , hide_inactive(true) + , timeout_set(false) + , hide_inactive_set(false) + { + } + + bool options_set() const + { + return timeout_set || hide_inactive_set; + } + + std::chrono::steady_clock::duration timeout; + bool hide_inactive; + bool timeout_set; + bool hide_inactive_set; +}; + + //------------------------------------------------- // ctor - set up the user interface //------------------------------------------------- @@ -168,8 +218,8 @@ mame_ui_manager::mame_ui_manager(running_machine &machine) : ui_manager(machine) , m_font() , m_handler_callback() - , m_handler_callback_type(ui_callback_type::GENERAL) - , m_handler_param(0) + , m_handler_callback_type(ui_callback_type::NOINPUT) + , m_ui_active(true) , m_single_step(false) , m_showfps(false) , m_showfps_end(0) @@ -177,16 +227,18 @@ mame_ui_manager::mame_ui_manager(running_machine &machine) , m_popup_text_end(0) , m_mouse_bitmap(32, 32) , m_mouse_arrow_texture(nullptr) - , m_mouse_show(false) + , m_pointers_changed(false) , m_target_font_height(0) , m_has_warnings(false) , m_unthrottle_mute(false) + , m_image_display_enabled(true) , m_machine_info() , m_unemulated_features() , m_imperfect_features() , m_last_launch_time(std::time_t(-1)) , m_last_warning_time(std::time_t(-1)) -{ } +{ +} mame_ui_manager::~mame_ui_manager() { @@ -200,8 +252,6 @@ void mame_ui_manager::init() ui::system_list::instance().cache_data(options()); // initialize the other UI bits - ui_gfx_init(machine()); - m_ui_colors.refresh(options()); // update font row info from setting @@ -209,7 +259,7 @@ void mame_ui_manager::init() // more initialization set_handler( - ui_callback_type::GENERAL, + ui_callback_type::NOINPUT, handler_callback_func( [this] (render_container &container) -> uint32_t { @@ -217,14 +267,18 @@ void mame_ui_manager::init() return 0; })); m_non_char_keys_down = std::make_unique<uint8_t[]>((std::size(non_char_keys) + 7) / 8); - m_mouse_show = machine().system().flags & machine_flags::CLICKABLE_ARTWORK ? true : false; // request notification callbacks + machine().add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(&mame_ui_manager::frame_update, this)); machine().add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&mame_ui_manager::exit, this)); machine().configuration().config_register( "ui_warnings", - configuration_manager::load_delegate(&mame_ui_manager::config_load, this), - configuration_manager::save_delegate(&mame_ui_manager::config_save, this)); + configuration_manager::load_delegate(&mame_ui_manager::config_load_warnings, this), + configuration_manager::save_delegate(&mame_ui_manager::config_save_warnings, this)); + machine().configuration().config_register( + "pointer_input", + configuration_manager::load_delegate(&mame_ui_manager::config_load_pointers, this), + configuration_manager::save_delegate(&mame_ui_manager::config_save_pointers, this)); // create mouse bitmap uint32_t *dst = &m_mouse_bitmap.pix(0); @@ -245,6 +299,25 @@ void mame_ui_manager::update_target_font_height() //------------------------------------------------- +// exit - called for each emulated frame +//------------------------------------------------- + +void mame_ui_manager::frame_update() +{ + // this hackery is needed to ensure natural keyboard and clickable artwork input is in sync with I/O ports + if (ui_callback_type::GENERAL == m_handler_callback_type) + { + process_ui_events(); + for (auto *target = machine().render().first_target(); target; target = target->next()) + { + if (!target->hidden()) + target->update_pointer_fields(); + } + } +} + + +//------------------------------------------------- // exit - clean up ourselves on exit //------------------------------------------------- @@ -263,10 +336,14 @@ void mame_ui_manager::exit() //------------------------------------------------- -// config_load - load configuration data +// config_load_warnings - load info on last time +// emulation status warnings showed //------------------------------------------------- -void mame_ui_manager::config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode) +void mame_ui_manager::config_load_warnings( + config_type cfg_type, + config_level cfg_level, + util::xml::data_node const *parentnode) { // make sure it's relevant and there's data available if (config_type::SYSTEM == cfg_type) @@ -304,10 +381,13 @@ void mame_ui_manager::config_load(config_type cfg_type, config_level cfg_level, //------------------------------------------------- -// config_save - save configuration data +// config_save_warnings - save information on +// last time emulation status warnings showed //------------------------------------------------- -void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *parentnode) +void mame_ui_manager::config_save_warnings( + config_type cfg_type, + util::xml::data_node *parentnode) { // only save system-level configuration when times are valid if ((config_type::SYSTEM == cfg_type) && (std::time_t(-1) != m_last_launch_time) && (std::time_t(-1) != m_last_warning_time)) @@ -335,12 +415,108 @@ void mame_ui_manager::config_save(config_type cfg_type, util::xml::data_node *pa //------------------------------------------------- +// config_load_pointers - load pointer input +// settings +//------------------------------------------------- + +void mame_ui_manager::config_load_pointers( + config_type cfg_type, + config_level cfg_level, + util::xml::data_node const *parentnode) +{ + switch (cfg_type) + { + case config_type::INIT: + { + int last(-1); + for (auto const &target : machine().render().targets()) + { + assert(target.index() >= 0); + if (!target.hidden()) + last = (std::max)(target.index(), last); + } + m_pointer_options.resize(last + 1); + } + break; + + case config_type::CONTROLLER: + case config_type::SYSTEM: + if (!parentnode) + break; + for (auto const *targetnode = parentnode->get_child("target"); targetnode; targetnode = targetnode->get_next_sibling("target")) + { + auto const index(targetnode->get_attribute_int("index", -1)); + if ((0 <= index) && (m_pointer_options.size() > index)) + { + auto const timeout(targetnode->get_attribute_float("activity_timeout", -1.0F)); + auto const ms(std::lround(timeout * 1000.0F)); + if ((100 <= ms) && (10'000 >= ms)) + { + m_pointer_options[index].timeout = std::chrono::milliseconds(ms); + if (config_type::SYSTEM == cfg_type) + m_pointer_options[index].timeout_set = true; + } + + auto const hide(targetnode->get_attribute_int("hide_inactive", -1)); + if (0 <= hide) + { + m_pointer_options[index].hide_inactive = hide != 0; + if (config_type::SYSTEM == cfg_type) + m_pointer_options[index].hide_inactive_set = true; + } + } + } + break; + + case config_type::DEFAULT: + case config_type::FINAL: + break; + } +} + + +//------------------------------------------------- +// config_save_pointers - save pointer input +// settings +//------------------------------------------------- + +void mame_ui_manager::config_save_pointers( + config_type cfg_type, + util::xml::data_node *parentnode) +{ + if (config_type::SYSTEM == cfg_type) + { + for (std::size_t i = 0; m_pointer_options.size() > i; ++i) + { + pointer_options const &options(m_pointer_options[i]); + if (options.options_set()) + { + util::xml::data_node *const targetnode = parentnode->add_child("target", nullptr); + if (targetnode) + { + targetnode->set_attribute_int("index", i); + if (options.timeout_set) + { + auto const ms(std::chrono::duration_cast<std::chrono::milliseconds>(options.timeout)); + targetnode->set_attribute_float("activity_timeout", float(ms.count()) * 0.001F); + } + if (options.hide_inactive_set) + targetnode->set_attribute_int("hide_inactive", options.hide_inactive); + } + } + } + } +} + + +//------------------------------------------------- // initialize - initialize ui lists //------------------------------------------------- void mame_ui_manager::initialize(running_machine &machine) { m_machine_info = std::make_unique<ui::machine_info>(machine); + set_ui_active(!machine_info().has_keyboard() || machine.options().ui_active()); // initialize the on-screen display system slider_list = slider_init(machine); @@ -351,7 +527,7 @@ void mame_ui_manager::initialize(running_machine &machine) const char *const service_mode_dipname = ioport_configurer::string_from_token(DEF_STR(Service_Mode)); for (auto &port : machine.ioport().ports()) for (ioport_field &field : port.second->fields()) - if (field.type() == IPT_DIPSWITCH && strcmp(field.name(), service_mode_dipname) == 0) + if ((field.type() == IPT_DIPSWITCH) && (field.name() == service_mode_dipname)) // FIXME: probably breaks with localisation, also issues with multiple devices field.set_defseq(machine.ioport().type_seq(IPT_SERVICE)); } @@ -371,6 +547,12 @@ void mame_ui_manager::initialize(running_machine &machine) void mame_ui_manager::set_handler(ui_callback_type callback_type, handler_callback_func &&callback) { + m_active_pointers.clear(); + if (!m_display_pointers.empty()) + { + m_display_pointers.clear(); + m_pointers_changed = true; + } m_handler_callback = std::move(callback); m_handler_callback_type = callback_type; } @@ -434,17 +616,17 @@ void mame_ui_manager::display_startup_screens(bool first_time) { // if the user cancels, exit out completely machine().schedule_exit(); - return UI_HANDLER_CANCEL; + return HANDLER_CANCEL; } - else if (machine().ui_input().pressed(IPT_UI_CONFIGURE)) + else if (machine().ui_input().pressed(IPT_UI_MENU)) { config_menu = true; - return UI_HANDLER_CANCEL; + return HANDLER_CANCEL; } else if (poller.poll() != INPUT_CODE_INVALID) { // if any key is pressed, just exit - return UI_HANDLER_CANCEL; + return HANDLER_CANCEL; } return 0; @@ -551,7 +733,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) if (!mandatory_images.empty() && show_mandatory_fileman) { std::ostringstream warning; - warning << _("This driver requires images to be loaded in the following device(s): "); + warning << _("This system requires media images to be mounted for the following device(s): "); output_joined_collection(mandatory_images, [&warning](const std::reference_wrapper<const std::string> &img) { warning << "\"" << img.get() << "\""; }, @@ -627,10 +809,14 @@ void mame_ui_manager::set_startup_text(const char *text, bool force) // render it; called by video.c //------------------------------------------------- -void mame_ui_manager::update_and_render(render_container &container) +bool mame_ui_manager::update_and_render(render_container &container) { // always start clean - container.empty(); + for (auto &target : machine().render().targets()) + { + if (target.ui_container()) + target.ui_container()->empty(); + } // if we're paused, dim the whole screen if (machine().phase() >= machine_phase::RESET && (single_step() || machine().paused())) @@ -662,8 +848,13 @@ void mame_ui_manager::update_and_render(render_container &container) if (machine().phase() >= machine_phase::RESET) mame_machine_manager::instance()->cheat().render_text(*this, container); + // draw the FPS counter if it should be visible + if (show_fps_counter()) + draw_fps_counter(container); + // call the current UI handler - m_handler_param = m_handler_callback(container); + machine().ui_input().check_ui_inputs(); + uint32_t const handler_result = m_handler_callback(container); // display any popup messages if (osd_ticks() < m_popup_text_end) @@ -671,29 +862,34 @@ void mame_ui_manager::update_and_render(render_container &container) else m_popup_text_end = 0; - // display the internal mouse cursor - if (m_mouse_show || (is_menu_active() && machine().options().ui_mouse())) + // display the internal pointers + bool const pointer_update = m_pointers_changed; + m_pointers_changed = false; + if (!is_menu_active() || machine().options().ui_mouse()) { - int32_t mouse_target_x, mouse_target_y; - bool mouse_button; - render_target *mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); - - if (mouse_target != nullptr) + const float cursor_size = 0.6 * get_line_height(); + for (auto const &pointer : m_display_pointers) { - float mouse_y=-1,mouse_x=-1; - if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, container, mouse_x, mouse_y)) - { - const float cursor_size = 0.6 * get_line_height(); - container.add_quad(mouse_x, mouse_y, mouse_x + cursor_size * container.manager().ui_aspect(&container), mouse_y + cursor_size, colors().text_color(), m_mouse_arrow_texture, PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - } + render_container &container = *pointer.target.get().ui_container(); + container.add_quad( + pointer.x, + pointer.y, + pointer.x + cursor_size * container.manager().ui_aspect(&container), + pointer.y + cursor_size, + rgb_t::white(), + m_mouse_arrow_texture, + PRIMFLAG_ANTIALIAS(1) | PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); } } - // cancel takes us back to the ingame handler - if (m_handler_param == UI_HANDLER_CANCEL) + // cancel takes us back to the in-game handler + if (handler_result & HANDLER_CANCEL) { + machine().ui_input().reset(); set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_ingame, this)); } + + return pointer_update || (handler_result & HANDLER_UPDATE); } @@ -715,19 +911,16 @@ render_font *mame_ui_manager::get_font() // of a line //------------------------------------------------- -float mame_ui_manager::get_line_height() +float mame_ui_manager::get_line_height(float scale) { - int32_t raw_font_pixel_height = get_font()->pixel_height(); - render_target &ui_target = machine().render().ui_target(); - int32_t target_pixel_height = ui_target.height(); - float one_to_one_line_height; - float scale_factor; + int32_t const raw_font_pixel_height = get_font()->pixel_height(); + float target_pixel_height = machine().render().ui_target().height(); // compute the font pixel height at the nominal size - one_to_one_line_height = (float)raw_font_pixel_height / (float)target_pixel_height; + float const one_to_one_line_height = float(raw_font_pixel_height) / target_pixel_height; // determine the scale factor - scale_factor = target_font_height() / one_to_one_line_height; + float scale_factor = target_font_height() * scale / one_to_one_line_height; // if our font is small-ish, do integral scaling if (raw_font_pixel_height < 24) @@ -738,17 +931,17 @@ float mame_ui_manager::get_line_height() if (one_to_one_line_height < UI_MAX_FONT_HEIGHT || raw_font_pixel_height < 12) scale_factor = 1.0f; } - - // otherwise, just ensure an integral scale factor else - scale_factor = floor(scale_factor); + { + // otherwise, just ensure an integral scale factor + scale_factor = floorf(scale_factor); + } } - - // otherwise, just make sure we hit an even number of pixels else { - int32_t height = scale_factor * one_to_one_line_height * (float)target_pixel_height; - scale_factor = (float)height / (one_to_one_line_height * (float)target_pixel_height); + // otherwise, just make sure we hit an even number of pixels + int32_t height = scale_factor * one_to_one_line_height * target_pixel_height; + scale_factor = float(height) / (one_to_one_line_height * target_pixel_height); } return scale_factor * one_to_one_line_height; @@ -771,9 +964,14 @@ float mame_ui_manager::get_char_width(char32_t ch) // character string //------------------------------------------------- +float mame_ui_manager::get_string_width(std::string_view s) +{ + return get_string_width(s, get_line_height()); +} + float mame_ui_manager::get_string_width(std::string_view s, float text_size) { - return get_font()->utf8string_width(get_line_height() * text_size, machine().render().ui_aspect(), s); + return get_font()->utf8string_width(text_size, machine().render().ui_aspect(), s); } @@ -832,18 +1030,37 @@ void mame_ui_manager::draw_text_full( float x, float y, float origwrapwidth, ui::text_layout::text_justify justify, ui::text_layout::word_wrapping wrap, draw_mode draw, rgb_t fgcolor, rgb_t bgcolor, + float *totalwidth, float *totalheight) +{ + draw_text_full( + container, + origs, + x, y, origwrapwidth, + justify, wrap, + draw, fgcolor, bgcolor, + totalwidth, totalheight, + get_line_height()); +} + +void mame_ui_manager::draw_text_full( + render_container &container, + std::string_view origs, + float x, float y, float origwrapwidth, + ui::text_layout::text_justify justify, ui::text_layout::word_wrapping wrap, + draw_mode draw, rgb_t fgcolor, rgb_t bgcolor, float *totalwidth, float *totalheight, float text_size) { // create the layout - auto layout = create_layout(container, origwrapwidth, justify, wrap); + ui::text_layout layout( + *get_font(), machine().render().ui_aspect(&container) * text_size, text_size, + origwrapwidth, justify, wrap); // append text to it layout.add_text( origs, fgcolor, - (draw == OPAQUE_) ? bgcolor : rgb_t::transparent(), - text_size); + (draw == OPAQUE_) ? bgcolor : rgb_t::transparent()); // and emit it (if we are asked to do so) if (draw != NONE) @@ -924,7 +1141,7 @@ void mame_ui_manager::draw_message_window(render_container &container, std::stri void mame_ui_manager::show_fps_temp(double seconds) { if (!m_showfps) - m_showfps_end = osd_ticks() + seconds * osd_ticks_per_second(); + m_showfps_end = std::max<osd_ticks_t>(osd_ticks() + seconds * osd_ticks_per_second(), m_showfps_end); } @@ -936,10 +1153,7 @@ void mame_ui_manager::set_show_fps(bool show) { m_showfps = show; if (!show) - { - m_showfps = 0; m_showfps_end = 0; - } } @@ -960,7 +1174,7 @@ bool mame_ui_manager::show_fps() const bool mame_ui_manager::show_fps_counter() { - bool result = m_showfps || osd_ticks() < m_showfps_end; + bool const result = m_showfps || (osd_ticks() < m_showfps_end); if (!result) m_showfps_end = 0; return result; @@ -995,17 +1209,13 @@ bool mame_ui_manager::show_profiler() const void mame_ui_manager::show_menu() { - set_handler(ui_callback_type::MENU, ui::menu::get_ui_handler(*this)); -} - - -//------------------------------------------------- -// show_mouse - change mouse status -//------------------------------------------------- + for (auto *target = machine().render().first_target(); target; target = target->next()) + { + if (!target->hidden()) + target->forget_pointers(); + } -void mame_ui_manager::show_mouse(bool status) -{ - m_mouse_show = status; + set_handler(ui_callback_type::MENU, ui::menu::get_ui_handler(*this)); } @@ -1014,10 +1224,9 @@ void mame_ui_manager::show_mouse(bool status) // UI handler is active //------------------------------------------------- -bool mame_ui_manager::is_menu_active(void) +bool mame_ui_manager::is_menu_active() { - return m_handler_callback_type == ui_callback_type::MENU - || m_handler_callback_type == ui_callback_type::VIEWER; + return m_handler_callback_type == ui_callback_type::MENU; } @@ -1027,48 +1236,113 @@ bool mame_ui_manager::is_menu_active(void) ***************************************************************************/ //------------------------------------------------- -// process_natural_keyboard - processes any -// natural keyboard input +// process_ui_events - processes queued UI input +// events //------------------------------------------------- -void mame_ui_manager::process_natural_keyboard() +void mame_ui_manager::process_ui_events() { + // process UI events + bool const use_natkbd(machine().natkeyboard().in_use() && (machine().phase() == machine_phase::RUNNING)); ui_event event; - - // loop while we have interesting events while (machine().ui_input().pop_event(&event)) { - // if this was a UI_EVENT_CHAR event, post it - if (event.event_type == ui_event::type::IME_CHAR) - machine().natkeyboard().post_char(event.ch); - } + switch (event.event_type) + { + case ui_event::type::NONE: + case ui_event::type::WINDOW_FOCUS: + case ui_event::type::WINDOW_DEFOCUS: + case ui_event::type::MOUSE_WHEEL: + break; - // process natural keyboard keys that don't get UI_EVENT_CHARs - for (int i = 0; i < std::size(non_char_keys); i++) - { - // identify this keycode - input_item_id itemid = non_char_keys[i]; - input_code code = machine().input().code_from_itemid(itemid); + case ui_event::type::POINTER_UPDATE: + if (event.target) + { + if (osd::ui_event_handler::pointer::TOUCH != event.pointer_type) + { + auto pos(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), std::make_pair(event.target, event.pointer_id))); + if ((m_active_pointers.end() == pos) || (pos->target != event.target) || (pos->ptrid != event.pointer_id)) + pos = m_active_pointers.emplace(pos, event); + else + assert(pos->type == event.pointer_type); + pos->updated = std::chrono::steady_clock::now(); + event.target->map_point_container(event.pointer_x, event.pointer_y, *event.target->ui_container(), pos->x, pos->y); + } - // ...and determine if it is pressed - bool pressed = machine().input().code_pressed(code); + event.target->pointer_updated( + event.pointer_type, event.pointer_id, event.pointer_device, + event.pointer_x, event.pointer_y, + event.pointer_buttons, event.pointer_pressed, event.pointer_released, + event.pointer_clicks); + } + break; - // figure out whey we are in the key_down map - uint8_t *key_down_ptr = &m_non_char_keys_down[i / 8]; - uint8_t key_down_mask = 1 << (i % 8); + case ui_event::type::POINTER_LEAVE: + if (event.target) + { + auto const pos(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), std::make_pair(event.target, event.pointer_id))); + if (m_active_pointers.end() != pos) + m_active_pointers.erase(pos); + + event.target->pointer_left( + event.pointer_type, event.pointer_id, event.pointer_device, + event.pointer_x, event.pointer_y, + event.pointer_released, + event.pointer_clicks); + } + break; - if (pressed && !(*key_down_ptr & key_down_mask)) - { - // this key is now down - *key_down_ptr |= key_down_mask; + case ui_event::type::POINTER_ABORT: + if (event.target) + { + auto const pos(std::lower_bound(m_active_pointers.begin(), m_active_pointers.end(), std::make_pair(event.target, event.pointer_id))); + if (m_active_pointers.end() != pos) + m_active_pointers.erase(pos); + + event.target->pointer_aborted( + event.pointer_type, event.pointer_id, event.pointer_device, + event.pointer_x, event.pointer_y, + event.pointer_released, + event.pointer_clicks); + } + break; - // post the key - machine().natkeyboard().post_char(UCHAR_MAMEKEY_BEGIN + code.item_id()); + case ui_event::type::IME_CHAR: + if (use_natkbd) + machine().natkeyboard().post_char(event.ch); + break; } - else if (!pressed && (*key_down_ptr & key_down_mask)) + } + + // process natural keyboard keys that don't get IME text input events + if (use_natkbd) + { + for (int i = 0; i < std::size(non_char_keys); i++) { - // this key is now up - *key_down_ptr &= ~key_down_mask; + // identify this keycode + input_item_id itemid = non_char_keys[i]; + input_code code = machine().input().code_from_itemid(itemid); + + // ...and determine if it is pressed + bool pressed = machine().input().code_pressed(code); + + // figure out whey we are in the key_down map + uint8_t *key_down_ptr = &m_non_char_keys_down[i / 8]; + uint8_t key_down_mask = 1 << (i % 8); + + if (pressed && !(*key_down_ptr & key_down_mask)) + { + // this key is now down + *key_down_ptr |= key_down_mask; + + // post the key + machine().natkeyboard().post_char(UCHAR_MAMEKEY_BEGIN + code.item_id()); + } + else if (!pressed && (*key_down_ptr & key_down_mask)) + { + // this key is now up + *key_down_ptr &= ~key_down_mask; + } } } } @@ -1115,6 +1389,7 @@ void mame_ui_manager::decrease_frameskip() bool mame_ui_manager::can_paste() { // check to see if the clipboard is not empty + // FIXME: this is expensive - need a cheaper way to check if clipboard contains suitable content return !osd_get_clipboard_text().empty(); } @@ -1151,28 +1426,6 @@ void mame_ui_manager::draw_profiler(render_container &container) //------------------------------------------------- -// start_save_state -//------------------------------------------------- - -void mame_ui_manager::start_save_state() -{ - show_menu(); - ui::menu::stack_push<ui::menu_save_state>(*this, machine().render().ui_container(), true); -} - - -//------------------------------------------------- -// start_load_state -//------------------------------------------------- - -void mame_ui_manager::start_load_state() -{ - show_menu(); - ui::menu::stack_push<ui::menu_load_state>(*this, machine().render().ui_container(), true); -} - - -//------------------------------------------------- // image_handler_ingame - execute display // callback function for each image device //------------------------------------------------- @@ -1180,7 +1433,7 @@ void mame_ui_manager::start_load_state() void mame_ui_manager::image_handler_ingame() { // run display routine for devices - if (machine().phase() == machine_phase::RUNNING) + if (m_image_display_enabled && machine().phase() == machine_phase::RUNNING) { auto layout = create_layout(machine().render().ui_container()); @@ -1212,11 +1465,10 @@ void mame_ui_manager::image_handler_ingame() uint32_t mame_ui_manager::handler_ingame(render_container &container) { - bool is_paused = machine().paused(); + // let the OSD do its thing first + machine().osd().check_osd_inputs(); - // first draw the FPS counter - if (show_fps_counter()) - draw_fps_counter(container); + bool is_paused = machine().paused(); // draw the profiler if visible if (show_profiler()) @@ -1230,8 +1482,8 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) } // determine if we should disable the rest of the UI - bool has_keyboard = machine_info().has_keyboard(); - bool ui_disabled = (has_keyboard && !machine().ui_active()); + bool const has_keyboard = machine_info().has_keyboard(); + bool const ui_disabled = !ui_active(); // is ScrLk UI toggling applicable here? if (has_keyboard) @@ -1240,20 +1492,42 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) if (machine().ui_input().pressed(IPT_UI_TOGGLE_UI)) { // toggle the UI - machine().set_ui_active(!machine().ui_active()); + set_ui_active(!ui_active()); // display a popup indicating the new status std::string const name = get_general_input_setting(IPT_UI_TOGGLE_UI); - if (machine().ui_active()) + if (ui_active()) popup_time(2, _("UI controls enabled\nUse %1$s to toggle"), name); else popup_time(2, _("UI controls disabled\nUse %1$s to toggle"), name); } } - // is the natural keyboard enabled? - if (machine().natkeyboard().in_use() && (machine().phase() == machine_phase::RUNNING)) - process_natural_keyboard(); + // process UI events and update pointers if necessary + process_ui_events(); + display_pointer_vector pointers; + pointers.reserve(m_active_pointers.size()); + auto const now(std::chrono::steady_clock::now()); + auto expiry(now); + render_target *target(nullptr); + layout_view const *view(nullptr); + bool hide_inactive(true); + for (auto const &pointer : m_active_pointers) + { + if (pointer.target != target) + { + target = pointer.target; + view = &target->current_view(); + hide_inactive = m_pointer_options[target->index()].hide_inactive && view->hide_inactive_pointers(); + expiry = now - m_pointer_options[target->index()].timeout; + } + if (view->show_pointers()) + { + if (!hide_inactive || (osd::ui_event_handler::pointer::PEN == pointer.type) || (pointer.updated >= expiry)) + pointers.emplace_back(display_pointer{ *target, pointer.type, pointer.x, pointer.y }); + } + } + set_pointers(pointers.begin(), pointers.end()); if (!ui_disabled) { @@ -1265,7 +1539,7 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) image_handler_ingame(); if (ui_disabled) - return ui_disabled; + return 0; if (machine().ui_input().pressed(IPT_UI_CANCEL)) { @@ -1274,7 +1548,7 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) } // turn on menus if requested - if (machine().ui_input().pressed(IPT_UI_CONFIGURE)) + if (machine().ui_input().pressed(IPT_UI_MENU)) { show_menu(); return 0; @@ -1284,8 +1558,8 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) if (!(machine().debug_flags & DEBUG_FLAG_ENABLED) && machine().ui_input().pressed(IPT_UI_ON_SCREEN_DISPLAY)) { ui::menu::stack_push<ui::menu_sliders>(*this, machine().render().ui_container(), true); - set_handler(ui_callback_type::MENU, ui::menu::get_ui_handler(*this)); - return 1; + show_menu(); + return 0; } // handle a reset request @@ -1297,17 +1571,23 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) // handle a request to display graphics/palette if (machine().ui_input().pressed(IPT_UI_SHOW_GFX)) { + for (auto *target = machine().render().first_target(); target; target = target->next()) + { + if (!target->hidden()) + target->forget_pointers(); + } + if (!is_paused) machine().pause(); using namespace std::placeholders; set_handler( - ui_callback_type::VIEWER, + ui_callback_type::MENU, handler_callback_func( [this, is_paused] (render_container &container) -> uint32_t { return ui_gfx_ui_handler(container, *this, is_paused); })); - return is_paused ? 1 : 0; + return 0; } // handle a tape control key @@ -1331,15 +1611,31 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) // handle a save state request if (machine().ui_input().pressed(IPT_UI_SAVE_STATE)) { - start_save_state(); - return LOADSAVE_SAVE; + ui::menu::stack_push<ui::menu_save_state>(*this, machine().render().ui_container(), true); + show_menu(); + return 0; } // handle a load state request if (machine().ui_input().pressed(IPT_UI_LOAD_STATE)) { - start_load_state(); - return LOADSAVE_LOAD; + ui::menu::stack_push<ui::menu_load_state>(*this, machine().render().ui_container(), true); + show_menu(); + return 0; + } + + // handle a quick save state request + if (machine().ui_input().pressed(IPT_UI_SAVE_STATE_QUICK)) + { + machine().schedule_save("quick"); + return 0; + } + + // handle a quick load state request + if (machine().ui_input().pressed(IPT_UI_LOAD_STATE_QUICK)) + { + machine().schedule_load("quick"); + return 0; } // handle a save snapshot request @@ -1364,7 +1660,7 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) // handle a toggle cheats request if (machine().ui_input().pressed(IPT_UI_TOGGLE_CHEAT)) - mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled()); + mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled(), true); // toggle MNG recording if (machine().ui_input().pressed(IPT_UI_RECORD_MNG)) @@ -1424,12 +1720,76 @@ void mame_ui_manager::request_quit() } else { - show_menu(); ui::menu::stack_push<ui::menu_confirm_quit>(*this, machine().render().ui_container()); + show_menu(); + } +} + + +//------------------------------------------------- +// set_pointer_activity_timeout - set per-target +// pointer activity timeout +//------------------------------------------------- + +void mame_ui_manager::set_pointer_activity_timeout(int target, std::chrono::steady_clock::duration timeout) noexcept +{ + assert((0 <= target) && (m_pointer_options.size() > target)); + if ((0 <= target) && (m_pointer_options.size() > target)) + { + m_pointer_options[target].timeout = timeout; + m_pointer_options[target].timeout_set = true; + } +} + + +//------------------------------------------------- +// set_hide_inactive_pointers - set per-target +// hide inactive pointers setting +//------------------------------------------------- + +void mame_ui_manager::set_hide_inactive_pointers(int target, bool hide) noexcept +{ + assert((0 <= target) && (m_pointer_options.size() > target)); + if ((0 <= target) && (m_pointer_options.size() > target)) + { + m_pointer_options[target].hide_inactive = hide; + m_pointer_options[target].hide_inactive_set = true; } } +//------------------------------------------------- +// pointer_activity_timeout - get per-target +// pointer activity timeout +//------------------------------------------------- + +std::chrono::steady_clock::duration mame_ui_manager::pointer_activity_timeout(int target) const noexcept +{ + assert((0 <= target) && (m_pointer_options.size() > target)); + if ((0 <= target) && (m_pointer_options.size() > target)) + return m_pointer_options[target].timeout; + else + return pointer_options().timeout; +} + + + +//------------------------------------------------- +// hide_inactive_pointers - get per-target hide +// inactive pointers setting +//------------------------------------------------- + +bool mame_ui_manager::hide_inactive_pointers(int target) const noexcept +{ + assert((0 <= target) && (m_pointer_options.size() > target)); + if ((0 <= target) && (m_pointer_options.size() > target)) + return m_pointer_options[target].hide_inactive; + else + return pointer_options().hide_inactive; +} + + + /*************************************************************************** SLIDER CONTROLS ***************************************************************************/ @@ -1438,7 +1798,7 @@ void mame_ui_manager::request_quit() // ui_get_slider_list - get the list of sliders //------------------------------------------------- -std::vector<ui::menu_item>& mame_ui_manager::get_slider_list(void) +std::vector<ui::menu_item> &mame_ui_manager::get_slider_list() { return slider_list; } @@ -1462,11 +1822,16 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine mixer_input info; for (int item = 0; machine.sound().indexed_mixer_input(item, info); item++) { - int32_t maxval = 2000; - int32_t defval = 1000; - std::string str = string_format(_("%1$s Volume"), info.stream->input(info.inputnum).name()); - slider_alloc(std::move(str), 0, defval, maxval, 20, std::bind(&mame_ui_manager::slider_mixervol, this, item, _1, _2)); + slider_alloc(std::move(str), 0, 1000, 4000, 20, std::bind(&mame_ui_manager::slider_mixervol, this, item, _1, _2)); + } + + // add speaker panning + for (speaker_device &speaker : speaker_device_enumerator(machine.root_device())) + { + int defpan = floorf(speaker.defpan() * 1000.0f + 0.5f); + std::string str = string_format(_("%s '%s' Panning"), speaker.name(), speaker.tag()); + slider_alloc(std::move(str), -1000, defpan, 1000, 20, std::bind(&mame_ui_manager::slider_panning, this, std::ref(speaker), _1, _2)); } // add analog adjusters @@ -1476,8 +1841,7 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine { if (field.type() == IPT_ADJUSTER) { - slider_alloc(field.name(), field.minval(), field.defvalue(), field.maxval(), 1, - std::bind(&mame_ui_manager::slider_adjuster, this, std::ref(field), _1, _2)); + slider_alloc(field.name(), field.minval(), field.defvalue(), field.maxval(), 1, std::bind(&mame_ui_manager::slider_adjuster, this, std::ref(field), _1, _2)); } } } @@ -1505,10 +1869,10 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine screen_device_enumerator scriter(machine.root_device()); for (screen_device &screen : scriter) { - int defxscale = floor(screen.xscale() * 1000.0f + 0.5f); - int defyscale = floor(screen.yscale() * 1000.0f + 0.5f); - int defxoffset = floor(screen.xoffset() * 1000.0f + 0.5f); - int defyoffset = floor(screen.yoffset() * 1000.0f + 0.5f); + int defxscale = floorf(screen.xscale() * 1000.0f + 0.5f); + int defyscale = floorf(screen.yscale() * 1000.0f + 0.5f); + int defxoffset = floorf(screen.xoffset() * 1000.0f + 0.5f); + int defyoffset = floorf(screen.yoffset() * 1000.0f + 0.5f); std::string screen_desc = machine_info().get_screen_desc(screen); // add refresh rate tweaker @@ -1543,20 +1907,18 @@ std::vector<ui::menu_item> mame_ui_manager::slider_init(running_machine &machine { laserdisc_overlay_config config; laserdisc.get_overlay_config(config); - int defxscale = floor(config.m_overscalex * 1000.0f + 0.5f); - int defyscale = floor(config.m_overscaley * 1000.0f + 0.5f); - int defxoffset = floor(config.m_overposx * 1000.0f + 0.5f); - int defyoffset = floor(config.m_overposy * 1000.0f + 0.5f); + int defxscale = floorf(config.m_overscalex * 1000.0f + 0.5f); + int defyscale = floorf(config.m_overscaley * 1000.0f + 0.5f); + int defxoffset = floorf(config.m_overposx * 1000.0f + 0.5f); + int defyoffset = floorf(config.m_overposy * 1000.0f + 0.5f); // add scale and offset controls per-overlay std::string str = string_format(_("Laserdisc '%1$s' Horiz Stretch"), laserdisc.tag()); - slider_alloc(std::move(str), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, - std::bind(&mame_ui_manager::slider_overxscale, this, std::ref(laserdisc), _1, _2)); + slider_alloc(std::move(str), 500, (defxscale == 0) ? 1000 : defxscale, 1500, 2, std::bind(&mame_ui_manager::slider_overxscale, this, std::ref(laserdisc), _1, _2)); str = string_format(_("Laserdisc '%1$s' Horiz Position"), laserdisc.tag()); slider_alloc(std::move(str), -500, defxoffset, 500, 2, std::bind(&mame_ui_manager::slider_overxoffset, this, std::ref(laserdisc), _1, _2)); str = string_format(_("Laserdisc '%1$s' Vert Stretch"), laserdisc.tag()); - slider_alloc(std::move(str), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, - std::bind(&mame_ui_manager::slider_overyscale, this, std::ref(laserdisc), _1, _2)); + slider_alloc(std::move(str), 500, (defyscale == 0) ? 1000 : defyscale, 1500, 2, std::bind(&mame_ui_manager::slider_overyscale, this, std::ref(laserdisc), _1, _2)); str = string_format(_("Laserdisc '%1$s' Vert Position"), laserdisc.tag()); slider_alloc(std::move(str), -500, defyoffset, 500, 2, std::bind(&mame_ui_manager::slider_overyoffset, this, std::ref(laserdisc), _1, _2)); } @@ -1613,9 +1975,12 @@ int32_t mame_ui_manager::slider_volume(std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) machine().sound().set_attenuation(newval); + + int32_t curval = machine().sound().attenuation(); if (str) - *str = string_format(_("%1$3ddB"), machine().sound().attenuation()); - return machine().sound().attenuation(); + *str = string_format(_(u8"%1$3d\u00a0dB"), curval); + + return curval; } @@ -1629,15 +1994,61 @@ int32_t mame_ui_manager::slider_mixervol(int item, std::string *str, int32_t new mixer_input info; if (!machine().sound().indexed_mixer_input(item, info)) return 0; + if (newval != SLIDER_NOCHANGE) + info.stream->input(info.inputnum).set_user_gain(float(newval) * 0.001f); + + int32_t curval = floorf(info.stream->input(info.inputnum).user_gain() * 1000.0f + 0.5f); + if (str) { - int32_t curval = floor(info.stream->input(info.inputnum).user_gain() * 1000.0f + 0.5f); - if (newval > curval && (newval - curval) <= 4) newval += 4; // round up on increment - info.stream->input(info.inputnum).set_user_gain((float)newval * 0.001f); + if (curval == 0) + *str = _("Mute"); + else if (curval % 10) + *str = string_format(_("%1$.1f%%"), float(curval) * 0.1f); + else + *str = string_format(_("%1$3d%%"), curval / 10); } + + return curval; +} + + +//------------------------------------------------- +// slider_panning - speaker panning slider +// callback +//------------------------------------------------- + +int32_t mame_ui_manager::slider_panning(speaker_device &speaker, std::string *str, int32_t newval) +{ + if (newval != SLIDER_NOCHANGE) + speaker.set_pan(float(newval) * 0.001f); + + int32_t curval = floorf(speaker.pan() * 1000.0f + 0.5f); if (str) - *str = string_format("%4.2f", info.stream->input(info.inputnum).user_gain()); - return floorf(info.stream->input(info.inputnum).user_gain() * 1000.0f + 0.5f); + { + switch (curval) + { + // preset strings for exact center/left/right + case 0: + *str = _("Center"); + break; + + case -1000: + *str = _("Left"); + break; + + case 1000: + *str = _("Right"); + break; + + // otherwise show as floating point + default: + *str = string_format(_("%1$.3f"), float(curval) * 0.001f); + break; + } + } + + return curval; } @@ -1657,7 +2068,7 @@ int32_t mame_ui_manager::slider_adjuster(ioport_field &field, std::string *str, field.set_user_settings(settings); } if (str) - *str = string_format(_("%1$d%%"), settings.value); + *str = string_format(_("%1$3d%%"), settings.value); return settings.value; } @@ -1670,10 +2081,18 @@ int32_t mame_ui_manager::slider_adjuster(ioport_field &field, std::string *str, int32_t mame_ui_manager::slider_overclock(device_t &device, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - device.set_clock_scale((float)newval * 0.001f); + device.set_clock_scale(double(newval) * 0.001); + + int32_t curval = floor(device.clock_scale() * 1000.0 + 0.5); if (str) - *str = string_format(_("%1$3.0f%%"), floor(device.clock_scale() * 100.0 + 0.5)); - return floor(device.clock_scale() * 1000.0 + 0.5); + { + if (curval % 10) + *str = string_format(_("%1$.1f%%"), float(curval) * 0.1f); + else + *str = string_format(_("%1$3d%%"), curval / 10); + } + + return curval; } @@ -1691,11 +2110,11 @@ int32_t mame_ui_manager::slider_refresh(screen_device &screen, std::string *str, int width = screen.width(); int height = screen.height(); const rectangle &visarea = screen.visible_area(); - screen.configure(width, height, visarea, HZ_TO_ATTOSECONDS(defrefresh + (double)newval * 0.001)); + screen.configure(width, height, visarea, HZ_TO_ATTOSECONDS(defrefresh + double(newval) * 0.001)); } if (str) - *str = string_format(_("%1$.3f" UTF8_NBSP "Hz"), screen.frame_period().as_hz()); + *str = string_format(_(u8"%1$.3f\u00a0Hz"), screen.frame_period().as_hz()); refresh = screen.frame_period().as_hz(); return floor((refresh - defrefresh) * 1000.0 + 0.5); } @@ -1711,12 +2130,12 @@ int32_t mame_ui_manager::slider_brightness(screen_device &screen, std::string *s render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_brightness = (float)newval * 0.001f; + settings.m_brightness = float(newval) * 0.001f; screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_brightness); - return floor(settings.m_brightness * 1000.0f + 0.5f); + return floorf(settings.m_brightness * 1000.0f + 0.5f); } @@ -1730,12 +2149,12 @@ int32_t mame_ui_manager::slider_contrast(screen_device &screen, std::string *str render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_contrast = (float)newval * 0.001f; + settings.m_contrast = float(newval) * 0.001f; screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_contrast); - return floor(settings.m_contrast * 1000.0f + 0.5f); + return floorf(settings.m_contrast * 1000.0f + 0.5f); } @@ -1748,12 +2167,12 @@ int32_t mame_ui_manager::slider_gamma(screen_device &screen, std::string *str, i render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_gamma = (float)newval * 0.001f; + settings.m_gamma = float(newval) * 0.001f; screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_gamma); - return floor(settings.m_gamma * 1000.0f + 0.5f); + return floorf(settings.m_gamma * 1000.0f + 0.5f); } @@ -1767,12 +2186,12 @@ int32_t mame_ui_manager::slider_xscale(screen_device &screen, std::string *str, render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_xscale = (float)newval * 0.001f; + settings.m_xscale = float(newval) * 0.001f; screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_xscale); - return floor(settings.m_xscale * 1000.0f + 0.5f); + return floorf(settings.m_xscale * 1000.0f + 0.5f); } @@ -1786,12 +2205,12 @@ int32_t mame_ui_manager::slider_yscale(screen_device &screen, std::string *str, render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_yscale = (float)newval * 0.001f; + settings.m_yscale = float(newval) * 0.001f; screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_yscale); - return floor(settings.m_yscale * 1000.0f + 0.5f); + return floorf(settings.m_yscale * 1000.0f + 0.5f); } @@ -1805,12 +2224,12 @@ int32_t mame_ui_manager::slider_xoffset(screen_device &screen, std::string *str, render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_xoffset = (float)newval * 0.001f; + settings.m_xoffset = float(newval) * 0.001f; screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_xoffset); - return floor(settings.m_xoffset * 1000.0f + 0.5f); + return floorf(settings.m_xoffset * 1000.0f + 0.5f); } @@ -1824,12 +2243,12 @@ int32_t mame_ui_manager::slider_yoffset(screen_device &screen, std::string *str, render_container::user_settings settings = screen.container().get_user_settings(); if (newval != SLIDER_NOCHANGE) { - settings.m_yoffset = (float)newval * 0.001f; + settings.m_yoffset = float(newval) * 0.001f; screen.container().set_user_settings(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_yoffset); - return floor(settings.m_yoffset * 1000.0f + 0.5f); + return floorf(settings.m_yoffset * 1000.0f + 0.5f); } @@ -1845,12 +2264,12 @@ int32_t mame_ui_manager::slider_overxscale(laserdisc_device &laserdisc, std::str laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overscalex = (float)newval * 0.001f; + settings.m_overscalex = float(newval) * 0.001f; laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overscalex); - return floor(settings.m_overscalex * 1000.0f + 0.5f); + return floorf(settings.m_overscalex * 1000.0f + 0.5f); } @@ -1866,12 +2285,12 @@ int32_t mame_ui_manager::slider_overyscale(laserdisc_device &laserdisc, std::str laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overscaley = (float)newval * 0.001f; + settings.m_overscaley = float(newval) * 0.001f; laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overscaley); - return floor(settings.m_overscaley * 1000.0f + 0.5f); + return floorf(settings.m_overscaley * 1000.0f + 0.5f); } @@ -1887,12 +2306,12 @@ int32_t mame_ui_manager::slider_overxoffset(laserdisc_device &laserdisc, std::st laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overposx = (float)newval * 0.001f; + settings.m_overposx = float(newval) * 0.001f; laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overposx); - return floor(settings.m_overposx * 1000.0f + 0.5f); + return floorf(settings.m_overposx * 1000.0f + 0.5f); } @@ -1908,12 +2327,12 @@ int32_t mame_ui_manager::slider_overyoffset(laserdisc_device &laserdisc, std::st laserdisc.get_overlay_config(settings); if (newval != SLIDER_NOCHANGE) { - settings.m_overposy = (float)newval * 0.001f; + settings.m_overposy = float(newval) * 0.001f; laserdisc.set_overlay_config(settings); } if (str) *str = string_format(_("%1$.3f"), settings.m_overposy); - return floor(settings.m_overposy * 1000.0f + 0.5f); + return floorf(settings.m_overposy * 1000.0f + 0.5f); } @@ -1925,10 +2344,10 @@ int32_t mame_ui_manager::slider_overyoffset(laserdisc_device &laserdisc, std::st int32_t mame_ui_manager::slider_flicker([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_flicker = (float)newval * 0.001f; + vector_options::s_flicker = float(newval) * 0.001f; if (str) *str = string_format(_("%1$1.2f"), vector_options::s_flicker); - return floor(vector_options::s_flicker * 1000.0f + 0.5f); + return floorf(vector_options::s_flicker * 1000.0f + 0.5f); } @@ -1940,10 +2359,10 @@ int32_t mame_ui_manager::slider_flicker([[maybe_unused]] screen_device &screen, int32_t mame_ui_manager::slider_beam_width_min([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_width_min = std::min((float)newval * 0.01f, vector_options::s_beam_width_max); + vector_options::s_beam_width_min = std::min(float(newval) * 0.01f, vector_options::s_beam_width_max); if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_width_min); - return floor(vector_options::s_beam_width_min * 100.0f + 0.5f); + return floorf(vector_options::s_beam_width_min * 100.0f + 0.5f); } @@ -1955,10 +2374,10 @@ int32_t mame_ui_manager::slider_beam_width_min([[maybe_unused]] screen_device &s int32_t mame_ui_manager::slider_beam_width_max([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_width_max = std::max((float)newval * 0.01f, vector_options::s_beam_width_min); + vector_options::s_beam_width_max = std::max(float(newval) * 0.01f, vector_options::s_beam_width_min); if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_width_max); - return floor(vector_options::s_beam_width_max * 100.0f + 0.5f); + return floorf(vector_options::s_beam_width_max * 100.0f + 0.5f); } @@ -1970,10 +2389,10 @@ int32_t mame_ui_manager::slider_beam_width_max([[maybe_unused]] screen_device &s int32_t mame_ui_manager::slider_beam_dot_size([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_dot_size = std::max((float)newval * 0.01f, 0.1f); + vector_options::s_beam_dot_size = std::max(float(newval) * 0.01f, 0.1f); if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_dot_size); - return floor(vector_options::s_beam_dot_size * 100.0f + 0.5f); + return floorf(vector_options::s_beam_dot_size * 100.0f + 0.5f); } @@ -1985,10 +2404,10 @@ int32_t mame_ui_manager::slider_beam_dot_size([[maybe_unused]] screen_device &sc int32_t mame_ui_manager::slider_beam_intensity_weight([[maybe_unused]] screen_device &screen, std::string *str, int32_t newval) { if (newval != SLIDER_NOCHANGE) - vector_options::s_beam_intensity_weight = (float)newval * 0.001f; + vector_options::s_beam_intensity_weight = float(newval) * 0.001f; if (str != nullptr) *str = string_format(_("%1$1.2f"), vector_options::s_beam_intensity_weight); - return floor(vector_options::s_beam_intensity_weight * 1000.0f + 0.5f); + return floorf(vector_options::s_beam_intensity_weight * 1000.0f + 0.5f); } @@ -2004,7 +2423,7 @@ int32_t mame_ui_manager::slider_crossscale(ioport_field &field, std::string *str field.set_crosshair_scale(float(newval) * 0.001); if (str) *str = string_format((field.crosshair_axis() == CROSSHAIR_AXIS_X) ? _("Crosshair Scale X %1$1.3f") : _("Crosshair Scale Y %1$1.3f"), float(newval) * 0.001f); - return floor(field.crosshair_scale() * 1000.0f + 0.5f); + return floorf(field.crosshair_scale() * 1000.0f + 0.5f); } #endif @@ -2033,8 +2452,8 @@ int32_t mame_ui_manager::slider_crossoffset(ioport_field &field, std::string *st ui::text_layout mame_ui_manager::create_layout(render_container &container, float width, ui::text_layout::text_justify justify, ui::text_layout::word_wrapping wrap) { // determine scale factors - float yscale = get_line_height(); - float xscale = yscale * machine().render().ui_aspect(&container); + float const yscale = get_line_height(); + float const xscale = yscale * machine().render().ui_aspect(&container); // create the layout return ui::text_layout(*get_font(), xscale, yscale, width, justify, wrap); @@ -2170,7 +2589,7 @@ void mame_ui_manager::save_main_option() return; } } - popup_time(3, "%s", _("\n Configuration saved \n\n")); + popup_time(3, "%s", _("\n Settings saved \n\n")); } void mame_ui_manager::menu_reset() @@ -2179,6 +2598,29 @@ void mame_ui_manager::menu_reset() } +bool mame_ui_manager::set_ui_event_handler(std::function<bool ()> &&handler) +{ + // only allow takeover if there's nothing else happening + if (ui_callback_type::GENERAL != m_handler_callback_type) + return false; + + for (auto *target = machine().render().first_target(); target; target = target->next()) + { + if (!target->hidden()) + target->forget_pointers(); + } + + set_handler( + ui_callback_type::CUSTOM, + handler_callback_func( + [cb = std::move(handler)] (render_container &container) -> uint32_t + { + return !cb() ? HANDLER_CANCEL : 0; + })); + return true; +} + + //------------------------------------------------- // get_general_input_setting - get the current // default setting for an input type (useful for |