summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/rendlay.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2021-11-18 10:34:38 +1100
committer Vas Crabb <vas@vastheman.com>2021-11-18 10:34:38 +1100
commit5afce6cfab6320ee062da5f7b7438294672f9af1 (patch)
tree5902ddf0b74f27e3d43bc0556dcfd29198e86efd /src/emu/rendlay.cpp
parentded9ecfc1cf7864f206b92480eaebf32092ef8f2 (diff)
emu/render.cpp, emu/rendlay.cpp: Added scroll support for all elements.
Diffstat (limited to 'src/emu/rendlay.cpp')
-rw-r--r--src/emu/rendlay.cpp547
1 files changed, 411 insertions, 136 deletions
diff --git a/src/emu/rendlay.cpp b/src/emu/rendlay.cpp
index b6709626d97..41075c2573b 100644
--- a/src/emu/rendlay.cpp
+++ b/src/emu/rendlay.cpp
@@ -1120,6 +1120,121 @@ inline render_color interpolate_color(emu::render::detail::color_vector const &s
}
}
+
+unsigned get_state_shift(ioport_value mask)
+{
+ // get shift to right-align LSB
+ unsigned result(0U);
+ while (mask && !BIT(mask, 0))
+ {
+ ++result;
+ mask >>= 1;
+ }
+ return result;
+}
+
+std::string make_child_output_tag(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode,
+ char const *child)
+{
+ util::xml::data_node const *const childnode(itemnode.get_child(child));
+ if (childnode)
+ return std::string(env.get_attribute_string(*childnode, "name"));
+ else
+ return std::string();
+}
+
+std::string make_child_input_tag(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode,
+ char const *child)
+{
+ util::xml::data_node const *const childnode(itemnode.get_child(child));
+ return childnode ? env.get_attribute_subtag(*childnode, "inputtag") : std::string();
+}
+
+ioport_value make_child_mask(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode,
+ char const *child)
+{
+ util::xml::data_node const *const childnode(itemnode.get_child(child));
+ return childnode ? env.get_attribute_int(*childnode, "mask", ~ioport_value(0)) : ~ioport_value(0);
+}
+
+bool make_child_wrap(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode,
+ char const *child)
+{
+ util::xml::data_node const *const childnode(itemnode.get_child(child));
+ return childnode ? env.get_attribute_bool(*childnode, "wrap", false) : false;
+}
+
+float make_child_size(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode,
+ char const *child)
+{
+ util::xml::data_node const *const childnode(itemnode.get_child(child));
+ return std::clamp(childnode ? env.get_attribute_float(*childnode, "size", 1.0f) : 1.0f, 0.01f, 1.0f);
+}
+
+ioport_value make_child_min(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode,
+ char const *child)
+{
+ util::xml::data_node const *const childnode(itemnode.get_child(child));
+ return childnode ? env.get_attribute_int(*childnode, "min", ioport_value(0)) : ioport_value(0);
+}
+
+ioport_value make_child_max(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode,
+ char const *child,
+ ioport_value mask)
+{
+ util::xml::data_node const *const childnode(itemnode.get_child(child));
+ ioport_value const dflt(mask >> get_state_shift(mask));
+ return childnode ? env.get_attribute_int(*childnode, "max", dflt) : dflt;
+}
+
+std::string make_input_tag(
+ emu::render::detail::view_environment &env,
+ util::xml::data_node const &itemnode)
+{
+ return env.get_attribute_subtag(itemnode, "inputtag");
+}
+
+int get_blend_mode(emu::render::detail::view_environment &env, util::xml::data_node const &itemnode)
+{
+ // see if there's a blend mode attribute
+ std::string const *const mode(itemnode.get_attribute_string_ptr("blend"));
+ if (mode)
+ {
+ if (*mode == "none")
+ return BLENDMODE_NONE;
+ else if (*mode == "alpha")
+ return BLENDMODE_ALPHA;
+ else if (*mode == "multiply")
+ return BLENDMODE_RGB_MULTIPLY;
+ else if (*mode == "add")
+ return BLENDMODE_ADD;
+ else
+ throw layout_syntax_error(util::string_format("unknown blend mode %s", *mode));
+ }
+
+ // fall back to implicit blend mode based on element type
+ if (!strcmp(itemnode.get_name(), "screen"))
+ return -1; // magic number recognised by render.cpp to allow per-element blend mode
+ else if (!strcmp(itemnode.get_name(), "overlay"))
+ return BLENDMODE_RGB_MULTIPLY;
+ else
+ return BLENDMODE_ALPHA;
+}
+
} // anonymous namespace
@@ -4096,7 +4211,7 @@ layout_view::~layout_view()
// get_item - get item by ID
//-------------------------------------------------
-layout_view::item *layout_view::get_item(std::string const &id)
+layout_view_item *layout_view::get_item(std::string const &id)
{
auto const found(m_items_by_id.find(id));
return (m_items_by_id.end() != found) ? &found->second : nullptr;
@@ -4502,10 +4617,10 @@ std::string layout_view::make_name(layout_environment &env, util::xml::data_node
//**************************************************************************
//-------------------------------------------------
-// item - constructor
+// layout_view_item - constructor
//-------------------------------------------------
-layout_view::item::item(
+layout_view_item::layout_view_item(
view_environment &env,
util::xml::data_node const &itemnode,
element_map &elemmap,
@@ -4514,11 +4629,29 @@ layout_view::item::item(
render_color const &color)
: m_element(find_element(env, itemnode, elemmap))
, m_output(env.device(), std::string(env.get_attribute_string(itemnode, "name")))
- , m_animoutput(env.device(), make_animoutput_tag(env, itemnode))
+ , m_animoutput(env.device(), make_child_output_tag(env, itemnode, "animate"))
+ , m_scrollxoutput(env.device(), make_child_output_tag(env, itemnode, "xscroll"))
+ , m_scrollyoutput(env.device(), make_child_output_tag(env, itemnode, "yscroll"))
, m_animinput_port(nullptr)
+ , m_scrollxinput_port(nullptr)
+ , m_scrollyinput_port(nullptr)
+ , m_scrollwrapx(make_child_wrap(env, itemnode, "xscroll"))
+ , m_scrollwrapy(make_child_wrap(env, itemnode, "yscroll"))
, m_elem_state(m_element ? m_element->default_state() : 0)
- , m_animmask(make_animmask(env, itemnode))
+ , m_scrollsizex(make_child_size(env, itemnode, "xscroll"))
+ , m_scrollsizey(make_child_size(env, itemnode, "yscroll"))
+ , m_scrollposx(0.0f)
+ , m_scrollposy(0.0f)
+ , m_animmask(make_child_mask(env, itemnode, "animate"))
+ , m_scrollxmask(make_child_mask(env, itemnode, "xscroll"))
+ , m_scrollymask(make_child_mask(env, itemnode, "yscroll"))
+ , m_scrollxmin(make_child_min(env, itemnode, "xscroll"))
+ , m_scrollymin(make_child_min(env, itemnode, "yscroll"))
+ , m_scrollxmax(make_child_max(env, itemnode, "xscroll", m_scrollxmask))
+ , m_scrollymax(make_child_max(env, itemnode, "yscroll", m_scrollymask))
, m_animshift(get_state_shift(m_animmask))
+ , m_scrollxshift(get_state_shift(m_scrollxmask))
+ , m_scrollyshift(get_state_shift(m_scrollymask))
, m_input_port(nullptr)
, m_input_field(nullptr)
, m_input_mask(env.get_attribute_int(itemnode, "inputmask", 0))
@@ -4531,11 +4664,15 @@ layout_view::item::item(
, m_visibility_mask(env.visibility_mask())
, m_id(env.get_attribute_string(itemnode, "id"))
, m_input_tag(make_input_tag(env, itemnode))
- , m_animinput_tag(make_animinput_tag(env, itemnode))
+ , m_animinput_tag(make_child_input_tag(env, itemnode, "animate"))
+ , m_scrollxinput_tag(make_child_input_tag(env, itemnode, "xscroll"))
+ , m_scrollyinput_tag(make_child_input_tag(env, itemnode, "yscroll"))
, m_rawbounds(make_bounds(env, itemnode, trans))
, m_have_output(!env.get_attribute_string(itemnode, "name").empty())
, m_input_raw(env.get_attribute_bool(itemnode, "inputraw", 0))
- , m_have_animoutput(!make_animoutput_tag(env, itemnode).empty())
+ , m_have_animoutput(!make_child_output_tag(env, itemnode, "animate").empty())
+ , m_have_scrollxoutput(!make_child_output_tag(env, itemnode, "xscroll").empty())
+ , m_have_scrollyoutput(!make_child_output_tag(env, itemnode, "yscroll").empty())
, m_has_clickthrough(!env.get_attribute_string(itemnode, "clickthrough").empty())
{
// fetch common data
@@ -4562,6 +4699,14 @@ layout_view::item::item(
{
throw layout_syntax_error(util::string_format("item of type %s requires an element tag", itemnode.get_name()));
}
+ else if (m_scrollxmin == m_scrollxmax)
+ {
+ throw layout_syntax_error(util::string_format("item X scroll minimum and maximum both equal to %u", m_scrollxmin));
+ }
+ else if (m_scrollymin == m_scrollymax)
+ {
+ throw layout_syntax_error(util::string_format("item Y scroll minimum and maximum both equal to %u", m_scrollymin));
+ }
// this can be called before resolving tags, make it return something valid
m_bounds = m_rawbounds;
@@ -4570,10 +4715,10 @@ layout_view::item::item(
//-------------------------------------------------
-// item - destructor
+// layout_view_item - destructor
//-------------------------------------------------
-layout_view::item::~item()
+layout_view_item::~layout_view_item()
{
}
@@ -4583,7 +4728,7 @@ layout_view::item::~item()
// obtain element state value
//-------------------------------------------------
-void layout_view::item::set_element_state_callback(state_delegate &&handler)
+void layout_view_item::set_element_state_callback(state_delegate &&handler)
{
if (!handler.isnull())
m_get_elem_state = std::move(handler);
@@ -4597,7 +4742,7 @@ void layout_view::item::set_element_state_callback(state_delegate &&handler)
// obtain animation state
//-------------------------------------------------
-void layout_view::item::set_animation_state_callback(state_delegate &&handler)
+void layout_view_item::set_animation_state_callback(state_delegate &&handler)
{
if (!handler.isnull())
m_get_anim_state = std::move(handler);
@@ -4611,7 +4756,7 @@ void layout_view::item::set_animation_state_callback(state_delegate &&handler)
// bounds
//-------------------------------------------------
-void layout_view::item::set_bounds_callback(bounds_delegate &&handler)
+void layout_view_item::set_bounds_callback(bounds_delegate &&handler)
{
if (!handler.isnull())
m_get_bounds = std::move(handler);
@@ -4625,7 +4770,7 @@ void layout_view::item::set_bounds_callback(bounds_delegate &&handler)
// color
//-------------------------------------------------
-void layout_view::item::set_color_callback(color_delegate &&handler)
+void layout_view_item::set_color_callback(color_delegate &&handler)
{
if (!handler.isnull())
m_get_color = std::move(handler);
@@ -4635,10 +4780,66 @@ void layout_view::item::set_color_callback(color_delegate &&handler)
//-------------------------------------------------
+// set_scroll_size_x_callback - set callback to
+// obtain horizontal scroll window size
+//-------------------------------------------------
+
+void layout_view_item::set_scroll_size_x_callback(scroll_size_delegate &&handler)
+{
+ if (!handler.isnull())
+ m_get_scroll_size_x = std::move(handler);
+ else
+ m_get_scroll_size_x = default_get_scroll_size_x();
+}
+
+
+//-------------------------------------------------
+// set_scroll_size_y_callback - set callback to
+// obtain vertical scroll window size
+//-------------------------------------------------
+
+void layout_view_item::set_scroll_size_y_callback(scroll_size_delegate &&handler)
+{
+ if (!handler.isnull())
+ m_get_scroll_size_y = std::move(handler);
+ else
+ m_get_scroll_size_y = default_get_scroll_size_y();
+}
+
+
+//-------------------------------------------------
+// set_scroll_pos_x_callback - set callback to
+// obtain horizontal scroll position
+//-------------------------------------------------
+
+void layout_view_item::set_scroll_pos_x_callback(scroll_pos_delegate &&handler)
+{
+ if (!handler.isnull())
+ m_get_scroll_pos_x = std::move(handler);
+ else
+ m_get_scroll_pos_x = default_get_scroll_pos_x();
+}
+
+
+//-------------------------------------------------
+// set_scroll_pos_y_callback - set callback to
+// obtain vertical scroll position
+//-------------------------------------------------
+
+void layout_view_item::set_scroll_pos_y_callback(scroll_pos_delegate &&handler)
+{
+ if (!handler.isnull())
+ m_get_scroll_pos_y = std::move(handler);
+ else
+ m_get_scroll_pos_y = default_get_scroll_pos_y();
+}
+
+
+//-------------------------------------------------
// resolve_tags - resolve tags, if any are set
//-------------------------------------------------
-void layout_view::item::resolve_tags()
+void layout_view_item::resolve_tags()
{
// resolve element state output and set default value
if (m_have_output)
@@ -4648,13 +4849,21 @@ void layout_view::item::resolve_tags()
m_output = m_element->default_state();
}
- // resolve animation state output
+ // resolve animation state and scroll outputs
if (m_have_animoutput)
m_animoutput.resolve();
+ if (m_have_scrollxoutput)
+ m_scrollxoutput.resolve();
+ if (m_have_scrollyoutput)
+ m_scrollyoutput.resolve();
- // resolve animation state input
+ // resolve animation state and scroll inputs
if (!m_animinput_tag.empty())
m_animinput_port = m_element->machine().root_device().ioport(m_animinput_tag);
+ if (!m_scrollxinput_tag.empty())
+ m_scrollxinput_port = m_element->machine().root_device().ioport(m_scrollxinput_tag);
+ if (!m_scrollyinput_tag.empty())
+ m_scrollyinput_port = m_element->machine().root_device().ioport(m_scrollyinput_tag);
// resolve element state input
if (!m_input_tag.empty())
@@ -4684,6 +4893,10 @@ void layout_view::item::resolve_tags()
m_get_anim_state = default_get_anim_state();
m_get_bounds = default_get_bounds();
m_get_color = default_get_color();
+ m_get_scroll_size_x = default_get_scroll_size_x();
+ m_get_scroll_size_y = default_get_scroll_size_y();
+ m_get_scroll_pos_x = default_get_scroll_pos_x();
+ m_get_scroll_pos_y = default_get_scroll_pos_y();
}
@@ -4692,18 +4905,18 @@ void layout_view::item::resolve_tags()
// state handler
//-------------------------------------------------
-layout_view::item::state_delegate layout_view::item::default_get_elem_state()
+layout_view_item::state_delegate layout_view_item::default_get_elem_state()
{
if (m_have_output)
- return state_delegate(&item::get_output, this);
+ return state_delegate(&layout_view_item::get_output, this);
else if (!m_input_port)
- return state_delegate(&item::get_state, this);
+ return state_delegate(&layout_view_item::get_state, this);
else if (m_input_raw)
- return state_delegate(&item::get_input_raw, this);
+ return state_delegate(&layout_view_item::get_input_raw, this);
else if (m_input_field)
- return state_delegate(&item::get_input_field_cached, this);
+ return state_delegate(&layout_view_item::get_input_field_cached, this);
else
- return state_delegate(&item::get_input_field_conditional, this);
+ return state_delegate(&layout_view_item::get_input_field_conditional, this);
}
@@ -4712,12 +4925,12 @@ layout_view::item::state_delegate layout_view::item::default_get_elem_state()
// state handler
//-------------------------------------------------
-layout_view::item::state_delegate layout_view::item::default_get_anim_state()
+layout_view_item::state_delegate layout_view_item::default_get_anim_state()
{
if (m_have_animoutput)
- return state_delegate(&item::get_anim_output, this);
+ return state_delegate(&layout_view_item::get_anim_output, this);
else if (m_animinput_port)
- return state_delegate(&item::get_anim_input, this);
+ return state_delegate(&layout_view_item::get_anim_input, this);
else
return default_get_elem_state();
}
@@ -4727,11 +4940,11 @@ layout_view::item::state_delegate layout_view::item::default_get_anim_state()
// default_get_bounds - get default bounds handler
//-------------------------------------------------
-layout_view::item::bounds_delegate layout_view::item::default_get_bounds()
+layout_view_item::bounds_delegate layout_view_item::default_get_bounds()
{
return (m_bounds.size() == 1U)
? bounds_delegate(&emu::render::detail::bounds_step::get, &m_bounds.front())
- : bounds_delegate(&item::get_interpolated_bounds, this);
+ : bounds_delegate(&layout_view_item::get_interpolated_bounds, this);
}
@@ -4739,11 +4952,65 @@ layout_view::item::bounds_delegate layout_view::item::default_get_bounds()
// default_get_color - get default color handler
//-------------------------------------------------
-layout_view::item::color_delegate layout_view::item::default_get_color()
+layout_view_item::color_delegate layout_view_item::default_get_color()
{
return (m_color.size() == 1U)
? color_delegate(&emu::render::detail::color_step::get, &const_cast<emu::render::detail::color_step &>(m_color.front()))
- : color_delegate(&item::get_interpolated_color, this);
+ : color_delegate(&layout_view_item::get_interpolated_color, this);
+}
+
+
+//-------------------------------------------------
+// default_get_scroll_size_x - get default
+// horizontal scroll window size handler
+//-------------------------------------------------
+
+layout_view_item::scroll_size_delegate layout_view_item::default_get_scroll_size_x()
+{
+ return scroll_size_delegate(&layout_view_item::get_scrollsizex, this);
+}
+
+
+//-------------------------------------------------
+// default_get_scroll_size_y - get default
+// vertical scroll window size handler
+//-------------------------------------------------
+
+layout_view_item::scroll_size_delegate layout_view_item::default_get_scroll_size_y()
+{
+ return scroll_size_delegate(&layout_view_item::get_scrollsizey, this);
+}
+
+
+//-------------------------------------------------
+// default_get_scroll_pos_x - get default
+// horizontal scroll position handler
+//-------------------------------------------------
+
+layout_view_item::scroll_pos_delegate layout_view_item::default_get_scroll_pos_x()
+{
+ if (m_have_scrollxoutput)
+ return scroll_pos_delegate(m_scrollwrapx ? &layout_view_item::get_scrollx_output<true> : &layout_view_item::get_scrollx_output<false>, this);
+ else if (m_scrollxinput_port)
+ return scroll_pos_delegate(m_scrollwrapx ? &layout_view_item::get_scrollx_input<true> : &layout_view_item::get_scrollx_input<false>, this);
+ else
+ return scroll_pos_delegate(&layout_view_item::get_scrollposx, this);
+}
+
+
+//-------------------------------------------------
+// default_get_scroll_pos_y - get default
+// vertical scroll position handler
+//-------------------------------------------------
+
+layout_view_item::scroll_pos_delegate layout_view_item::default_get_scroll_pos_y()
+{
+ if (m_have_scrollyoutput)
+ return scroll_pos_delegate(m_scrollwrapy ? &layout_view_item::get_scrolly_output<true> : &layout_view_item::get_scrolly_output<false>, this);
+ else if (m_scrollyinput_port)
+ return scroll_pos_delegate(m_scrollwrapy ? &layout_view_item::get_scrolly_input<true> : &layout_view_item::get_scrolly_input<false>, this);
+ else
+ return scroll_pos_delegate(&layout_view_item::get_scrollposy, this);
}
@@ -4751,7 +5018,7 @@ layout_view::item::color_delegate layout_view::item::default_get_color()
// get_state - get state when no bindings
//-------------------------------------------------
-int layout_view::item::get_state() const
+int layout_view_item::get_state() const
{
return m_elem_state;
}
@@ -4761,7 +5028,7 @@ int layout_view::item::get_state() const
// get_output - get element state output
//-------------------------------------------------
-int layout_view::item::get_output() const
+int layout_view_item::get_output() const
{
assert(m_have_output);
return int(s32(m_output));
@@ -4772,7 +5039,7 @@ int layout_view::item::get_output() const
// get_input_raw - get element state input
//-------------------------------------------------
-int layout_view::item::get_input_raw() const
+int layout_view_item::get_input_raw() const
{
assert(m_input_port);
return int(std::make_signed_t<ioport_value>((m_input_port->read() & m_input_mask) >> m_input_shift));
@@ -4783,7 +5050,7 @@ int layout_view::item::get_input_raw() const
// get_input_field_cached - element state
//-------------------------------------------------
-int layout_view::item::get_input_field_cached() const
+int layout_view_item::get_input_field_cached() const
{
assert(m_input_port);
assert(m_input_field);
@@ -4795,7 +5062,7 @@ int layout_view::item::get_input_field_cached() const
// get_input_field_conditional - element state
//-------------------------------------------------
-int layout_view::item::get_input_field_conditional() const
+int layout_view_item::get_input_field_conditional() const
{
assert(m_input_port);
assert(!m_input_field);
@@ -4808,7 +5075,7 @@ int layout_view::item::get_input_field_conditional() const
// get_anim_output - get animation output
//-------------------------------------------------
-int layout_view::item::get_anim_output() const
+int layout_view_item::get_anim_output() const
{
assert(m_have_animoutput);
return int(unsigned((u32(s32(m_animoutput) & m_animmask) >> m_animshift)));
@@ -4819,7 +5086,7 @@ int layout_view::item::get_anim_output() const
// get_anim_input - get animation input
//-------------------------------------------------
-int layout_view::item::get_anim_input() const
+int layout_view_item::get_anim_input() const
{
assert(m_animinput_port);
return int(std::make_signed_t<ioport_value>((m_animinput_port->read() & m_animmask) >> m_animshift));
@@ -4827,10 +5094,113 @@ int layout_view::item::get_anim_input() const
//-------------------------------------------------
+// get_scrollsizex - get horizontal scroll window
+// size
+//-------------------------------------------------
+
+float layout_view_item::get_scrollsizex() const
+{
+ return m_scrollsizex;
+}
+
+
+//-------------------------------------------------
+// get_scrollsizey - get vertical scroll window
+// size
+//-------------------------------------------------
+
+float layout_view_item::get_scrollsizey() const
+{
+ return m_scrollsizey;
+}
+
+
+//-------------------------------------------------
+// get_scrollposx - get horizontal scroll
+// position
+//-------------------------------------------------
+
+float layout_view_item::get_scrollposx() const
+{
+ return m_scrollposx;
+}
+
+
+//-------------------------------------------------
+// get_scrollposy - get vertical scroll position
+//-------------------------------------------------
+
+float layout_view_item::get_scrollposy() const
+{
+ return m_scrollposy;
+}
+
+
+//-------------------------------------------------
+// get_scrollx_output - get scaled horizontal
+// scroll output
+//-------------------------------------------------
+
+template <bool Wrap>
+float layout_view_item::get_scrollx_output() const
+{
+ assert(m_have_scrollxoutput);
+ u32 const unscaled(((u32(s32(m_scrollxoutput)) & m_scrollxmask) >> m_scrollxshift) - m_scrollxmin);
+ float const range(std::make_signed_t<ioport_value>(m_scrollxmax - m_scrollxmin) + (!Wrap ? 0 : (m_scrollxmin < m_scrollxmax) ? 1 : -1));
+ return float(s32(unscaled)) / range;
+}
+
+
+//-------------------------------------------------
+// get_scrollx_input - get scaled horizontal
+// scroll input
+//-------------------------------------------------
+
+template <bool Wrap>
+float layout_view_item::get_scrollx_input() const
+{
+ assert(m_scrollxinput_port);
+ ioport_value const unscaled(((m_scrollxinput_port->read() & m_scrollxmask) >> m_scrollxshift) - m_scrollxmin);
+ float const range(std::make_signed_t<ioport_value>(m_scrollxmax - m_scrollxmin) + (!Wrap ? 0 : (m_scrollxmin < m_scrollxmax) ? 1 : -1));
+ return float(std::make_signed_t<ioport_value>(unscaled)) / range;
+}
+
+
+//-------------------------------------------------
+// get_scrolly_output - get scaled vertical
+// scroll output
+//-------------------------------------------------
+
+template <bool Wrap>
+float layout_view_item::get_scrolly_output() const
+{
+ assert(m_have_scrollyoutput);
+ u32 const unscaled(((u32(s32(m_scrollyoutput)) & m_scrollymask) >> m_scrollyshift) - m_scrollymin);
+ float const range(std::make_signed_t<ioport_value>(m_scrollymax - m_scrollymin) + (!Wrap ? 0 : (m_scrollymin < m_scrollymax) ? 1 : -1));
+ return float(s32(unscaled)) / range;
+}
+
+
+//-------------------------------------------------
+// get_scrolly_input - get scaled vertical scroll
+// input
+//-------------------------------------------------
+
+template <bool Wrap>
+float layout_view_item::get_scrolly_input() const
+{
+ assert(m_scrollyinput_port);
+ ioport_value const unscaled(((m_scrollyinput_port->read() & m_scrollymask) >> m_scrollyshift) - m_scrollymin);
+ float const range(std::make_signed_t<ioport_value>(m_scrollymax - m_scrollymin) + (!Wrap ? 0 : (m_scrollymin < m_scrollymax) ? 1 : -1));
+ return float(std::make_signed_t<ioport_value>(unscaled)) / range;
+}
+
+
+//-------------------------------------------------
// get_interpolated_bounds - animated bounds
//-------------------------------------------------
-render_bounds layout_view::item::get_interpolated_bounds() const
+render_bounds layout_view_item::get_interpolated_bounds() const
{
assert(m_bounds.size() > 1U);
return interpolate_bounds(m_bounds, m_get_anim_state());
@@ -4841,7 +5211,7 @@ render_bounds layout_view::item::get_interpolated_bounds() const
// get_interpolated_color - animated color
//-------------------------------------------------
-render_color layout_view::item::get_interpolated_color() const
+render_color layout_view_item::get_interpolated_color() const
{
assert(m_color.size() > 1U);
return interpolate_color(m_color, m_get_anim_state());
@@ -4852,7 +5222,7 @@ render_color layout_view::item::get_interpolated_color() const
// find_element - find element definition
//-------------------------------------------------
-layout_element *layout_view::item::find_element(view_environment &env, util::xml::data_node const &itemnode, element_map &elemmap)
+layout_element *layout_view_item::find_element(view_environment &env, util::xml::data_node const &itemnode, element_map &elemmap)
{
std::string const name(env.get_attribute_string(itemnode, !strcmp(itemnode.get_name(), "element") ? "ref" : "element"));
if (name.empty())
@@ -4871,7 +5241,7 @@ layout_element *layout_view::item::find_element(view_environment &env, util::xml
// make_bounds - get transformed bounds
//-------------------------------------------------
-layout_view::item::bounds_vector layout_view::item::make_bounds(
+layout_view_item::bounds_vector layout_view_item::make_bounds(
view_environment &env,
util::xml::data_node const &itemnode,
layout_group::transform const &trans)
@@ -4904,7 +5274,7 @@ layout_view::item::bounds_vector layout_view::item::make_bounds(
// make_color - get color inflection points
//-------------------------------------------------
-layout_view::item::color_vector layout_view::item::make_color(
+layout_view_item::color_vector layout_view_item::make_color(
view_environment &env,
util::xml::data_node const &itemnode,
render_color const &mult)
@@ -4934,101 +5304,6 @@ layout_view::item::color_vector layout_view::item::make_color(
}
-//-------------------------------------------------
-// make_animoutput_tag - get animation output tag
-//-------------------------------------------------
-
-std::string layout_view::item::make_animoutput_tag(view_environment &env, util::xml::data_node const &itemnode)
-{
- util::xml::data_node const *const animate(itemnode.get_child("animate"));
- if (animate)
- return std::string(env.get_attribute_string(*animate, "name"));
- else
- return std::string();
-}
-
-
-//-------------------------------------------------
-// make_animmask - get animation state mask
-//-------------------------------------------------
-
-ioport_value layout_view::item::make_animmask(view_environment &env, util::xml::data_node const &itemnode)
-{
- util::xml::data_node const *const animate(itemnode.get_child("animate"));
- return animate ? env.get_attribute_int(*animate, "mask", ~ioport_value(0)) : ~ioport_value(0);
-}
-
-
-//-------------------------------------------------
-// make_animinput_tag - get absolute tag for
-// animation input
-//-------------------------------------------------
-
-std::string layout_view::item::make_animinput_tag(view_environment &env, util::xml::data_node const &itemnode)
-{
- util::xml::data_node const *const animate(itemnode.get_child("animate"));
- return animate ? env.get_attribute_subtag(*animate, "inputtag") : std::string();
-}
-
-
-//-------------------------------------------------
-// make_input_tag - get absolute input tag
-//-------------------------------------------------
-
-std::string layout_view::item::make_input_tag(view_environment &env, util::xml::data_node const &itemnode)
-{
- return env.get_attribute_subtag(itemnode, "inputtag");
-}
-
-
-//-------------------------------------------------
-// get_blend_mode - explicit or implicit blend
-//-------------------------------------------------
-
-int layout_view::item::get_blend_mode(view_environment &env, util::xml::data_node const &itemnode)
-{
- // see if there's a blend mode attribute
- std::string const *const mode(itemnode.get_attribute_string_ptr("blend"));
- if (mode)
- {
- if (*mode == "none")
- return BLENDMODE_NONE;
- else if (*mode == "alpha")
- return BLENDMODE_ALPHA;
- else if (*mode == "multiply")
- return BLENDMODE_RGB_MULTIPLY;
- else if (*mode == "add")
- return BLENDMODE_ADD;
- else
- throw layout_syntax_error(util::string_format("unknown blend mode %s", *mode));
- }
-
- // fall back to implicit blend mode based on element type
- if (!strcmp(itemnode.get_name(), "screen"))
- return -1; // magic number recognised by render.cpp to allow per-element blend mode
- else if (!strcmp(itemnode.get_name(), "overlay"))
- return BLENDMODE_RGB_MULTIPLY;
- else
- return BLENDMODE_ALPHA;
-}
-
-
-//-------------------------------------------------
-// get_state_shift - shift to right-align LSB
-//-------------------------------------------------
-
-unsigned layout_view::item::get_state_shift(ioport_value mask)
-{
- unsigned result(0U);
- while (mask && !BIT(mask, 0))
- {
- ++result;
- mask >>= 1;
- }
- return result;
-}
-
-
//**************************************************************************
// LAYOUT VIEW VISIBILITY TOGGLE