diff options
Diffstat (limited to 'src/emu/ui/menu.cpp')
-rw-r--r-- | src/emu/ui/menu.cpp | 2019 |
1 files changed, 195 insertions, 1824 deletions
diff --git a/src/emu/ui/menu.cpp b/src/emu/ui/menu.cpp index 547030298bb..069b05aa913 100644 --- a/src/emu/ui/menu.cpp +++ b/src/emu/ui/menu.cpp @@ -2,9 +2,9 @@ // copyright-holders:Nicola Salmoria, Aaron Giles, Nathan Woods /********************************************************************* - ui/menu.c + ui/menu.c - Internal MAME menus for the user interface. + Internal MAME menus for the user interface. *********************************************************************/ @@ -15,60 +15,18 @@ #include "ui/ui.h" #include "ui/menu.h" #include "ui/mainmenu.h" -#include "ui/utils.h" -#include "ui/defimg.h" -#include "ui/starimg.h" -#include "ui/optsmenu.h" -#include "ui/datfile.h" -#include "rendfont.h" -#include "ui/custmenu.h" -#include "ui/icorender.h" -#include "ui/toolbar.h" + /*************************************************************************** - CONSTANTS + CONSTANTS ***************************************************************************/ -#define UI_MENU_POOL_SIZE 65536 -#define MAX_ICONS_RENDER 40 - -struct ui_arts_info -{ - const char *title, *path, *addpath; -}; - -static const ui_arts_info arts_info[] = -{ - { "Snapshots", OPTION_SNAPSHOT_DIRECTORY, "snap" }, - { "Cabinets", OPTION_CABINETS_PATH, "cabinets;cabdevs" }, - { "Control Panels", OPTION_CPANELS_PATH, "cpanel" }, - { "PCBs", OPTION_PCBS_PATH, "pcb" }, - { "Flyers", OPTION_FLYERS_PATH, "flyers" }, - { "Titles", OPTION_TITLES_PATH, "titles" }, - { "Ends", OPTION_ENDS_PATH, "ends" }, - { "Artwork Preview", OPTION_ARTPREV_PATH, "artwork preview" }, - { "Bosses", OPTION_BOSSES_PATH, "bosses" }, - { "Logos", OPTION_LOGOS_PATH, "logo" }, - { "Versus", OPTION_VERSUS_PATH, "versus" }, - { "Game Over", OPTION_GAMEOVER_PATH, "gameover" }, - { "HowTo", OPTION_HOWTO_PATH, "howto" }, - { "Scores", OPTION_SCORES_PATH, "scores" }, - { "Select", OPTION_SELECT_PATH, "select" }, - { "Marquees", OPTION_MARQUEES_PATH, "marquees" }, - { nullptr } -}; - -static const char *hover_msg[] = { - "Add or remove favorites", - "Export displayed list to file", - "Show DATs view", - "Setup directories", - "Configure options" -}; +#define UI_MENU_POOL_SIZE 65536 +#define UI_MENU_ALLOC_ITEMS 256 /*************************************************************************** - GLOBAL VARIABLES + GLOBAL VARIABLES ***************************************************************************/ ui_menu *ui_menu::menu_stack; @@ -76,24 +34,9 @@ ui_menu *ui_menu::menu_free; std::unique_ptr<bitmap_rgb32> ui_menu::hilight_bitmap; render_texture *ui_menu::hilight_texture; render_texture *ui_menu::arrow_texture; -render_texture *ui_menu::snapx_texture; -render_texture *ui_menu::hilight_main_texture; -render_texture *ui_menu::bgrnd_texture; -render_texture *ui_menu::star_texture; -render_texture *ui_menu::toolbar_texture[UI_TOOLBAR_BUTTONS]; -render_texture *ui_menu::sw_toolbar_texture[UI_TOOLBAR_BUTTONS]; -render_texture *ui_menu::icons_texture[MAX_ICONS_RENDER]; -std::unique_ptr<bitmap_argb32> ui_menu::snapx_bitmap; -std::unique_ptr<bitmap_argb32> ui_menu::no_avail_bitmap; -std::unique_ptr<bitmap_argb32> ui_menu::star_bitmap; -std::unique_ptr<bitmap_argb32> ui_menu::bgrnd_bitmap; -bitmap_argb32 *ui_menu::icons_bitmap[MAX_ICONS_RENDER]; -std::unique_ptr<bitmap_rgb32> ui_menu::hilight_main_bitmap; -bitmap_argb32 *ui_menu::toolbar_bitmap[UI_TOOLBAR_BUTTONS]; -bitmap_argb32 *ui_menu::sw_toolbar_bitmap[UI_TOOLBAR_BUTTONS]; /*************************************************************************** - INLINE FUNCTIONS + INLINE FUNCTIONS ***************************************************************************/ //------------------------------------------------- @@ -126,7 +69,7 @@ inline bool ui_menu::exclusive_input_pressed(int key, int repeat) /*************************************************************************** - CORE SYSTEM MANAGEMENT + CORE SYSTEM MANAGEMENT ***************************************************************************/ //------------------------------------------------- @@ -135,12 +78,14 @@ inline bool ui_menu::exclusive_input_pressed(int key, int repeat) void ui_menu::init(running_machine &machine) { + int x; + // initialize the menu stack ui_menu::stack_reset(machine); // create a texture for hilighting items hilight_bitmap = std::make_unique<bitmap_rgb32>(256, 1); - for (int x = 0; x < 256; x++) + for (x = 0; x < 256; x++) { int alpha = 0xff; if (x < 25) alpha = 0xff * x / 25; @@ -153,9 +98,6 @@ void ui_menu::init(running_machine &machine) // create a texture for arrow icons arrow_texture = machine.render().texture_alloc(render_triangle); - // initialize ui - init_ui(machine); - // add an exit callback to free memory machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(ui_menu::exit), &machine)); } @@ -172,28 +114,14 @@ void ui_menu::exit(running_machine &machine) ui_menu::clear_free_list(machine); // free textures - render_manager &mre = machine.render(); - mre.texture_free(hilight_texture); - mre.texture_free(arrow_texture); - mre.texture_free(snapx_texture); - mre.texture_free(hilight_main_texture); - mre.texture_free(bgrnd_texture); - mre.texture_free(star_texture); - - for (auto & elem : icons_texture) - mre.texture_free(elem); - - for (int i = 0; i < UI_TOOLBAR_BUTTONS; i++) - { - mre.texture_free(sw_toolbar_texture[i]); - mre.texture_free(toolbar_texture[i]); - } + machine.render().texture_free(hilight_texture); + machine.render().texture_free(arrow_texture); } /*************************************************************************** - CORE MENU MANAGEMENT + CORE MENU MANAGEMENT ***************************************************************************/ //------------------------------------------------- @@ -206,8 +134,6 @@ ui_menu::ui_menu(running_machine &machine, render_container *_container) : m_mac container = _container; reset(UI_MENU_RESET_SELECT_FIRST); - - top_line = 0; } @@ -222,8 +148,12 @@ ui_menu::~ui_menu() { ui_menu_pool *ppool = pool; pool = pool->next; - global_free(ppool); + auto_free(machine(), ppool); } + + // free the item array + if (item) + auto_free(machine(), item); } @@ -242,14 +172,14 @@ void ui_menu::reset(ui_menu_reset_options options) else if (options == UI_MENU_RESET_REMEMBER_REF) resetref = item[selected].ref; - // reset all the pools and the item.size() back to 0 + // reset all the pools and the numitems back to 0 for (ui_menu_pool *ppool = pool; ppool != nullptr; ppool = ppool->next) ppool->top = (UINT8 *)(ppool + 1); - item.clear(); + numitems = 0; visitems = 0; selected = 0; std::string backtext; - strprintf(backtext, "Return to Machine"); + strprintf(backtext, "Return to %s", emulator_info::get_capstartgamenoun()); // add an item to return if (parent == nullptr) @@ -284,42 +214,66 @@ void ui_menu::set_special_main_menu(bool special) //------------------------------------------------- +// populated - returns true if the menu +// has any non-default items in it +//------------------------------------------------- + +bool ui_menu::populated() +{ + return numitems > 1; +} + + +//------------------------------------------------- // item_append - append a new item to the // end of the menu //------------------------------------------------- void ui_menu::item_append(const char *text, const char *subtext, UINT32 flags, void *ref) { + ui_menu_item *pitem; + int index; + // only allow multiline as the first item if ((flags & MENU_FLAG_MULTILINE) != 0) - assert(item.size() == 1); + assert(numitems == 1); // only allow a single multi-line item - else if (item.size() >= 2) + else if (numitems >= 2) assert((item[0].flags & MENU_FLAG_MULTILINE) == 0); - // allocate a new item and populate it - ui_menu_item pitem; - pitem.text = (text != nullptr) ? pool_strdup(text) : nullptr; - pitem.subtext = (subtext != nullptr) ? pool_strdup(subtext) : nullptr; - pitem.flags = flags; - pitem.ref = ref; - - // append to array - int index = item.size(); - if (!item.empty()) + // realloc the item array if necessary + if (numitems >= allocitems) { - item.insert(item.end() - 1, pitem); - --index; + int olditems = allocitems; + allocitems += UI_MENU_ALLOC_ITEMS; + ui_menu_item *newitems = auto_alloc_array(machine(), ui_menu_item, allocitems); + for (int itemnum = 0; itemnum < olditems; itemnum++) + newitems[itemnum] = item[itemnum]; + auto_free(machine(), item); + item = newitems; } - else - item.push_back(pitem); + index = numitems++; + + // copy the previous last item to the next one + if (index != 0) + { + index--; + item[index + 1] = item[index]; + } + + // allocate a new item and populate it + pitem = &item[index]; + pitem->text = (text != nullptr) ? pool_strdup(text) : nullptr; + pitem->subtext = (subtext != nullptr) ? pool_strdup(subtext) : nullptr; + pitem->flags = flags; + pitem->ref = ref; // update the selection if we need to if (resetpos == index || (resetref != nullptr && resetref == ref)) selected = index; - if (resetpos == item.size() - 1) - selected = item.size() - 1; + if (resetpos == numitems - 1) + selected = numitems - 1; } @@ -334,42 +288,27 @@ const ui_menu_event *ui_menu::process(UINT32 flags) menu_event.iptkey = IPT_INVALID; // first make sure our selection is valid -// if (!(flags & UI_MENU_PROCESS_NOINPUT)) - validate_selection(1); + validate_selection(1); // draw the menu - if (item.size() > 1 && (item[0].flags & MENU_FLAG_MULTILINE) != 0) + if (numitems > 1 && (item[0].flags & MENU_FLAG_MULTILINE) != 0) draw_text_box(); - else if ((item[0].flags & MENU_FLAG_UI ) != 0 || (item[0].flags & MENU_FLAG_UI_SWLIST ) != 0) - draw_select_game(flags & UI_MENU_PROCESS_NOINPUT); - else if ((item[0].flags & MENU_FLAG_UI_PALETTE ) != 0) - draw_palette_menu(); - else if ((item[0].flags & MENU_FLAG_UI_DATS) != 0) - draw_dats_menu(); else - draw(flags & UI_MENU_PROCESS_CUSTOM_ONLY, flags & UI_MENU_PROCESS_NOIMAGE, flags & UI_MENU_PROCESS_NOINPUT); + draw(flags & UI_MENU_PROCESS_CUSTOM_ONLY); // process input - if (!(flags & UI_MENU_PROCESS_NOKEYS) && !(flags & UI_MENU_PROCESS_NOINPUT)) + if (!(flags & UI_MENU_PROCESS_NOKEYS)) { // read events - if ((item[0].flags & MENU_FLAG_UI ) != 0 || (item[0].flags & MENU_FLAG_UI_SWLIST ) != 0) - handle_main_events(flags); - else - handle_events(flags); + handle_events(); // handle the keys if we don't already have an menu_event if (menu_event.iptkey == IPT_INVALID) - { - if ((item[0].flags & MENU_FLAG_UI ) != 0 || (item[0].flags & MENU_FLAG_UI_SWLIST ) != 0) - handle_main_keys(flags); - else - handle_keys(flags); - } + handle_keys(flags); } // update the selected item in the menu_event - if (menu_event.iptkey != IPT_INVALID && selected >= 0 && selected < item.size()) + if (menu_event.iptkey != IPT_INVALID && selected >= 0 && selected < numitems) { menu_event.itemref = item[selected].ref; return &menu_event; @@ -399,7 +338,7 @@ void *ui_menu::m_pool_alloc(size_t size) } // allocate a new pool - ppool = (ui_menu_pool *)global_alloc_array_clear<UINT8>(sizeof(*ppool) + UI_MENU_POOL_SIZE); + ppool = (ui_menu_pool *)auto_alloc_array_clear(machine(), UINT8, sizeof(*ppool) + UI_MENU_POOL_SIZE); // wire it up ppool->next = pool; @@ -428,7 +367,7 @@ const char *ui_menu::pool_strdup(const char *string) void *ui_menu::get_selection() { - return (selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr; + return (selected >= 0 && selected < numitems) ? item[selected].ref : nullptr; } @@ -439,8 +378,10 @@ void *ui_menu::get_selection() void ui_menu::set_selection(void *selected_itemref) { + int itemnum; + selected = -1; - for (int itemnum = 0; itemnum < item.size(); itemnum++) + for (itemnum = 0; itemnum < numitems; itemnum++) if (item[itemnum].ref == selected_itemref) { selected = itemnum; @@ -451,39 +392,38 @@ void ui_menu::set_selection(void *selected_itemref) /*************************************************************************** - INTERNAL MENU PROCESSING + INTERNAL MENU PROCESSING ***************************************************************************/ //------------------------------------------------- // draw - draw a menu //------------------------------------------------- -void ui_menu::draw(bool customonly, bool noimage, bool noinput) +void ui_menu::draw(bool customonly) { - // first draw the FPS counter - if (machine().ui().show_fps_counter()) - { - machine().ui().draw_text_full(container, machine().video().speed_text().c_str(), 0.0f, 0.0f, 1.0f, - JUSTIFY_RIGHT, WRAP_WORD, DRAW_OPAQUE, ARGB_WHITE, ARGB_BLACK, nullptr, nullptr); - } - float line_height = machine().ui().get_line_height(); float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(); float ud_arrow_width = line_height * machine().render().ui_aspect(); float gutter_width = lr_arrow_width * 1.3f; - - bool selected_subitem_too_big = false; + float x1, y1, x2, y2; + + float effective_width, effective_left; + float visible_width, visible_main_menu_height; + float visible_extra_menu_height; + float visible_top, visible_left; + int selected_subitem_too_big = FALSE; + int visible_lines; + int top_line; int itemnum, linenum; bool mouse_hit, mouse_button; + render_target *mouse_target; + INT32 mouse_target_x, mouse_target_y; float mouse_x = -1, mouse_y = -1; - if (machine().ui().options().use_background_image() && &machine().system() == &GAME_NAME(___empty) && bgrnd_bitmap->valid() && !noimage) - container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - // compute the width and height of the full menu - float visible_width = 0; - float visible_main_menu_height = 0; - for (itemnum = 0; itemnum < item.size(); itemnum++) + visible_width = 0; + visible_main_menu_height = 0; + for (itemnum = 0; itemnum < numitems; itemnum++) { const ui_menu_item &pitem = item[itemnum]; float total_width; @@ -504,7 +444,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) } // account for extra space at the top and bottom - float visible_extra_menu_height = customtop + custombottom; + visible_extra_menu_height = customtop + custombottom; // add a little bit of slop for rounding visible_width += 0.01f; @@ -522,46 +462,44 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) visible_main_menu_height = (float)visible_lines * line_height; // compute top/left of inner menu area by centering - float visible_left = (1.0f - visible_width) * 0.5f; - float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f; + visible_left = (1.0f - visible_width) * 0.5f; + visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f; // if the menu is at the bottom of the extra, adjust visible_top += customtop; // first add us a box - float x1 = visible_left - UI_BOX_LR_BORDER; - float y1 = visible_top - UI_BOX_TB_BORDER; - float x2 = visible_left + visible_width + UI_BOX_LR_BORDER; - float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER; + x1 = visible_left - UI_BOX_LR_BORDER; + y1 = visible_top - UI_BOX_TB_BORDER; + x2 = visible_left + visible_width + UI_BOX_LR_BORDER; + y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER; if (!customonly) machine().ui().draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); // determine the first visible line based on the current selection - if (top_line < 0 || selected == 0) + top_line = selected - visible_lines / 2; + if (top_line < 0) top_line = 0; - if (top_line + visible_lines >= item.size()) - top_line = item.size() - visible_lines; + if (top_line + visible_lines >= numitems) + top_line = numitems - visible_lines; // determine effective positions taking into account the hilighting arrows - float effective_width = visible_width - 2.0f * gutter_width; - float effective_left = visible_left + gutter_width; + effective_width = visible_width - 2.0f * gutter_width; + effective_left = visible_left + gutter_width; // locate mouse mouse_hit = false; mouse_button = false; - if (!customonly && !noinput) + if (!customonly) { - INT32 mouse_target_x, mouse_target_y; - render_target *mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); + mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); if (mouse_target != nullptr) if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y)) mouse_hit = true; } // loop over visible lines - hover = item.size() + 1; - float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; + hover = numitems + 1; if (!customonly) for (linenum = 0; linenum < visible_lines; linenum++) { @@ -573,7 +511,9 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) rgb_t bgcolor = UI_TEXT_BG_COLOR; rgb_t fgcolor2 = UI_SUBITEM_COLOR; rgb_t fgcolor3 = UI_CLONE_COLOR; + float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; float line_y0 = line_y; + float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; float line_y1 = line_y + line_height; // set the hover if this is our item @@ -590,7 +530,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) } // else if the mouse is over this item, draw with a different background - else if (itemnum == hover && ((linenum == 0 && top_line != 0) || (linenum == visible_lines - 1 && itemnum != item.size() - 1))) + else if (itemnum == hover) { fgcolor = UI_MOUSEOVER_COLOR; bgcolor = UI_MOUSEOVER_BG_COLOR; @@ -605,7 +545,8 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) // if we're on the top line, display the up arrow if (linenum == 0 && top_line != 0) { - draw_arrow(container, + draw_arrow( + container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, @@ -613,13 +554,14 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) fgcolor, ROT0); if (hover == itemnum) - hover = HOVER_ARROW_UP; + hover = -2; } // if we're on the bottom line, display the down arrow - else if (linenum == visible_lines - 1 && itemnum != item.size() - 1) + else if (linenum == visible_lines - 1 && itemnum != numitems - 1) { - draw_arrow(container, + draw_arrow( + container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, @@ -627,7 +569,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); if (hover == itemnum) - hover = HOVER_ARROW_DOWN; + hover = -1; } // if we're just a divider, draw a line @@ -637,7 +579,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) // if we don't have a subitem, just draw the string centered else if (pitem.subtext == nullptr) machine().ui().draw_text_full(container, itemtext, effective_left, line_y, effective_width, - JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); + JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); // otherwise, draw the item on the left and the subitem text on the right else @@ -658,19 +600,9 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) { subitem_text = "..."; if (itemnum == selected) - selected_subitem_too_big = true; + selected_subitem_too_big = TRUE; } - // customize subitem text color - if (!core_stricmp(subitem_text, "On")) - fgcolor2 = rgb_t(0xff,0x00,0xff,0x00); - - if (!core_stricmp(subitem_text, "Off")) - fgcolor2 = rgb_t(0xff,0xff,0x00,0x00); - - if (!core_stricmp(subitem_text, "Auto")) - fgcolor2 = rgb_t(0xff,0xff,0xff,0x00); - // draw the subitem right-justified machine().ui().draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width, JUSTIFY_RIGHT, WRAP_TRUNCATE, DRAW_NORMAL, subitem_invert ? fgcolor3 : fgcolor2, bgcolor, &subitem_width, nullptr); @@ -678,7 +610,8 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) // apply arrows if (itemnum == selected && (pitem.flags & MENU_FLAG_LEFT_ARROW)) { - draw_arrow(container, + draw_arrow( + container, effective_left + effective_width - subitem_width - gutter_width, line_y + 0.1f * line_height, effective_left + effective_width - subitem_width - gutter_width + lr_arrow_width, @@ -688,7 +621,8 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) } if (itemnum == selected && (pitem.flags & MENU_FLAG_RIGHT_ARROW)) { - draw_arrow(container, + draw_arrow( + container, effective_left + effective_width + gutter_width - lr_arrow_width, line_y + 0.1f * line_height, effective_left + effective_width + gutter_width, @@ -711,7 +645,7 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) // compute the multi-line target width/height machine().ui().draw_text_full(container, pitem.subtext, 0, 0, visible_width * 0.75f, - JUSTIFY_RIGHT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height); + JUSTIFY_RIGHT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height); // determine the target location target_x = visible_left + visible_width - target_width - UI_BOX_LR_BORDER; @@ -723,19 +657,16 @@ void ui_menu::draw(bool customonly, bool noimage, bool noinput) machine().ui().draw_outlined_box(container, target_x - UI_BOX_LR_BORDER, target_y - UI_BOX_TB_BORDER, target_x + target_width + UI_BOX_LR_BORDER, - target_y + target_height + UI_BOX_TB_BORDER, - subitem_invert ? UI_SELECTED_BG_COLOR : UI_BACKGROUND_COLOR); + target_y + target_height + UI_BOX_TB_BORDER, subitem_invert ? UI_SELECTED_BG_COLOR : UI_BACKGROUND_COLOR); machine().ui().draw_text_full(container, pitem.subtext, target_x, target_y, target_width, JUSTIFY_RIGHT, WRAP_WORD, DRAW_NORMAL, UI_SELECTED_COLOR, UI_SELECTED_BG_COLOR, nullptr, nullptr); } // if there is something special to add, do it by calling the virtual method - custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2); + custom_render((selected >= 0 && selected < numitems) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2); // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != item.size()); -// if (history_flag && (top_line + visible_lines >= item.size())) -// selected = item.size() - 1; + visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != numitems); } void ui_menu::custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) @@ -760,7 +691,7 @@ void ui_menu::draw_text_box() // compute the multi-line target width/height machine().ui().draw_text_full(container, text, 0, 0, 1.0f - 2.0f * UI_BOX_LR_BORDER - 2.0f * gutter_width, - JUSTIFY_LEFT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height); + JUSTIFY_LEFT, WRAP_WORD, DRAW_NONE, ARGB_WHITE, ARGB_BLACK, &target_width, &target_height); target_height += 2.0f * line_height; if (target_height > 1.0f - 2.0f * UI_BOX_TB_BORDER) target_height = floorf((1.0f - 2.0f * UI_BOX_TB_BORDER) / line_height) * line_height; @@ -785,25 +716,25 @@ void ui_menu::draw_text_box() // add a box around that machine().ui().draw_outlined_box(container, target_x - UI_BOX_LR_BORDER - gutter_width, - target_y - UI_BOX_TB_BORDER, - target_x + target_width + gutter_width + UI_BOX_LR_BORDER, - target_y + target_height + UI_BOX_TB_BORDER, - (item[0].flags & MENU_FLAG_REDTEXT) ? UI_RED_COLOR : UI_BACKGROUND_COLOR); + target_y - UI_BOX_TB_BORDER, + target_x + target_width + gutter_width + UI_BOX_LR_BORDER, + target_y + target_height + UI_BOX_TB_BORDER, (item[0].flags & MENU_FLAG_REDTEXT) ? UI_RED_COLOR : UI_BACKGROUND_COLOR); machine().ui().draw_text_full(container, text, target_x, target_y, target_width, JUSTIFY_LEFT, WRAP_WORD, DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); // draw the "return to prior menu" text with a hilight behind it - highlight(container, - target_x + 0.5f * UI_LINE_WIDTH, - target_y + target_height - line_height, - target_x + target_width - 0.5f * UI_LINE_WIDTH, - target_y + target_height, - UI_SELECTED_BG_COLOR); + highlight( + container, + target_x + 0.5f * UI_LINE_WIDTH, + target_y + target_height - line_height, + target_x + target_width - 0.5f * UI_LINE_WIDTH, + target_y + target_height, + UI_SELECTED_BG_COLOR); machine().ui().draw_text_full(container, backtext, target_x, target_y + target_height - line_height, target_width, JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, UI_SELECTED_COLOR, UI_SELECTED_BG_COLOR, nullptr, nullptr); // artificially set the hover to the last item so a double-click exits - hover = item.size() - 1; + hover = numitems - 1; } @@ -812,9 +743,9 @@ void ui_menu::draw_text_box() // input events for a menu //------------------------------------------------- -void ui_menu::handle_events(UINT32 flags) +void ui_menu::handle_events() { - bool stop = false; + int stop = FALSE; ui_event local_menu_event; // loop while we have interesting events @@ -824,82 +755,35 @@ void ui_menu::handle_events(UINT32 flags) { // if we are hovering over a valid item, select it with a single click case UI_EVENT_MOUSE_DOWN: - if ((flags & UI_MENU_PROCESS_ONLYCHAR) == 0) + if (hover >= 0 && hover < numitems) + selected = hover; + else if (hover == -2) { - if (hover >= 0 && hover < item.size()) - selected = hover; - else if (hover == HOVER_ARROW_UP) - { - if ((flags & MENU_FLAG_UI_DATS) != 0) - { - top_line -= visitems - (top_line + visible_lines == item.size() - 1); - return; - } - selected -= visitems; - if (selected < 0) - selected = 0; - top_line -= visitems - (top_line + visible_lines == item.size() - 1); - } - else if (hover == HOVER_ARROW_DOWN) - { - if ((flags & MENU_FLAG_UI_DATS) != 0) - { - top_line += visible_lines - 2; - return; - } - selected += visible_lines - 2 + (selected == 0); - if (selected > item.size() - 1) - selected = item.size() - 1; - top_line += visible_lines - 2; - } + selected -= visitems - 1; + validate_selection(1); + } + else if (hover == -1) + { + selected += visitems - 1; + validate_selection(1); } break; // if we are hovering over a valid item, fake a UI_SELECT with a double-click case UI_EVENT_MOUSE_DOUBLE_CLICK: - if ((flags & UI_MENU_PROCESS_ONLYCHAR) == 0 && hover >= 0 && hover < item.size()) + if (hover >= 0 && hover < numitems) { selected = hover; - menu_event.iptkey = IPT_UI_SELECT; - if (selected == item.size() - 1) + if (local_menu_event.event_type == UI_EVENT_MOUSE_DOUBLE_CLICK) { - menu_event.iptkey = IPT_UI_CANCEL; - ui_menu::stack_pop(machine()); - } - stop = true; - } - break; - - // caught scroll event - case UI_EVENT_MOUSE_WHEEL: - if ((flags & UI_MENU_PROCESS_ONLYCHAR) == 0) - { - if (local_menu_event.zdelta > 0) - { - if ((flags & MENU_FLAG_UI_DATS) != 0) + menu_event.iptkey = IPT_UI_SELECT; + if (selected == numitems - 1) { - top_line -= local_menu_event.num_lines; - return; + menu_event.iptkey = IPT_UI_CANCEL; + ui_menu::stack_pop(machine()); } - selected -= local_menu_event.num_lines; - validate_selection(-1); - if (selected < top_line + (top_line != 0)) - top_line -= local_menu_event.num_lines; - } - else - { - if ((flags & MENU_FLAG_UI_DATS) != 0) - { - top_line += local_menu_event.num_lines; - return; - } - selected += local_menu_event.num_lines; - validate_selection(1); - if (selected > item.size() - 1) - selected = item.size() - 1; - if (selected >= top_line + visitems + (top_line != 0)) - top_line += local_menu_event.num_lines; } + stop = TRUE; } break; @@ -907,7 +791,7 @@ void ui_menu::handle_events(UINT32 flags) case UI_EVENT_CHAR: menu_event.iptkey = IPT_SPECIAL; menu_event.unichar = local_menu_event.ch; - stop = true; + stop = TRUE; break; // ignore everything else @@ -925,17 +809,19 @@ void ui_menu::handle_events(UINT32 flags) void ui_menu::handle_keys(UINT32 flags) { - bool ignorepause = ui_menu::stack_has_special_main_menu(); + int ignorepause = ui_menu::stack_has_special_main_menu(); + int ignoreright; + int ignoreleft; int code; // bail if no items - if (item.empty()) + if (numitems == 0) return; // if we hit select, return TRUE or pop the stack, depending on the item if (exclusive_input_pressed(IPT_UI_SELECT, 0)) { - if (selected == item.size() - 1) + if (selected == numitems - 1) { menu_event.iptkey = IPT_UI_CANCEL; ui_menu::stack_pop(machine()); @@ -943,15 +829,10 @@ void ui_menu::handle_keys(UINT32 flags) return; } - // bail out - if ((flags & UI_MENU_PROCESS_ONLYCHAR) != 0) - return; - // hitting cancel also pops the stack if (exclusive_input_pressed(IPT_UI_CANCEL, 0)) { - if (!menu_has_search_active()) - ui_menu::stack_pop(machine()); + ui_menu::stack_pop(machine()); return; } @@ -959,11 +840,8 @@ void ui_menu::handle_keys(UINT32 flags) validate_selection(1); // swallow left/right keys if they are not appropriate - bool ignoreleft = ((item[selected].flags & MENU_FLAG_LEFT_ARROW) == 0); - bool ignoreright = ((item[selected].flags & MENU_FLAG_RIGHT_ARROW) == 0); - - if ((item[0].flags & MENU_FLAG_UI_DATS) != 0) - ignoreleft = ignoreright = false; + ignoreleft = ((item[selected].flags & MENU_FLAG_LEFT_ARROW) == 0); + ignoreright = ((item[selected].flags & MENU_FLAG_RIGHT_ARROW) == 0); // accept left/right keys as-is with repeat if (!ignoreleft && exclusive_input_pressed(IPT_UI_LEFT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0)) @@ -974,60 +852,42 @@ void ui_menu::handle_keys(UINT32 flags) // up backs up by one item if (exclusive_input_pressed(IPT_UI_UP, 6)) { - if ((item[0].flags & MENU_FLAG_UI_DATS) != 0) - { - top_line--; - return; - } - (selected == 0) ? selected = top_line = item.size() - 1 : --selected; + selected = (selected + numitems - 1) % numitems; validate_selection(-1); - top_line -= (selected == top_line && top_line != 0); } // down advances by one item if (exclusive_input_pressed(IPT_UI_DOWN, 6)) { - if ((item[0].flags & MENU_FLAG_UI_DATS) != 0) - { - top_line++; - return; - } - (selected == item.size() - 1) ? selected = top_line = 0 : ++selected; - top_line += (selected == top_line + visitems + (top_line != 0)); + selected = (selected + 1) % numitems; + validate_selection(1); } // page up backs up by visitems if (exclusive_input_pressed(IPT_UI_PAGE_UP, 6)) { - selected -= visitems; - top_line -= visitems - (top_line + visible_lines == item.size() - 1); - if (selected < 0) - selected = 0; + selected -= visitems - 1; validate_selection(1); } // page down advances by visitems if (exclusive_input_pressed(IPT_UI_PAGE_DOWN, 6)) { - selected += visible_lines - 2 + (selected == 0); - top_line += visible_lines - 2; - - if (selected > item.size() - 1) - selected = item.size() - 1; + selected += visitems - 1; validate_selection(-1); } // home goes to the start if (exclusive_input_pressed(IPT_UI_HOME, 0)) { - selected = top_line = 0; + selected = 0; validate_selection(1); } // end goes to the last if (exclusive_input_pressed(IPT_UI_END, 0)) { - selected = top_line = item.size() - 1; + selected = numitems - 1; validate_selection(-1); } @@ -1067,12 +927,12 @@ void ui_menu::validate_selection(int scandir) // clamp to be in range if (selected < 0) selected = 0; - else if (selected >= item.size()) - selected = item.size() - 1; + else if (selected >= numitems) + selected = numitems - 1; // skip past unselectable items while (!item[selected].is_selectable()) - selected = (selected + item.size() + scandir) % item.size(); + selected = (selected + numitems + scandir) % numitems; } @@ -1088,14 +948,14 @@ void ui_menu::clear_free_list(running_machine &machine) { ui_menu *menu = menu_free; menu_free = menu->parent; - global_free(menu); + auto_free(machine, menu); } } /*************************************************************************** - MENU STACK MANAGEMENT + MENU STACK MANAGEMENT ***************************************************************************/ //------------------------------------------------- @@ -1158,14 +1018,14 @@ bool ui_menu::stack_has_special_main_menu() void ui_menu::do_handle() { - if(item.size() < 2) + if(!populated()) populate(); handle(); } /*************************************************************************** - UI SYSTEM INTERACTION + UI SYSTEM INTERACTION ***************************************************************************/ //------------------------------------------------- @@ -1177,7 +1037,7 @@ UINT32 ui_menu::ui_handler(running_machine &machine, render_container *container { // if we have no menus stacked up, start with the main menu if (menu_stack == nullptr) - stack_push(global_alloc_clear<ui_menu_main>(machine, container)); + stack_push(auto_alloc_clear(machine, <ui_menu_main>(machine, container))); // update the menu state if (menu_stack != nullptr) @@ -1194,7 +1054,7 @@ UINT32 ui_menu::ui_handler(running_machine &machine, render_container *container } /*************************************************************************** - MENU HELPERS + MENU HELPERS ***************************************************************************/ //------------------------------------------------- @@ -1258,7 +1118,8 @@ void ui_menu::render_triangle(bitmap_argb32 &dest, bitmap_argb32 &source, const void ui_menu::highlight(render_container *container, float x0, float y0, float x1, float y1, rgb_t bgcolor) { - container->add_quad(x0, y0, x1, y1, bgcolor, hilight_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE) | PRIMFLAG_PACKABLE); + container->add_quad(x0, y0, x1, y1, bgcolor, hilight_texture, + PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); } @@ -1268,1502 +1129,12 @@ void ui_menu::highlight(render_container *container, float x0, float y0, float x void ui_menu::draw_arrow(render_container *container, float x0, float y0, float x1, float y1, rgb_t fgcolor, UINT32 orientation) { - container->add_quad(x0, y0, x1, y1, fgcolor, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation) | PRIMFLAG_PACKABLE); -} - -//------------------------------------------------- -// init - initialize the ui menu system -//------------------------------------------------- - -void ui_menu::init_ui(running_machine &machine) -{ - render_manager &mrender = machine.render(); - // create a texture for hilighting items in main menu - hilight_main_bitmap = std::make_unique<bitmap_rgb32>(1, 26); - int r1 = 0, g1 = 169, b1 = 255; //Any start color - int r2 = 0, g2 = 39, b2 = 130; //Any stop color - for (int y = 0; y < 26; y++) - { - int r = r1 + (y * (r2 - r1) / 26); - int g = g1 + (y * (g2 - g1) / 26); - int b = b1 + (y * (b2 - b1) / 26); - hilight_main_bitmap->pix32(y, 0) = rgb_t(0xff, r, g, b); - } - - hilight_main_texture = mrender.texture_alloc(); - hilight_main_texture->set_bitmap(*hilight_main_bitmap, hilight_main_bitmap->cliprect(), TEXFORMAT_ARGB32); - - // create a texture for snapshot - snapx_bitmap = std::make_unique<bitmap_argb32>(0, 0); - snapx_texture = mrender.texture_alloc(render_texture::hq_scale); - - // allocates and sets the default "no available" image - no_avail_bitmap = std::make_unique<bitmap_argb32>(256, 256); - UINT32 *dst = &no_avail_bitmap->pix32(0); - memcpy(dst, no_avail_bmp, 256 * 256 * sizeof(UINT32)); - - // allocates and sets the favorites star image - star_bitmap = std::make_unique<bitmap_argb32>(32, 32); - dst = &star_bitmap->pix32(0); - memcpy(dst, favorite_star_bmp, 32 * 32 * sizeof(UINT32)); - star_texture = mrender.texture_alloc(); - star_texture->set_bitmap(*star_bitmap, star_bitmap->cliprect(), TEXFORMAT_ARGB32); - - // allocate icons - for (int i = 0; i < MAX_ICONS_RENDER; i++) - { - icons_bitmap[i] = auto_alloc(machine, bitmap_argb32); - icons_texture[i] = mrender.texture_alloc(); - } - - // create a texture for main menu background - bgrnd_bitmap = std::make_unique<bitmap_argb32>(0, 0); - bgrnd_texture = mrender.texture_alloc(render_texture::hq_scale); - - ui_options &mopt = machine.ui().options(); - if (mopt.use_background_image() && &machine.system() == &GAME_NAME(___empty)) - { - emu_file backgroundfile(".", OPEN_FLAG_READ); - render_load_jpeg(*bgrnd_bitmap, backgroundfile, nullptr, "background.jpg"); - - if (!bgrnd_bitmap->valid()) - render_load_png(*bgrnd_bitmap, backgroundfile, nullptr, "background.png"); - - if (bgrnd_bitmap->valid()) - bgrnd_texture->set_bitmap(*bgrnd_bitmap, bgrnd_bitmap->cliprect(), TEXFORMAT_ARGB32); - else - bgrnd_bitmap->reset(); - } - else - bgrnd_bitmap->reset(); - - // create a texture for toolbar - for (int x = 0; x < UI_TOOLBAR_BUTTONS; ++x) - { - toolbar_bitmap[x] = auto_alloc(machine, bitmap_argb32(32, 32)); - sw_toolbar_bitmap[x] = auto_alloc(machine, bitmap_argb32(32, 32)); - toolbar_texture[x] = mrender.texture_alloc(); - sw_toolbar_texture[x] = mrender.texture_alloc(); - UINT32 *dst = &toolbar_bitmap[x]->pix32(0); - memcpy(dst, toolbar_bitmap_bmp[x], 32 * 32 * sizeof(UINT32)); - if (toolbar_bitmap[x]->valid()) - toolbar_texture[x]->set_bitmap(*toolbar_bitmap[x], toolbar_bitmap[x]->cliprect(), TEXFORMAT_ARGB32); - else - toolbar_bitmap[x]->reset(); - - if (x == 0 || x == 2) - { - dst = &sw_toolbar_bitmap[x]->pix32(0); - memcpy(dst, toolbar_bitmap_bmp[x], 32 * 32 * sizeof(UINT32)); - if (sw_toolbar_bitmap[x]->valid()) - sw_toolbar_texture[x]->set_bitmap(*sw_toolbar_bitmap[x], sw_toolbar_bitmap[x]->cliprect(), TEXFORMAT_ARGB32); - else - sw_toolbar_bitmap[x]->reset(); - } - else - sw_toolbar_bitmap[x]->reset(); - - } -} - - -//------------------------------------------------- -// draw main menu -//------------------------------------------------- - -void ui_menu::draw_select_game(bool noinput) -{ - float line_height = machine().ui().get_line_height(); - float ud_arrow_width = line_height * machine().render().ui_aspect(); - float gutter_width = 0.52f * line_height * machine().render().ui_aspect(); - mouse_x = -1, mouse_y = -1; - float right_panel_size = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL) ? 2.0f * UI_BOX_LR_BORDER : 0.3f; - float visible_width = 1.0f - 4.0f * UI_BOX_LR_BORDER; - float primary_left = (1.0f - visible_width) * 0.5f; - float primary_width = visible_width; - bool is_swlist = ((item[0].flags & MENU_FLAG_UI_SWLIST) != 0); - bool is_favorites = ((item[0].flags & MENU_FLAG_UI_FAVORITE) != 0); - ui_manager &mui = machine().ui(); - - // draw background image if available - if (machine().ui().options().use_background_image() && bgrnd_bitmap->valid()) - container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - hover = item.size() + 1; - visible_items = (is_swlist) ? item.size() - 2 : item.size() - 2 - skip_main_items; - float extra_height = (is_swlist) ? 2.0f * line_height : (2.0f + skip_main_items) * line_height; - float visible_extra_menu_height = customtop + custombottom + extra_height; - - // locate mouse - mouse_hit = false; - mouse_button = false; - if (!noinput) - { - mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); - if (mouse_target != nullptr) - if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y)) - mouse_hit = true; - } - - // account for extra space at the top and bottom - float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height; - visible_lines = floor(visible_main_menu_height / line_height); - visible_main_menu_height = (float)(visible_lines * line_height); - - if (!is_swlist) - ui_globals::visible_main_lines = visible_lines; - else - ui_globals::visible_sw_lines = visible_lines; - - // compute top/left of inner menu area by centering - float visible_left = primary_left; - float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f; - - // if the menu is at the bottom of the extra, adjust - visible_top += customtop; - - // compute left box size - float x1 = visible_left - UI_BOX_LR_BORDER; - float y1 = visible_top - UI_BOX_TB_BORDER; - float x2 = x1 + 2.0f * UI_BOX_LR_BORDER; - float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height; - - // add left box - visible_left = draw_left_panel(x1, y1, x2, y2); - visible_width -= right_panel_size + visible_left - 2.0f * UI_BOX_LR_BORDER; - - // compute and add main box - x1 = visible_left - UI_BOX_LR_BORDER; - x2 = visible_left + visible_width + UI_BOX_LR_BORDER; - float line = visible_top + (float)(visible_lines * line_height); - - //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); - mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - - if (visible_items < visible_lines) - visible_lines = visible_items; - if (top_line < 0 || selected == 0) - top_line = 0; - if (selected < visible_items && top_line + visible_lines >= visible_items) - top_line = visible_items - visible_lines; - - // determine effective positions taking into account the hilighting arrows - float effective_width = visible_width - 2.0f * gutter_width; - float effective_left = visible_left + gutter_width; - - int n_loop = (visible_items >= visible_lines) ? visible_lines : visible_items; - - for (int linenum = 0; linenum < n_loop; linenum++) - { - float line_y = visible_top + (float)linenum * line_height; - int itemnum = top_line + linenum; - const ui_menu_item &pitem = item[itemnum]; - const char *itemtext = pitem.text; - rgb_t fgcolor = UI_TEXT_COLOR; - rgb_t bgcolor = UI_TEXT_BG_COLOR; - rgb_t fgcolor3 = UI_CLONE_COLOR; - float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float line_y0 = line_y; - float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float line_y1 = line_y + line_height; - - // set the hover if this is our item - if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable()) - hover = itemnum; - - // if we're selected, draw with a different background - if (itemnum == selected) - { - fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00); - bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff); - fgcolor3 = rgb_t(0xff, 0xcc, 0xcc, 0x00); - } - // else if the mouse is over this item, draw with a different background - else if (itemnum == hover) - { - fgcolor = fgcolor3 = UI_MOUSEOVER_COLOR; - bgcolor = UI_MOUSEOVER_BG_COLOR; - } - - // if we have some background hilighting to do, add a quad behind everything else - if (bgcolor != UI_TEXT_BG_COLOR) - mui.draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(255, 43, 43, 43), - hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - - // if we're on the top line, display the up arrow - if (linenum == 0 && top_line != 0) - { - draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0); - - if (hover == itemnum) - hover = HOVER_ARROW_UP; - } - // if we're on the bottom line, display the down arrow - else if (linenum == visible_lines - 1 && itemnum != visible_items - 1) - { - draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); - - if (hover == itemnum) - hover = HOVER_ARROW_DOWN; - } - // if we're just a divider, draw a line - else if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0) - container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, - UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - // draw the item centered - else if (pitem.subtext == nullptr) - { - int item_invert = pitem.flags & MENU_FLAG_INVERT; - float space = 0.0f; - - if (ui_globals::has_icons && !is_swlist) - { - if (is_favorites) - { - ui_software_info *soft = (ui_software_info *)item[itemnum].ref; - if (soft->startempty == 1) - draw_icon(linenum, (void *)soft->driver, effective_left, line_y); - } - else - draw_icon(linenum, item[itemnum].ref, effective_left, line_y); - - space = mui.get_line_height() * container->manager().ui_aspect() * 1.5f; - } - mui.draw_text_full(container, itemtext, effective_left + space, line_y, effective_width - space, JUSTIFY_LEFT, WRAP_TRUNCATE, - DRAW_NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr); - } - else - { - int item_invert = pitem.flags & MENU_FLAG_INVERT; - const char *subitem_text = pitem.subtext; - float item_width, subitem_width; - - // compute right space for subitem - mui.draw_text_full(container, subitem_text, effective_left, line_y, machine().ui().get_string_width(pitem.subtext), - JUSTIFY_RIGHT, WRAP_NEVER, DRAW_NONE, item_invert ? fgcolor3 : fgcolor, bgcolor, &subitem_width, nullptr); - subitem_width += gutter_width; - - // draw the item left-justified - mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width - subitem_width, - JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, &item_width, nullptr); - - // draw the subitem right-justified - mui.draw_text_full(container, subitem_text, effective_left + item_width, line_y, effective_width - item_width, - JUSTIFY_RIGHT, WRAP_NEVER, DRAW_NORMAL, item_invert ? fgcolor3 : fgcolor, bgcolor, nullptr, nullptr); - } - } - - for (size_t count = visible_items; count < item.size(); count++) - { - const ui_menu_item &pitem = item[count]; - const char *itemtext = pitem.text; - float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float line_y0 = line; - float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float line_y1 = line + line_height; - rgb_t fgcolor = UI_TEXT_COLOR; - rgb_t bgcolor = UI_TEXT_BG_COLOR; - - if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable()) - hover = count; - - // if we're selected, draw with a different background - if (count == selected) - { - fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00); - bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff); - } - // else if the mouse is over this item, draw with a different background - else if (count == hover) - { - fgcolor = UI_MOUSEOVER_COLOR; - bgcolor = UI_MOUSEOVER_BG_COLOR; - } - - // if we have some background hilighting to do, add a quad behind everything else - if (bgcolor != UI_TEXT_BG_COLOR) - mui.draw_textured_box(container, line_x0 + 0.01f, line_y0, line_x1 - 0.01f, line_y1, bgcolor, rgb_t(255, 43, 43, 43), - hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - - if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0) - container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height, - UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - else - mui.draw_text_full(container, itemtext, effective_left, line, effective_width, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); - line += line_height; - } - - x1 = x2; - x2 += right_panel_size; - - draw_right_panel((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, x1, y1, x2, y2); - - x1 = primary_left - UI_BOX_LR_BORDER; - x2 = primary_left + primary_width + UI_BOX_LR_BORDER; - - // if there is something special to add, do it by calling the virtual method - custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2); - - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != visible_items); - - // reset redraw icon stage - if (!is_swlist) - ui_globals::redraw_icon = false; -} - -//------------------------------------------------- -// get title and search path for right panel -//------------------------------------------------- - -void ui_menu::get_title_search(std::string &snaptext, std::string &searchstr) -{ - // get arts title text - snaptext.assign(arts_info[ui_globals::curimage_view].title); - - // get search path - if (ui_globals::curimage_view == SNAPSHOT_VIEW) - searchstr = machine().options().value(arts_info[ui_globals::curimage_view].path); - else - searchstr = machine().ui().options().value(arts_info[ui_globals::curimage_view].path); - - path_iterator path(searchstr.c_str()); - std::string curpath; - - // iterate over path and add path for zipped formats - while (path.next(curpath)) - { - path_iterator path_iter(arts_info[ui_globals::curimage_view].addpath); - std::string c_path; - while (path_iter.next(c_path)) - searchstr.append(";").append(curpath).append(PATH_SEPARATOR).append(c_path); - } -} - -//------------------------------------------------- -// handle keys for main menu -//------------------------------------------------- - -void ui_menu::handle_main_keys(UINT32 flags) -{ - bool ignorepause = ui_menu::stack_has_special_main_menu(); - - // bail if no items - if (item.size() == 0) - return; - - // if we hit select, return TRUE or pop the stack, depending on the item - if (exclusive_input_pressed(IPT_UI_SELECT, 0)) - { - if (selected == item.size() - 1) - { - menu_event.iptkey = IPT_UI_CANCEL; - ui_menu::stack_pop(machine()); - } - return; - } - - // hitting cancel also pops the stack - if (exclusive_input_pressed(IPT_UI_CANCEL, 0)) - { - if (!menu_has_search_active()) - ui_menu::stack_pop(machine()); - // else if (!ui_error) - // ui_menu::stack_pop(machine()); TODO - return; - } - - // validate the current selection - validate_selection(1); - - // swallow left/right keys if they are not appropriate - bool ignoreleft = ((item[selected].flags & MENU_FLAG_LEFT_ARROW) == 0 || ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL); - bool ignoreright = ((item[selected].flags & MENU_FLAG_RIGHT_ARROW) == 0 || ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_RIGHT_PANEL); - bool ignoreup = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_LEFT_PANEL); - bool ignoredown = (ui_globals::panels_status == HIDE_BOTH || ui_globals::panels_status == HIDE_LEFT_PANEL); - - input_manager &minput = machine().input(); - // accept left/right keys as-is with repeat - if (!ignoreleft && exclusive_input_pressed(IPT_UI_LEFT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0)) - { - // Swap the right panel - if (minput.code_pressed(KEYCODE_LCONTROL) || minput.code_pressed(JOYCODE_BUTTON1)) - menu_event.iptkey = IPT_UI_LEFT_PANEL; - return; - } - - if (!ignoreright && exclusive_input_pressed(IPT_UI_RIGHT, (flags & UI_MENU_PROCESS_LR_REPEAT) ? 6 : 0)) - return; - - // up backs up by one item - if (exclusive_input_pressed(IPT_UI_UP, 6)) - { - // Filter - if (!ignoreup && (minput.code_pressed(KEYCODE_LALT) || minput.code_pressed(JOYCODE_BUTTON2))) - { - menu_event.iptkey = IPT_UI_UP_FILTER; - return; - } - - // Infos - if (!ignoreleft && (minput.code_pressed(KEYCODE_LCONTROL) || minput.code_pressed(JOYCODE_BUTTON1))) - { - menu_event.iptkey = IPT_UI_UP_PANEL; - topline_datsview--; - return; - } - - if (selected == visible_items + 1 || selected == 0 || ui_error) - return; - - selected--; - - if (selected == top_line && top_line != 0) - top_line--; - } - - // down advances by one item - if (exclusive_input_pressed(IPT_UI_DOWN, 6)) - { - // Filter - if (!ignoredown && (minput.code_pressed(KEYCODE_LALT) || minput.code_pressed(JOYCODE_BUTTON2))) - { - menu_event.iptkey = IPT_UI_DOWN_FILTER; - return; - } - - // Infos - if (!ignoreright && (minput.code_pressed(KEYCODE_LCONTROL) || minput.code_pressed(JOYCODE_BUTTON1))) - { - menu_event.iptkey = IPT_UI_DOWN_PANEL; - topline_datsview++; - return; - } - - if (selected == item.size() - 1 || selected == visible_items - 1 || ui_error) - return; - - selected++; - - if (selected == top_line + visitems + (top_line != 0)) - top_line++; - } - - // page up backs up by visitems - if (exclusive_input_pressed(IPT_UI_PAGE_UP, 6)) - { - // Infos - if (!ignoreleft && (minput.code_pressed(KEYCODE_LCONTROL) || minput.code_pressed(JOYCODE_BUTTON1))) - { - menu_event.iptkey = IPT_UI_DOWN_PANEL; - topline_datsview -= right_visible_lines - 1; - return; - } - - if (selected < visible_items && !ui_error) - { - selected -= visitems; - - if (selected < 0) - selected = 0; - - top_line -= visitems - (top_line + visible_lines == visible_items); - } - } - - // page down advances by visitems - if (exclusive_input_pressed(IPT_UI_PAGE_DOWN, 6)) - { - // Infos - if (!ignoreleft && (minput.code_pressed(KEYCODE_LCONTROL) || minput.code_pressed(JOYCODE_BUTTON1))) - { - menu_event.iptkey = IPT_UI_DOWN_PANEL; - topline_datsview += right_visible_lines - 1; - return; - } - - if (selected < visible_items && !ui_error) - { - selected += visible_lines - 2 + (selected == 0); - - if (selected >= visible_items) - selected = visible_items - 1; - - top_line += visible_lines - 2; - } - } - - // home goes to the start - if (exclusive_input_pressed(IPT_UI_HOME, 0)) - { - // Infos - if (!ignoreleft && (minput.code_pressed(KEYCODE_LCONTROL) || minput.code_pressed(JOYCODE_BUTTON1))) - { - menu_event.iptkey = IPT_UI_DOWN_PANEL; - topline_datsview = 0; - return; - } - - if (selected < visible_items && !ui_error) - { - selected = 0; - top_line = 0; - } - } - - // end goes to the last - if (exclusive_input_pressed(IPT_UI_END, 0)) - { - // Infos - if (!ignoreleft && (minput.code_pressed(KEYCODE_LCONTROL) || minput.code_pressed(JOYCODE_BUTTON1))) - { - menu_event.iptkey = IPT_UI_DOWN_PANEL; - topline_datsview = totallines; - return; - } - - if (selected < visible_items && !ui_error) - selected = top_line = visible_items - 1; - } - - // pause enables/disables pause - if (!ui_error && !ignorepause && exclusive_input_pressed(IPT_UI_PAUSE, 0)) - { - if (machine().paused()) - machine().resume(); - else - machine().pause(); - } - - // handle a toggle cheats request - if (!ui_error && machine().ui_input().pressed_repeat(IPT_UI_TOGGLE_CHEAT, 0)) - machine().cheat().set_enable(!machine().cheat().enabled()); - - // see if any other UI keys are pressed - if (menu_event.iptkey == IPT_INVALID) - for (int code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++) - { - if (ui_error || code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause)) - continue; - - if (exclusive_input_pressed(code, 0)) - break; - } -} - -//------------------------------------------------- -// handle input events for main menu -//------------------------------------------------- - -void ui_menu::handle_main_events(UINT32 flags) -{ - bool stop = false; - ui_event local_menu_event; - - // loop while we have interesting events - while (!stop && machine().ui_input().pop_event(&local_menu_event)) - { - switch (local_menu_event.event_type) - { - // if we are hovering over a valid item, select it with a single click - case UI_EVENT_MOUSE_DOWN: - { - if (ui_error) - { - menu_event.iptkey = IPT_OTHER; - stop = true; - } - else - { - if (hover >= 0 && hover < item.size()) - selected = hover; - else if (hover == HOVER_ARROW_UP) - { - selected -= visitems; - if (selected < 0) - selected = 0; - top_line -= visitems - (top_line + visible_lines == visible_items); - } - else if (hover == HOVER_ARROW_DOWN) - { - selected += visible_lines - 2 + (selected == 0); - if (selected >= visible_items) - selected = visible_items - 1; - top_line += visible_lines - 2; - } - else if (hover == HOVER_UI_RIGHT) - menu_event.iptkey = IPT_UI_RIGHT; - else if (hover == HOVER_UI_LEFT) - menu_event.iptkey = IPT_UI_LEFT; - else if (hover == HOVER_DAT_DOWN) - topline_datsview += right_visible_lines - 1; - else if (hover == HOVER_DAT_UP) - topline_datsview -= right_visible_lines - 1; - else if (hover == HOVER_LPANEL_ARROW) - { - if (ui_globals::panels_status == HIDE_LEFT_PANEL) - ui_globals::panels_status = SHOW_PANELS; - else if (ui_globals::panels_status == HIDE_BOTH) - ui_globals::panels_status = HIDE_RIGHT_PANEL; - else if (ui_globals::panels_status == SHOW_PANELS) - ui_globals::panels_status = HIDE_LEFT_PANEL; - else if (ui_globals::panels_status == HIDE_RIGHT_PANEL) - ui_globals::panels_status = HIDE_BOTH; - } - else if (hover == HOVER_RPANEL_ARROW) - { - if (ui_globals::panels_status == HIDE_RIGHT_PANEL) - ui_globals::panels_status = SHOW_PANELS; - else if (ui_globals::panels_status == HIDE_BOTH) - ui_globals::panels_status = HIDE_LEFT_PANEL; - else if (ui_globals::panels_status == SHOW_PANELS) - ui_globals::panels_status = HIDE_RIGHT_PANEL; - else if (ui_globals::panels_status == HIDE_LEFT_PANEL) - ui_globals::panels_status = HIDE_BOTH; - } - else if (hover == HOVER_B_FAV) - { - menu_event.iptkey = IPT_UI_FAVORITES; - stop = true; - } - else if (hover == HOVER_B_EXPORT) - { - menu_event.iptkey = IPT_UI_EXPORT; - stop = true; - } - else if (hover == HOVER_B_DATS) - { - menu_event.iptkey = IPT_UI_DATS; - stop = true; - } - else if (hover == HOVER_B_SETTINGS) - { - menu_event.iptkey = IPT_UI_SELECT; - selected = visible_items + 1; - stop = true; - } - else if (hover == HOVER_B_FOLDERS) - { - menu_event.iptkey = IPT_UI_SELECT; - selected = visible_items + 2; - stop = true; - } - else if (hover >= HOVER_RP_FIRST && hover <= HOVER_RP_LAST) - { - ui_globals::rpanel = (HOVER_RP_FIRST - hover) * (-1); - stop = true; - } - else if (hover >= HOVER_SW_FILTER_FIRST && hover <= HOVER_SW_FILTER_LAST) - { - l_sw_hover = (HOVER_SW_FILTER_FIRST - hover) * (-1); - menu_event.iptkey = IPT_OTHER; - stop = true; - } - else if (hover >= HOVER_FILTER_FIRST && hover <= HOVER_FILTER_LAST) - { - l_hover = (HOVER_FILTER_FIRST - hover) * (-1); - menu_event.iptkey = IPT_OTHER; - stop = true; - } - } - break; - } - - // if we are hovering over a valid item, fake a UI_SELECT with a double-click - case UI_EVENT_MOUSE_DOUBLE_CLICK: - if (hover >= 0 && hover < item.size()) - { - selected = hover; - menu_event.iptkey = IPT_UI_SELECT; - } - - if (selected == item.size() - 1) - { - menu_event.iptkey = IPT_UI_CANCEL; - ui_menu::stack_pop(machine()); - } - stop = true; - break; - - // caught scroll event - case UI_EVENT_MOUSE_WHEEL: - if (local_menu_event.zdelta > 0) - { - if (selected >= visible_items || selected == 0 || ui_error) - break; - selected -= local_menu_event.num_lines; - if (selected < top_line + (top_line != 0)) - top_line -= local_menu_event.num_lines; - } - else - { - if (selected >= visible_items - 1 || ui_error) - break; - selected += local_menu_event.num_lines; - if (selected > visible_items - 1) - selected = visible_items - 1; - if (selected >= top_line + visitems + (top_line != 0)) - top_line += local_menu_event.num_lines; - } - break; - - // translate CHAR events into specials - case UI_EVENT_CHAR: - menu_event.iptkey = IPT_SPECIAL; - menu_event.unichar = local_menu_event.ch; - stop = true; - break; - - // ignore everything else - default: - break; - } - } -} - -//------------------------------------------------- -// draw right box title -//------------------------------------------------- - -float ui_menu::draw_right_box_title(float x1, float y1, float x2, float y2) -{ - ui_manager &mui = machine().ui(); - float line_height = mui.get_line_height(); - float midl = (x2 - x1) * 0.5f; - - // add outlined box for options - mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - - // add separator line - container->add_line(x1 + midl, y1, x1 + midl, y1 + line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - std::string buffer[RP_LAST + 1]; - buffer[RP_IMAGES].assign("Images"); - buffer[RP_INFOS].assign("Infos"); - - for (int cells = RP_IMAGES; cells <= RP_INFOS; cells++) - { - rgb_t bgcolor = UI_TEXT_BG_COLOR; - rgb_t fgcolor = UI_TEXT_COLOR; - - if (mouse_hit && x1 <= mouse_x && x1 + midl > mouse_x && y1 <= mouse_y && y1 + line_height > mouse_y) - { - if (ui_globals::rpanel != cells) - { - bgcolor = UI_MOUSEOVER_BG_COLOR; - fgcolor = UI_MOUSEOVER_COLOR; - hover = HOVER_RP_FIRST + cells; - } - } - - if (ui_globals::rpanel != cells) - { - container->add_line(x1, y1 + line_height, x1 + midl, y1 + line_height, UI_LINE_WIDTH, - UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - if (fgcolor != UI_MOUSEOVER_COLOR) - fgcolor = UI_CLONE_COLOR; - } - - if (bgcolor != UI_TEXT_BG_COLOR) - container->add_rect(x1 + UI_LINE_WIDTH, y1 + UI_LINE_WIDTH, x1 + midl - UI_LINE_WIDTH, y1 + line_height, - bgcolor, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - - mui.draw_text_full(container, buffer[cells].c_str(), x1 + UI_LINE_WIDTH, y1, midl - UI_LINE_WIDTH, - JUSTIFY_CENTER, WRAP_NEVER, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); - x1 += midl; - } - - return (y1 + line_height + UI_LINE_WIDTH); -} - -//------------------------------------------------- -// common function for images render -//------------------------------------------------- - -std::string ui_menu::arts_render_common(float origx1, float origy1, float origx2, float origy2) -{ - std::string snaptext, searchstr; - get_title_search(snaptext, searchstr); - - // apply title to right panel - float title_size = 0.0f; - float txt_lenght = 0.0f; - - for (int x = FIRST_VIEW; x < LAST_VIEW; x++) - { - machine().ui().draw_text_full(container, arts_info[x].title, origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, - WRAP_TRUNCATE, DRAW_NONE, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, &txt_lenght, nullptr); - txt_lenght += 0.01f; - title_size = MAX(txt_lenght, title_size); - } - - machine().ui().draw_text_full(container, snaptext.c_str(), origx1, origy1, origx2 - origx1, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NORMAL, UI_TEXT_COLOR, UI_TEXT_BG_COLOR, nullptr, nullptr); - - draw_common_arrow(origx1, origy1, origx2, origy2, ui_globals::curimage_view, FIRST_VIEW, LAST_VIEW, title_size); - - return searchstr; + container->add_quad( + x0, + y0, + x1, + y1, + fgcolor, + arrow_texture, + PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation)); } - -//------------------------------------------------- -// draw favorites star -//------------------------------------------------- - -void ui_menu::draw_star(float x0, float y0) -{ - float y1 = y0 + machine().ui().get_line_height(); - float x1 = x0 + machine().ui().get_line_height() * container->manager().ui_aspect(); - container->add_quad(x0, y0, x1, y1, ARGB_WHITE, star_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE); -} - -//------------------------------------------------- -// draw toolbar -//------------------------------------------------- - -void ui_menu::draw_toolbar(float x1, float y1, float x2, float y2, bool software) -{ - ui_manager &mui = machine().ui(); - // draw a box - mui.draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); - - // take off the borders - x1 += UI_BOX_LR_BORDER; - x2 -= UI_BOX_LR_BORDER; - y1 += UI_BOX_TB_BORDER; - y2 -= UI_BOX_TB_BORDER; - - render_texture **t_texture = (software) ? sw_toolbar_texture : toolbar_texture; - bitmap_argb32 **t_bitmap = (software) ? sw_toolbar_bitmap : toolbar_bitmap; - - int m_valid = 0; - for (int x = 0; x < UI_TOOLBAR_BUTTONS; ++x) - if (t_bitmap[x]->valid()) - m_valid++; - - float x_pixel = 1.0f / container->manager().ui_target().width(); - int h_len = mui.get_line_height() * container->manager().ui_target().height(); - h_len = (h_len % 2 == 0) ? h_len : h_len - 1; - x1 = (x1 + x2) * 0.5f - x_pixel * (m_valid * ((h_len / 2) + 2)); - - for (int z = 0; z < UI_TOOLBAR_BUTTONS; ++z) - { - if (t_bitmap[z]->valid()) - { - x2 = x1 + x_pixel * h_len; - rgb_t color(0xEFEFEFEF); - if (mouse_hit && x1 <= mouse_x && x2 > mouse_x && y1 <= mouse_y && y2 > mouse_y) - { - hover = HOVER_B_FAV + z; - color = ARGB_WHITE; - float ypos = y2 + machine().ui().get_line_height() + 2.0f * UI_BOX_TB_BORDER; - mui.draw_text_box(container, hover_msg[z], JUSTIFY_CENTER, 0.5f, ypos, UI_BACKGROUND_COLOR); - } - - container->add_quad(x1, y1, x2, y2, color, t_texture[z], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - x1 += x_pixel * (h_len + 2); - } - } -} - - -//------------------------------------------------- -// perform rendering of image -//------------------------------------------------- - -void ui_menu::arts_render_images(bitmap_argb32 *tmp_bitmap, float origx1, float origy1, float origx2, float origy2, bool software) -{ - bool no_available = false; - float line_height = machine().ui().get_line_height(); - - // if it fails, use the default image - if (!tmp_bitmap->valid()) - { - tmp_bitmap->allocate(256, 256); - for (int x = 0; x < 256; x++) - for (int y = 0; y < 256; y++) - tmp_bitmap->pix32(y, x) = no_avail_bitmap->pix32(y, x); - no_available = true; - } - - if (tmp_bitmap->valid()) - { - float panel_width = origx2 - origx1 - 0.02f; - float panel_height = origy2 - origy1 - 0.02f - (2.0f * UI_BOX_TB_BORDER) - (2.0f * line_height); - int screen_width = machine().render().ui_target().width(); - int screen_height = machine().render().ui_target().height(); - int panel_width_pixel = panel_width * screen_width; - int panel_height_pixel = panel_height * screen_height; - float ratio = 0.0f; - - // Calculate resize ratios for resizing - float ratioW = (float)panel_width_pixel / tmp_bitmap->width(); - float ratioH = (float)panel_height_pixel / tmp_bitmap->height(); - float ratioI = (float)tmp_bitmap->height() / tmp_bitmap->width(); - int dest_xPixel = tmp_bitmap->width(); - int dest_yPixel = tmp_bitmap->height(); - - // force 4:3 ratio min - if (machine().ui().options().forced_4x3_snapshot() && ratioI < 0.75f && ui_globals::curimage_view == SNAPSHOT_VIEW) - { - // smaller ratio will ensure that the image fits in the view - dest_yPixel = tmp_bitmap->width() * 0.75f; - ratioH = (float)panel_height_pixel / dest_yPixel; - ratio = MIN(ratioW, ratioH); - dest_xPixel = tmp_bitmap->width() * ratio; - dest_yPixel *= ratio; - } - // resize the bitmap if necessary - else if (ratioW < 1 || ratioH < 1 || (machine().ui().options().enlarge_snaps() && !no_available)) - { - // smaller ratio will ensure that the image fits in the view - ratio = MIN(ratioW, ratioH); - dest_xPixel = tmp_bitmap->width() * ratio; - dest_yPixel = tmp_bitmap->height() * ratio; - } - - bitmap_argb32 *dest_bitmap; - - // resample if necessary - if (dest_xPixel != tmp_bitmap->width() || dest_yPixel != tmp_bitmap->height()) - { - dest_bitmap = auto_alloc(machine(), bitmap_argb32); - dest_bitmap->allocate(dest_xPixel, dest_yPixel); - render_color color = { 1.0f, 1.0f, 1.0f, 1.0f }; - render_resample_argb_bitmap_hq(*dest_bitmap, *tmp_bitmap, color, true); - } - else - dest_bitmap = tmp_bitmap; - - snapx_bitmap->allocate(panel_width_pixel, panel_height_pixel); - int x1 = (0.5f * panel_width_pixel) - (0.5f * dest_xPixel); - int y1 = (0.5f * panel_height_pixel) - (0.5f * dest_yPixel); - - for (int x = 0; x < dest_xPixel; x++) - for (int y = 0; y < dest_yPixel; y++) - snapx_bitmap->pix32(y + y1, x + x1) = dest_bitmap->pix32(y, x); - - auto_free(machine(), dest_bitmap); - - // apply bitmap - snapx_texture->set_bitmap(*snapx_bitmap, snapx_bitmap->cliprect(), TEXFORMAT_ARGB32); - } - else - snapx_bitmap->reset(); -} - -//------------------------------------------------- -// draw common arrows -//------------------------------------------------- - -void ui_menu::draw_common_arrow(float origx1, float origy1, float origx2, float origy2, int current, int dmin, int dmax, float title_size) -{ - float line_height = machine().ui().get_line_height(); - float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(); - float gutter_width = lr_arrow_width * 1.3f; - - // set left-right arrows dimension - float ar_x0 = 0.5f * (origx2 + origx1) + 0.5f * title_size + gutter_width - lr_arrow_width; - float ar_y0 = origy1 + 0.1f * line_height; - float ar_x1 = 0.5f * (origx2 + origx1) + 0.5f * title_size + gutter_width; - float ar_y1 = origy1 + 0.9f * line_height; - - float al_x0 = 0.5f * (origx2 + origx1) - 0.5f * title_size - gutter_width; - float al_y0 = origy1 + 0.1f * line_height; - float al_x1 = 0.5f * (origx2 + origx1) - 0.5f * title_size - gutter_width + lr_arrow_width; - float al_y1 = origy1 + 0.9f * line_height; - - rgb_t fgcolor_right, fgcolor_left; - fgcolor_right = fgcolor_left = UI_TEXT_COLOR; - - // set hover - if (mouse_hit && ar_x0 <= mouse_x && ar_x1 > mouse_x && ar_y0 <= mouse_y && ar_y1 > mouse_y && current != dmax) - { - machine().ui().draw_textured_box(container, ar_x0 + 0.01f, ar_y0, ar_x1 - 0.01f, ar_y1, UI_MOUSEOVER_BG_COLOR, rgb_t(255, 43, 43, 43), - hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - hover = HOVER_UI_RIGHT; - fgcolor_right = UI_MOUSEOVER_COLOR; - } - else if (mouse_hit && al_x0 <= mouse_x && al_x1 > mouse_x && al_y0 <= mouse_y && al_y1 > mouse_y && current != dmin) - { - machine().ui().draw_textured_box(container, al_x0 + 0.01f, al_y0, al_x1 - 0.01f, al_y1, UI_MOUSEOVER_BG_COLOR, rgb_t(255, 43, 43, 43), - hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - hover = HOVER_UI_LEFT; - fgcolor_left = UI_MOUSEOVER_COLOR; - } - - // apply arrow - if (current == dmin) - container->add_quad(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90) | PRIMFLAG_PACKABLE); - else if (current == dmax) - container->add_quad(al_x0, al_y0, al_x1, al_y1, fgcolor_left, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X) | PRIMFLAG_PACKABLE); - else - { - container->add_quad(ar_x0, ar_y0, ar_x1, ar_y1, fgcolor_right, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90) | PRIMFLAG_PACKABLE); - container->add_quad(al_x0, al_y0, al_x1, al_y1, fgcolor_left, arrow_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(ROT90 ^ ORIENTATION_FLIP_X) | PRIMFLAG_PACKABLE); - } -} - -//------------------------------------------------- -// draw icons -//------------------------------------------------- - -void ui_menu::draw_icon(int linenum, void *selectedref, float x0, float y0) -{ - static const game_driver *olddriver[MAX_ICONS_RENDER] = { nullptr }; - float x1 = x0 + machine().ui().get_line_height() * container->manager().ui_aspect(container); - float y1 = y0 + machine().ui().get_line_height(); - const game_driver *driver = (const game_driver *)selectedref; - - if (olddriver[linenum] != driver || ui_globals::redraw_icon) - { - olddriver[linenum] = driver; - - // set clone status - bool cloneof = strcmp(driver->parent, "0"); - if (cloneof) - { - int cx = driver_list::find(driver->parent); - if (cx != -1 && ((driver_list::driver(cx).flags & MACHINE_IS_BIOS_ROOT) != 0)) - cloneof = false; - } - - // get search path - path_iterator path(machine().ui().options().icons_directory()); - std::string curpath; - std::string searchstr(machine().ui().options().icons_directory()); - - // iterate over path and add path for zipped formats - while (path.next(curpath)) - searchstr.append(";").append(curpath.c_str()).append(PATH_SEPARATOR).append("icons"); - - bitmap_argb32 *tmp = auto_alloc(machine(), bitmap_argb32); - emu_file snapfile(searchstr.c_str(), OPEN_FLAG_READ); - std::string fullname = std::string(driver->name).append(".ico"); - render_load_ico(*tmp, snapfile, nullptr, fullname.c_str()); - - if (!tmp->valid() && cloneof) - { - fullname.assign(driver->parent).append(".ico"); - render_load_ico(*tmp, snapfile, nullptr, fullname.c_str()); - } - - if (tmp->valid()) - { - float panel_width = x1 - x0; - float panel_height = y1 - y0; - int screen_width = machine().render().ui_target().width(); - int screen_height = machine().render().ui_target().height(); - int panel_width_pixel = panel_width * screen_width; - int panel_height_pixel = panel_height * screen_height; - - // Calculate resize ratios for resizing - float ratioW = (float)panel_width_pixel / tmp->width(); - float ratioH = (float)panel_height_pixel / tmp->height(); - int dest_xPixel = tmp->width(); - int dest_yPixel = tmp->height(); - - if (ratioW < 1 || ratioH < 1) - { - // smaller ratio will ensure that the image fits in the view - float ratio = MIN(ratioW, ratioH); - dest_xPixel = tmp->width() * ratio; - dest_yPixel = tmp->height() * ratio; - } - - bitmap_argb32 *dest_bitmap; - dest_bitmap = auto_alloc(machine(), bitmap_argb32); - - // resample if necessary - if (dest_xPixel != tmp->width() || dest_yPixel != tmp->height()) - { - dest_bitmap->allocate(dest_xPixel, dest_yPixel); - render_color color = { 1.0f, 1.0f, 1.0f, 1.0f }; - render_resample_argb_bitmap_hq(*dest_bitmap, *tmp, color, true); - } - else - dest_bitmap = tmp; - - icons_bitmap[linenum]->reset(); - icons_bitmap[linenum]->allocate(panel_width_pixel, panel_height_pixel); - - for (int x = 0; x < dest_xPixel; x++) - for (int y = 0; y < dest_yPixel; y++) - icons_bitmap[linenum]->pix32(y, x) = dest_bitmap->pix32(y, x); - - auto_free(machine(), dest_bitmap); - - icons_texture[linenum]->set_bitmap(*icons_bitmap[linenum], icons_bitmap[linenum]->cliprect(), TEXFORMAT_ARGB32); - } - else { - if (icons_bitmap[linenum] != nullptr) - { - icons_bitmap[linenum]->reset(); - } - } - auto_free(machine(), tmp); - } - - if (icons_bitmap[linenum] != nullptr && icons_bitmap[linenum]->valid()) - container->add_quad(x0, y0, x1, y1, ARGB_WHITE, icons_texture[linenum], PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_PACKABLE); -} - -//------------------------------------------------- -// draw info arrow -//------------------------------------------------- - -void ui_menu::info_arrow(int ub, float origx1, float origx2, float oy1, float line_height, float text_size, float ud_arrow_width) -{ - rgb_t fgcolor = UI_TEXT_COLOR; - UINT32 orientation = (!ub) ? ROT0 : ROT0 ^ ORIENTATION_FLIP_Y; - - if (mouse_hit && origx1 <= mouse_x && origx2 > mouse_x && oy1 <= mouse_y && oy1 + (line_height * text_size) > mouse_y) - { - machine().ui().draw_textured_box(container, origx1 + 0.01f, oy1, origx2 - 0.01f, oy1 + (line_height * text_size), UI_MOUSEOVER_BG_COLOR, - rgb_t(255, 43, 43, 43), hilight_main_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(TRUE)); - hover = (!ub) ? HOVER_DAT_UP : HOVER_DAT_DOWN; - fgcolor = UI_MOUSEOVER_COLOR; - } - - draw_arrow(container, 0.5f * (origx1 + origx2) - 0.5f * (ud_arrow_width * text_size), oy1 + 0.25f * (line_height * text_size), - 0.5f * (origx1 + origx2) + 0.5f * (ud_arrow_width * text_size), oy1 + 0.75f * (line_height * text_size), fgcolor, orientation); -} - -//------------------------------------------------- -// draw - draw palette menu -//------------------------------------------------- - -void ui_menu::draw_palette_menu() -{ - ui_manager &mui = machine().ui(); - float line_height = mui.get_line_height(); - float lr_arrow_width = 0.4f * line_height * machine().render().ui_aspect(); - float ud_arrow_width = line_height * machine().render().ui_aspect(); - float gutter_width = lr_arrow_width * 1.3f; - int itemnum, linenum; - - if (machine().ui().options().use_background_image() && machine().options().system() == nullptr && bgrnd_bitmap->valid()) - container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - // compute the width and height of the full menu - float visible_width = 0; - float visible_main_menu_height = 0; - for (itemnum = 0; itemnum < item.size(); itemnum++) - { - const ui_menu_item &pitem = item[itemnum]; - - // compute width of left hand side - float total_width = gutter_width + mui.get_string_width(pitem.text) + gutter_width; - - // add in width of right hand side - if (pitem.subtext) - total_width += 2.0f * gutter_width + mui.get_string_width(pitem.subtext); - - // track the maximum - if (total_width > visible_width) - visible_width = total_width; - - // track the height as well - visible_main_menu_height += line_height; - } - - // account for extra space at the top and bottom - float visible_extra_menu_height = customtop + custombottom; - - // add a little bit of slop for rounding - visible_width += 0.01f; - visible_main_menu_height += 0.01f; - - // if we are too wide or too tall, clamp it down - if (visible_width + 2.0f * UI_BOX_LR_BORDER > 1.0f) - visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER; - - // if the menu and extra menu won't fit, take away part of the regular menu, it will scroll - if (visible_main_menu_height + visible_extra_menu_height + 2.0f * UI_BOX_TB_BORDER > 1.0f) - visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height; - - int visible_lines = floor(visible_main_menu_height / line_height); - visible_main_menu_height = (float)visible_lines * line_height; - - // compute top/left of inner menu area by centering - float visible_left = (1.0f - visible_width) * 0.5f; - float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f; - - // if the menu is at the bottom of the extra, adjust - visible_top += customtop; - - // first add us a box - float x1 = visible_left - UI_BOX_LR_BORDER; - float y1 = visible_top - UI_BOX_TB_BORDER; - float x2 = visible_left + visible_width + UI_BOX_LR_BORDER; - float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER; - mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - - // determine the first visible line based on the current selection - int top_line = selected - visible_lines / 2; - if (top_line < 0) - top_line = 0; - if (top_line + visible_lines >= item.size()) - top_line = item.size() - visible_lines; - - // determine effective positions taking into account the hilighting arrows - float effective_width = visible_width - 2.0f * gutter_width; - float effective_left = visible_left + gutter_width; - - // locate mouse - mouse_hit = false; - mouse_button = false; - mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); - if (mouse_target != nullptr) - if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y)) - mouse_hit = true; - - // loop over visible lines - hover = item.size() + 1; - float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - - for (linenum = 0; linenum < visible_lines; linenum++) - { - float line_y = visible_top + (float)linenum * line_height; - itemnum = top_line + linenum; - const ui_menu_item &pitem = item[itemnum]; - const char *itemtext = pitem.text; - rgb_t fgcolor = UI_TEXT_COLOR; - rgb_t bgcolor = UI_TEXT_BG_COLOR; - float line_y0 = line_y; - float line_y1 = line_y + line_height; - - // set the hover if this is our item - if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable()) - hover = itemnum; - - // if we're selected, draw with a different background - if (itemnum == selected) - { - fgcolor = UI_SELECTED_COLOR; - bgcolor = UI_SELECTED_BG_COLOR; - } - - // else if the mouse is over this item, draw with a different background - else if (itemnum == hover) - { - fgcolor = UI_MOUSEOVER_COLOR; - bgcolor = UI_MOUSEOVER_BG_COLOR; - } - - // if we have some background hilighting to do, add a quad behind everything else - if (bgcolor != UI_TEXT_BG_COLOR) - highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor); - - // if we're on the top line, display the up arrow - if (linenum == 0 && top_line != 0) - { - draw_arrow(container, - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, - line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, - line_y + 0.75f * line_height, - fgcolor, - ROT0); - if (hover == itemnum) - hover = HOVER_ARROW_UP; - } - - // if we're on the bottom line, display the down arrow - else if (linenum == visible_lines - 1 && itemnum != item.size() - 1) - { - draw_arrow(container, - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, - line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, - line_y + 0.75f * line_height, - fgcolor, - ROT0 ^ ORIENTATION_FLIP_Y); - if (hover == itemnum) - hover = HOVER_ARROW_DOWN; - } - - // if we're just a divider, draw a line - else if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0) - container->add_line(visible_left, line_y + 0.5f * line_height, visible_left + visible_width, line_y + 0.5f * line_height, UI_LINE_WIDTH, UI_BORDER_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - // if we don't have a subitem, just draw the string centered - else if (pitem.subtext == nullptr) - mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width, - JUSTIFY_CENTER, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); - - // otherwise, draw the item on the left and the subitem text on the right - else - { - const char *subitem_text = pitem.subtext; - rgb_t color = rgb_t((UINT32)strtoul(subitem_text, nullptr, 16)); - - // draw the left-side text - mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width, - JUSTIFY_LEFT, WRAP_TRUNCATE, DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); - - // give 2 spaces worth of padding - float subitem_width = mui.get_string_width("FF00FF00"); - - mui.draw_outlined_box(container, effective_left + effective_width - subitem_width, line_y0, - effective_left + effective_width, line_y1, color); - } - } - - // if there is something special to add, do it by calling the virtual method - custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2); - - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != item.size()); -} - -//------------------------------------------------- -// draw - draw dats menu -//------------------------------------------------- - -void ui_menu::draw_dats_menu() -{ - float line_height = machine().ui().get_line_height(); - float ud_arrow_width = line_height * machine().render().ui_aspect(); - float gutter_width = 0.52f * line_height * machine().render().ui_aspect(); - mouse_x = -1, mouse_y = -1; - float visible_width = 1.0f - 2.0f * UI_BOX_LR_BORDER; - float visible_left = (1.0f - visible_width) * 0.5f; - ui_manager &mui = machine().ui(); - - // draw background image if available - if (machine().ui().options().use_background_image() && bgrnd_bitmap->valid()) - container->add_quad(0.0f, 0.0f, 1.0f, 1.0f, ARGB_WHITE, bgrnd_texture, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - hover = item.size() + 1; - visible_items = item.size() - 2; - float extra_height = 2.0f * line_height; - float visible_extra_menu_height = customtop + custombottom + extra_height; - - // locate mouse - mouse_hit = false; - mouse_button = false; - mouse_target = machine().ui_input().find_mouse(&mouse_target_x, &mouse_target_y, &mouse_button); - if (mouse_target != nullptr) - if (mouse_target->map_point_container(mouse_target_x, mouse_target_y, *container, mouse_x, mouse_y)) - mouse_hit = true; - - // account for extra space at the top and bottom - float visible_main_menu_height = 1.0f - 2.0f * UI_BOX_TB_BORDER - visible_extra_menu_height; - visible_lines = floor(visible_main_menu_height / line_height); - visible_main_menu_height = (float)(visible_lines * line_height); - - // compute top/left of inner menu area by centering - float visible_top = (1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f; - - // if the menu is at the bottom of the extra, adjust - visible_top += customtop; - - // compute left box size - float x1 = visible_left; - float y1 = visible_top - UI_BOX_TB_BORDER; - float x2 = x1 + visible_width; - float y2 = visible_top + visible_main_menu_height + UI_BOX_TB_BORDER + extra_height; - float line = visible_top + (float)(visible_lines * line_height); - - //machine().ui().draw_outlined_box(container, x1, y1, x2, y2, rgb_t(0xEF, 0x12, 0x47, 0x7B)); - mui.draw_outlined_box(container, x1, y1, x2, y2, UI_BACKGROUND_COLOR); - - if (visible_items < visible_lines) - visible_lines = visible_items; - if (top_line < 0) - top_line = 0; - if (top_line + visible_lines >= visible_items) - top_line = visible_items - visible_lines; - - // determine effective positions taking into account the hilighting arrows - float effective_width = visible_width - 2.0f * gutter_width; - float effective_left = visible_left + gutter_width; - - int n_loop = (visible_items >= visible_lines) ? visible_lines : visible_items; - - for (int linenum = 0; linenum < n_loop; linenum++) - { - float line_y = visible_top + (float)linenum * line_height; - int itemnum = top_line + linenum; - const ui_menu_item &pitem = item[itemnum]; - const char *itemtext = pitem.text; - rgb_t fgcolor = UI_TEXT_COLOR; - rgb_t bgcolor = UI_TEXT_BG_COLOR; - float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float line_y0 = line_y; - float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float line_y1 = line_y + line_height; - - // if we're on the top line, display the up arrow - if (linenum == 0 && top_line != 0) - { - draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0); - - if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y) - { - fgcolor = UI_MOUSEOVER_COLOR; - bgcolor = UI_MOUSEOVER_BG_COLOR; - highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor); - hover = HOVER_ARROW_UP; - } - } - // if we're on the bottom line, display the down arrow - else if (linenum == visible_lines - 1 && itemnum != visible_items - 1) - { - draw_arrow(container, 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); - - if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y) - { - fgcolor = UI_MOUSEOVER_COLOR; - bgcolor = UI_MOUSEOVER_BG_COLOR; - highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor); - hover = HOVER_ARROW_DOWN; - } - } - - // draw dats text - else if (pitem.subtext == nullptr) - { - mui.draw_text_full(container, itemtext, effective_left, line_y, effective_width, JUSTIFY_LEFT, WRAP_NEVER, - DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); - } - } - - for (size_t count = visible_items; count < item.size(); count++) - { - const ui_menu_item &pitem = item[count]; - const char *itemtext = pitem.text; - float line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float line_y0 = line; - float line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float line_y1 = line + line_height; - rgb_t fgcolor = UI_SELECTED_COLOR; - rgb_t bgcolor = UI_SELECTED_BG_COLOR; - - if (mouse_hit && line_x0 <= mouse_x && line_x1 > mouse_x && line_y0 <= mouse_y && line_y1 > mouse_y && pitem.is_selectable()) - hover = count; - - if (strcmp(itemtext, MENU_SEPARATOR_ITEM) == 0) - container->add_line(visible_left, line + 0.5f * line_height, visible_left + visible_width, line + 0.5f * line_height, - UI_LINE_WIDTH, UI_TEXT_COLOR, PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - else - { - highlight(container, line_x0, line_y0, line_x1, line_y1, bgcolor); - mui.draw_text_full(container, itemtext, effective_left, line, effective_width, JUSTIFY_CENTER, WRAP_TRUNCATE, - DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr); - } - line += line_height; - } - - // if there is something special to add, do it by calling the virtual method - custom_render((selected >= 0 && selected < item.size()) ? item[selected].ref : nullptr, customtop, custombottom, x1, y1, x2, y2); - - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - visitems = visible_lines - (top_line != 0) - (top_line + visible_lines != visible_items); -}
\ No newline at end of file |