diff options
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/emuopts.cpp | 5 | ||||
-rw-r--r-- | src/emu/emuopts.h | 10 | ||||
-rw-r--r-- | src/emu/render.cpp | 230 | ||||
-rw-r--r-- | src/emu/render.h | 106 | ||||
-rw-r--r-- | src/emu/rendlay.cpp | 296 | ||||
-rw-r--r-- | src/emu/uiinput.cpp | 20 | ||||
-rw-r--r-- | src/emu/video.cpp | 5 |
7 files changed, 301 insertions, 371 deletions
diff --git a/src/emu/emuopts.cpp b/src/emu/emuopts.cpp index 68e3bf7c2d2..c99748e67de 100644 --- a/src/emu/emuopts.cpp +++ b/src/emu/emuopts.cpp @@ -113,11 +113,6 @@ const options_entry emu_options::s_option_entries[] = // artwork options { nullptr, nullptr, OPTION_HEADER, "CORE ARTWORK OPTIONS" }, { OPTION_ARTWORK_CROP ";artcrop", "0", OPTION_BOOLEAN, "crop artwork so emulated screen image fills output screen/window in one axis" }, - { OPTION_USE_BACKDROPS ";backdrop", "1", OPTION_BOOLEAN, "enable backdrops if artwork is enabled and available" }, - { OPTION_USE_OVERLAYS ";overlay", "1", OPTION_BOOLEAN, "enable overlays if artwork is enabled and available" }, - { OPTION_USE_BEZELS ";bezel", "1", OPTION_BOOLEAN, "enable bezels if artwork is enabled and available" }, - { OPTION_USE_CPANELS ";cpanel", "1", OPTION_BOOLEAN, "enable cpanels if artwork is enabled and available" }, - { OPTION_USE_MARQUEES ";marquee", "1", OPTION_BOOLEAN, "enable marquees if artwork is enabled and available" }, { OPTION_FALLBACK_ARTWORK, nullptr, OPTION_STRING, "fallback artwork if no external artwork or internal driver layout defined" }, { OPTION_OVERRIDE_ARTWORK, nullptr, OPTION_STRING, "override artwork for external artwork and internal driver layout" }, diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index b1869c82c16..c16e9c24567 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -97,11 +97,6 @@ // core artwork options #define OPTION_ARTWORK_CROP "artwork_crop" -#define OPTION_USE_BACKDROPS "use_backdrops" -#define OPTION_USE_OVERLAYS "use_overlays" -#define OPTION_USE_BEZELS "use_bezels" -#define OPTION_USE_CPANELS "use_cpanels" -#define OPTION_USE_MARQUEES "use_marquees" #define OPTION_FALLBACK_ARTWORK "fallback_artwork" #define OPTION_OVERRIDE_ARTWORK "override_artwork" @@ -379,11 +374,6 @@ public: // core artwork options bool artwork_crop() const { return bool_value(OPTION_ARTWORK_CROP); } - bool use_backdrops() const { return bool_value(OPTION_USE_BACKDROPS); } - bool use_overlays() const { return bool_value(OPTION_USE_OVERLAYS); } - bool use_bezels() const { return bool_value(OPTION_USE_BEZELS); } - bool use_cpanels() const { return bool_value(OPTION_USE_CPANELS); } - bool use_marquees() const { return bool_value(OPTION_USE_MARQUEES); } const char *fallback_artwork() const { return value(OPTION_FALLBACK_ARTWORK); } const char *override_artwork() const { return value(OPTION_OVERRIDE_ARTWORK); } diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 9b1c09a6f3a..34d29285162 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -111,22 +111,6 @@ static const render_quad_texuv oriented_texcoords[8] = { { 1,1 }, { 1,0 }, { 0,1 }, { 0,0 } } // ORIENTATION_SWAP_XY | ORIENTATION_FLIP_X | ORIENTATION_FLIP_Y }; -// layer orders -static constexpr std::pair<item_layer, int> layer_order_standard[]{ - { ITEM_LAYER_SCREEN, -1 }, // FIXME: invalid blend mode - we're relying on the goodness of the OSD - { ITEM_LAYER_OVERLAY, BLENDMODE_RGB_MULTIPLY }, - { ITEM_LAYER_BACKDROP, BLENDMODE_ADD }, - { ITEM_LAYER_BEZEL, BLENDMODE_ALPHA }, - { ITEM_LAYER_CPANEL, BLENDMODE_ALPHA }, - { ITEM_LAYER_MARQUEE, BLENDMODE_ALPHA } }; -static constexpr std::pair<item_layer, int> layer_order_alternate[]{ - { ITEM_LAYER_BACKDROP, BLENDMODE_ALPHA }, - { ITEM_LAYER_SCREEN, BLENDMODE_ADD }, - { ITEM_LAYER_OVERLAY, BLENDMODE_RGB_MULTIPLY }, - { ITEM_LAYER_BEZEL, BLENDMODE_ALPHA }, - { ITEM_LAYER_CPANEL, BLENDMODE_ALPHA }, - { ITEM_LAYER_MARQUEE, BLENDMODE_ALPHA } }; - //************************************************************************** @@ -177,25 +161,6 @@ inline void normalize_bounds(render_bounds &bounds) } -//------------------------------------------------- -// get_layer_and_blendmode - return the -// appropriate layer index and blendmode -//------------------------------------------------- - -inline item_layer get_layer_and_blendmode(layout_view &view, int index, int &blendmode) -{ - // if we have multiple backdrop pieces and no overlays, render: - // backdrop (add) + screens (add) + bezels (alpha) + cpanels (alpha) + marquees (alpha) - // else render: - // screens (add) + overlays (RGB multiply) + backdrop (add) + bezels (alpha) + cpanels (alpha) + marquees (alpha) - - std::pair<item_layer, int> const *const layer_order(((view.items(ITEM_LAYER_BACKDROP).size() > 1) && view.items(ITEM_LAYER_OVERLAY).empty()) ? layer_order_alternate : layer_order_standard); - - // select the layer and blend mode - blendmode = layer_order[index].second; - return layer_order[index].first; -} - //************************************************************************** // RENDER PRIMITIVE //************************************************************************** @@ -941,11 +906,6 @@ template <typename T> render_target::render_target(render_manager &manager, T && , m_transform_container(true) { // determine the base layer configuration based on options - m_base_layerconfig.set_backdrops_enabled(manager.machine().options().use_backdrops()); - m_base_layerconfig.set_overlays_enabled(manager.machine().options().use_overlays()); - m_base_layerconfig.set_bezels_enabled(manager.machine().options().use_bezels()); - m_base_layerconfig.set_cpanels_enabled(manager.machine().options().use_cpanels()); - m_base_layerconfig.set_marquees_enabled(manager.machine().options().use_marquees()); m_base_layerconfig.set_zoom_to_screen(manager.machine().options().artwork_crop()); // aspect and scale options @@ -1296,40 +1256,38 @@ void render_target::compute_minimum_size(s32 &minwidth, s32 &minheight) throw emu_fatalerror("Mandatory artwork is missing"); // scan the current view for all screens - for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; ++layer) + for (layout_view::item &curitem : m_curview->items()) { - // iterate over items in the layer - for (layout_view::item &curitem : m_curview->items(layer)) - if (curitem.screen()) + if (curitem.screen()) + { + // use a hard-coded default visible area for vector screens + screen_device *const screen = curitem.screen(); + const rectangle vectorvis(0, 639, 0, 479); + const rectangle &visarea = (screen->screen_type() == SCREEN_TYPE_VECTOR) ? vectorvis : screen->visible_area(); + + // apply target orientation to the bounds + render_bounds bounds = curitem.bounds(); + apply_orientation(bounds, m_orientation); + normalize_bounds(bounds); + + // based on the orientation of the screen container, check the bitmap + float xscale, yscale; + if (!(orientation_add(m_orientation, screen->container().orientation()) & ORIENTATION_SWAP_XY)) { - // use a hard-coded default visible area for vector screens - screen_device *const screen = curitem.screen(); - const rectangle vectorvis(0, 639, 0, 479); - const rectangle &visarea = (screen->screen_type() == SCREEN_TYPE_VECTOR) ? vectorvis : screen->visible_area(); - - // apply target orientation to the bounds - render_bounds bounds = curitem.bounds(); - apply_orientation(bounds, m_orientation); - normalize_bounds(bounds); - - // based on the orientation of the screen container, check the bitmap - float xscale, yscale; - if (!(orientation_add(m_orientation, screen->container().orientation()) & ORIENTATION_SWAP_XY)) - { - xscale = float(visarea.width()) / bounds.width(); - yscale = float(visarea.height()) / bounds.height(); - } - else - { - xscale = float(visarea.height()) / bounds.width(); - yscale = float(visarea.width()) / bounds.height(); - } - - // pick the greater - maxxscale = std::max(xscale, maxxscale); - maxyscale = std::max(yscale, maxyscale); - screens_considered++; + xscale = float(visarea.width()) / bounds.width(); + yscale = float(visarea.height()) / bounds.height(); + } + else + { + xscale = float(visarea.height()) / bounds.width(); + yscale = float(visarea.width()) / bounds.height(); } + + // pick the greater + maxxscale = std::max(xscale, maxxscale); + maxyscale = std::max(yscale, maxyscale); + screens_considered++; + } } // if there were no screens considered, pick a nominal default @@ -1378,42 +1336,33 @@ render_primitive_list &render_target::get_primitives() root_xform.orientation = m_orientation; root_xform.no_center = false; - // iterate over layers back-to-front, but only if we're running + // iterate over items in the view, but only if we're running if (m_manager.machine().phase() >= machine_phase::RESET) - for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; ++layernum) + for (layout_view::item &curitem : m_curview->items()) { - int blendmode; - item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode); - if (m_curview->layer_enabled(layer)) - { - // iterate over items in the layer - for (layout_view::item &curitem : m_curview->items(layer)) - { - // first apply orientation to the bounds - render_bounds bounds = curitem.bounds(); - apply_orientation(bounds, root_xform.orientation); - normalize_bounds(bounds); - - // apply the transform to the item - object_transform item_xform; - item_xform.xoffs = root_xform.xoffs + bounds.x0 * root_xform.xscale; - item_xform.yoffs = root_xform.yoffs + bounds.y0 * root_xform.yscale; - item_xform.xscale = (bounds.x1 - bounds.x0) * root_xform.xscale; - item_xform.yscale = (bounds.y1 - bounds.y0) * root_xform.yscale; - item_xform.color.r = curitem.color().r * root_xform.color.r; - item_xform.color.g = curitem.color().g * root_xform.color.g; - item_xform.color.b = curitem.color().b * root_xform.color.b; - item_xform.color.a = curitem.color().a * root_xform.color.a; - item_xform.orientation = orientation_add(curitem.orientation(), root_xform.orientation); - item_xform.no_center = false; - - // if there is no associated element, it must be a screen element - if (curitem.screen() != nullptr) - add_container_primitives(list, root_xform, item_xform, curitem.screen()->container(), blendmode); - else - add_element_primitives(list, item_xform, *curitem.element(), curitem.state(), blendmode); - } - } + // first apply orientation to the bounds + render_bounds bounds = curitem.bounds(); + apply_orientation(bounds, root_xform.orientation); + normalize_bounds(bounds); + + // apply the transform to the item + object_transform item_xform; + item_xform.xoffs = root_xform.xoffs + bounds.x0 * root_xform.xscale; + item_xform.yoffs = root_xform.yoffs + bounds.y0 * root_xform.yscale; + item_xform.xscale = (bounds.x1 - bounds.x0) * root_xform.xscale; + item_xform.yscale = (bounds.y1 - bounds.y0) * root_xform.yscale; + item_xform.color.r = curitem.color().r * root_xform.color.r; + item_xform.color.g = curitem.color().g * root_xform.color.g; + item_xform.color.b = curitem.color().b * root_xform.color.b; + item_xform.color.a = curitem.color().a * root_xform.color.a; + item_xform.orientation = orientation_add(curitem.orientation(), root_xform.orientation); + item_xform.no_center = false; + + // if there is no associated element, it must be a screen element + if (curitem.screen() != nullptr) + add_container_primitives(list, root_xform, item_xform, curitem.screen()->container(), curitem.blend_mode()); + else + add_element_primitives(list, item_xform, *curitem.element(), curitem.state(), curitem.blend_mode()); } // if we are not in the running stage, draw an outer box @@ -2521,38 +2470,30 @@ bool render_target::map_point_internal(s32 target_x, s32 target_y, render_contai return false; } - // loop through each layer - for (item_layer layernum = ITEM_LAYER_FIRST; layernum < ITEM_LAYER_MAX; ++layernum) + // iterate over items in the view + for (layout_view::item &item : m_curview->items()) { - int blendmode; - item_layer layer = get_layer_and_blendmode(*m_curview, layernum, blendmode); - if (m_curview->layer_enabled(layer)) - { - // iterate over items in the layer - for (layout_view::item &item : m_curview->items(layer)) - { - bool checkit; + bool checkit; - // if we're looking for a particular container, verify that we have the right one - if (container != nullptr) - checkit = (item.screen() != nullptr && &item.screen()->container() == container); + // if we're looking for a particular container, verify that we have the right one + if (container != nullptr) + checkit = (item.screen() != nullptr && &item.screen()->container() == container); - // otherwise, assume we're looking for an input - else - checkit = item.has_input(); + // otherwise, assume we're looking for an input + else + checkit = item.has_input(); - // this target is worth looking at; now check the point - if (checkit && target_fx >= item.bounds().x0 && target_fx < item.bounds().x1 && target_fy >= item.bounds().y0 && target_fy < item.bounds().y1) - { - // point successfully mapped - mapped_x = (target_fx - item.bounds().x0) / (item.bounds().x1 - item.bounds().x0); - mapped_y = (target_fy - item.bounds().y0) / (item.bounds().y1 - item.bounds().y0); - mapped_input_port = item.input_tag_and_mask(mapped_input_mask); - return true; - } - } + // this target is worth looking at; now check the point + if (checkit && target_fx >= item.bounds().x0 && target_fx < item.bounds().x1 && target_fy >= item.bounds().y0 && target_fy < item.bounds().y1) + { + // point successfully mapped + mapped_x = (target_fx - item.bounds().x0) / (item.bounds().x1 - item.bounds().x0); + mapped_y = (target_fy - item.bounds().y0) / (item.bounds().y1 - item.bounds().y0); + mapped_input_port = item.input_tag_and_mask(mapped_input_mask); + return true; } } + return false; } @@ -2603,6 +2544,8 @@ int render_target::view_index(layout_view &targetview) const void render_target::config_load(util::xml::data_node const &targetnode) { + int tmpint; + // find the view const char *viewname = targetnode.get_attribute_string("view", nullptr); if (viewname != nullptr) @@ -2619,26 +2562,6 @@ void render_target::config_load(util::xml::data_node const &targetnode) } // modify the artwork config - int tmpint = targetnode.get_attribute_int("backdrops", -1); - if (tmpint == 0 || tmpint == 1) - set_backdrops_enabled(tmpint); - - tmpint = targetnode.get_attribute_int("overlays", -1); - if (tmpint == 0 || tmpint == 1) - set_overlays_enabled(tmpint); - - tmpint = targetnode.get_attribute_int("bezels", -1); - if (tmpint == 0 || tmpint == 1) - set_bezels_enabled(tmpint); - - tmpint = targetnode.get_attribute_int("cpanels", -1); - if (tmpint == 0 || tmpint == 1) - set_cpanels_enabled(tmpint); - - tmpint = targetnode.get_attribute_int("marquees", -1); - if (tmpint == 0 || tmpint == 1) - set_marquees_enabled(tmpint); - tmpint = targetnode.get_attribute_int("zoom", -1); if (tmpint == 0 || tmpint == 1) set_zoom_to_screen(tmpint); @@ -2693,11 +2616,6 @@ bool render_target::config_save(util::xml::data_node &targetnode) // output the layer config if (m_layerconfig != m_base_layerconfig) { - targetnode.set_attribute_int("backdrops", m_layerconfig.backdrops_enabled()); - targetnode.set_attribute_int("overlays", m_layerconfig.overlays_enabled()); - targetnode.set_attribute_int("bezels", m_layerconfig.bezels_enabled()); - targetnode.set_attribute_int("cpanels", m_layerconfig.cpanels_enabled()); - targetnode.set_attribute_int("marquees", m_layerconfig.marquees_enabled()); targetnode.set_attribute_int("zoom", m_layerconfig.zoom_to_screen()); changed = true; } diff --git a/src/emu/render.h b/src/emu/render.h index 93621ea92c1..27e54c90885 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -270,14 +270,9 @@ private: class render_layer_config { private: - static constexpr u8 ENABLE_BACKDROP = 0x01; // enable backdrop layers - static constexpr u8 ENABLE_OVERLAY = 0x02; // enable overlay layers - static constexpr u8 ENABLE_BEZEL = 0x04; // enable bezel layers - static constexpr u8 ENABLE_CPANEL = 0x08; // enable cpanel layers - static constexpr u8 ENABLE_MARQUEE = 0x10; // enable marquee layers - static constexpr u8 ZOOM_TO_SCREEN = 0x20; // zoom to screen area by default - static constexpr u8 ENABLE_SCREEN_OVERLAY = 0x40; // enable screen overlays - static constexpr u8 DEFAULT = ENABLE_BACKDROP | ENABLE_OVERLAY | ENABLE_BEZEL | ENABLE_CPANEL | ENABLE_MARQUEE | ENABLE_SCREEN_OVERLAY; + static constexpr u8 ZOOM_TO_SCREEN = 0x01; // zoom to screen area by default + static constexpr u8 ENABLE_SCREEN_OVERLAY = 0x02; // enable screen overlays + static constexpr u8 DEFAULT = ENABLE_SCREEN_OVERLAY; u8 m_state = DEFAULT; @@ -294,19 +289,9 @@ public: bool operator==(const render_layer_config &rhs) const { return m_state == rhs.m_state; } bool operator!=(const render_layer_config &rhs) const { return m_state != rhs.m_state; } - constexpr bool backdrops_enabled() const { return (m_state & ENABLE_BACKDROP) != 0; } - constexpr bool overlays_enabled() const { return (m_state & ENABLE_OVERLAY) != 0; } - constexpr bool bezels_enabled() const { return (m_state & ENABLE_BEZEL) != 0; } - constexpr bool cpanels_enabled() const { return (m_state & ENABLE_CPANEL) != 0; } - constexpr bool marquees_enabled() const { return (m_state & ENABLE_MARQUEE) != 0; } constexpr bool screen_overlay_enabled() const { return (m_state & ENABLE_SCREEN_OVERLAY) != 0; } constexpr bool zoom_to_screen() const { return (m_state & ZOOM_TO_SCREEN) != 0; } - render_layer_config &set_backdrops_enabled(bool enable) { return set_flag(ENABLE_BACKDROP, enable); } - render_layer_config &set_overlays_enabled(bool enable) { return set_flag(ENABLE_OVERLAY, enable); } - render_layer_config &set_bezels_enabled(bool enable) { return set_flag(ENABLE_BEZEL, enable); } - render_layer_config &set_cpanels_enabled(bool enable) { return set_flag(ENABLE_CPANEL, enable); } - render_layer_config &set_marquees_enabled(bool enable) { return set_flag(ENABLE_MARQUEE, enable); } render_layer_config &set_screen_overlay_enabled(bool enable) { return set_flag(ENABLE_SCREEN_OVERLAY, enable); } render_layer_config &set_zoom_to_screen(bool zoom) { return set_flag(ZOOM_TO_SCREEN, zoom); } }; @@ -602,25 +587,6 @@ private: //************************************************************************** -// CONSTANTS -//************************************************************************** - -enum item_layer -{ - ITEM_LAYER_FIRST = 0, - ITEM_LAYER_BACKDROP = ITEM_LAYER_FIRST, - ITEM_LAYER_SCREEN, - ITEM_LAYER_OVERLAY, - ITEM_LAYER_BEZEL, - ITEM_LAYER_CPANEL, - ITEM_LAYER_MARQUEE, - ITEM_LAYER_MAX -}; -DECLARE_ENUM_INCDEC_OPERATORS(item_layer) - - - -//************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -833,9 +799,10 @@ public: screen_device *screen() { return m_screen; } const render_bounds &bounds() const { return m_bounds; } const render_color &color() const { return m_color; } + int blend_mode() const { return m_blend_mode; } int orientation() const { return m_orientation; } render_container *screen_container(running_machine &machine) const; - bool has_input() const { return !m_input_tag.empty(); } + bool has_input() const { return bool(m_input_field); } ioport_port *input_tag_and_mask(ioport_value &mask) const { mask = m_input_mask; return m_input_port; }; // fetch state based on configured source @@ -844,21 +811,31 @@ public: // resolve tags, if any void resolve_tags(); + // setters + void set_blend_mode(int mode) { m_blend_mode = mode; } + private: + static layout_element *find_element(environment &env, util::xml::data_node const &itemnode, element_map &elemmap); + static render_bounds make_bounds(environment &env, util::xml::data_node const &itemnode, layout_group::transform const &trans); + static std::string make_input_tag(environment &env, util::xml::data_node const &itemnode); + static int get_blend_mode(environment &env, util::xml::data_node const &itemnode); + // internal state - layout_element * m_element; // pointer to the associated element (non-screens only) - output_finder<> m_output; // associated output - bool const m_have_output; // whether we actually have an output - std::string m_input_tag; // input tag of this item - ioport_port * m_input_port; // input port of this item - ioport_value m_input_mask; // input mask of this item - u8 m_input_shift; // input mask rightshift for raw (trailing 0s) - bool m_input_raw; // get raw data from input port - screen_device * m_screen; // pointer to screen - int m_orientation; // orientation of this item - render_bounds m_bounds; // bounds of the item - render_bounds m_rawbounds; // raw (original) bounds of the item - render_color m_color; // color of the item + layout_element *const m_element; // pointer to the associated element (non-screens only) + output_finder<> m_output; // associated output + bool const m_have_output; // whether we actually have an output + std::string const m_input_tag; // input tag of this item + ioport_port * m_input_port; // input port of this item + ioport_field const * m_input_field; // input port field of this item + ioport_value const m_input_mask; // input mask of this item + u8 m_input_shift; // input mask rightshift for raw (trailing 0s) + bool const m_input_raw; // get raw data from input port + screen_device * m_screen; // pointer to screen + int m_orientation; // orientation of this item + render_bounds m_bounds; // bounds of the item + render_bounds const m_rawbounds; // raw (original) bounds of the item + render_color m_color; // color of the item + int m_blend_mode; // blending mode to use when drawing }; using item_list = std::list<item>; @@ -871,15 +848,14 @@ public: ~layout_view(); // getters - item_list &items(item_layer layer); + item_list &items() { return m_items; } const std::string &name() const { return m_name; } const render_bounds &bounds() const { return m_bounds; } const render_bounds &screen_bounds() const { return m_scrbounds; } const render_screen_list &screens() const { return m_screens; } - bool layer_enabled(item_layer layer) const { return m_layenabled[layer]; } // - bool has_art() const { return !m_backdrop_list.empty() || !m_overlay_list.empty() || !m_bezel_list.empty() || !m_cpanel_list.empty() || !m_marquee_list.empty(); } + bool has_art() const { return m_has_art; } float effective_aspect(render_layer_config config) const { return (config.zoom_to_screen() && m_screens.count() != 0) ? m_scraspect : m_aspect; } // operations @@ -889,8 +865,11 @@ public: void resolve_tags(); private: + struct layer_lists; + // add items, recursing for groups void add_items( + layer_lists &layers, environment &env, util::xml::data_node const &parentnode, element_map &elemmap, @@ -912,13 +891,8 @@ private: render_bounds m_bounds; // computed bounds of the view render_bounds m_scrbounds; // computed bounds of the screens within the view render_bounds m_expbounds; // explicit bounds of the view - bool m_layenabled[ITEM_LAYER_MAX]; // is this layer enabled? - item_list m_backdrop_list; // list of backdrop items - item_list m_screen_list; // list of screen items - item_list m_overlay_list; // list of overlay items - item_list m_bezel_list; // list of bezel items - item_list m_cpanel_list; // list of marquee items - item_list m_marquee_list; // list of marquee items + item_list m_items; // list of layout items + bool m_has_art; // true if the layout contains non-screen elements }; @@ -1001,20 +975,10 @@ public: void set_scale_mode(int scale_mode) { m_scale_mode = scale_mode; } // layer config getters - bool backdrops_enabled() const { return m_layerconfig.backdrops_enabled(); } - bool overlays_enabled() const { return m_layerconfig.overlays_enabled(); } - bool bezels_enabled() const { return m_layerconfig.bezels_enabled(); } - bool cpanels_enabled() const { return m_layerconfig.cpanels_enabled(); } - bool marquees_enabled() const { return m_layerconfig.marquees_enabled(); } bool screen_overlay_enabled() const { return m_layerconfig.screen_overlay_enabled(); } bool zoom_to_screen() const { return m_layerconfig.zoom_to_screen(); } // layer config setters - void set_backdrops_enabled(bool enable) { m_layerconfig.set_backdrops_enabled(enable); update_layer_config(); } - void set_overlays_enabled(bool enable) { m_layerconfig.set_overlays_enabled(enable); update_layer_config(); } - void set_bezels_enabled(bool enable) { m_layerconfig.set_bezels_enabled(enable); update_layer_config(); } - void set_cpanels_enabled(bool enable) { m_layerconfig.set_cpanels_enabled(enable); update_layer_config(); } - void set_marquees_enabled(bool enable) { m_layerconfig.set_marquees_enabled(enable); update_layer_config(); } void set_screen_overlay_enabled(bool enable) { m_layerconfig.set_screen_overlay_enabled(enable); update_layer_config(); } void set_zoom_to_screen(bool zoom) { m_layerconfig.set_zoom_to_screen(zoom); update_layer_config(); } diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp index d083ba5510a..8fc785b74a7 100644 --- a/src/emu/rendlay.cpp +++ b/src/emu/rendlay.cpp @@ -2944,6 +2944,9 @@ void layout_element::component::apply_skew(bitmap_argb32 &dest, int skewwidth) // LAYOUT VIEW //************************************************************************** +struct layout_view::layer_lists { item_list backdrops, screens, overlays, bezels, cpanels, marquees; }; + + //------------------------------------------------- // layout_view - constructor //------------------------------------------------- @@ -2956,11 +2959,41 @@ layout_view::layout_view( : m_name(make_name(env, viewnode)) , m_aspect(1.0f) , m_scraspect(1.0f) + , m_items() + , m_has_art(false) { + // parse the layout m_expbounds.x0 = m_expbounds.y0 = m_expbounds.x1 = m_expbounds.y1 = 0; environment local(env); + layer_lists layers; local.set_parameter("viewname", std::string(m_name)); - add_items(local, viewnode, elemmap, groupmap, ROT0, identity_transform, render_color{ 1.0F, 1.0F, 1.0F, 1.0F }, true, false, true); + add_items(layers, local, viewnode, elemmap, groupmap, ROT0, identity_transform, render_color{ 1.0F, 1.0F, 1.0F, 1.0F }, true, false, true); + + // deal with legacy element groupings + if ((layers.backdrops.size() > 1) && layers.overlays.empty()) + { + // multiple backdrop pieces and no overlays (Golly! Ghost! mode): + // backdrop (alpha) + screens (add) + bezels (alpha) + cpanels (alpha) + marquees (alpha) + m_items.splice(m_items.end(), layers.backdrops); + m_items.splice(m_items.end(), layers.screens); + m_items.splice(m_items.end(), layers.bezels); + m_items.splice(m_items.end(), layers.cpanels); + m_items.splice(m_items.end(), layers.marquees); + } + else + { + // screens (add) + overlays (RGB multiply) + backdrop (add) + bezels (alpha) + cpanels (alpha) + marquees (alpha) + for (item &backdrop : layers.backdrops) + backdrop.set_blend_mode(BLENDMODE_ADD); + m_items.splice(m_items.end(), layers.screens); + m_items.splice(m_items.end(), layers.overlays); + m_items.splice(m_items.end(), layers.backdrops); + m_items.splice(m_items.end(), layers.bezels); + m_items.splice(m_items.end(), layers.cpanels); + m_items.splice(m_items.end(), layers.marquees); + } + + // calculate metrics recompute(render_layer_config()); for (group_map::value_type &group : groupmap) group.second.set_bounds_unresolved(); @@ -2977,25 +3010,6 @@ layout_view::~layout_view() //------------------------------------------------- -// items - return the appropriate list -//------------------------------------------------- - -layout_view::item_list &layout_view::items(item_layer layer) -{ - switch (layer) - { - case ITEM_LAYER_BACKDROP: return m_backdrop_list; - case ITEM_LAYER_SCREEN: return m_screen_list; - case ITEM_LAYER_OVERLAY: return m_overlay_list; - case ITEM_LAYER_BEZEL: return m_bezel_list; - case ITEM_LAYER_CPANEL: return m_cpanel_list; - case ITEM_LAYER_MARQUEE: return m_marquee_list; - default: throw false; // calling this with an invalid layer is bad, m'kay? - } -} - - -//------------------------------------------------- // recompute - recompute the bounds and aspect // ratio of a view and all of its contained items //------------------------------------------------- @@ -3010,43 +3024,27 @@ void layout_view::recompute(render_layer_config layerconfig) // loop over all layers bool first = true; bool scrfirst = true; - for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; ++layer) + for (item &curitem : m_items) { - // determine if this layer should be visible - switch (layer) - { - case ITEM_LAYER_BACKDROP: m_layenabled[layer] = layerconfig.backdrops_enabled(); break; - case ITEM_LAYER_OVERLAY: m_layenabled[layer] = layerconfig.overlays_enabled(); break; - case ITEM_LAYER_BEZEL: m_layenabled[layer] = layerconfig.bezels_enabled(); break; - case ITEM_LAYER_CPANEL: m_layenabled[layer] = layerconfig.cpanels_enabled(); break; - case ITEM_LAYER_MARQUEE: m_layenabled[layer] = layerconfig.marquees_enabled(); break; - default: m_layenabled[layer] = true; break; - } - - // only do it if requested - if (m_layenabled[layer]) - for (item &curitem : items(layer)) - { - // accumulate bounds - if (first) - m_bounds = curitem.m_rawbounds; - else - union_render_bounds(m_bounds, curitem.m_rawbounds); - first = false; + // accumulate bounds + if (first) + m_bounds = curitem.m_rawbounds; + else + union_render_bounds(m_bounds, curitem.m_rawbounds); + first = false; - // accumulate screen bounds - if (curitem.m_screen) - { - if (scrfirst) - m_scrbounds = curitem.m_rawbounds; - else - union_render_bounds(m_scrbounds, curitem.m_rawbounds); - scrfirst = false; + // accumulate screen bounds + if (curitem.m_screen) + { + if (scrfirst) + m_scrbounds = curitem.m_rawbounds; + else + union_render_bounds(m_scrbounds, curitem.m_rawbounds); + scrfirst = false; - // accumulate the screens in use while we're scanning - m_screens.add(*curitem.m_screen); - } - } + // accumulate the screens in use while we're scanning + m_screens.add(*curitem.m_screen); + } } // if we have an explicit bounds, override it @@ -3085,14 +3083,13 @@ void layout_view::recompute(render_layer_config layerconfig) float yscale = (target_bounds.y1 - target_bounds.y0) / (m_bounds.y1 - m_bounds.y0); // normalize all the item bounds - for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; ++layer) - for (item &curitem : items(layer)) - { - curitem.m_bounds.x0 = target_bounds.x0 + (curitem.m_rawbounds.x0 - xoffs) * xscale; - curitem.m_bounds.x1 = target_bounds.x0 + (curitem.m_rawbounds.x1 - xoffs) * xscale; - curitem.m_bounds.y0 = target_bounds.y0 + (curitem.m_rawbounds.y0 - yoffs) * yscale; - curitem.m_bounds.y1 = target_bounds.y0 + (curitem.m_rawbounds.y1 - yoffs) * yscale; - } + for (item &curitem : items()) + { + curitem.m_bounds.x0 = target_bounds.x0 + (curitem.m_rawbounds.x0 - xoffs) * xscale; + curitem.m_bounds.x1 = target_bounds.x0 + (curitem.m_rawbounds.x1 - xoffs) * xscale; + curitem.m_bounds.y0 = target_bounds.y0 + (curitem.m_rawbounds.y0 - yoffs) * yscale; + curitem.m_bounds.y1 = target_bounds.y0 + (curitem.m_rawbounds.y1 - yoffs) * yscale; + } } @@ -3102,13 +3099,8 @@ void layout_view::recompute(render_layer_config layerconfig) void layout_view::resolve_tags() { - for (item_layer layer = ITEM_LAYER_FIRST; layer < ITEM_LAYER_MAX; ++layer) - { - for (item &curitem : items(layer)) - { - curitem.resolve_tags(); - } - } + for (item &curitem : items()) + curitem.resolve_tags(); } @@ -3117,6 +3109,7 @@ void layout_view::resolve_tags() //------------------------------------------------- void layout_view::add_items( + layer_lists &layers, environment &env, util::xml::data_node const &parentnode, element_map &elemmap, @@ -3154,27 +3147,37 @@ void layout_view::add_items( } else if (!strcmp(itemnode->get_name(), "backdrop")) { - m_backdrop_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + layers.backdrops.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + m_has_art = true; } else if (!strcmp(itemnode->get_name(), "screen")) { - m_screen_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + layers.screens.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + } + else if (!strcmp(itemnode->get_name(), "element")) + { + layers.screens.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + m_has_art = true; } else if (!strcmp(itemnode->get_name(), "overlay")) { - m_overlay_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + layers.overlays.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + m_has_art = true; } else if (!strcmp(itemnode->get_name(), "bezel")) { - m_bezel_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + layers.bezels.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + m_has_art = true; } else if (!strcmp(itemnode->get_name(), "cpanel")) { - m_cpanel_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + layers.cpanels.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + m_has_art = true; } else if (!strcmp(itemnode->get_name(), "marquee")) { - m_marquee_list.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + layers.marquees.emplace_back(env, *itemnode, elemmap, orientation, trans, color); + m_has_art = true; } else if (!strcmp(itemnode->get_name(), "group")) { @@ -3205,6 +3208,7 @@ void layout_view::add_items( environment local(env); add_items( + layers, local, found->second.get_groupnode(), elemmap, @@ -3224,7 +3228,7 @@ void layout_view::add_items( environment local(env); for (int i = 0; count > i; ++i) { - add_items(local, *itemnode, elemmap, groupmap, orientation, trans, color, false, true, !i); + add_items(layers, local, *itemnode, elemmap, groupmap, orientation, trans, color, false, true, !i); local.increment_parameters(); } } @@ -3277,30 +3281,21 @@ layout_view::item::item( int orientation, layout_group::transform const &trans, render_color const &color) - : m_element(nullptr) + : m_element(find_element(env, itemnode, elemmap)) , m_output(env.device(), env.get_attribute_string(itemnode, "name", "")) , m_have_output(env.get_attribute_string(itemnode, "name", "")[0]) - , m_input_tag(env.get_attribute_string(itemnode, "inputtag", "")) + , m_input_tag(make_input_tag(env, itemnode)) , m_input_port(nullptr) - , m_input_mask(0) + , m_input_field(nullptr) + , m_input_mask(env.get_attribute_int(itemnode, "inputmask", 0)) , m_input_shift(0) - , m_input_raw(false) + , m_input_raw(0 != env.get_attribute_int(itemnode, "inputraw", 0)) , m_screen(nullptr) , m_orientation(orientation_add(env.parse_orientation(itemnode.get_child("orientation")), orientation)) + , m_rawbounds(make_bounds(env, itemnode, trans)) , m_color(render_color_multiply(env.parse_color(itemnode.get_child("color")), color)) + , m_blend_mode(get_blend_mode(env, itemnode)) { - // find the associated element - char const *const name(env.get_attribute_string(itemnode, "element", nullptr)); - if (name) - { - // search the list of elements for a match, error if not found - element_map::iterator const found(elemmap.find(name)); - if (elemmap.end() != found) - m_element = &found->second; - else - throw layout_syntax_error(util::string_format("unable to find element %s", name)); - } - // outputs need resolving if (m_have_output) m_output.resolve(); @@ -3309,17 +3304,10 @@ layout_view::item::item( int index = env.get_attribute_int(itemnode, "index", -1); if (index != -1) m_screen = screen_device_iterator(env.machine().root_device()).byindex(index); - m_input_mask = env.get_attribute_int(itemnode, "inputmask", 0); - for (u32 mask = m_input_mask; (mask != 0) && (~mask & 1); mask >>= 1) m_input_shift++; - m_input_raw = env.get_attribute_int(itemnode, "inputraw", 0) == 1; + for (u32 mask = m_input_mask; (mask != 0) && (~mask & 1); mask >>= 1) + m_input_shift++; if (m_have_output && m_element) m_output = m_element->default_state(); - env.parse_bounds(itemnode.get_child("bounds"), m_rawbounds); - render_bounds_transform(m_rawbounds, trans); - if (m_rawbounds.x0 > m_rawbounds.x1) - std::swap(m_rawbounds.x0, m_rawbounds.x1); - if (m_rawbounds.y0 > m_rawbounds.y1) - std::swap(m_rawbounds.y0, m_rawbounds.y1); // sanity checks if (strcmp(itemnode.get_name(), "screen") == 0) @@ -3340,9 +3328,6 @@ layout_view::item::item( { throw layout_syntax_error(util::string_format("item of type %s require an element tag", itemnode.get_name())); } - - if (has_input()) - m_input_port = env.device().ioport(m_input_tag.c_str()); } @@ -3382,17 +3367,17 @@ int layout_view::item::state() const else if (!m_input_tag.empty()) { // if configured to an input, fetch the input value - if (m_input_port) + if (m_input_raw) { - if (m_input_raw) - { + if (m_input_port) return (m_input_port->read() & m_input_mask) >> m_input_shift; - } - else + } + else + { + if (m_input_field) { - ioport_field const *const field = m_input_port->field(m_input_mask); - if (field) - return ((m_input_port->read() ^ field->defvalue()) & m_input_mask) ? 1 : 0; + assert(m_input_port); + return ((m_input_port->read() ^ m_input_field->defvalue()) & m_input_mask) ? 1 : 0; } } } @@ -3405,13 +3390,96 @@ int layout_view::item::state() const // resolve_tags - resolve tags, if any are set //--------------------------------------------- - void layout_view::item::resolve_tags() { - if (has_input()) + if (!m_input_tag.empty()) { m_input_port = m_element->machine().root_device().ioport(m_input_tag.c_str()); + if (m_input_port) + m_input_field = m_input_port->field(m_input_mask); + } +} + + +//--------------------------------------------- +// find_element - find element definition +//--------------------------------------------- + +layout_element *layout_view::item::find_element(environment &env, util::xml::data_node const &itemnode, element_map &elemmap) +{ + char const *const name(env.get_attribute_string(itemnode, !strcmp(itemnode.get_name(), "element") ? "ref" : "element", nullptr)); + if (!name) + return nullptr; + + // search the list of elements for a match, error if not found + element_map::iterator const found(elemmap.find(name)); + if (elemmap.end() != found) + return &found->second; + else + throw layout_syntax_error(util::string_format("unable to find element %s", name)); +} + + +//--------------------------------------------- +// make_bounds - get transformed bounds +//--------------------------------------------- + +render_bounds layout_view::item::make_bounds( + environment &env, + util::xml::data_node const &itemnode, + layout_group::transform const &trans) +{ + render_bounds bounds; + env.parse_bounds(itemnode.get_child("bounds"), bounds); + render_bounds_transform(bounds, trans); + if (bounds.x0 > bounds.x1) + std::swap(bounds.x0, bounds.x1); + if (bounds.y0 > bounds.y1) + std::swap(bounds.y0, bounds.y1); + return bounds; +} + + +//--------------------------------------------- +// make_input_tag - get absolute input tag +//--------------------------------------------- + +std::string layout_view::item::make_input_tag(environment &env, util::xml::data_node const &itemnode) +{ + char const *tag(env.get_attribute_string(itemnode, "inputtag", nullptr)); + return tag ? env.device().subtag(tag) : std::string(); +} + + +//--------------------------------------------- +// get_blend_mode - explicit or implicit blend +//--------------------------------------------- + +int layout_view::item::get_blend_mode(environment &env, util::xml::data_node const &itemnode) +{ + // see if there's a blend mode attribute + char const *const mode(env.get_attribute_string(itemnode, "blend", nullptr)); + if (mode) + { + if (!strcmp(mode, "none")) + return BLENDMODE_NONE; + else if (!strcmp(mode, "alpha")) + return BLENDMODE_ALPHA; + else if (!strcmp(mode, "multiply")) + return BLENDMODE_RGB_MULTIPLY; + else if (!strcmp(mode, "add")) + return BLENDMODE_ADD; + else + throw layout_syntax_error(util::string_format("unknown blend mode %s", mode)); } + + // fall back to implicit blend mode based on element type + if (!strcmp(itemnode.get_name(), "screen")) + return BLENDMODE_ADD; + else if (!strcmp(itemnode.get_name(), "overlay")) + return BLENDMODE_RGB_MULTIPLY; + else + return BLENDMODE_ALPHA; } diff --git a/src/emu/uiinput.cpp b/src/emu/uiinput.cpp index 18fee890eec..78cc662022a 100644 --- a/src/emu/uiinput.cpp +++ b/src/emu/uiinput.cpp @@ -33,18 +33,18 @@ enum //------------------------------------------------- ui_input_manager::ui_input_manager(running_machine &machine) - : m_machine(machine), - m_current_mouse_target(nullptr), - m_current_mouse_down(false), - m_current_mouse_field(nullptr), - m_events_start(0), - m_events_end(0) + : m_machine(machine) + , m_current_mouse_target(nullptr) + , m_current_mouse_down(false) + , m_current_mouse_field(nullptr) + , m_events_start(0) + , m_events_end(0) { - /* create the private data */ + // create the private data m_current_mouse_x = -1; m_current_mouse_y = -1; - /* add a frame callback to poll inputs */ + // add a frame callback to poll inputs machine.add_notifier(MACHINE_NOTIFY_FRAME, machine_notify_delegate(&ui_input_manager::frame_update, this)); } @@ -95,7 +95,7 @@ void ui_input_manager::frame_update() bool ui_input_manager::push_event(ui_event evt) { - /* some pre-processing (this is an icky place to do this stuff!) */ + // some pre-processing (this is an icky place to do this stuff!) switch (evt.event_type) { case ui_event::MOUSE_MOVE: @@ -126,7 +126,7 @@ bool ui_input_manager::push_event(ui_event evt) break; } - /* is the queue filled up? */ + // is the queue filled up? if ((m_events_end + 1) % ARRAY_LENGTH(m_events) == m_events_start) return false; diff --git a/src/emu/video.cpp b/src/emu/video.cpp index f967ef78935..8732fa9307e 100644 --- a/src/emu/video.cpp +++ b/src/emu/video.cpp @@ -152,11 +152,6 @@ video_manager::video_manager(running_machine &machine) } m_snap_target = machine.render().target_alloc(*root, RENDER_CREATE_SINGLE_FILE | RENDER_CREATE_HIDDEN); - m_snap_target->set_backdrops_enabled(false); - m_snap_target->set_overlays_enabled(false); - m_snap_target->set_bezels_enabled(false); - m_snap_target->set_cpanels_enabled(false); - m_snap_target->set_marquees_enabled(false); m_snap_target->set_screen_overlay_enabled(false); m_snap_target->set_zoom_to_screen(false); } |