summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/render.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2019-07-06 00:23:20 +1000
committer Vas Crabb <vas@vastheman.com>2019-07-06 00:23:20 +1000
commitc38a3395e94e38a37cf6b8efdf9f49a5c9d415df (patch)
tree8ad5f6ee37953b4d19241ce31d11da23a712cc3e /src/emu/render.cpp
parent7ee50ffec7afabd20a027f89e47f11b116301071 (diff)
Make layout format more flexible:
* There is no longer a concept of "layers" - there are only screens and elements. * Elements are now instantiated with <element ref="..."> * Screens and elements can have explicit blending mode specified with blend="..." * Default blending mode for screens is "add" and default for other elements is "alpha" * Other supported modes are "none" and "multiply" * This removes the options to enable/disable layers individually - use views instead * Legacy layouts can still be loaded, and support won't be removed for at least a year The current artwork model is over-stretched. It's based on a Space Invaders cabinet model, and isn't applicable to a lot of the systems MAME emulates now. The fact that MAME has to switch to an "alternate" mode to deal with games like Golly! Ghost! without requiring pre-matted bitmaps shows that the Space Invaders model wasn't even adequate for general arcade use. It shows in that for a lot of the systems that heavily depend on artwork, people just seem to randomly choose layers for elements until they get something that works. Also, the fact that MAME will switch to an alternate (Golly! Ghost!) mode depending on the combination of elements is a trap for people learning to make artwork. There are cases that the current approach of implying the blending mode from the layer doesn't work with. Examples include LEDs behind diffusers (requires additive blending for layout elements), and mutliple stacked LCD panels (requires RGB multiplication for screens). For configurability, it's now a lot easier to make multiple views using groups. For example, if you want to make it possible to hide the control panel section of your layout, you can put the control panel elements in a group and create views with and without it. I will gradually migrate the internal artwork to use the new approach. I have an XSLT stylesheet that helps with this, but I'm not comfortable adding it because it isn't a complete solution and it still requires manul steps. I wanted to get the re-worked pointer handling done sooner so I could push them both at the same time, but unfortunately various things have prevented me from progressing as quickly as I wanted to. Sorry guys, that stuff's going to have to wait.
Diffstat (limited to 'src/emu/render.cpp')
-rw-r--r--src/emu/render.cpp230
1 files changed, 74 insertions, 156 deletions
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;
}