diff options
Diffstat (limited to 'src/frontend/mame/ui/analogipt.cpp')
-rw-r--r-- | src/frontend/mame/ui/analogipt.cpp | 269 |
1 files changed, 207 insertions, 62 deletions
diff --git a/src/frontend/mame/ui/analogipt.cpp b/src/frontend/mame/ui/analogipt.cpp index 209a84b4f06..3cc732cb82c 100644 --- a/src/frontend/mame/ui/analogipt.cpp +++ b/src/frontend/mame/ui/analogipt.cpp @@ -12,6 +12,7 @@ #include "ui/analogipt.h" #include <algorithm> +#include <iterator> #include <string> #include <utility> @@ -50,7 +51,10 @@ menu_analog::menu_analog(mame_ui_manager &mui, render_container &container) : menu(mui, container) , m_item_data() , m_field_data() + , m_prompt() , m_visible_fields(0U) + , m_top_field(0) + , m_hide_menu(false) { set_process_flags(PROCESS_LR_REPEAT); } @@ -71,29 +75,96 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa for (field_data &data : m_field_data) namewidth = (std::min)((std::max)(ui().get_string_width(data.field.get().name()), namewidth), nameavail); - // make a box + // make a box or two + rgb_t const fgcolor(ui().colors().text_color()); + float const lineheight(ui().get_line_height()); + float const border(ui().box_tb_border()); float const boxleft((1.0f - namewidth - extrawidth) / 2.0f); float const boxright(boxleft + namewidth + extrawidth); - ui().draw_outlined_box(container(), boxleft, y2 + ui().box_tb_border(), boxright, y2 + bottom, ui().colors().background_color()); + float boxtop; + float boxbottom; + float firstliney; + int visible_fields; + if (m_hide_menu) + { + if (m_prompt.empty()) + m_prompt = util::string_format(_("Press %s to show menu"), ui().get_general_input_setting(IPT_UI_ON_SCREEN_DISPLAY)); + draw_text_box( + &m_prompt, &m_prompt + 1, + boxleft, boxright, y - top, y - top + lineheight + (border * 2.0f), + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, + fgcolor, ui().colors().background_color(), 1.0f); + boxtop = y - top + lineheight + (border * 3.0f); + firstliney = y - top + lineheight + (border * 4.0f); + visible_fields = std::min<int>(m_field_data.size(), int((y2 + bottom - border - firstliney) / lineheight)); + boxbottom = firstliney + (lineheight * visible_fields) + border; + } + else + { + boxtop = y2 + border; + boxbottom = y2 + bottom; + firstliney = y2 + (border * 2.0f); + visible_fields = m_visible_fields; + } + ui().draw_outlined_box(container(), boxleft, boxtop, boxright, boxbottom, ui().colors().background_color()); + + // force the field being configured to be visible + ioport_field *const selfield(selectedref ? &reinterpret_cast<item_data *>(selectedref)->field.get() : nullptr); + if (!m_hide_menu && selfield) + { + auto const found( + std::find_if( + m_field_data.begin(), + m_field_data.end(), + [selfield] (field_data const &d) { return &d.field.get() == selfield; })); + if (m_field_data.end() != found) + { + auto const i(std::distance(m_field_data.begin(), found)); + if (m_top_field > i) + m_top_field = i; + if ((m_top_field + visible_fields) <= i) + m_top_field = i - m_visible_fields + 1; + } + } + if (0 > m_top_field) + m_top_field = 0; + if ((m_top_field + visible_fields) > m_field_data.size()) + m_top_field = m_field_data.size() - visible_fields; // show live fields - namewidth += ui().get_line_height() * aspect; - unsigned line(0U); + namewidth += lineheight * aspect; float const nameleft(boxleft + (ui().box_lr_border() * aspect)); float const indleft(nameleft + namewidth); float const indright(indleft + 0.4f); - ioport_field *const selfield(selectedref ? &reinterpret_cast<item_data *>(selectedref)->field.get() : nullptr); - for (field_data &data : m_field_data) + for (unsigned line = 0; visible_fields > line; ++line) { + // draw arrows if scrolling is possible and menu is hidden + float const liney(firstliney + (lineheight * line)); + if (m_hide_menu) + { + bool const uparrow(!line && m_top_field); + bool const downarrow(((visible_fields - 1) == line) && ((m_field_data.size() - 1) > (line + m_top_field))); + if (uparrow || downarrow) + { + float const arrowwidth = lineheight * aspect; + draw_arrow( + 0.5f * (nameleft + indright - arrowwidth), liney + (0.25f * lineheight), + 0.5f * (nameleft + indright + arrowwidth), liney + (0.75f * lineheight), + fgcolor, line ? (ROT0 ^ ORIENTATION_FLIP_Y) : ROT0); + continue; + } + } + + // draw the field name, using the selected colour if it's being configured + field_data &data(m_field_data[line + m_top_field]); bool const selected(&data.field.get() == selfield); - rgb_t const fgcolor(selected ? ui().colors().selected_color() : ui().colors().text_color()); - float const liney(y2 + (ui().box_tb_border() * 2.0f) + (ui().get_line_height() * line)); + rgb_t const fieldcolor(selected ? ui().colors().selected_color() : fgcolor); ui().draw_text_full( container(), data.field.get().name(), nameleft, liney, namewidth, text_layout::text_justify::LEFT, text_layout::word_wrapping::NEVER, - mame_ui_manager::NORMAL, fgcolor, ui().colors().text_bg_color()); + mame_ui_manager::NORMAL, fieldcolor, ui().colors().text_bg_color()); ioport_value cur(0U); data.field.get().live().analog->read(cur); @@ -102,8 +173,8 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa if (data.field.get().analog_reverse()) fill = 1.0f - fill; - float const indtop(liney + (ui().get_line_height() * 0.2f)); - float const indbottom(liney + (ui().get_line_height() * 0.8f)); + float const indtop(liney + (lineheight * 0.2f)); + float const indbottom(liney + (lineheight * 0.8f)); if (data.origin > fill) container().add_rect(indleft + (fill * 0.4f), indtop, indleft + (data.origin * 0.4f), indbottom, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); else @@ -114,10 +185,6 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa container().add_line(indleft, indbottom, indleft, indtop, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); if (data.show_neutral) container().add_line(indleft + (data.neutral * 0.4f), indtop, indleft + (data.neutral * 0.4f), indbottom, UI_LINE_WIDTH, fgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - // TODO: ensure field being configured is visible - if (++line >= m_visible_fields) - break; } } @@ -125,53 +192,133 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa void menu_analog::handle(event const *ev) { // handle events - if (ev && ev->itemref) + if (ev) { - item_data &data(*reinterpret_cast<item_data *>(ev->itemref)); - int newval(data.cur); - - switch (ev->iptkey) + if (IPT_UI_ON_SCREEN_DISPLAY == ev->iptkey) { - // if selected, reset to default value - case IPT_UI_SELECT: - newval = data.defvalue; - break; - - // left decrements - case IPT_UI_LEFT: - newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; - break; - - // right increments - case IPT_UI_RIGHT: - newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; - break; + m_hide_menu = !m_hide_menu; + set_process_flags(PROCESS_LR_REPEAT | (m_hide_menu ? (PROCESS_CUSTOM_NAV | PROCESS_CUSTOM_ONLY) : 0)); } - - // clamp to range - if (newval < data.min) - newval = data.min; - if (newval > data.max) - newval = data.max; - - // if things changed, update - if (newval != data.cur) + else if (m_hide_menu) { - ioport_field::user_settings settings; + switch (ev->iptkey) + { + case IPT_UI_UP: + --m_top_field; + break; + case IPT_UI_DOWN: + ++m_top_field; + break; + case IPT_UI_HOME: + m_top_field = 0; + break; + case IPT_UI_END: + m_top_field = m_field_data.size(); + break; + } + } + else if (ev->itemref) + { + item_data &data(*reinterpret_cast<item_data *>(ev->itemref)); + int newval(data.cur); - // get the settings and set the new value - data.field.get().get_user_settings(settings); - switch (data.type) + switch (ev->iptkey) { - case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break; - case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break; - case ANALOG_ITEM_REVERSE: settings.reverse = newval; break; - case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break; + // if selected, reset to default value + case IPT_UI_SELECT: + newval = data.defvalue; + break; + + // left decrements + case IPT_UI_LEFT: + newval -= machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; + break; + + // right increments + case IPT_UI_RIGHT: + newval += machine().input().code_pressed(KEYCODE_LSHIFT) ? 10 : 1; + break; + + // move to first item for previous device + case IPT_UI_PREV_GROUP: + { + auto current = std::distance(m_item_data.data(), &data); + device_t const *dev(&data.field.get().device()); + bool found_break = false; + while (0 < current) + { + if (!found_break) + { + device_t const *prev(&m_item_data[--current].field.get().device()); + if (prev != dev) + { + dev = prev; + found_break = true; + } + } + else if (&m_item_data[current - 1].field.get().device() != dev) + { + set_selection(&m_item_data[current]); + set_top_line(selected_index() - 1); + break; + } + else + { + --current; + } + if (found_break && !current) + { + set_selection(&m_item_data[current]); + set_top_line(selected_index() - 1); + break; + } + } + } + break; + + // move to first item for next device + case IPT_UI_NEXT_GROUP: + { + auto current = std::distance(m_item_data.data(), &data); + device_t const *const dev(&data.field.get().device()); + while (m_item_data.size() > ++current) + { + if (&m_item_data[current].field.get().device() != dev) + { + set_selection(&m_item_data[current]); + set_top_line(selected_index() - 1); + break; + } + } + } + break; } - data.field.get().set_user_settings(settings); - // rebuild the menu - reset(reset_options::REMEMBER_POSITION); + // clamp to range + if (newval < data.min) + newval = data.min; + if (newval > data.max) + newval = data.max; + + // if things changed, update + if (newval != data.cur) + { + ioport_field::user_settings settings; + + // get the settings and set the new value + data.field.get().get_user_settings(settings); + switch (data.type) + { + case ANALOG_ITEM_KEYSPEED: settings.delta = newval; break; + case ANALOG_ITEM_CENTERSPEED: settings.centerdelta = newval; break; + case ANALOG_ITEM_REVERSE: settings.reverse = newval; break; + case ANALOG_ITEM_SENSITIVITY: settings.sensitivity = newval; break; + } + data.field.get().set_user_settings(settings); + + // rebuild the menu + reset(reset_options::REMEMBER_POSITION); + } } } } @@ -184,7 +331,6 @@ void menu_analog::populate(float &customtop, float &custombottom) find_fields(); device_t *prev_owner(nullptr); - bool first_entry(true); ioport_field *field(nullptr); ioport_field::user_settings settings; @@ -202,11 +348,10 @@ void menu_analog::populate(float &customtop, float &custombottom) if (&field->device() != prev_owner) { prev_owner = &field->device(); - if (first_entry) - first_entry = false; + if (prev_owner->owner()) + item_append(string_format(_("%1$s [root%2$s]"), prev_owner->type().fullname(), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); else - item_append(menu_item_type::SEPARATOR); - item_append(string_format("[root%s]", prev_owner->tag()), 0, nullptr); + item_append(string_format(_("[root%1$s]"), prev_owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); } } @@ -304,9 +449,9 @@ void menu_analog::find_fields() } } - // restrict live display to 60% height plus borders - if ((ui().get_line_height() * m_field_data.size()) > 0.6f) - m_visible_fields = unsigned(0.6f / ui().get_line_height()); + // restrict live display to 40% height plus borders + if ((ui().get_line_height() * m_field_data.size()) > 0.4f) + m_visible_fields = unsigned(0.4f / ui().get_line_height()); else m_visible_fields = m_field_data.size(); } |