summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu
diff options
context:
space:
mode:
author AJR <ajrhacker@users.noreply.github.com>2021-01-04 12:08:16 -0500
committer AJR <ajrhacker@users.noreply.github.com>2021-01-04 12:15:09 -0500
commitc231ee373a461ee8555b2df25e68efea4506229d (patch)
tree30cfd37e502317b69d3695bc74aebaacc5756418 /src/emu
parent687e7e162dbadc4b4d0ca58343493f15a0cdabbc (diff)
render.h, rendlay.h: Dependency refactoring
- render.h: Split out layout class declarations into rendlay.h, with some adjustments for the resulting incomplete types (std::reference_wrapper unfortunately does not allow these by C++17 rules) - rendlay.h: Move old header contents to layout/generic.h
Diffstat (limited to 'src/emu')
-rw-r--r--src/emu/layout/generic.h35
-rw-r--r--src/emu/render.cpp47
-rw-r--r--src/emu/render.h558
-rw-r--r--src/emu/rendertypes.h2
-rw-r--r--src/emu/rendlay.cpp6
-rw-r--r--src/emu/rendlay.h558
6 files changed, 611 insertions, 595 deletions
diff --git a/src/emu/layout/generic.h b/src/emu/layout/generic.h
new file mode 100644
index 00000000000..502e38e0765
--- /dev/null
+++ b/src/emu/layout/generic.h
@@ -0,0 +1,35 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+/***************************************************************************
+
+ generic.h
+
+ Generic system layouts.
+
+***************************************************************************/
+
+#ifndef MAME_EMU_LAYOUT_GENERIC_H
+#define MAME_EMU_LAYOUT_GENERIC_H
+
+#pragma once
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+// no screens layouts
+extern const internal_layout layout_noscreens; // for screenless systems
+
+// dual screen layouts
+extern const internal_layout layout_dualhsxs; // dual 4:3 screens side-by-side
+extern const internal_layout layout_dualhovu; // dual 4:3 screens above and below
+extern const internal_layout layout_dualhuov; // dual 4:3 screens below and above
+
+// triple screen layouts
+extern const internal_layout layout_triphsxs; // triple 4:3 screens side-by-side
+
+// quad screen layouts
+extern const internal_layout layout_quadhsxs; // quad 4:3 screens side-by-side
+
+#endif // MAME_EMU_LAYOUT_GENERIC_H
diff --git a/src/emu/render.cpp b/src/emu/render.cpp
index 68c840f89a6..b9b98528547 100644
--- a/src/emu/render.cpp
+++ b/src/emu/render.cpp
@@ -45,6 +45,7 @@
#include "rendutil.h"
#include "config.h"
#include "drivenum.h"
+#include "layout/generic.h"
#include "ui/uimain.h"
@@ -891,6 +892,7 @@ render_target::render_target(render_manager &manager, util::xml::data_node const
template <typename T> render_target::render_target(render_manager &manager, T &&layout, u32 flags, constructor_impl_t)
: m_next(nullptr)
, m_manager(manager)
+ , m_filelist(std::make_unique<std::list<layout_file>>())
, m_curview(0U)
, m_flags(flags)
, m_listindex(0)
@@ -947,7 +949,7 @@ template <typename T> render_target::render_target(render_manager &manager, T &&
// load the layout files
load_layout_files(std::forward<T>(layout), flags & RENDER_CREATE_SINGLE_FILE);
- for (layout_file &file : m_filelist)
+ for (layout_file &file : *m_filelist)
for (layout_view &view : file.views())
if (!(m_flags & RENDER_CREATE_NO_ART) || !view.has_art())
m_views.emplace_back(view, view.default_visibility_mask());
@@ -1042,7 +1044,7 @@ void render_target::set_max_texture_size(int maxwidth, int maxheight)
void render_target::set_visibility_toggle(unsigned index, bool enable)
{
- assert(visibility_toggles().size() > index);
+ assert(current_view().visibility_toggles().size() > index);
if (enable)
m_views[m_curview].second |= u32(1) << index;
else
@@ -1067,8 +1069,8 @@ unsigned render_target::configured_view(const char *viewname, int targetindex, i
// scan for a matching view name
size_t const viewlen = strlen(viewname);
for (unsigned i = 0; !view && (m_views.size() > i); ++i)
- if (!core_strnicmp(m_views[i].first.get().name().c_str(), viewname, viewlen))
- view = &m_views[i].first.get();
+ if (!core_strnicmp(m_views[i].first.name().c_str(), viewname, viewlen))
+ view = &m_views[i].first;
}
// if we don't have a match, default to the nth view
@@ -1084,12 +1086,12 @@ unsigned render_target::configured_view(const char *viewname, int targetindex, i
screen_device const &screen = screens[index() % screens.size()];
for (unsigned i = 0; !view && (m_views.size() > i); ++i)
{
- for (layout_view::item &viewitem : m_views[i].first.get().items())
+ for (layout_view::item &viewitem : m_views[i].first.items())
{
screen_device const *const viewscreen(viewitem.screen());
if (viewscreen == &screen)
{
- view = &m_views[i].first.get();
+ view = &m_views[i].first;
}
else if (viewscreen)
{
@@ -1123,12 +1125,7 @@ unsigned render_target::configured_view(const char *viewname, int targetindex, i
const char *render_target::view_name(unsigned viewindex)
{
- return (m_views.size() > viewindex) ? m_views[viewindex].first.get().name().c_str() : nullptr;
-}
-
-layout_view::visibility_toggle_vector const &render_target::visibility_toggles()
-{
- return current_view().visibility_toggles();
+ return (m_views.size() > viewindex) ? m_views[viewindex].first.name().c_str() : nullptr;
}
@@ -1262,7 +1259,7 @@ void render_target::compute_minimum_size(s32 &minwidth, s32 &minheight)
// scan the current view for all screens
for (layout_view::item &curitem : current_view().items())
{
- screen_device *const screen = curitem.screen();
+ screen_device const *const screen = curitem.screen();
if (screen)
{
// use a hard-coded default visible area for vector screens
@@ -1615,7 +1612,7 @@ void render_target::debug_append(render_container &container)
void render_target::resolve_tags()
{
- for (layout_file &file : m_filelist)
+ for (layout_file &file : *m_filelist)
file.resolve_tags();
current_view().recompute(visibility_mask(), m_layerconfig.zoom_to_screen());
@@ -1780,7 +1777,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have
auto const nth_view =
[this] (unsigned n) -> layout_view *
{
- for (layout_file &file : m_filelist)
+ for (layout_file &file : *m_filelist)
for (layout_view &view : file.views())
if (!(m_flags & RENDER_CREATE_NO_ART) || !view.has_art())
if (n-- == 0)
@@ -1793,7 +1790,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have
if (!nth_view(0))
{
load_layout_file(nullptr, layout_noscreens);
- if (m_filelist.empty())
+ if (m_filelist->empty())
throw emu_fatalerror("Couldn't parse default layout??");
}
}
@@ -2200,7 +2197,7 @@ bool render_target::load_layout_file(device_t &device, util::xml::data_node cons
// parse and catch any errors
try
{
- m_filelist.emplace_back(device, rootnode, searchpath, dirname);
+ m_filelist->emplace_back(device, rootnode, searchpath, dirname);
}
catch (emu_fatalerror &err)
{
@@ -2570,7 +2567,7 @@ std::pair<float, float> render_target::map_point_internal(s32 target_x, s32 targ
layout_view *render_target::view_by_index(unsigned index)
{
- return (m_views.size() > index) ? &m_views[index].first.get() : nullptr;
+ return (m_views.size() > index) ? &m_views[index].first : nullptr;
}
@@ -2584,7 +2581,7 @@ int render_target::view_index(layout_view &targetview) const
// return index of view, or zero if not found
for (int index = 0; m_views.size() > index; ++index)
{
- if (&m_views[index].first.get() == &targetview)
+ if (&m_views[index].first == &targetview)
return index;
}
return 0;
@@ -2648,7 +2645,7 @@ void render_target::config_load(util::xml::data_node const &targetnode)
if (!viewname)
continue;
- auto const view = std::find_if(m_views.begin(), m_views.end(), [viewname] (auto const &x) { return x.first.get().name() == viewname; });
+ auto const view = std::find_if(m_views.begin(), m_views.end(), [viewname] (auto const &x) { return x.first.name() == viewname; });
if (m_views.end() == view)
continue;
@@ -2658,7 +2655,7 @@ void render_target::config_load(util::xml::data_node const &targetnode)
if (!vistogglename)
continue;
- auto const &vistoggles = view->first.get().visibility_toggles();
+ auto const &vistoggles = view->first.visibility_toggles();
auto const vistoggle = std::find_if(vistoggles.begin(), vistoggles.end(), [vistogglename] (auto const &x) { return x.name() == vistogglename; });
if (vistoggles.end() == vistoggle)
continue;
@@ -2673,7 +2670,7 @@ void render_target::config_load(util::xml::data_node const &targetnode)
}
}
- if (&current_view() == &view->first.get())
+ if (&current_view() == &view->first)
{
current_view().recompute(visibility_mask(), m_layerconfig.zoom_to_screen());
current_view().preload();
@@ -2726,19 +2723,19 @@ bool render_target::config_save(util::xml::data_node &targetnode)
// output layer configuration
for (auto const &view : m_views)
{
- u32 const defvismask = view.first.get().default_visibility_mask();
+ u32 const defvismask = view.first.default_visibility_mask();
if (defvismask != view.second)
{
util::xml::data_node *viewnode = nullptr;
unsigned i = 0;
- for (layout_view::visibility_toggle const &toggle : view.first.get().visibility_toggles())
+ for (layout_view::visibility_toggle const &toggle : view.first.visibility_toggles())
{
if (BIT(defvismask, i) != BIT(view.second, i))
{
if (!viewnode)
{
viewnode = targetnode.add_child("view", nullptr);
- viewnode->set_attribute("name", view.first.get().name().c_str());
+ viewnode->set_attribute("name", view.first.name().c_str());
}
util::xml::data_node *const vistogglenode = viewnode->add_child("collection", nullptr);
vistogglenode->set_attribute("name", toggle.name().c_str());
diff --git a/src/emu/render.h b/src/emu/render.h
index 37d70b6ec8d..deb28d2f4ba 100644
--- a/src/emu/render.h
+++ b/src/emu/render.h
@@ -173,35 +173,6 @@ struct render_texinfo
};
-namespace emu::render::detail {
-
-struct bounds_step
-{
- void get(render_bounds &result) const { result = bounds; }
-
- int state;
- render_bounds bounds;
- render_bounds delta;
-};
-using bounds_vector = std::vector<bounds_step>;
-
-struct color_step
-{
- void get(render_color &result) const { result = color; }
-
- int state;
- render_color color;
- render_color delta;
-};
-using color_vector = std::vector<color_step>;
-
-
-class layout_environment;
-class view_environment;
-
-} // namespace emu::render::detail
-
-
// ======================> render_layer_config
// render_layer_config - describes the state of layers
@@ -523,528 +494,6 @@ private:
};
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-
-/// \brief A description of a piece of visible artwork
-///
-/// Most view_items (except for those in the screen layer) have exactly
-/// one layout_element which describes the contents of the item.
-/// Elements are separate from items because they can be re-used
-/// multiple times within a layout. Even though an element can contain
-/// a number of components, they are treated as if they were a single
-/// bitmap.
-class layout_element
-{
-public:
- using environment = emu::render::detail::layout_environment;
-
- // construction/destruction
- layout_element(environment &env, util::xml::data_node const &elemnode);
- virtual ~layout_element();
-
- // getters
- running_machine &machine() const { return m_machine; }
- int default_state() const { return m_defstate; }
- render_texture *state_texture(int state);
-
- // operations
- void preload();
-
-private:
- /// \brief An image, rectangle, or disk in an element
- ///
- /// Each layout_element contains one or more components. Each
- /// component can describe either an image or a rectangle/disk
- /// primitive. Each component also has a "state" associated with it,
- /// which controls whether or not the component is visible (if the
- /// owning item has the same state, it is visible).
- class component
- {
- public:
- typedef std::unique_ptr<component> ptr;
-
- // construction/destruction
- component(environment &env, util::xml::data_node const &compnode);
- virtual ~component() = default;
-
- // setup
- void normalize_bounds(float xoffs, float yoffs, float xscale, float yscale);
-
- // getters
- int statemask() const { return m_statemask; }
- int stateval() const { return m_stateval; }
- std::pair<int, bool> statewrap() const;
- render_bounds overall_bounds() const;
- render_bounds bounds(int state) const;
- render_color color(int state) const;
-
- // operations
- virtual void preload(running_machine &machine);
- virtual void draw(running_machine &machine, bitmap_argb32 &dest, int state);
-
- protected:
- // helpers
- virtual int maxstate() const;
- virtual void draw_aligned(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state);
-
- // drawing helpers
- void draw_text(render_font &font, bitmap_argb32 &dest, const rectangle &bounds, std::string_view str, int align, const render_color &color);
- void draw_segment_horizontal_caps(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color);
- void draw_segment_horizontal(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, rgb_t color);
- void draw_segment_vertical_caps(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color);
- void draw_segment_vertical(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, rgb_t color);
- void draw_segment_diagonal_1(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
- void draw_segment_diagonal_2(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
- void draw_segment_decimal(bitmap_argb32 &dest, int midx, int midy, int width, rgb_t color);
- void draw_segment_comma(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
- void apply_skew(bitmap_argb32 &dest, int skewwidth);
-
- private:
- using bounds_vector = emu::render::detail::bounds_vector;
- using color_vector = emu::render::detail::color_vector;
-
- // internal state
- int const m_statemask; // bits of state used to control visibility
- int const m_stateval; // masked state value to make component visible
- bounds_vector m_bounds; // bounds of the element
- color_vector m_color; // color of the element
- };
-
- // component implementations
- class image_component;
- class rect_component;
- class disk_component;
- class text_component;
- class led7seg_component;
- class led8seg_gts1_component;
- class led14seg_component;
- class led16seg_component;
- class led14segsc_component;
- class led16segsc_component;
- class dotmatrix_component;
- class simplecounter_component;
- class reel_component;
-
- // a texture encapsulates a texture for a given element in a given state
- class texture
- {
- public:
- texture();
- texture(texture const &that) = delete;
- texture(texture &&that);
-
- ~texture();
-
- texture &operator=(texture const &that) = delete;
- texture &operator=(texture &&that);
-
- layout_element * m_element; // pointer back to the element
- render_texture * m_texture; // texture for this state
- int m_state; // associated state number
- };
-
- typedef component::ptr (*make_component_func)(environment &env, util::xml::data_node const &compnode);
- typedef std::map<std::string, make_component_func> make_component_map;
-
- // internal helpers
- static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
- template <typename T> static component::ptr make_component(environment &env, util::xml::data_node const &compnode);
- template <int D> static component::ptr make_dotmatrix_component(environment &env, util::xml::data_node const &compnode);
-
- static make_component_map const s_make_component; // maps component XML names to creator functions
-
- // internal state
- running_machine & m_machine; // reference to the owning machine
- std::vector<component::ptr> m_complist; // list of components
- int const m_defstate; // default state of this element
- int m_statemask; // mask to apply to state values
- bool m_foldhigh; // whether we need to fold state values above the mask range
- std::vector<texture> m_elemtex; // array of element textures used for managing the scaled bitmaps
-};
-
-
-/// \brief A reusable group of elements
-///
-/// Views expand/flatten groups into their component elements applying
-/// an optional coordinate transform. This is mainly useful duplicating
-/// the same sublayout in multiple views. It would be more useful
-/// within a view if it could be parameterised. Groups only exist while
-/// parsing a layout file - no information about element grouping is
-/// preserved.
-class layout_group
-{
-public:
- using environment = emu::render::detail::layout_environment;
- using group_map = std::unordered_map<std::string, layout_group>;
- using transform = std::array<std::array<float, 3>, 3>;
-
- layout_group(util::xml::data_node const &groupnode);
- ~layout_group();
-
- util::xml::data_node const &get_groupnode() const { return m_groupnode; }
-
- transform make_transform(int orientation, render_bounds const &dest) const;
- transform make_transform(int orientation, transform const &trans) const;
- transform make_transform(int orientation, render_bounds const &dest, transform const &trans) const;
-
- void set_bounds_unresolved();
- void resolve_bounds(environment &env, group_map &groupmap);
-
-private:
- void resolve_bounds(environment &env, group_map &groupmap, std::vector<layout_group const *> &seen);
- void resolve_bounds(
- environment &env,
- util::xml::data_node const &parentnode,
- group_map &groupmap,
- std::vector<layout_group const *> &seen,
- bool &empty,
- bool vistoggle,
- bool repeat,
- bool init);
-
- util::xml::data_node const & m_groupnode;
- render_bounds m_bounds;
- bool m_bounds_resolved;
-};
-
-
-/// \brief A single view within a layout_file
-///
-/// The view is described using arbitrary coordinates that are scaled to
-/// fit within the render target. Pixels within a view are assumed to
-/// be square.
-class layout_view
-{
-public:
- using layout_environment = emu::render::detail::layout_environment;
- using view_environment = emu::render::detail::view_environment;
- using element_map = std::unordered_map<std::string, layout_element>;
- using group_map = std::unordered_map<std::string, layout_group>;
- using screen_ref_vector = std::vector<std::reference_wrapper<screen_device> >;
- using prepare_items_delegate = delegate<void ()>;
- using preload_delegate = delegate<void ()>;
- using recomputed_delegate = delegate<void ()>;
-
- /// \brief A single item in a view
- ///
- /// Each view has a list of item structures describing the visual
- /// elements to draw, where they are located, additional blending
- /// modes, and bindings for inputs and outputs.
- class item
- {
- friend class layout_view;
-
- public:
- using state_delegate = delegate<int ()>;
- using bounds_delegate = delegate<void (render_bounds &)>;
- using color_delegate = delegate<void (render_color &)>;
-
- // construction/destruction
- item(
- view_environment &env,
- util::xml::data_node const &itemnode,
- element_map &elemmap,
- int orientation,
- layout_group::transform const &trans,
- render_color const &color);
- ~item();
-
- // getters
- std::string const &id() const { return m_id; }
- layout_element *element() const { return m_element; }
- screen_device *screen() { return m_screen; }
- bool bounds_animated() const { return m_bounds.size() > 1U; }
- bool color_animated() const { return m_color.size() > 1U; }
- render_bounds bounds() const { render_bounds result; m_get_bounds(result); return result; }
- render_color color() const { render_color result; m_get_color(result); return result; }
- int blend_mode() const { return m_blend_mode; }
- u32 visibility_mask() const { return m_visibility_mask; }
- int orientation() const { return m_orientation; }
- render_container *screen_container() const { return m_screen ? &m_screen->container() : nullptr; }
-
- // interactivity
- bool has_input() const { return bool(m_input_port); }
- std::pair<ioport_port *, ioport_value> input_tag_and_mask() const { return std::make_pair(m_input_port, m_input_mask); };
- bool clickthrough() const { return m_clickthrough; }
-
- // fetch state based on configured source
- int element_state() const { return m_get_elem_state(); }
- int animation_state() const { return m_get_anim_state(); }
-
- // set state
- void set_state(int state) { m_elem_state = state; }
-
- // set handlers
- void set_element_state_callback(state_delegate &&handler);
- void set_animation_state_callback(state_delegate &&handler);
- void set_bounds_callback(bounds_delegate &&handler);
- void set_color_callback(color_delegate &&handler);
-
- // resolve tags, if any
- void resolve_tags();
-
- private:
- using bounds_vector = emu::render::detail::bounds_vector;
- using color_vector = emu::render::detail::color_vector;
-
- state_delegate default_get_elem_state();
- state_delegate default_get_anim_state();
- bounds_delegate default_get_bounds();
- color_delegate default_get_color();
- int get_state() const;
- int get_output() const;
- int get_input_raw() const;
- int get_input_field_cached() const;
- int get_input_field_conditional() const;
- int get_anim_output() const;
- int get_anim_input() const;
- void get_interpolated_bounds(render_bounds &result) const;
- void get_interpolated_color(render_color &result) const;
-
- static layout_element *find_element(view_environment &env, util::xml::data_node const &itemnode, element_map &elemmap);
- static bounds_vector make_bounds(view_environment &env, util::xml::data_node const &itemnode, layout_group::transform const &trans);
- static color_vector make_color(view_environment &env, util::xml::data_node const &itemnode, render_color const &mult);
- static std::string make_animoutput_tag(view_environment &env, util::xml::data_node const &itemnode);
- static std::string make_animinput_tag(view_environment &env, util::xml::data_node const &itemnode);
- static ioport_value make_animmask(view_environment &env, util::xml::data_node const &itemnode);
- static std::string make_input_tag(view_environment &env, util::xml::data_node const &itemnode);
- static int get_blend_mode(view_environment &env, util::xml::data_node const &itemnode);
- static unsigned get_state_shift(ioport_value mask);
-
- // internal state
- layout_element *const m_element; // pointer to the associated element (non-screens only)
- state_delegate m_get_elem_state; // resolved element state function
- state_delegate m_get_anim_state; // resolved animation state function
- bounds_delegate m_get_bounds; // resolved bounds function
- color_delegate m_get_color; // resolved color function
- output_finder<> m_output; // associated output
- output_finder<> m_animoutput; // associated output for animation if different
- ioport_port * m_animinput_port; // input port used for animation
- int m_elem_state; // element state used in absence of bindings
- ioport_value const m_animmask; // mask for animation state
- u8 const m_animshift; // shift for animation state
- 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 const m_input_shift; // input mask rightshift for raw (trailing 0s)
- bool m_clickthrough; // should click pass through to lower elements
- screen_device * m_screen; // pointer to screen
- int const m_orientation; // orientation of this item
- bounds_vector m_bounds; // bounds of the item
- color_vector const m_color; // color of the item
- int m_blend_mode; // blending mode to use when drawing
- u32 m_visibility_mask; // combined mask of parent visibility groups
-
- // cold items
- std::string const m_id; // optional unique item identifier
- std::string const m_input_tag; // input tag of this item
- std::string const m_animinput_tag; // tag of input port for animation state
- bounds_vector const m_rawbounds; // raw (original) bounds of the item
- bool const m_have_output; // whether we actually have an output
- bool const m_input_raw; // get raw data from input port
- bool const m_have_animoutput; // whether we actually have an output for animation
- bool const m_has_clickthrough; // whether clickthrough was explicitly configured
- };
- using item_list = std::list<item>;
- using item_ref_vector = std::vector<std::reference_wrapper<item> >;
-
- /// \brief A subset of items in a view that can be hidden or shown
- ///
- /// Visibility toggles allow the user to show or hide selected parts
- /// of a view.
- class visibility_toggle
- {
- public:
- // construction/destruction/assignment
- visibility_toggle(std::string &&name, u32 mask);
- visibility_toggle(visibility_toggle const &) = default;
- visibility_toggle(visibility_toggle &&) = default;
- visibility_toggle &operator=(visibility_toggle const &) = default;
- visibility_toggle &operator=(visibility_toggle &&) = default;
-
- // getters
- std::string const &name() const { return m_name; }
- u32 mask() const { return m_mask; }
-
- private:
- std::string m_name; // display name for the toggle
- u32 m_mask; // toggle combination to show
- };
- using visibility_toggle_vector = std::vector<visibility_toggle>;
-
- /// \brief An edge of an item in a view
- class edge
- {
- public:
- // construction/destruction
- constexpr edge(unsigned index, float position, bool trailing)
- : m_index(index)
- , m_position(position)
- , m_trailing(trailing)
- {
- }
-
- // getters
- constexpr unsigned index() const { return m_index; }
- constexpr float position() const { return m_position; }
- constexpr bool trailing() const { return m_trailing; }
-
- // comparison
- constexpr bool operator<(edge const &that) const
- {
- return std::make_tuple(m_position, m_trailing, m_index) < std::make_tuple(that.m_position, that.m_trailing, that.m_index);
- }
-
- private:
- unsigned m_index; // index of item in some collection
- float m_position; // position of edge on given axis
- bool m_trailing; // false for edge at lower position on axis
- };
- using edge_vector = std::vector<edge>;
-
- // construction/destruction
- layout_view(
- layout_environment &env,
- util::xml::data_node const &viewnode,
- element_map &elemmap,
- group_map &groupmap);
- ~layout_view();
-
- // getters
- item *get_item(std::string const &id);
- item_list &items() { return m_items; }
- bool has_screen(screen_device &screen);
- const std::string &name() const { return m_name; }
- const std::string &unqualified_name() const { return m_unqualified_name; }
- size_t visible_screen_count() const { return m_screens.size(); }
- float effective_aspect() const { return m_effaspect; }
- const render_bounds &bounds() const { return m_bounds; }
- bool has_visible_screen(screen_device &screen) const;
- const item_ref_vector &visible_items() const { return m_visible_items; }
- const item_ref_vector &visible_screen_items() const { return m_screen_items; }
- const item_ref_vector &interactive_items() const { return m_interactive_items; }
- const edge_vector &interactive_edges_x() const { return m_interactive_edges_x; }
- const edge_vector &interactive_edges_y() const { return m_interactive_edges_y; }
- const screen_ref_vector &visible_screens() const { return m_screens; }
- const visibility_toggle_vector &visibility_toggles() const { return m_vistoggles; }
- u32 default_visibility_mask() const { return m_defvismask; }
- bool has_art() const { return m_has_art; }
-
- // set handlers
- void set_prepare_items_callback(prepare_items_delegate &&handler);
- void set_preload_callback(preload_delegate &&handler);
- void set_recomputed_callback(recomputed_delegate &&handler);
-
- // operations
- void prepare_items() { if (!m_prepare_items.isnull()) m_prepare_items(); }
- void recompute(u32 visibility_mask, bool zoom_to_screens);
- void preload();
-
- // resolve tags, if any
- void resolve_tags();
-
-private:
- struct layer_lists;
-
- using item_id_map = std::unordered_map<
- std::reference_wrapper<std::string const>,
- item &,
- std::hash<std::string>,
- std::equal_to<std::string> >;
-
- // add items, recursing for groups
- void add_items(
- layer_lists &layers,
- view_environment &env,
- util::xml::data_node const &parentnode,
- element_map &elemmap,
- group_map &groupmap,
- int orientation,
- layout_group::transform const &trans,
- render_color const &color,
- bool root,
- bool repeat,
- bool init);
-
- static std::string make_name(layout_environment &env, util::xml::data_node const &viewnode);
-
- // internal state
- float m_effaspect; // X/Y of the layout in current configuration
- render_bounds m_bounds; // computed bounds of the view in current configuration
- item_list m_items; // list of layout items
- item_ref_vector m_visible_items; // all visible items
- item_ref_vector m_screen_items; // visible items that represent screens to draw
- item_ref_vector m_interactive_items;// visible items that can accept pointer input
- edge_vector m_interactive_edges_x;
- edge_vector m_interactive_edges_y;
- screen_ref_vector m_screens; // list screens visible in current configuration
-
- // handlers
- prepare_items_delegate m_prepare_items; // prepare items for adding to render container
- preload_delegate m_preload; // additional actions when visible items change
- recomputed_delegate m_recomputed; // additional actions on resizing/visibility change
-
- // cold items
- std::string m_name; // display name for the view
- std::string m_unqualified_name; // the name exactly as specified in the layout file
- item_id_map m_items_by_id; // items with non-empty ID indexed by ID
- visibility_toggle_vector m_vistoggles; // collections of items that can be shown/hidden
- render_bounds m_expbounds; // explicit bounds of the view
- u32 m_defvismask; // default visibility mask
- bool m_has_art; // true if the layout contains non-screen elements
-};
-
-
-/// \brief Layout description file
-///
-/// Comprises a list of elements and a list of views. The elements are
-/// reusable items that the views reference.
-class layout_file
-{
-public:
- using element_map = std::unordered_map<std::string, layout_element>;
- using group_map = std::unordered_map<std::string, layout_group>;
- using view_list = std::list<layout_view>;
- using resolve_tags_delegate = delegate<void ()>;
-
- // construction/destruction
- layout_file(device_t &device, util::xml::data_node const &rootnode, char const *searchpath, char const *dirname);
- ~layout_file();
-
- // getters
- device_t &device() const { return m_device; }
- element_map const &elements() const { return m_elemmap; }
- view_list &views() { return m_viewlist; }
- view_list const &views() const { return m_viewlist; }
-
- // resolve tags, if any
- void resolve_tags();
-
- // set handlers
- void set_resolve_tags_callback(resolve_tags_delegate &&handler);
-
-private:
- using environment = emu::render::detail::layout_environment;
-
- // add elements and parameters
- void add_elements(
- environment &env,
- util::xml::data_node const &parentnode,
- group_map &groupmap,
- bool repeat,
- bool init);
-
- // internal state
- device_t & m_device; // device that caused file to be loaded
- element_map m_elemmap; // list of shared layout elements
- view_list m_viewlist; // list of views
- resolve_tags_delegate m_resolve_tags; // additional actions after resolving tags
-};
-
// ======================> render_target
// a render_target describes a surface that is being rendered to
@@ -1071,7 +520,7 @@ public:
float max_update_rate() const { return m_max_refresh; }
int orientation() const { return m_orientation; }
render_layer_config layer_config() const { return m_layerconfig; }
- layout_view &current_view() const { return m_views[m_curview].first.get(); }
+ layout_view &current_view() const { return m_views[m_curview].first; }
unsigned view() const { return m_curview; }
bool external_artwork() const { return m_external_artwork; }
bool hidden() const { return ((m_flags & RENDER_CREATE_HIDDEN) != 0); }
@@ -1103,7 +552,6 @@ public:
// view information
char const *view_name(unsigned index);
- layout_view::visibility_toggle_vector const &visibility_toggles();
// bounds computations
void compute_visible_area(s32 target_width, s32 target_height, float target_pixel_aspect, int target_orientation, s32 &visible_width, s32 &visible_height);
@@ -1128,7 +576,7 @@ public:
void resolve_tags();
private:
- using view_mask_pair = std::pair<std::reference_wrapper<layout_view>, u32>;
+ using view_mask_pair = std::pair<layout_view &, u32>;
using view_mask_vector = std::vector<view_mask_pair>;
// private classes declared in render.cpp
@@ -1169,7 +617,7 @@ private:
// internal state
render_target * m_next; // link to next target
render_manager & m_manager; // reference to our owning manager
- std::list<layout_file> m_filelist; // list of layout files
+ std::unique_ptr<std::list<layout_file>> m_filelist; // list of layout files
view_mask_vector m_views; // views we consider
unsigned m_curview; // current view index
u32 m_flags; // creation flags
diff --git a/src/emu/rendertypes.h b/src/emu/rendertypes.h
index 0fa698cc931..43f2ebb85e7 100644
--- a/src/emu/rendertypes.h
+++ b/src/emu/rendertypes.h
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
- render.h
+ rendertypes.h
Core renderer constants and structures for MAME.
diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp
index e343435a6f0..ec2cec7c336 100644
--- a/src/emu/rendlay.cpp
+++ b/src/emu/rendlay.cpp
@@ -52,6 +52,8 @@
STANDARD LAYOUTS
***************************************************************************/
+#include "layout/generic.h"
+
// screenless layouts
#include "noscreens.lh"
@@ -4056,7 +4058,7 @@ layout_view::item *layout_view::get_item(std::string const &id)
// the specified screen
//-------------------------------------------------
-bool layout_view::has_screen(screen_device &screen)
+bool layout_view::has_screen(screen_device const &screen) const
{
return std::find_if(m_items.begin(), m_items.end(), [&screen] (auto &itm) { return itm.screen() == &screen; }) != m_items.end();
}
@@ -4067,7 +4069,7 @@ bool layout_view::has_screen(screen_device &screen)
// has the given screen visble
//-------------------------------------------------
-bool layout_view::has_visible_screen(screen_device &screen) const
+bool layout_view::has_visible_screen(screen_device const &screen) const
{
return std::find_if(m_screens.begin(), m_screens.end(), [&screen] (auto const &scr) { return &scr.get() == &screen; }) != m_screens.end();
}
diff --git a/src/emu/rendlay.h b/src/emu/rendlay.h
index d1de55f73ef..fb7871bd0ef 100644
--- a/src/emu/rendlay.h
+++ b/src/emu/rendlay.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
+// copyright-holders:Aaron Giles, Vas Crabb
/***************************************************************************
rendlay.h
@@ -13,23 +13,557 @@
#pragma once
+#include "rendertypes.h"
+#include "screen.h"
+
//**************************************************************************
-// GLOBAL VARIABLES
+// TYPE DEFINITIONS
//**************************************************************************
-// no screens layouts
-extern const internal_layout layout_noscreens; // for screenless systems
+namespace emu::render::detail {
+
+struct bounds_step
+{
+ void get(render_bounds &result) const { result = bounds; }
+
+ int state;
+ render_bounds bounds;
+ render_bounds delta;
+};
+using bounds_vector = std::vector<bounds_step>;
+
+struct color_step
+{
+ void get(render_color &result) const { result = color; }
+
+ int state;
+ render_color color;
+ render_color delta;
+};
+using color_vector = std::vector<color_step>;
+
+
+class layout_environment;
+class view_environment;
+
+} // namespace emu::render::detail
+
+
+/// \brief A description of a piece of visible artwork
+///
+/// Most view_items (except for those in the screen layer) have exactly
+/// one layout_element which describes the contents of the item.
+/// Elements are separate from items because they can be re-used
+/// multiple times within a layout. Even though an element can contain
+/// a number of components, they are treated as if they were a single
+/// bitmap.
+class layout_element
+{
+public:
+ using environment = emu::render::detail::layout_environment;
+
+ // construction/destruction
+ layout_element(environment &env, util::xml::data_node const &elemnode);
+ virtual ~layout_element();
+
+ // getters
+ running_machine &machine() const { return m_machine; }
+ int default_state() const { return m_defstate; }
+ render_texture *state_texture(int state);
+
+ // operations
+ void preload();
+
+private:
+ /// \brief An image, rectangle, or disk in an element
+ ///
+ /// Each layout_element contains one or more components. Each
+ /// component can describe either an image or a rectangle/disk
+ /// primitive. Each component also has a "state" associated with it,
+ /// which controls whether or not the component is visible (if the
+ /// owning item has the same state, it is visible).
+ class component
+ {
+ public:
+ typedef std::unique_ptr<component> ptr;
+
+ // construction/destruction
+ component(environment &env, util::xml::data_node const &compnode);
+ virtual ~component() = default;
+
+ // setup
+ void normalize_bounds(float xoffs, float yoffs, float xscale, float yscale);
+
+ // getters
+ int statemask() const { return m_statemask; }
+ int stateval() const { return m_stateval; }
+ std::pair<int, bool> statewrap() const;
+ render_bounds overall_bounds() const;
+ render_bounds bounds(int state) const;
+ render_color color(int state) const;
+
+ // operations
+ virtual void preload(running_machine &machine);
+ virtual void draw(running_machine &machine, bitmap_argb32 &dest, int state);
+
+ protected:
+ // helpers
+ virtual int maxstate() const;
+ virtual void draw_aligned(running_machine &machine, bitmap_argb32 &dest, const rectangle &bounds, int state);
+
+ // drawing helpers
+ void draw_text(render_font &font, bitmap_argb32 &dest, const rectangle &bounds, std::string_view str, int align, const render_color &color);
+ void draw_segment_horizontal_caps(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, int caps, rgb_t color);
+ void draw_segment_horizontal(bitmap_argb32 &dest, int minx, int maxx, int midy, int width, rgb_t color);
+ void draw_segment_vertical_caps(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, int caps, rgb_t color);
+ void draw_segment_vertical(bitmap_argb32 &dest, int miny, int maxy, int midx, int width, rgb_t color);
+ void draw_segment_diagonal_1(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void draw_segment_diagonal_2(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void draw_segment_decimal(bitmap_argb32 &dest, int midx, int midy, int width, rgb_t color);
+ void draw_segment_comma(bitmap_argb32 &dest, int minx, int maxx, int miny, int maxy, int width, rgb_t color);
+ void apply_skew(bitmap_argb32 &dest, int skewwidth);
+
+ private:
+ using bounds_vector = emu::render::detail::bounds_vector;
+ using color_vector = emu::render::detail::color_vector;
+
+ // internal state
+ int const m_statemask; // bits of state used to control visibility
+ int const m_stateval; // masked state value to make component visible
+ bounds_vector m_bounds; // bounds of the element
+ color_vector m_color; // color of the element
+ };
+
+ // component implementations
+ class image_component;
+ class rect_component;
+ class disk_component;
+ class text_component;
+ class led7seg_component;
+ class led8seg_gts1_component;
+ class led14seg_component;
+ class led16seg_component;
+ class led14segsc_component;
+ class led16segsc_component;
+ class dotmatrix_component;
+ class simplecounter_component;
+ class reel_component;
+
+ // a texture encapsulates a texture for a given element in a given state
+ class texture
+ {
+ public:
+ texture();
+ texture(texture const &that) = delete;
+ texture(texture &&that);
+
+ ~texture();
+
+ texture &operator=(texture const &that) = delete;
+ texture &operator=(texture &&that);
+
+ layout_element * m_element; // pointer back to the element
+ render_texture * m_texture; // texture for this state
+ int m_state; // associated state number
+ };
+
+ typedef component::ptr (*make_component_func)(environment &env, util::xml::data_node const &compnode);
+ typedef std::map<std::string, make_component_func> make_component_map;
+
+ // internal helpers
+ static void element_scale(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
+ template <typename T> static component::ptr make_component(environment &env, util::xml::data_node const &compnode);
+ template <int D> static component::ptr make_dotmatrix_component(environment &env, util::xml::data_node const &compnode);
+
+ static make_component_map const s_make_component; // maps component XML names to creator functions
+
+ // internal state
+ running_machine & m_machine; // reference to the owning machine
+ std::vector<component::ptr> m_complist; // list of components
+ int const m_defstate; // default state of this element
+ int m_statemask; // mask to apply to state values
+ bool m_foldhigh; // whether we need to fold state values above the mask range
+ std::vector<texture> m_elemtex; // array of element textures used for managing the scaled bitmaps
+};
+
+
+/// \brief A reusable group of elements
+///
+/// Views expand/flatten groups into their component elements applying
+/// an optional coordinate transform. This is mainly useful duplicating
+/// the same sublayout in multiple views. It would be more useful
+/// within a view if it could be parameterised. Groups only exist while
+/// parsing a layout file - no information about element grouping is
+/// preserved.
+class layout_group
+{
+public:
+ using environment = emu::render::detail::layout_environment;
+ using group_map = std::unordered_map<std::string, layout_group>;
+ using transform = std::array<std::array<float, 3>, 3>;
+
+ layout_group(util::xml::data_node const &groupnode);
+ ~layout_group();
+
+ util::xml::data_node const &get_groupnode() const { return m_groupnode; }
+
+ transform make_transform(int orientation, render_bounds const &dest) const;
+ transform make_transform(int orientation, transform const &trans) const;
+ transform make_transform(int orientation, render_bounds const &dest, transform const &trans) const;
+
+ void set_bounds_unresolved();
+ void resolve_bounds(environment &env, group_map &groupmap);
+
+private:
+ void resolve_bounds(environment &env, group_map &groupmap, std::vector<layout_group const *> &seen);
+ void resolve_bounds(
+ environment &env,
+ util::xml::data_node const &parentnode,
+ group_map &groupmap,
+ std::vector<layout_group const *> &seen,
+ bool &empty,
+ bool vistoggle,
+ bool repeat,
+ bool init);
+
+ util::xml::data_node const & m_groupnode;
+ render_bounds m_bounds;
+ bool m_bounds_resolved;
+};
+
+
+/// \brief A single view within a layout_file
+///
+/// The view is described using arbitrary coordinates that are scaled to
+/// fit within the render target. Pixels within a view are assumed to
+/// be square.
+class layout_view
+{
+public:
+ using layout_environment = emu::render::detail::layout_environment;
+ using view_environment = emu::render::detail::view_environment;
+ using element_map = std::unordered_map<std::string, layout_element>;
+ using group_map = std::unordered_map<std::string, layout_group>;
+ using screen_ref_vector = std::vector<std::reference_wrapper<screen_device const>>;
+ using prepare_items_delegate = delegate<void ()>;
+ using preload_delegate = delegate<void ()>;
+ using recomputed_delegate = delegate<void ()>;
+
+ /// \brief A single item in a view
+ ///
+ /// Each view has a list of item structures describing the visual
+ /// elements to draw, where they are located, additional blending
+ /// modes, and bindings for inputs and outputs.
+ class item
+ {
+ friend class layout_view;
+
+ public:
+ using state_delegate = delegate<int ()>;
+ using bounds_delegate = delegate<void (render_bounds &)>;
+ using color_delegate = delegate<void (render_color &)>;
+
+ // construction/destruction
+ item(
+ view_environment &env,
+ util::xml::data_node const &itemnode,
+ element_map &elemmap,
+ int orientation,
+ layout_group::transform const &trans,
+ render_color const &color);
+ ~item();
+
+ // getters
+ std::string const &id() const { return m_id; }
+ layout_element *element() const { return m_element; }
+ screen_device *screen() const { return m_screen; }
+ bool bounds_animated() const { return m_bounds.size() > 1U; }
+ bool color_animated() const { return m_color.size() > 1U; }
+ render_bounds bounds() const { render_bounds result; m_get_bounds(result); return result; }
+ render_color color() const { render_color result; m_get_color(result); return result; }
+ int blend_mode() const { return m_blend_mode; }
+ u32 visibility_mask() const { return m_visibility_mask; }
+ int orientation() const { return m_orientation; }
+ render_container *screen_container() const { return m_screen ? &m_screen->container() : nullptr; }
+
+ // interactivity
+ bool has_input() const { return bool(m_input_port); }
+ std::pair<ioport_port *, ioport_value> input_tag_and_mask() const { return std::make_pair(m_input_port, m_input_mask); };
+ bool clickthrough() const { return m_clickthrough; }
+
+ // fetch state based on configured source
+ int element_state() const { return m_get_elem_state(); }
+ int animation_state() const { return m_get_anim_state(); }
+
+ // set state
+ void set_state(int state) { m_elem_state = state; }
+
+ // set handlers
+ void set_element_state_callback(state_delegate &&handler);
+ void set_animation_state_callback(state_delegate &&handler);
+ void set_bounds_callback(bounds_delegate &&handler);
+ void set_color_callback(color_delegate &&handler);
+
+ // resolve tags, if any
+ void resolve_tags();
+
+ private:
+ using bounds_vector = emu::render::detail::bounds_vector;
+ using color_vector = emu::render::detail::color_vector;
+
+ state_delegate default_get_elem_state();
+ state_delegate default_get_anim_state();
+ bounds_delegate default_get_bounds();
+ color_delegate default_get_color();
+ int get_state() const;
+ int get_output() const;
+ int get_input_raw() const;
+ int get_input_field_cached() const;
+ int get_input_field_conditional() const;
+ int get_anim_output() const;
+ int get_anim_input() const;
+ void get_interpolated_bounds(render_bounds &result) const;
+ void get_interpolated_color(render_color &result) const;
+
+ static layout_element *find_element(view_environment &env, util::xml::data_node const &itemnode, element_map &elemmap);
+ static bounds_vector make_bounds(view_environment &env, util::xml::data_node const &itemnode, layout_group::transform const &trans);
+ static color_vector make_color(view_environment &env, util::xml::data_node const &itemnode, render_color const &mult);
+ static std::string make_animoutput_tag(view_environment &env, util::xml::data_node const &itemnode);
+ static std::string make_animinput_tag(view_environment &env, util::xml::data_node const &itemnode);
+ static ioport_value make_animmask(view_environment &env, util::xml::data_node const &itemnode);
+ static std::string make_input_tag(view_environment &env, util::xml::data_node const &itemnode);
+ static int get_blend_mode(view_environment &env, util::xml::data_node const &itemnode);
+ static unsigned get_state_shift(ioport_value mask);
+
+ // internal state
+ layout_element *const m_element; // pointer to the associated element (non-screens only)
+ state_delegate m_get_elem_state; // resolved element state function
+ state_delegate m_get_anim_state; // resolved animation state function
+ bounds_delegate m_get_bounds; // resolved bounds function
+ color_delegate m_get_color; // resolved color function
+ output_finder<> m_output; // associated output
+ output_finder<> m_animoutput; // associated output for animation if different
+ ioport_port * m_animinput_port; // input port used for animation
+ int m_elem_state; // element state used in absence of bindings
+ ioport_value const m_animmask; // mask for animation state
+ u8 const m_animshift; // shift for animation state
+ 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 const m_input_shift; // input mask rightshift for raw (trailing 0s)
+ bool m_clickthrough; // should click pass through to lower elements
+ screen_device * m_screen; // pointer to screen
+ int const m_orientation; // orientation of this item
+ bounds_vector m_bounds; // bounds of the item
+ color_vector const m_color; // color of the item
+ int m_blend_mode; // blending mode to use when drawing
+ u32 m_visibility_mask; // combined mask of parent visibility groups
+
+ // cold items
+ std::string const m_id; // optional unique item identifier
+ std::string const m_input_tag; // input tag of this item
+ std::string const m_animinput_tag; // tag of input port for animation state
+ bounds_vector const m_rawbounds; // raw (original) bounds of the item
+ bool const m_have_output; // whether we actually have an output
+ bool const m_input_raw; // get raw data from input port
+ bool const m_have_animoutput; // whether we actually have an output for animation
+ bool const m_has_clickthrough; // whether clickthrough was explicitly configured
+ };
+ using item_list = std::list<item>;
+ using item_ref_vector = std::vector<std::reference_wrapper<item> >;
+
+ /// \brief A subset of items in a view that can be hidden or shown
+ ///
+ /// Visibility toggles allow the user to show or hide selected parts
+ /// of a view.
+ class visibility_toggle
+ {
+ public:
+ // construction/destruction/assignment
+ visibility_toggle(std::string &&name, u32 mask);
+ visibility_toggle(visibility_toggle const &) = default;
+ visibility_toggle(visibility_toggle &&) = default;
+ visibility_toggle &operator=(visibility_toggle const &) = default;
+ visibility_toggle &operator=(visibility_toggle &&) = default;
+
+ // getters
+ std::string const &name() const { return m_name; }
+ u32 mask() const { return m_mask; }
+
+ private:
+ std::string m_name; // display name for the toggle
+ u32 m_mask; // toggle combination to show
+ };
+ using visibility_toggle_vector = std::vector<visibility_toggle>;
+
+ /// \brief An edge of an item in a view
+ class edge
+ {
+ public:
+ // construction/destruction
+ constexpr edge(unsigned index, float position, bool trailing)
+ : m_index(index)
+ , m_position(position)
+ , m_trailing(trailing)
+ {
+ }
+
+ // getters
+ constexpr unsigned index() const { return m_index; }
+ constexpr float position() const { return m_position; }
+ constexpr bool trailing() const { return m_trailing; }
+
+ // comparison
+ constexpr bool operator<(edge const &that) const
+ {
+ return std::make_tuple(m_position, m_trailing, m_index) < std::make_tuple(that.m_position, that.m_trailing, that.m_index);
+ }
+
+ private:
+ unsigned m_index; // index of item in some collection
+ float m_position; // position of edge on given axis
+ bool m_trailing; // false for edge at lower position on axis
+ };
+ using edge_vector = std::vector<edge>;
+
+ // construction/destruction
+ layout_view(
+ layout_environment &env,
+ util::xml::data_node const &viewnode,
+ element_map &elemmap,
+ group_map &groupmap);
+ ~layout_view();
+
+ // getters
+ item *get_item(std::string const &id);
+ item_list &items() { return m_items; }
+ bool has_screen(screen_device const &screen) const;
+ const std::string &name() const { return m_name; }
+ const std::string &unqualified_name() const { return m_unqualified_name; }
+ size_t visible_screen_count() const { return m_screens.size(); }
+ float effective_aspect() const { return m_effaspect; }
+ const render_bounds &bounds() const { return m_bounds; }
+ bool has_visible_screen(screen_device const &screen) const;
+ const item_ref_vector &visible_items() const { return m_visible_items; }
+ const item_ref_vector &visible_screen_items() const { return m_screen_items; }
+ const item_ref_vector &interactive_items() const { return m_interactive_items; }
+ const edge_vector &interactive_edges_x() const { return m_interactive_edges_x; }
+ const edge_vector &interactive_edges_y() const { return m_interactive_edges_y; }
+ const screen_ref_vector &visible_screens() const { return m_screens; }
+ const visibility_toggle_vector &visibility_toggles() const { return m_vistoggles; }
+ u32 default_visibility_mask() const { return m_defvismask; }
+ bool has_art() const { return m_has_art; }
+
+ // set handlers
+ void set_prepare_items_callback(prepare_items_delegate &&handler);
+ void set_preload_callback(preload_delegate &&handler);
+ void set_recomputed_callback(recomputed_delegate &&handler);
+
+ // operations
+ void prepare_items() { if (!m_prepare_items.isnull()) m_prepare_items(); }
+ void recompute(u32 visibility_mask, bool zoom_to_screens);
+ void preload();
+
+ // resolve tags, if any
+ void resolve_tags();
+
+private:
+ struct layer_lists;
+
+ using item_id_map = std::unordered_map<
+ std::reference_wrapper<std::string const>,
+ item &,
+ std::hash<std::string>,
+ std::equal_to<std::string> >;
+
+ // add items, recursing for groups
+ void add_items(
+ layer_lists &layers,
+ view_environment &env,
+ util::xml::data_node const &parentnode,
+ element_map &elemmap,
+ group_map &groupmap,
+ int orientation,
+ layout_group::transform const &trans,
+ render_color const &color,
+ bool root,
+ bool repeat,
+ bool init);
+
+ static std::string make_name(layout_environment &env, util::xml::data_node const &viewnode);
+
+ // internal state
+ float m_effaspect; // X/Y of the layout in current configuration
+ render_bounds m_bounds; // computed bounds of the view in current configuration
+ item_list m_items; // list of layout items
+ item_ref_vector m_visible_items; // all visible items
+ item_ref_vector m_screen_items; // visible items that represent screens to draw
+ item_ref_vector m_interactive_items;// visible items that can accept pointer input
+ edge_vector m_interactive_edges_x;
+ edge_vector m_interactive_edges_y;
+ screen_ref_vector m_screens; // list screens visible in current configuration
+
+ // handlers
+ prepare_items_delegate m_prepare_items; // prepare items for adding to render container
+ preload_delegate m_preload; // additional actions when visible items change
+ recomputed_delegate m_recomputed; // additional actions on resizing/visibility change
+
+ // cold items
+ std::string m_name; // display name for the view
+ std::string m_unqualified_name; // the name exactly as specified in the layout file
+ item_id_map m_items_by_id; // items with non-empty ID indexed by ID
+ visibility_toggle_vector m_vistoggles; // collections of items that can be shown/hidden
+ render_bounds m_expbounds; // explicit bounds of the view
+ u32 m_defvismask; // default visibility mask
+ bool m_has_art; // true if the layout contains non-screen elements
+};
+
+
+/// \brief Layout description file
+///
+/// Comprises a list of elements and a list of views. The elements are
+/// reusable items that the views reference.
+class layout_file
+{
+public:
+ using element_map = std::unordered_map<std::string, layout_element>;
+ using group_map = std::unordered_map<std::string, layout_group>;
+ using view_list = std::list<layout_view>;
+ using resolve_tags_delegate = delegate<void ()>;
+
+ // construction/destruction
+ layout_file(device_t &device, util::xml::data_node const &rootnode, char const *searchpath, char const *dirname);
+ ~layout_file();
+
+ // getters
+ device_t &device() const { return m_device; }
+ element_map const &elements() const { return m_elemmap; }
+ view_list &views() { return m_viewlist; }
+ view_list const &views() const { return m_viewlist; }
+
+ // resolve tags, if any
+ void resolve_tags();
+
+ // set handlers
+ void set_resolve_tags_callback(resolve_tags_delegate &&handler);
-// dual screen layouts
-extern const internal_layout layout_dualhsxs; // dual 4:3 screens side-by-side
-extern const internal_layout layout_dualhovu; // dual 4:3 screens above and below
-extern const internal_layout layout_dualhuov; // dual 4:3 screens below and above
+private:
+ using environment = emu::render::detail::layout_environment;
-// triple screen layouts
-extern const internal_layout layout_triphsxs; // triple 4:3 screens side-by-side
+ // add elements and parameters
+ void add_elements(
+ environment &env,
+ util::xml::data_node const &parentnode,
+ group_map &groupmap,
+ bool repeat,
+ bool init);
-// quad screen layouts
-extern const internal_layout layout_quadhsxs; // quad 4:3 screens side-by-side
+ // internal state
+ device_t & m_device; // device that caused file to be loaded
+ element_map m_elemmap; // list of shared layout elements
+ view_list m_viewlist; // list of views
+ resolve_tags_delegate m_resolve_tags; // additional actions after resolving tags
+};
#endif // MAME_EMU_RENDLAY_H