diff options
author | 2021-01-04 12:08:16 -0500 | |
---|---|---|
committer | 2021-01-04 12:15:09 -0500 | |
commit | c231ee373a461ee8555b2df25e68efea4506229d (patch) | |
tree | 30cfd37e502317b69d3695bc74aebaacc5756418 | |
parent | 687e7e162dbadc4b4d0ca58343493f15a0cdabbc (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
38 files changed, 655 insertions, 625 deletions
diff --git a/scripts/src/emu.lua b/scripts/src/emu.lua index 4e7e294ad32..d1d3f0b0d1f 100644 --- a/scripts/src/emu.lua +++ b/scripts/src/emu.lua @@ -254,6 +254,7 @@ files { MAME_DIR .. "src/emu/debug/textbuf.h", MAME_DIR .. "src/emu/drivers/empty.cpp", MAME_DIR .. "src/emu/drivers/xtal.h", + MAME_DIR .. "src/emu/layout/generic.h", MAME_DIR .. "src/emu/video/generic.cpp", MAME_DIR .. "src/emu/video/generic.h", MAME_DIR .. "src/emu/video/resnet.cpp", 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 (¤t_view() == &view->first.get()) + if (¤t_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 ¤t_view() const { return m_views[m_curview].first.get(); } + layout_view ¤t_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 diff --git a/src/frontend/mame/luaengine_render.cpp b/src/frontend/mame/luaengine_render.cpp index 8a84fcc4e82..eab50d89a90 100644 --- a/src/frontend/mame/luaengine_render.cpp +++ b/src/frontend/mame/luaengine_render.cpp @@ -12,6 +12,7 @@ #include "luaengine.ipp" #include "render.h" +#include "rendlay.h" #include <iterator> diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp index f48cbd46563..919d3583074 100644 --- a/src/frontend/mame/mame.cpp +++ b/src/frontend/mame/mame.cpp @@ -22,6 +22,7 @@ #include "luaengine.h" #include "mameopts.h" #include "pluginopts.h" +#include "rendlay.h" #include "validity.h" #include "xmlfile.h" diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp index e49b743fc15..861bc9ce94e 100644 --- a/src/frontend/mame/ui/videoopt.cpp +++ b/src/frontend/mame/ui/videoopt.cpp @@ -11,6 +11,7 @@ #include "emu.h" #include "ui/videoopt.h" +#include "rendlay.h" #include "rendutil.h" @@ -147,7 +148,8 @@ void menu_video_options::populate(float &customtop, float &custombottom) } // add items for visibility toggles - auto const &toggles = m_target.visibility_toggles(); + layout_view const &curview = m_target.current_view(); + auto const &toggles = curview.visibility_toggles(); if (!toggles.empty()) { ref = 0U; @@ -177,7 +179,7 @@ void menu_video_options::populate(float &customtop, float &custombottom) item_append(_("Rotate"), subtext, FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW, reinterpret_cast<void *>(ITEM_ROTATE)); // cropping - bool const canzoom(m_target.current_view().has_art() && !m_target.current_view().visible_screens().empty()); + bool const canzoom(curview.has_art() && !curview.visible_screens().empty()); item_append_on_off(_("Zoom to Screen Area"), m_target.zoom_to_screen(), canzoom ? 0U : (FLAG_INVERT | FLAG_DISABLE), reinterpret_cast<void *>(ITEM_ZOOM)); if (!m_snapshot) diff --git a/src/mame/drivers/backfire.cpp b/src/mame/drivers/backfire.cpp index 6b939043d04..198d4d6b07c 100644 --- a/src/mame/drivers/backfire.cpp +++ b/src/mame/drivers/backfire.cpp @@ -23,7 +23,7 @@ #include "video/deco16ic.h" #include "video/decospr.h" #include "emupal.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/bnstars.cpp b/src/mame/drivers/bnstars.cpp index fdbcfea3228..49303c3d3c4 100644 --- a/src/mame/drivers/bnstars.cpp +++ b/src/mame/drivers/bnstars.cpp @@ -94,7 +94,7 @@ ROMs : MR96004-10.1 [125661cd] (IC5 - Samples) #include "cpu/v60/v60.h" #include "machine/jalcrpt.h" -#include "rendlay.h" +#include "layout/generic.h" #include "speaker.h" #include "tilemap.h" diff --git a/src/mame/drivers/coolridr.cpp b/src/mame/drivers/coolridr.cpp index d54b9c5d15a..0a0c11bd03c 100644 --- a/src/mame/drivers/coolridr.cpp +++ b/src/mame/drivers/coolridr.cpp @@ -288,7 +288,7 @@ to the same bank as defined through A20. #include "machine/315_5649.h" #include "sound/scsp.h" #include "emupal.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/cyberbal.cpp b/src/mame/drivers/cyberbal.cpp index 448fab33b85..7fb2c986f52 100644 --- a/src/mame/drivers/cyberbal.cpp +++ b/src/mame/drivers/cyberbal.cpp @@ -28,7 +28,7 @@ #include "machine/watchdog.h" #include "speaker.h" -#include "rendlay.h" +#include "layout/generic.h" /************************************* diff --git a/src/mame/drivers/cybertnk.cpp b/src/mame/drivers/cybertnk.cpp index bc713eedbe1..b073f8c9cf3 100644 --- a/src/mame/drivers/cybertnk.cpp +++ b/src/mame/drivers/cybertnk.cpp @@ -175,7 +175,7 @@ lev 7 : 0x7c : 0000 07e0 - input device clear? #include "machine/gen_latch.h" #include "sound/8950intf.h" #include "emupal.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "speaker.h" #include "tilemap.h" diff --git a/src/mame/drivers/dynax.cpp b/src/mame/drivers/dynax.cpp index bc52c62c14d..4d9ce423966 100644 --- a/src/mame/drivers/dynax.cpp +++ b/src/mame/drivers/dynax.cpp @@ -90,7 +90,7 @@ TODO: #include "sound/ym2413.h" #include "sound/3812intf.h" -#include "rendlay.h" +#include "layout/generic.h" #include "speaker.h" diff --git a/src/mame/drivers/fromanc2.cpp b/src/mame/drivers/fromanc2.cpp index be86fd55d4d..552a5d28058 100644 --- a/src/mame/drivers/fromanc2.cpp +++ b/src/mame/drivers/fromanc2.cpp @@ -24,10 +24,11 @@ #include "cpu/m68000/m68000.h" #include "cpu/z80/z80.h" #include "sound/2610intf.h" -#include "rendlay.h" #include "screen.h" #include "speaker.h" +#include "layout/generic.h" + /************************************* * diff --git a/src/mame/drivers/gaelco2.cpp b/src/mame/drivers/gaelco2.cpp index 8dd8abfa485..7eb611a4cdb 100644 --- a/src/mame/drivers/gaelco2.cpp +++ b/src/mame/drivers/gaelco2.cpp @@ -42,7 +42,7 @@ #include "machine/eepromser.h" #include "sound/gaelco.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/gal3.cpp b/src/mame/drivers/gal3.cpp index b7938dc399c..34fb85a8935 100644 --- a/src/mame/drivers/gal3.cpp +++ b/src/mame/drivers/gal3.cpp @@ -132,7 +132,7 @@ better notes (complete chip lists) for each board still needed #include "cpu/tms32025/tms32025.h" #include "machine/nvram.h" #include "sound/c140.h" -#include "rendlay.h" +#include "layout/generic.h" #include "speaker.h" #include "video/namco_c355spr.h" #include "machine/namcos21_dsp_c67.h" diff --git a/src/mame/drivers/gticlub.cpp b/src/mame/drivers/gticlub.cpp index 8e2e45b4cb1..ddeeaf2f38e 100644 --- a/src/mame/drivers/gticlub.cpp +++ b/src/mame/drivers/gticlub.cpp @@ -241,7 +241,7 @@ Hang Pilot (uses an unknown but similar video board) 12W #include "video/k001604.h" #include "emupal.h" -#include "rendlay.h" +#include "layout/generic.h" #include "speaker.h" diff --git a/src/mame/drivers/hornet.cpp b/src/mame/drivers/hornet.cpp index c28fb906cfb..127f4c0322a 100644 --- a/src/mame/drivers/hornet.cpp +++ b/src/mame/drivers/hornet.cpp @@ -360,10 +360,11 @@ #include "video/voodoo.h" #include "video/k037122.h" #include "emupal.h" -#include "rendlay.h" #include "screen.h" #include "speaker.h" +#include "layout/generic.h" + namespace { diff --git a/src/mame/drivers/konamigx.cpp b/src/mame/drivers/konamigx.cpp index bf432147a74..b96c5828a99 100644 --- a/src/mame/drivers/konamigx.cpp +++ b/src/mame/drivers/konamigx.cpp @@ -106,9 +106,10 @@ #include "sound/k054539.h" //#include "machine/k056230.h" #include "sound/k056800.h" -#include "rendlay.h" #include "speaker.h" +#include "layout/generic.h" + // TODO: check on PCB #define MASTER_CLOCK XTAL(24'000'000) diff --git a/src/mame/drivers/megatech.cpp b/src/mame/drivers/megatech.cpp index cd07e17998a..1e710038671 100644 --- a/src/mame/drivers/megatech.cpp +++ b/src/mame/drivers/megatech.cpp @@ -78,13 +78,12 @@ Sonic Hedgehog 2 171-6215A 837-6963-62 610-0239-62 MPR #include "emu.h" #include "cpu/z80/z80.h" #include "machine/cxd1095.h" -#include "rendlay.h" #include "includes/megadriv.h" #include "bus/generic/slot.h" #include "bus/generic/carts.h" -#include "softlist.h" +#include "layout/generic.h" #define MASTER_CLOCK 53693100 diff --git a/src/mame/drivers/nss.cpp b/src/mame/drivers/nss.cpp index 4370d06bc32..aabebcc5ade 100644 --- a/src/mame/drivers/nss.cpp +++ b/src/mame/drivers/nss.cpp @@ -302,7 +302,7 @@ Contra III CONTRA_III_1 TC574000 CONTRA_III_0 TC574000 GAME1_NSSU #include "machine/rp5h01.h" #include "video/m50458.h" #include "emupal.h" -#include "rendlay.h" +#include "layout/generic.h" #include "speaker.h" diff --git a/src/mame/drivers/punchout.cpp b/src/mame/drivers/punchout.cpp index c18d6806095..23887ed219d 100644 --- a/src/mame/drivers/punchout.cpp +++ b/src/mame/drivers/punchout.cpp @@ -121,10 +121,11 @@ DIP locations verified for: #include "machine/74259.h" #include "machine/gen_latch.h" #include "machine/nvram.h" -#include "rendlay.h" #include "screen.h" #include "speaker.h" +#include "layout/generic.h" + /*************************************************************************** diff --git a/src/mame/drivers/segas32.cpp b/src/mame/drivers/segas32.cpp index 52bd98a5f74..068a140bc9e 100644 --- a/src/mame/drivers/segas32.cpp +++ b/src/mame/drivers/segas32.cpp @@ -543,10 +543,9 @@ orunners: Interleaved with the dj and << >> buttons is the data the drives the #include "machine/315_5296.h" #include "sound/2612intf.h" #include "sound/rf5c68.h" - -#include "rendlay.h" #include "speaker.h" +#include "layout/generic.h" #include "radr.lh" /* diff --git a/src/mame/drivers/sfcbox.cpp b/src/mame/drivers/sfcbox.cpp index 441ccb304e8..13b1f7006f7 100644 --- a/src/mame/drivers/sfcbox.cpp +++ b/src/mame/drivers/sfcbox.cpp @@ -122,7 +122,8 @@ How does the Super Famicom Box operates #include "cpu/z180/z180.h" #include "machine/s3520cf.h" #include "video/mb90082.h" -#include "rendlay.h" + +#include "layout/generic.h" #include "speaker.h" diff --git a/src/mame/drivers/subs.cpp b/src/mame/drivers/subs.cpp index d3b6e50ff98..27db54a2313 100644 --- a/src/mame/drivers/subs.cpp +++ b/src/mame/drivers/subs.cpp @@ -24,10 +24,11 @@ #include "cpu/m6502/m6502.h" #include "machine/74259.h" -#include "rendlay.h" #include "screen.h" #include "speaker.h" +#include "layout/generic.h" + /************************************* * diff --git a/src/mame/drivers/tbowl.cpp b/src/mame/drivers/tbowl.cpp index 55d1c880abf..c51ee2c76e3 100644 --- a/src/mame/drivers/tbowl.cpp +++ b/src/mame/drivers/tbowl.cpp @@ -20,7 +20,7 @@ Might be some priority glitches #include "cpu/z80/z80.h" #include "sound/3812intf.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/tmmjprd.cpp b/src/mame/drivers/tmmjprd.cpp index 50c527f21ff..2730a5c1bab 100644 --- a/src/mame/drivers/tmmjprd.cpp +++ b/src/mame/drivers/tmmjprd.cpp @@ -32,10 +32,11 @@ #include "machine/timer.h" #include "sound/i5000.h" #include "emupal.h" -#include "rendlay.h" #include "screen.h" #include "speaker.h" +#include "layout/generic.h" + #define EMULATE_BLITTER 0 // FIXME: code is incomplete diff --git a/src/mame/drivers/tx1.cpp b/src/mame/drivers/tx1.cpp index 4f013057a31..39fb1313e0f 100644 --- a/src/mame/drivers/tx1.cpp +++ b/src/mame/drivers/tx1.cpp @@ -48,8 +48,8 @@ #include "machine/nvram.h" #include "machine/watchdog.h" #include "sound/ay8910.h" -#include "rendlay.h" +#include "layout/generic.h" #include "tx1.lh" #include "buggyboy.lh" #include "buggybjr.lh" diff --git a/src/mame/drivers/vcombat.cpp b/src/mame/drivers/vcombat.cpp index 9baedcd674f..d51a4648c3b 100644 --- a/src/mame/drivers/vcombat.cpp +++ b/src/mame/drivers/vcombat.cpp @@ -89,7 +89,7 @@ TODO : This is a partially working driver. Most of the memory maps for #include "sound/dac.h" #include "video/mc6845.h" #include "video/tlc34076.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/vsnes.cpp b/src/mame/drivers/vsnes.cpp index 14e66fec213..e303f2d1049 100644 --- a/src/mame/drivers/vsnes.cpp +++ b/src/mame/drivers/vsnes.cpp @@ -143,10 +143,11 @@ Changes: #include "cpu/m6502/n2a03.h" #include "cpu/z80/z80.h" -#include "rendlay.h" #include "screen.h" #include "speaker.h" +#include "layout/generic.h" + /******************************************************************************/ diff --git a/src/mame/drivers/warriorb.cpp b/src/mame/drivers/warriorb.cpp index baf1e0e4dd7..29849975e11 100644 --- a/src/mame/drivers/warriorb.cpp +++ b/src/mame/drivers/warriorb.cpp @@ -154,7 +154,7 @@ Colscroll effects? #include "cpu/m68000/m68000.h" #include "sound/2610intf.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "speaker.h" diff --git a/src/mame/drivers/x1twin.cpp b/src/mame/drivers/x1twin.cpp index 8d173f76a4a..0db55cf63cc 100644 --- a/src/mame/drivers/x1twin.cpp +++ b/src/mame/drivers/x1twin.cpp @@ -18,7 +18,7 @@ #include "includes/x1.h" #include "includes/pce.h" -#include "rendlay.h" +#include "layout/generic.h" #include "screen.h" #include "softlist.h" #include "speaker.h" diff --git a/src/mame/drivers/xmen.cpp b/src/mame/drivers/xmen.cpp index a886ff9bb40..745a0fad552 100644 --- a/src/mame/drivers/xmen.cpp +++ b/src/mame/drivers/xmen.cpp @@ -31,9 +31,10 @@ likewise a 2 screen game. #include "machine/watchdog.h" #include "sound/ym2151.h" #include "emupal.h" -#include "rendlay.h" #include "speaker.h" +#include "layout/generic.h" + /*************************************************************************** diff --git a/src/osd/modules/render/bgfx/chain.cpp b/src/osd/modules/render/bgfx/chain.cpp index d75b9b296dd..6ff13cffebb 100644 --- a/src/osd/modules/render/bgfx/chain.cpp +++ b/src/osd/modules/render/bgfx/chain.cpp @@ -19,6 +19,7 @@ #include "chainmanager.h" #include "target.h" #include "vertex.h" +#include "rendlay.h" #include "screen.h" #include "clear.h" #include "modules/osdwindow.h" diff --git a/src/osd/modules/render/d3d/d3dhlsl.cpp b/src/osd/modules/render/d3d/d3dhlsl.cpp index b572c77de23..c082bddb5bf 100644 --- a/src/osd/modules/render/d3d/d3dhlsl.cpp +++ b/src/osd/modules/render/d3d/d3dhlsl.cpp @@ -10,6 +10,7 @@ #include "emu.h" #include "drivenum.h" #include "render.h" +#include "rendlay.h" #include "rendutil.h" #include "emuopts.h" #include "aviio.h" |