diff options
| author | 2024-04-18 05:59:03 +1000 | |
|---|---|---|
| committer | 2024-04-18 05:59:03 +1000 | |
| commit | 520ed5e44b49f80ec38bb812d8477e2b8a607cfc (patch) | |
| tree | 75b7c39026aab815269f1a69343c88a68984fa73 /src/frontend | |
| parent | 80dd0682d8ae2eecc9680069981b07b2b8a19948 (diff) | |
-ui/ui.cpp, ui/videoopt.cpp: Made pointer activity timeout configurable.
-midway/wmg.cpp: Use a memory bank for NVRAM; also got rid of a really pointless trampoline function.
Diffstat (limited to 'src/frontend')
| -rw-r--r-- | src/frontend/mame/ui/ui.cpp | 224 | ||||
| -rw-r--r-- | src/frontend/mame/ui/ui.h | 36 | ||||
| -rw-r--r-- | src/frontend/mame/ui/videoopt.cpp | 78 |
3 files changed, 314 insertions, 24 deletions
diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 0c4af7b8ba5..e697f861da2 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -48,7 +48,6 @@ #include "../osd/modules/lib/osdlib.h" #include "../osd/modules/lib/osdobj_common.h" -#include <chrono> #include <functional> #include <type_traits> @@ -189,6 +188,28 @@ struct mame_ui_manager::active_pointer }; +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 //------------------------------------------------- @@ -252,8 +273,12 @@ void mame_ui_manager::init() 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); @@ -311,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) @@ -352,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)) @@ -383,6 +415,101 @@ 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 //------------------------------------------------- @@ -1381,14 +1508,23 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) 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) { - layout_view const &view(pointer.target->current_view()); - if (view.show_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()) { - // TODO: make timeout configurable - if (!view.hide_inactive_pointers() || (osd::ui_event_handler::pointer::PEN == pointer.type) || ((now - pointer.updated) <= std::chrono::seconds(3))) - pointers.emplace_back(display_pointer{ *pointer.target, pointer.type, pointer.x, pointer.y }); + 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()); @@ -1590,6 +1726,70 @@ void mame_ui_manager::request_quit() } +//------------------------------------------------- +// 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 ***************************************************************************/ diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index d213d861f34..128300576e5 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -26,6 +26,7 @@ #include <any> #include <cassert> +#include <chrono> #include <ctime> #include <functional> #include <set> @@ -164,13 +165,21 @@ public: void display_startup_screens(bool first_time); virtual void set_startup_text(const char *text, bool force) override; bool update_and_render(render_container &container); + + // getting display font and metrics render_font *get_font(); float get_line_height(float scale = 1.0F); + float target_font_height() const { return m_target_font_height; } float get_char_width(char32_t ch); float get_string_width(std::string_view s); float get_string_width(std::string_view s, float text_size); + float box_lr_border() const { return target_font_height() * 0.25f; } + float box_tb_border() const { return target_font_height() * 0.25f; } + + // drawing boxes and text void draw_outlined_box(render_container &container, float x0, float y0, float x1, float y1, rgb_t backcolor); void draw_outlined_box(render_container &container, float x0, float y0, float x1, float y1, rgb_t fgcolor, rgb_t bgcolor); + void draw_textured_box(render_container &container, float x0, float y0, float x1, float y1, rgb_t backcolor, rgb_t linecolor, render_texture *texture = nullptr, uint32_t flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); void draw_text(render_container &container, std::string_view buf, float x, float y); void 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 = nullptr, float *totalheight = nullptr); void 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); @@ -197,13 +206,17 @@ public: bool can_paste(); bool found_machine_warnings() const { return m_has_warnings; } void image_handler_ingame(); - void increase_frameskip(); - void decrease_frameskip(); void request_quit(); + void set_pointer_activity_timeout(int target, std::chrono::steady_clock::duration timeout) noexcept; + void set_hide_inactive_pointers(int target, bool hide) noexcept; + std::chrono::steady_clock::duration pointer_activity_timeout(int target) const noexcept; + bool hide_inactive_pointers(int target) const noexcept; + + // drawing informational overlays void draw_fps_counter(render_container &container); void draw_profiler(render_container &container); - // pointer display + // pointer display for UI handlers template <typename T> void set_pointers(T first, T last) { @@ -238,9 +251,6 @@ public: std::vector<ui::menu_item> &get_slider_list(); // metrics - float target_font_height() const { return m_target_font_height; } - float box_lr_border() const { return target_font_height() * 0.25f; } - float box_tb_border() const { return target_font_height() * 0.25f; } void update_target_font_height(); // other @@ -248,9 +258,6 @@ public: ui::text_layout create_layout(render_container &container, float width = 1.0, ui::text_layout::text_justify justify = ui::text_layout::text_justify::LEFT, ui::text_layout::word_wrapping wrap = ui::text_layout::word_wrapping::WORD); void set_image_display_enabled(bool image_display_enabled) { m_image_display_enabled = image_display_enabled; } bool image_display_enabled() const { return m_image_display_enabled; } - - // draw an outlined box with given line color and filled with a texture - void draw_textured_box(render_container &container, float x0, float y0, float x1, float y1, rgb_t backcolor, rgb_t linecolor, render_texture *texture = nullptr, uint32_t flags = PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); virtual void popup_time_string(int seconds, std::string message) override; virtual void menu_reset() override; @@ -275,11 +282,13 @@ private: enum class ui_callback_type : int; struct active_pointer; + struct pointer_options; using handler_callback_func = delegate<uint32_t (render_container &)>; using device_feature_set = std::set<std::pair<std::string, std::string> >; using session_data_map = std::unordered_map<std::type_index, std::any>; using active_pointer_vector = std::vector<active_pointer>; + using pointer_options_vector = std::vector<pointer_options>; using display_pointer_vector = std::vector<display_pointer>; // instance variables @@ -294,6 +303,7 @@ private: osd_ticks_t m_popup_text_end; std::unique_ptr<uint8_t []> m_non_char_keys_down; + pointer_options_vector m_pointer_options; active_pointer_vector m_active_pointers; display_pointer_vector m_display_pointers; bitmap_argb32 m_mouse_bitmap; @@ -328,8 +338,12 @@ private: void set_handler(ui_callback_type callback_type, handler_callback_func &&callback); void frame_update(); void exit(); - void config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); - void config_save(config_type cfg_type, util::xml::data_node *parentnode); + void increase_frameskip(); + void decrease_frameskip(); + void config_load_warnings(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); + void config_save_warnings(config_type cfg_type, util::xml::data_node *parentnode); + void config_load_pointers(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); + void config_save_pointers(config_type cfg_type, util::xml::data_node *parentnode); template <typename... Params> void slider_alloc(Params &&...args) { m_sliders.push_back(std::make_unique<slider_state>(std::forward<Params>(args)...)); } // slider controls diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp index 84ae6b6867d..7aeb2ac7bf3 100644 --- a/src/frontend/mame/ui/videoopt.cpp +++ b/src/frontend/mame/ui/videoopt.cpp @@ -15,6 +15,8 @@ #include "rendlay.h" #include "rendutil.h" +#include <chrono> + namespace ui { @@ -24,6 +26,7 @@ constexpr uintptr_t ITEM_ROTATE = 0x00000100; constexpr uintptr_t ITEM_ZOOM = 0x00000101; constexpr uintptr_t ITEM_UNEVENSTRETCH = 0x00000102; constexpr uintptr_t ITEM_KEEPASPECT = 0x00000103; +constexpr uintptr_t ITEM_POINTERTIMEOUT = 0x00000104; constexpr uintptr_t ITEM_TOGGLE_FIRST = 0x00000200; constexpr uintptr_t ITEM_VIEW_FIRST = 0x00000300; @@ -192,6 +195,29 @@ void menu_video_options::populate() item_append_on_off(_("Maintain Aspect Ratio"), m_target.keepaspect(), 0, reinterpret_cast<void *>(ITEM_KEEPASPECT)); } + // add pointer display options + if (!m_target.hidden()) + { + item_append(menu_item_type::SEPARATOR); + + // use millisecond precision for timeout display + auto const timeout = std::chrono::duration_cast<std::chrono::milliseconds>(ui().pointer_activity_timeout(m_target.index())); + bool const hide = ui().hide_inactive_pointers(m_target.index()); + if (hide) + { + int const precision = (timeout.count() % 10) ? 3 : (timeout.count() % 100) ? 2 : 1; + item_append( + _("Hide Inactive Pointers After Delay"), + util::string_format(_("%1$.*2$f s"), timeout.count() * 1e-3, precision), + ((timeout > std::chrono::milliseconds(100)) ? FLAG_LEFT_ARROW : 0) | FLAG_RIGHT_ARROW, + reinterpret_cast<void *>(ITEM_POINTERTIMEOUT)); + } + else + { + item_append(_("Hide Inactive Pointers After Delay"), _("Never"), FLAG_LEFT_ARROW, reinterpret_cast<void *>(ITEM_POINTERTIMEOUT)); + } + } + item_append(menu_item_type::SEPARATOR); } @@ -211,6 +237,7 @@ bool menu_video_options::handle(event const *ev) }); bool const snap_lockout(m_snapshot && machine().video().is_recording()); bool changed(false); + set_process_flags((reinterpret_cast<uintptr_t>(get_selection_ref()) == ITEM_POINTERTIMEOUT) ? PROCESS_LR_REPEAT : 0); // process the menu if (ev && uintptr_t(ev->itemref)) @@ -306,7 +333,7 @@ bool menu_video_options::handle(event const *ev) } break; - // keep aspect handles left/right keys the same (toggle) + // keep aspect handles left/right keys identically (toggle) case ITEM_KEEPASPECT: if ((ev->iptkey == IPT_UI_LEFT) || (ev->iptkey == IPT_UI_RIGHT)) { @@ -317,6 +344,55 @@ bool menu_video_options::handle(event const *ev) } break; + // pointer inactivity timeout + case ITEM_POINTERTIMEOUT: + if (ev->iptkey == IPT_UI_SELECT) + { + // toggle hide after delay + ui().set_hide_inactive_pointers(m_target.index(), !ui().hide_inactive_pointers(m_target.index())); + changed = true; + } + else if (ev->iptkey == IPT_UI_LEFT) + { + if (!ui().hide_inactive_pointers(m_target.index())) + { + ui().set_hide_inactive_pointers(m_target.index(), true); + ui().set_pointer_activity_timeout(m_target.index(), std::chrono::milliseconds(10'000)); + changed = true; + } + else + { + auto const timeout = ui().pointer_activity_timeout(m_target.index()); + if (std::chrono::milliseconds(100) < timeout) + { + auto const remainder = timeout % std::chrono::milliseconds(100); + ui().set_pointer_activity_timeout( + m_target.index(), + timeout - (remainder.count() ? remainder : std::chrono::milliseconds(100))); + changed = true; + } + } + } + else if (ev->iptkey == IPT_UI_RIGHT) + { + if (ui().hide_inactive_pointers(m_target.index())) + { + auto const timeout = ui().pointer_activity_timeout(m_target.index()); + if (std::chrono::milliseconds(10'000) <= timeout) + { + ui().set_hide_inactive_pointers(m_target.index(), false); + } + else + { + ui().set_pointer_activity_timeout( + m_target.index(), + std::chrono::milliseconds((1 + (timeout / std::chrono::milliseconds(100))) * 100)); + } + changed = true; + } + } + break; + // anything else is a view item default: if (reinterpret_cast<uintptr_t>(ev->itemref) >= ITEM_VIEW_FIRST) |
