-emu/rendlay.cpp: Allow item animation.

-cgang.cpp: Make internal artwork more fun.
This commit is contained in:
Vas Crabb 2020-10-05 00:18:33 +11:00
parent e5d69d1edb
commit 0c8938f584
6 changed files with 445 additions and 461 deletions

View File

@ -291,11 +291,11 @@ class LayoutChecker(Minifyer):
self.have_bounds.append({ })
self.have_color.append({ })
def startObject(self):
def startObject(self, name):
self.handlers.append((self.objectStartHandler, self.objectEndHandler))
self.have_bounds.append(None)
self.have_bounds.append(None if 'group' == name else { })
self.have_orientation.append(False)
self.have_color.append(None)
self.have_color.append(None if 'group' == name else { })
def rootStartHandler(self, name, attrs):
if 'mamelayout' != name:
@ -499,7 +499,7 @@ class LayoutChecker(Minifyer):
if (inputmask is not None) and (0 == inputmask):
if (inputraw is None) or (0 == inputraw):
self.handleError('Element %s attribute inputmask "%s" is zero' % (name, attrs['inputmask']))
self.startObject();
self.startObject(name)
elif 'screen' == name:
if 'index' in attrs:
index = self.checkIntAttribute(name, attrs, 'index', None)
@ -512,7 +512,7 @@ class LayoutChecker(Minifyer):
self.checkTag(tag, name, 'tag')
if self.BADTAGPATTERN.search(tag):
self.handleError('Element screen attribute tag "%s" contains invalid characters' % (tag, ))
self.startObject();
self.startObject(name)
elif 'group' == name:
if 'ref' not in attrs:
self.handleError('Element group missing attribute ref')
@ -525,7 +525,7 @@ class LayoutChecker(Minifyer):
self.current_collections[n] = l
else:
self.handleError('Element group instantiates collection with duplicate name "%s" from %s (previous %s)' % (n, l, self.current_collections[n]))
self.startObject();
self.startObject(name)
elif 'repeat' == name:
if 'count' not in attrs:
self.handleError('Element repeat missing attribute count')
@ -579,18 +579,36 @@ class LayoutChecker(Minifyer):
def objectStartHandler(self, name, attrs):
if 'bounds' == name:
if self.have_bounds[-1] is not None:
self.handleError('Duplicate element bounds (previous %s)' % (self.have_bounds[-1], ))
else:
if self.have_bounds[-1] is None:
self.have_bounds[-1] = self.formatLocation()
elif isinstance(self.have_bounds[-1], dict):
state = self.checkIntAttribute(name, attrs, 'state', 0)
if state is not None:
if 0 > state:
self.handleError('Element bounds attribute state "%s" is negative' % (attrs['state'], ))
if state in self.have_bounds[-1]:
self.handleError('Duplicate bounds for state %d (previous %s)' % (state, self.have_bounds[-1][state]))
else:
self.have_bounds[-1][state] = self.formatLocation()
else:
self.handleError('Duplicate element bounds (previous %s)' % (self.have_bounds[-1], ))
self.checkBounds(attrs)
elif 'orientation' == name:
self.checkOrientation(attrs)
if 'color' == name:
if self.have_color[-1] is not None:
self.handleError('Duplicate element color (previous %s)' % (self.have_color[-1], ))
else:
if self.have_color[-1] is None:
self.have_color[-1] = self.formatLocation()
elif isinstance(self.have_color[-1], dict):
state = self.checkIntAttribute(name, attrs, 'state', 0)
if state is not None:
if 0 > state:
self.handleError('Element color attribute state "%s" is negative' % (attrs['state'], ))
if state in self.have_color[-1]:
self.handleError('Duplicate color for state %d (previous %s)' % (state, self.have_color[-1][state]))
else:
self.have_color[-1][state] = self.formatLocation()
else:
self.handleError('Duplicate element color (previous %s)' % (self.have_color[-1], ))
self.checkColor(attrs)
self.ignored_depth = 1

View File

@ -1356,10 +1356,7 @@ render_primitive_list &render_target::get_primitives()
item_xform.yoffs = root_xform.yoffs + bounds.y0 * root_xform.yscale;
item_xform.xscale = (bounds.x1 - bounds.x0) * root_xform.xscale;
item_xform.yscale = (bounds.y1 - bounds.y0) * root_xform.yscale;
item_xform.color.r = curitem.color().r * root_xform.color.r;
item_xform.color.g = curitem.color().g * root_xform.color.g;
item_xform.color.b = curitem.color().b * root_xform.color.b;
item_xform.color.a = curitem.color().a * root_xform.color.a;
item_xform.color = curitem.color() * root_xform.color;
item_xform.orientation = orientation_add(curitem.orientation(), root_xform.orientation);
item_xform.no_center = false;
@ -1474,11 +1471,12 @@ bool render_target::map_point_container(s32 target_x, s32 target_y, render_conta
if (items.end() != found)
{
layout_view::item &item(*found);
if (item.bounds().includes(target_f.first, target_f.second))
render_bounds const bounds(item.bounds());
if (bounds.includes(target_f.first, target_f.second))
{
// point successfully mapped
container_x = (target_f.first - item.bounds().x0) / item.bounds().width();
container_y = (target_f.second - item.bounds().y0) / item.bounds().height();
container_x = (target_f.first - bounds.x0) / bounds.width();
container_y = (target_f.second - bounds.y0) / bounds.height();
return true;
}
}
@ -1531,17 +1529,21 @@ bool render_target::map_point_input(s32 target_x, s32 target_y, ioport_port *&in
if (m_hit_test[i] && m_hit_test[items.size() + i])
{
layout_view::item &item(items[i]);
if (item.has_input())
render_bounds const bounds(item.bounds());
if (bounds.includes(target_f.first, target_f.second))
{
// point successfully mapped
input_port = item.input_tag_and_mask(input_mask);
input_x = (target_f.first - item.bounds().x0) / item.bounds().width();
input_y = (target_f.second - item.bounds().y0) / item.bounds().height();
return true;
}
else
{
break;
if (item.has_input())
{
// point successfully mapped
input_port = item.input_tag_and_mask(input_mask);
input_x = (target_f.first - bounds.x0) / bounds.width();
input_y = (target_f.second - bounds.y0) / bounds.height();
return true;
}
else
{
break;
}
}
}
}

View File

@ -61,14 +61,6 @@
#include <vector>
namespace emu { namespace render { namespace detail {
class layout_environment;
class view_environment;
} } } // namespace emu::render::detail
//**************************************************************************
// CONSTANTS
//**************************************************************************
@ -196,6 +188,20 @@ struct render_color
float r; // red component (0.0 = none, 1.0 = max)
float g; // green component (0.0 = none, 1.0 = max)
float b; // blue component (0.0 = none, 1.0 = max)
constexpr render_color operator*(render_color const &c) const
{
return render_color{ a * c.a, r * c.r, g * c.g, b * c.b };
}
render_color &operator*=(render_color const &c)
{
a *= c.a;
r *= c.r;
g *= c.g;
b *= c.b;
return *this;
}
};
@ -232,6 +238,31 @@ struct render_texinfo
};
namespace emu { namespace render { namespace detail {
struct bounds_step
{
int state;
render_bounds bounds;
render_bounds delta;
};
using bounds_vector = std::vector<bounds_step>;
struct color_step
{
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
@ -585,22 +616,6 @@ public:
void preload();
private:
struct bounds_step
{
int state;
render_bounds bounds;
render_bounds delta;
};
using bounds_vector = std::vector<bounds_step>;
struct color_step
{
int state;
render_color color;
render_color delta;
};
using color_vector = std::vector<color_step>;
/// \brief An image, rectangle, or disk in an element
///
/// Each layout_element contains one or more components. Each
@ -649,6 +664,9 @@ private:
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
@ -791,12 +809,12 @@ public:
// getters
layout_element *element() const { return m_element; }
screen_device *screen() { return m_screen; }
const render_bounds &bounds() const { return m_bounds; }
const render_color &color() const { return m_color; }
render_bounds bounds() const;
render_color color() const;
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(running_machine &machine) const;
render_container *screen_container() const { return m_screen ? &m_screen->container() : nullptr; }
// interactivity
bool has_input() const { return bool(m_input_port); }
@ -810,8 +828,13 @@ public:
void resolve_tags();
private:
using bounds_vector = emu::render::detail::bounds_vector;
using color_vector = emu::render::detail::color_vector;
static layout_element *find_element(view_environment &env, util::xml::data_node const &itemnode, element_map &elemmap);
static render_bounds make_bounds(view_environment &env, util::xml::data_node const &itemnode, layout_group::transform const &trans);
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_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_input_shift(ioport_value mask);
@ -819,7 +842,9 @@ public:
// internal state
layout_element *const m_element; // pointer to the associated element (non-screens only)
output_finder<> m_output; // associated output
output_finder<> m_animoutput; // associated output for animation if different
bool const m_have_output; // whether we actually have an output
bool const m_have_animoutput; // whether we actually have an output for animation
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
@ -828,14 +853,14 @@ public:
bool m_clickthrough; // should click pass through to lower elements
screen_device * m_screen; // pointer to screen
int m_orientation; // orientation of this item
render_bounds m_bounds; // bounds of the item
render_color m_color; // color of the 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_input_tag; // input tag of this item
render_bounds const m_rawbounds; // raw (original) bounds of the item
bounds_vector const m_rawbounds; // raw (original) bounds of the item
bool const m_has_clickthrough; // whether clickthrough was explicitly configured
};
using item_list = std::list<item>;

View File

@ -78,8 +78,6 @@ enum
LINE_CAP_END = 2
};
std::locale const f_portable_locale("C");
constexpr layout_group::transform identity_transform{{ {{ 1.0F, 0.0F, 0.0F }}, {{ 0.0F, 1.0F, 0.0F }}, {{ 0.0F, 0.0F, 1.0F }} }};
@ -97,11 +95,6 @@ inline void render_bounds_transform(render_bounds &bounds, layout_group::transfo
(bounds.x1 * trans[1][0]) + (bounds.y1 * trans[1][1]) + trans[1][2] };
}
constexpr render_color render_color_multiply(render_color const &x, render_color const &y)
{
return render_color{ x.a * y.a, x.r * y.r, x.g * y.g, x.b * y.b };
}
//**************************************************************************
@ -214,7 +207,7 @@ private:
if (m_text_valid && !m_float_valid)
{
std::istringstream stream(m_text);
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
if (m_text[0] == '$')
{
stream.get();
@ -250,7 +243,7 @@ private:
if (m_text_valid && !m_int_valid && !m_float_valid)
{
std::istringstream stream(m_text);
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
if (m_text[0] == '$')
{
stream.get();
@ -309,7 +302,7 @@ private:
if (m_text_valid && !m_int_valid)
{
std::istringstream stream(m_text);
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
if (m_text[0] == '$')
{
stream.get();
@ -531,7 +524,7 @@ private:
int parse_int(char const *begin, char const *end, int defvalue)
{
std::istringstream stream;
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
int result;
if (begin[0] == '$')
{
@ -661,7 +654,7 @@ public:
unsigned const decprefix((expanded.first[0] == '#') ? 1U : 0U);
bool const floatchars(std::find_if(expanded.first, expanded.second, [] (char ch) { return ('.' == ch) || ('e' == ch) || ('E' == ch); }) != expanded.second);
std::istringstream stream(std::string(expanded.first + hexprefix + decprefix, expanded.second));
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
if (!hexprefix && !decprefix && floatchars)
{
stream >> floatincrement;
@ -768,7 +761,7 @@ public:
// similar to what XML nodes do
std::pair<char const *, char const *> const expanded(expand(attrib));
std::istringstream stream(std::string(expanded.first, expanded.second));
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
float result;
return (stream >> result) ? result : defvalue;
}
@ -912,6 +905,175 @@ public:
} } } // namespace emu::render::detail
namespace {
bool add_bounds_step(emu::render::detail::layout_environment &env, emu::render::detail::bounds_vector &steps, util::xml::data_node const &node)
{
int const state(env.get_attribute_int(node, "state", 0));
auto const pos(
std::lower_bound(
steps.begin(),
steps.end(),
state,
[] (emu::render::detail::bounds_step const &lhs, int rhs) { return lhs.state < rhs; }));
if ((steps.end() != pos) && (state == pos->state))
return false;
auto &ins(*steps.emplace(pos, emu::render::detail::bounds_step{ state, { 0.0F, 0.0F, 0.0F, 0.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } }));
env.parse_bounds(&node, ins.bounds);
return true;
}
void set_bounds_deltas(emu::render::detail::bounds_vector &steps)
{
if (steps.empty())
{
steps.emplace_back(emu::render::detail::bounds_step{ 0, { 0.0F, 0.0F, 1.0F, 1.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } });
}
else
{
auto i(steps.begin());
auto j(i);
while (steps.end() != ++j)
{
assert(j->state > i->state);
i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state);
i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state);
i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state);
i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state);
i = j;
}
}
}
void normalize_bounds(emu::render::detail::bounds_vector &steps, float x0, float y0, float xoffs, float yoffs, float xscale, float yscale)
{
auto i(steps.begin());
i->bounds.x0 = x0 + (i->bounds.x0 - xoffs) * xscale;
i->bounds.x1 = x0 + (i->bounds.x1 - xoffs) * xscale;
i->bounds.y0 = y0 + (i->bounds.y0 - yoffs) * yscale;
i->bounds.y1 = y0 + (i->bounds.y1 - yoffs) * yscale;
auto j(i);
while (steps.end() != ++j)
{
j->bounds.x0 = x0 + (j->bounds.x0 - xoffs) * xscale;
j->bounds.x1 = x0 + (j->bounds.x1 - xoffs) * xscale;
j->bounds.y0 = y0 + (j->bounds.y0 - yoffs) * yscale;
j->bounds.y1 = y0 + (j->bounds.y1 - yoffs) * yscale;
i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state);
i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state);
i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state);
i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state);
i = j;
}
}
render_bounds accumulate_bounds(emu::render::detail::bounds_vector const &steps)
{
auto i(steps.begin());
render_bounds result(i->bounds);
while (steps.end() != ++i)
union_render_bounds(result, i->bounds);
return result;
}
inline render_bounds interpolate_bounds(emu::render::detail::bounds_vector const &steps, int state)
{
auto pos(
std::lower_bound(
steps.begin(),
steps.end(),
state,
[] (emu::render::detail::bounds_step const &lhs, int rhs) { return lhs.state < rhs; }));
if (steps.begin() == pos)
{
return pos->bounds;
}
else
{
--pos;
render_bounds result(pos->bounds);
result.x0 += pos->delta.x0 * (state - pos->state);
result.x1 += pos->delta.x1 * (state - pos->state);
result.y0 += pos->delta.y0 * (state - pos->state);
result.y1 += pos->delta.y1 * (state - pos->state);
return result;
}
}
bool add_color_step(emu::render::detail::layout_environment &env, emu::render::detail::color_vector &steps, util::xml::data_node const &node)
{
int const state(env.get_attribute_int(node, "state", 0));
auto const pos(
std::lower_bound(
steps.begin(),
steps.end(),
state,
[] (emu::render::detail::color_step const &lhs, int rhs) { return lhs.state < rhs; }));
if ((steps.end() != pos) && (state == pos->state))
return false;
steps.emplace(pos, emu::render::detail::color_step{ state, env.parse_color(&node), { 0.0F, 0.0F, 0.0F, 0.0F } });
return true;
}
void set_color_deltas(emu::render::detail::color_vector &steps)
{
if (steps.empty())
{
steps.emplace_back(emu::render::detail::color_step{ 0, { 1.0F, 1.0F, 1.0F, 1.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } });
}
else
{
auto i(steps.begin());
auto j(i);
while (steps.end() != ++j)
{
assert(j->state > i->state);
i->delta.a = (j->color.a - i->color.a) / (j->state - i->state);
i->delta.r = (j->color.r - i->color.r) / (j->state - i->state);
i->delta.g = (j->color.g - i->color.g) / (j->state - i->state);
i->delta.b = (j->color.b - i->color.b) / (j->state - i->state);
i = j;
}
}
}
inline render_color interpolate_color(emu::render::detail::color_vector const &steps, int state)
{
auto pos(
std::lower_bound(
steps.begin(),
steps.end(),
state,
[] (emu::render::detail::color_step const &lhs, int rhs) { return lhs.state < rhs; }));
if (steps.begin() == pos)
{
return pos->color;
}
else
{
--pos;
render_color result(pos->color);
result.a += pos->delta.a * (state - pos->state);
result.r += pos->delta.r * (state - pos->state);
result.g += pos->delta.g * (state - pos->state);
result.b += pos->delta.b * (state - pos->state);
return result;
}
}
} // anonymous namespace
//**************************************************************************
// LAYOUT ELEMENT
@ -1178,7 +1340,18 @@ void layout_group::resolve_bounds(
!strcmp(itemnode->get_name(), "marquee"))
{
render_bounds itembounds;
env.parse_bounds(itemnode->get_child("bounds"), itembounds);
util::xml::data_node const *boundsnode = itemnode->get_child("bounds");
env.parse_bounds(boundsnode, itembounds);
while (boundsnode)
{
boundsnode = boundsnode->get_next_sibling("bounds");
if (boundsnode)
{
render_bounds b;
env.parse_bounds(boundsnode, b);
union_render_bounds(itembounds, b);
}
}
if (empty)
m_bounds = itembounds;
else
@ -2829,84 +3002,27 @@ layout_element::component::component(environment &env, util::xml::data_node cons
{
if (!strcmp(child->get_name(), "bounds"))
{
int const state(env.get_attribute_int(*child, "state", 0));
auto const pos(
std::lower_bound(
m_bounds.begin(),
m_bounds.end(),
state,
[] (bounds_step const &lhs, int rhs) { return lhs.state < rhs; }));
if ((m_bounds.end() != pos) && (state == pos->state))
if (!add_bounds_step(env, m_bounds, *child))
{
throw layout_syntax_error(
util::string_format(
"%s component has duplicate bounds for state %d",
compnode.get_name(),
state));
"%s component has duplicate bounds for state",
compnode.get_name()));
}
bounds_step &ins(*m_bounds.emplace(pos, bounds_step{ state, { 0.0F, 0.0F, 0.0F, 0.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } }));
env.parse_bounds(child, ins.bounds);
}
else if (!strcmp(child->get_name(), "color"))
{
int const state(env.get_attribute_int(*child, "state", 0));
auto const pos(
std::lower_bound(
m_color.begin(),
m_color.end(),
state,
[] (color_step const &lhs, int rhs) { return lhs.state < rhs; }));
if ((m_color.end() != pos) && (state == pos->state))
if (!add_color_step(env, m_color, *child))
{
throw layout_syntax_error(
util::string_format(
"%s component has duplicate color for state %d",
compnode.get_name(),
state));
"%s component has duplicate color for state",
compnode.get_name()));
}
m_color.emplace(pos, color_step{ state, env.parse_color(child), { 0.0F, 0.0F, 0.0F, 0.0F } });
}
}
if (m_bounds.empty())
{
m_bounds.emplace_back(bounds_step{ 0, { 0.0F, 0.0F, 1.0F, 1.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } });
}
else
{
auto i(m_bounds.begin());
auto j(i);
while (m_bounds.end() != ++j)
{
assert(j->state > i->state);
i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state);
i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state);
i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state);
i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state);
i = j;
}
}
if (m_color.empty())
{
m_color.emplace_back(color_step{ 0, { 1.0F, 1.0F, 1.0F, 1.0F }, { 0.0F, 0.0F, 0.0F, 0.0F } });
}
else
{
auto i(m_color.begin());
auto j(i);
while (m_color.end() != ++j)
{
assert(j->state > i->state);
i->delta.a = (j->color.a - i->color.a) / (j->state - i->state);
i->delta.r = (j->color.r - i->color.r) / (j->state - i->state);
i->delta.g = (j->color.g - i->color.g) / (j->state - i->state);
i->delta.b = (j->color.b - i->color.b) / (j->state - i->state);
i = j;
}
}
set_bounds_deltas(m_bounds);
set_color_deltas(m_color);
}
@ -2916,27 +3032,7 @@ layout_element::component::component(environment &env, util::xml::data_node cons
void layout_element::component::normalize_bounds(float xoffs, float yoffs, float xscale, float yscale)
{
auto i(m_bounds.begin());
i->bounds.x0 = (i->bounds.x0 - xoffs) * xscale;
i->bounds.x1 = (i->bounds.x1 - xoffs) * xscale;
i->bounds.y0 = (i->bounds.y0 - yoffs) * yscale;
i->bounds.y1 = (i->bounds.y1 - yoffs) * yscale;
auto j(i);
while (m_bounds.end() != ++j)
{
j->bounds.x0 = (j->bounds.x0 - xoffs) * xscale;
j->bounds.x1 = (j->bounds.x1 - xoffs) * xscale;
j->bounds.y0 = (j->bounds.y0 - yoffs) * yscale;
j->bounds.y1 = (j->bounds.y1 - yoffs) * yscale;
i->delta.x0 = (j->bounds.x0 - i->bounds.x0) / (j->state - i->state);
i->delta.x1 = (j->bounds.x1 - i->bounds.x1) / (j->state - i->state);
i->delta.y0 = (j->bounds.y0 - i->bounds.y0) / (j->state - i->state);
i->delta.y1 = (j->bounds.y1 - i->bounds.y1) / (j->state - i->state);
i = j;
}
::normalize_bounds(m_bounds, 0.0F, 0.0F, xoffs, yoffs, xscale, yscale);
}
@ -2989,11 +3085,7 @@ std::pair<int, bool> layout_element::component::statewrap() const
render_bounds layout_element::component::overall_bounds() const
{
auto i(m_bounds.begin());
render_bounds result(i->bounds);
while (m_bounds.end() != ++i)
union_render_bounds(result, i->bounds);
return result;
return accumulate_bounds(m_bounds);
}
@ -3003,26 +3095,7 @@ render_bounds layout_element::component::overall_bounds() const
render_bounds layout_element::component::bounds(int state) const
{
auto pos(
std::lower_bound(
m_bounds.begin(),
m_bounds.end(),
state,
[] (bounds_step const &lhs, int rhs) { return lhs.state < rhs; }));
if (m_bounds.begin() == pos)
{
return pos->bounds;
}
else
{
--pos;
render_bounds result(pos->bounds);
result.x0 += pos->delta.x0 * (state - pos->state);
result.x1 += pos->delta.x1 * (state - pos->state);
result.y0 += pos->delta.y0 * (state - pos->state);
result.y1 += pos->delta.y1 * (state - pos->state);
return result;
}
return interpolate_bounds(m_bounds, state);
}
@ -3032,26 +3105,7 @@ render_bounds layout_element::component::bounds(int state) const
render_color layout_element::component::color(int state) const
{
auto pos(
std::lower_bound(
m_color.begin(),
m_color.end(),
state,
[] (color_step const &lhs, int rhs) { return lhs.state < rhs; }));
if (m_color.begin() == pos)
{
return pos->color;
}
else
{
--pos;
render_color result(pos->color);
result.a += pos->delta.a * (state - pos->state);
result.r += pos->delta.r * (state - pos->state);
result.g += pos->delta.g * (state - pos->state);
result.b += pos->delta.b * (state - pos->state);
return result;
}
return interpolate_color(m_color, state);
}
@ -3532,21 +3586,23 @@ void layout_view::recompute(u32 visibility_mask, bool zoom_to_screen)
{
if ((visibility_mask & curitem.visibility_mask()) == curitem.visibility_mask())
{
render_bounds const rawbounds = accumulate_bounds(curitem.m_rawbounds);
// accumulate bounds
m_visible_items.emplace_back(curitem);
if (first)
m_bounds = curitem.m_rawbounds;
m_bounds = rawbounds;
else
union_render_bounds(m_bounds, curitem.m_rawbounds);
union_render_bounds(m_bounds, rawbounds);
first = false;
// accumulate visible screens and their bounds bounds
if (curitem.screen())
{
if (scrfirst)
scrbounds = curitem.m_rawbounds;
scrbounds = rawbounds;
else
union_render_bounds(scrbounds, curitem.m_rawbounds);
union_render_bounds(scrbounds, rawbounds);
scrfirst = false;
// accumulate active screens
@ -3591,10 +3647,8 @@ void layout_view::recompute(u32 visibility_mask, bool zoom_to_screen)
// normalize all the item bounds
for (item &curitem : items())
{
curitem.m_bounds.x0 = target_bounds.x0 + (curitem.m_rawbounds.x0 - xoffs) * xscale;
curitem.m_bounds.x1 = target_bounds.x0 + (curitem.m_rawbounds.x1 - xoffs) * xscale;
curitem.m_bounds.y0 = target_bounds.y0 + (curitem.m_rawbounds.y0 - yoffs) * yscale;
curitem.m_bounds.y1 = target_bounds.y0 + (curitem.m_rawbounds.y1 - yoffs) * yscale;
curitem.m_bounds = curitem.m_rawbounds;
normalize_bounds(curitem.m_bounds, target_bounds.x0, target_bounds.y0, xoffs, yoffs, xscale, yscale);
}
// sort edges of interactive items
@ -3605,12 +3659,13 @@ void layout_view::recompute(u32 visibility_mask, bool zoom_to_screen)
for (unsigned i = 0; m_interactive_items.size() > i; ++i)
{
item &curitem(m_interactive_items[i]);
render_bounds const curbounds(accumulate_bounds(curitem.m_bounds));
LOGMASKED(LOG_INTERACTIVE_ITEMS, "%u: (%s %s %s %s) hasinput=%s clickthrough=%s\n",
i, curitem.bounds().x0, curitem.bounds().y0, curitem.bounds().x1, curitem.bounds().y1, curitem.has_input(), curitem.clickthrough());
m_interactive_edges_x.emplace_back(i, curitem.bounds().x0, false);
m_interactive_edges_x.emplace_back(i, curitem.bounds().x1, true);
m_interactive_edges_y.emplace_back(i, curitem.bounds().y0, false);
m_interactive_edges_y.emplace_back(i, curitem.bounds().y1, true);
i, curbounds.x0, curbounds.y0, curbounds.x1, curbounds.y1, curitem.has_input(), curitem.clickthrough());
m_interactive_edges_x.emplace_back(i, curbounds.x0, false);
m_interactive_edges_x.emplace_back(i, curbounds.x1, true);
m_interactive_edges_y.emplace_back(i, curbounds.y0, false);
m_interactive_edges_y.emplace_back(i, curbounds.y1, true);
}
std::sort(m_interactive_edges_x.begin(), m_interactive_edges_x.end());
std::sort(m_interactive_edges_y.begin(), m_interactive_edges_y.end());
@ -3771,7 +3826,7 @@ void layout_view::add_items(
groupmap,
orientation_add(grouporient, orientation),
grouptrans,
render_color_multiply(env.parse_color(itemnode->get_child("color")), color),
env.parse_color(itemnode->get_child("color")) * color,
false,
false,
true);
@ -3854,7 +3909,9 @@ layout_view::item::item(
render_color const &color)
: m_element(find_element(env, itemnode, elemmap))
, m_output(env.device(), env.get_attribute_string(itemnode, "name", ""))
, m_animoutput(env.device(), make_animoutput_tag(env, itemnode))
, m_have_output(env.get_attribute_string(itemnode, "name", "")[0])
, m_have_animoutput(!make_animoutput_tag(env, itemnode).empty())
, m_input_port(nullptr)
, m_input_field(nullptr)
, m_input_mask(env.get_attribute_int(itemnode, "inputmask", 0))
@ -3863,7 +3920,7 @@ layout_view::item::item(
, m_clickthrough(env.get_attribute_bool(itemnode, "clickthrough", "yes"))
, m_screen(nullptr)
, m_orientation(orientation_add(env.parse_orientation(itemnode.get_child("orientation")), orientation))
, m_color(render_color_multiply(env.parse_color(itemnode.get_child("color")), color))
, m_color(make_color(env, itemnode, color))
, m_blend_mode(get_blend_mode(env, itemnode))
, m_visibility_mask(env.visibility_mask())
, m_input_tag(make_input_tag(env, itemnode))
@ -3907,13 +3964,28 @@ layout_view::item::~item()
//-------------------------------------------------
// screen_container - retrieve screen container
// bounds - get bounds for current state
//-------------------------------------------------
render_container *layout_view::item::screen_container(running_machine &machine) const
render_bounds layout_view::item::bounds() const
{
return (m_screen != nullptr) ? &m_screen->container() : nullptr;
if (m_bounds.size() == 1U)
return m_bounds.front().bounds;
else
return interpolate_bounds(m_bounds, m_have_animoutput ? s32(m_animoutput) : state());
}
//-------------------------------------------------
// color - get color for current state
//-------------------------------------------------
render_color layout_view::item::color() const
{
if (m_color.size() == 1U)
return m_color.front().color;
else
return interpolate_color(m_color, m_have_animoutput ? s32(m_animoutput) : state());
}
@ -3963,6 +4035,9 @@ void layout_view::item::resolve_tags()
m_output = m_element->default_state();
}
if (m_have_animoutput)
m_animoutput.resolve();
if (!m_input_tag.empty())
{
m_input_port = m_element->machine().root_device().ioport(m_input_tag);
@ -4010,19 +4085,74 @@ layout_element *layout_view::item::find_element(view_environment &env, util::xml
// make_bounds - get transformed bounds
//---------------------------------------------
render_bounds 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)
{
render_bounds bounds;
env.parse_bounds(itemnode.get_child("bounds"), bounds);
render_bounds_transform(bounds, trans);
if (bounds.x0 > bounds.x1)
std::swap(bounds.x0, bounds.x1);
if (bounds.y0 > bounds.y1)
std::swap(bounds.y0, bounds.y1);
return bounds;
bounds_vector result;
for (util::xml::data_node const *bounds = itemnode.get_child("bounds"); bounds; bounds = bounds->get_next_sibling("bounds"))
{
if (!add_bounds_step(env, result, *bounds))
{
throw layout_syntax_error(
util::string_format(
"%s item has duplicate bounds for state",
itemnode.get_name()));
}
}
for (emu::render::detail::bounds_step &step : result)
{
render_bounds_transform(step.bounds, trans);
if (step.bounds.x0 > step.bounds.x1)
std::swap(step.bounds.x0, step.bounds.x1);
if (step.bounds.y0 > step.bounds.y1)
std::swap(step.bounds.y0, step.bounds.y1);
}
set_bounds_deltas(result);
return result;
}
//---------------------------------------------
// make_color - get color inflection points
//---------------------------------------------
layout_view::item::color_vector layout_view::item::make_color(
view_environment &env,
util::xml::data_node const &itemnode,
render_color const &mult)
{
color_vector result;
for (util::xml::data_node const *color = itemnode.get_child("color"); color; color = color->get_next_sibling("color"))
{
if (!add_color_step(env, result, *color))
{
throw layout_syntax_error(
util::string_format(
"%s item has duplicate color for state",
itemnode.get_name()));
}
}
for (emu::render::detail::color_step &step : result)
step.color *= mult;
set_color_deltas(result);
return result;
}
//---------------------------------------------
// 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 env.get_attribute_string(*animate, "name", "");
else
return std::string();
}

View File

@ -31,7 +31,6 @@ namespace {
***************************************************************************/
constexpr unsigned TEMP_BUFFER_SIZE(4096U);
std::locale const f_portable_locale("C");
/***************************************************************************
@ -629,7 +628,7 @@ long long data_node::get_attribute_int(const char *attribute, long long defvalue
return defvalue;
std::istringstream stream;
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
long long result;
if (string[0] == '$')
{
@ -694,7 +693,7 @@ float data_node::get_attribute_float(const char *attribute, float defvalue) cons
return defvalue;
std::istringstream stream(string);
stream.imbue(f_portable_locale);
stream.imbue(std::locale::classic());
float result;
return (stream >> result) ? result : defvalue;
}
@ -732,7 +731,7 @@ void data_node::set_attribute(const char *name, const char *value)
void data_node::set_attribute_int(const char *name, long long value)
{
set_attribute(name, string_format(f_portable_locale, "%d", value).c_str());
set_attribute(name, string_format(std::locale::classic(), "%d", value).c_str());
}
@ -743,7 +742,7 @@ void data_node::set_attribute_int(const char *name, long long value)
void data_node::set_attribute_float(const char *name, float value)
{
set_attribute(name, string_format(f_portable_locale, "%f", value).c_str());
set_attribute(name, string_format(std::locale::classic(), "%f", value).c_str());
}

View File

@ -253,213 +253,12 @@ license:CC0
</disk>
</element>
<element name="ani_white" defstate="0">
<rect><bounds x="0" y="0" width="1" height="100" /><color alpha="0" /></rect>
<rect state="1"><bounds x="0" y="0" width="1" height="1" /><color red="1" green="1" blue="1" /></rect>
<rect state="2"><bounds x="0" y="0" width="1" height="2" /><color red="1" green="1" blue="1" /></rect>
<rect state="3"><bounds x="0" y="0" width="1" height="3" /><color red="1" green="1" blue="1" /></rect>
<rect state="4"><bounds x="0" y="0" width="1" height="4" /><color red="1" green="1" blue="1" /></rect>
<rect state="5"><bounds x="0" y="0" width="1" height="5" /><color red="1" green="1" blue="1" /></rect>
<rect state="6"><bounds x="0" y="0" width="1" height="6" /><color red="1" green="1" blue="1" /></rect>
<rect state="7"><bounds x="0" y="0" width="1" height="7" /><color red="1" green="1" blue="1" /></rect>
<rect state="8"><bounds x="0" y="0" width="1" height="8" /><color red="1" green="1" blue="1" /></rect>
<rect state="9"><bounds x="0" y="0" width="1" height="9" /><color red="1" green="1" blue="1" /></rect>
<rect state="10"><bounds x="0" y="0" width="1" height="10" /><color red="1" green="1" blue="1" /></rect>
<rect state="11"><bounds x="0" y="0" width="1" height="11" /><color red="1" green="1" blue="1" /></rect>
<rect state="12"><bounds x="0" y="0" width="1" height="12" /><color red="1" green="1" blue="1" /></rect>
<rect state="13"><bounds x="0" y="0" width="1" height="13" /><color red="1" green="1" blue="1" /></rect>
<rect state="14"><bounds x="0" y="0" width="1" height="14" /><color red="1" green="1" blue="1" /></rect>
<rect state="15"><bounds x="0" y="0" width="1" height="15" /><color red="1" green="1" blue="1" /></rect>
<rect state="16"><bounds x="0" y="0" width="1" height="16" /><color red="1" green="1" blue="1" /></rect>
<rect state="17"><bounds x="0" y="0" width="1" height="17" /><color red="1" green="1" blue="1" /></rect>
<rect state="18"><bounds x="0" y="0" width="1" height="18" /><color red="1" green="1" blue="1" /></rect>
<rect state="19"><bounds x="0" y="0" width="1" height="19" /><color red="1" green="1" blue="1" /></rect>
<rect state="20"><bounds x="0" y="0" width="1" height="20" /><color red="1" green="1" blue="1" /></rect>
<rect state="21"><bounds x="0" y="0" width="1" height="21" /><color red="1" green="1" blue="1" /></rect>
<rect state="22"><bounds x="0" y="0" width="1" height="22" /><color red="1" green="1" blue="1" /></rect>
<rect state="23"><bounds x="0" y="0" width="1" height="23" /><color red="1" green="1" blue="1" /></rect>
<rect state="24"><bounds x="0" y="0" width="1" height="24" /><color red="1" green="1" blue="1" /></rect>
<rect state="25"><bounds x="0" y="0" width="1" height="25" /><color red="1" green="1" blue="1" /></rect>
<rect state="26"><bounds x="0" y="0" width="1" height="26" /><color red="1" green="1" blue="1" /></rect>
<rect state="27"><bounds x="0" y="0" width="1" height="27" /><color red="1" green="1" blue="1" /></rect>
<rect state="28"><bounds x="0" y="0" width="1" height="28" /><color red="1" green="1" blue="1" /></rect>
<rect state="29"><bounds x="0" y="0" width="1" height="29" /><color red="1" green="1" blue="1" /></rect>
<rect state="30"><bounds x="0" y="0" width="1" height="30" /><color red="1" green="1" blue="1" /></rect>
<rect state="31"><bounds x="0" y="0" width="1" height="31" /><color red="1" green="1" blue="1" /></rect>
<rect state="32"><bounds x="0" y="0" width="1" height="32" /><color red="1" green="1" blue="1" /></rect>
<rect state="33"><bounds x="0" y="0" width="1" height="33" /><color red="1" green="1" blue="1" /></rect>
<rect state="34"><bounds x="0" y="0" width="1" height="34" /><color red="1" green="1" blue="1" /></rect>
<rect state="35"><bounds x="0" y="0" width="1" height="35" /><color red="1" green="1" blue="1" /></rect>
<rect state="36"><bounds x="0" y="0" width="1" height="36" /><color red="1" green="1" blue="1" /></rect>
<rect state="37"><bounds x="0" y="0" width="1" height="37" /><color red="1" green="1" blue="1" /></rect>
<rect state="38"><bounds x="0" y="0" width="1" height="38" /><color red="1" green="1" blue="1" /></rect>
<rect state="39"><bounds x="0" y="0" width="1" height="39" /><color red="1" green="1" blue="1" /></rect>
<rect state="40"><bounds x="0" y="0" width="1" height="40" /><color red="1" green="1" blue="1" /></rect>
<rect state="41"><bounds x="0" y="0" width="1" height="41" /><color red="1" green="1" blue="1" /></rect>
<rect state="42"><bounds x="0" y="0" width="1" height="42" /><color red="1" green="1" blue="1" /></rect>
<rect state="43"><bounds x="0" y="0" width="1" height="43" /><color red="1" green="1" blue="1" /></rect>
<rect state="44"><bounds x="0" y="0" width="1" height="44" /><color red="1" green="1" blue="1" /></rect>
<rect state="45"><bounds x="0" y="0" width="1" height="45" /><color red="1" green="1" blue="1" /></rect>
<rect state="46"><bounds x="0" y="0" width="1" height="46" /><color red="1" green="1" blue="1" /></rect>
<rect state="47"><bounds x="0" y="0" width="1" height="47" /><color red="1" green="1" blue="1" /></rect>
<rect state="48"><bounds x="0" y="0" width="1" height="48" /><color red="1" green="1" blue="1" /></rect>
<rect state="49"><bounds x="0" y="0" width="1" height="49" /><color red="1" green="1" blue="1" /></rect>
<rect state="50"><bounds x="0" y="0" width="1" height="50" /><color red="1" green="1" blue="1" /></rect>
<rect state="51"><bounds x="0" y="0" width="1" height="51" /><color red="1" green="1" blue="1" /></rect>
<rect state="52"><bounds x="0" y="0" width="1" height="52" /><color red="1" green="1" blue="1" /></rect>
<rect state="53"><bounds x="0" y="0" width="1" height="53" /><color red="1" green="1" blue="1" /></rect>
<rect state="54"><bounds x="0" y="0" width="1" height="54" /><color red="1" green="1" blue="1" /></rect>
<rect state="55"><bounds x="0" y="0" width="1" height="55" /><color red="1" green="1" blue="1" /></rect>
<rect state="56"><bounds x="0" y="0" width="1" height="56" /><color red="1" green="1" blue="1" /></rect>
<rect state="57"><bounds x="0" y="0" width="1" height="57" /><color red="1" green="1" blue="1" /></rect>
<rect state="58"><bounds x="0" y="0" width="1" height="58" /><color red="1" green="1" blue="1" /></rect>
<rect state="59"><bounds x="0" y="0" width="1" height="59" /><color red="1" green="1" blue="1" /></rect>
<rect state="60"><bounds x="0" y="0" width="1" height="60" /><color red="1" green="1" blue="1" /></rect>
<rect state="61"><bounds x="0" y="0" width="1" height="61" /><color red="1" green="1" blue="1" /></rect>
<rect state="62"><bounds x="0" y="0" width="1" height="62" /><color red="1" green="1" blue="1" /></rect>
<rect state="63"><bounds x="0" y="0" width="1" height="63" /><color red="1" green="1" blue="1" /></rect>
<rect state="64"><bounds x="0" y="0" width="1" height="64" /><color red="1" green="1" blue="1" /></rect>
<rect state="65"><bounds x="0" y="0" width="1" height="65" /><color red="1" green="1" blue="1" /></rect>
<rect state="66"><bounds x="0" y="0" width="1" height="66" /><color red="1" green="1" blue="1" /></rect>
<rect state="67"><bounds x="0" y="0" width="1" height="67" /><color red="1" green="1" blue="1" /></rect>
<rect state="68"><bounds x="0" y="0" width="1" height="68" /><color red="1" green="1" blue="1" /></rect>
<rect state="69"><bounds x="0" y="0" width="1" height="69" /><color red="1" green="1" blue="1" /></rect>
<rect state="70"><bounds x="0" y="0" width="1" height="70" /><color red="1" green="1" blue="1" /></rect>
<rect state="71"><bounds x="0" y="0" width="1" height="71" /><color red="1" green="1" blue="1" /></rect>
<rect state="72"><bounds x="0" y="0" width="1" height="72" /><color red="1" green="1" blue="1" /></rect>
<rect state="73"><bounds x="0" y="0" width="1" height="73" /><color red="1" green="1" blue="1" /></rect>
<rect state="74"><bounds x="0" y="0" width="1" height="74" /><color red="1" green="1" blue="1" /></rect>
<rect state="75"><bounds x="0" y="0" width="1" height="75" /><color red="1" green="1" blue="1" /></rect>
<rect state="76"><bounds x="0" y="0" width="1" height="76" /><color red="1" green="1" blue="1" /></rect>
<rect state="77"><bounds x="0" y="0" width="1" height="77" /><color red="1" green="1" blue="1" /></rect>
<rect state="78"><bounds x="0" y="0" width="1" height="78" /><color red="1" green="1" blue="1" /></rect>
<rect state="79"><bounds x="0" y="0" width="1" height="79" /><color red="1" green="1" blue="1" /></rect>
<rect state="80"><bounds x="0" y="0" width="1" height="80" /><color red="1" green="1" blue="1" /></rect>
<rect state="81"><bounds x="0" y="0" width="1" height="81" /><color red="1" green="1" blue="1" /></rect>
<rect state="82"><bounds x="0" y="0" width="1" height="82" /><color red="1" green="1" blue="1" /></rect>
<rect state="83"><bounds x="0" y="0" width="1" height="83" /><color red="1" green="1" blue="1" /></rect>
<rect state="84"><bounds x="0" y="0" width="1" height="84" /><color red="1" green="1" blue="1" /></rect>
<rect state="85"><bounds x="0" y="0" width="1" height="85" /><color red="1" green="1" blue="1" /></rect>
<rect state="86"><bounds x="0" y="0" width="1" height="86" /><color red="1" green="1" blue="1" /></rect>
<rect state="87"><bounds x="0" y="0" width="1" height="87" /><color red="1" green="1" blue="1" /></rect>
<rect state="88"><bounds x="0" y="0" width="1" height="88" /><color red="1" green="1" blue="1" /></rect>
<rect state="89"><bounds x="0" y="0" width="1" height="89" /><color red="1" green="1" blue="1" /></rect>
<rect state="90"><bounds x="0" y="0" width="1" height="90" /><color red="1" green="1" blue="1" /></rect>
<rect state="91"><bounds x="0" y="0" width="1" height="91" /><color red="1" green="1" blue="1" /></rect>
<rect state="92"><bounds x="0" y="0" width="1" height="92" /><color red="1" green="1" blue="1" /></rect>
<rect state="93"><bounds x="0" y="0" width="1" height="93" /><color red="1" green="1" blue="1" /></rect>
<rect state="94"><bounds x="0" y="0" width="1" height="94" /><color red="1" green="1" blue="1" /></rect>
<rect state="95"><bounds x="0" y="0" width="1" height="95" /><color red="1" green="1" blue="1" /></rect>
<rect state="96"><bounds x="0" y="0" width="1" height="96" /><color red="1" green="1" blue="1" /></rect>
<rect state="97"><bounds x="0" y="0" width="1" height="97" /><color red="1" green="1" blue="1" /></rect>
<rect state="98"><bounds x="0" y="0" width="1" height="98" /><color red="1" green="1" blue="1" /></rect>
<rect state="99"><bounds x="0" y="0" width="1" height="99" /><color red="1" green="1" blue="1" /></rect>
<rect state="100"><bounds x="0" y="0" width="1" height="100" /><color red="1" green="1" blue="1" /></rect>
<element name="crate" defstate="0">
<rect><color red="0.75" green="0.1" blue="0.15" /></rect>
</element>
<element name="ani_crate" defstate="0">
<rect><bounds x="0" y="0" width="1" height="110" /><color alpha="0" /></rect>
<rect state="0"><bounds x="0" y="0" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="1"><bounds x="0" y="1" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="2"><bounds x="0" y="2" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="3"><bounds x="0" y="3" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="4"><bounds x="0" y="4" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="5"><bounds x="0" y="5" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="6"><bounds x="0" y="6" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="7"><bounds x="0" y="7" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="8"><bounds x="0" y="8" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="9"><bounds x="0" y="9" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="10"><bounds x="0" y="10" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="11"><bounds x="0" y="11" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="12"><bounds x="0" y="12" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="13"><bounds x="0" y="13" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="14"><bounds x="0" y="14" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="15"><bounds x="0" y="15" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="16"><bounds x="0" y="16" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="17"><bounds x="0" y="17" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="18"><bounds x="0" y="18" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="19"><bounds x="0" y="19" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="20"><bounds x="0" y="20" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="21"><bounds x="0" y="21" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="22"><bounds x="0" y="22" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="23"><bounds x="0" y="23" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="24"><bounds x="0" y="24" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="25"><bounds x="0" y="25" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="26"><bounds x="0" y="26" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="27"><bounds x="0" y="27" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="28"><bounds x="0" y="28" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="29"><bounds x="0" y="29" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="30"><bounds x="0" y="30" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="31"><bounds x="0" y="31" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="32"><bounds x="0" y="32" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="33"><bounds x="0" y="33" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="34"><bounds x="0" y="34" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="35"><bounds x="0" y="35" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="36"><bounds x="0" y="36" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="37"><bounds x="0" y="37" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="38"><bounds x="0" y="38" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="39"><bounds x="0" y="39" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="40"><bounds x="0" y="40" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="41"><bounds x="0" y="41" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="42"><bounds x="0" y="42" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="43"><bounds x="0" y="43" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="44"><bounds x="0" y="44" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="45"><bounds x="0" y="45" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="46"><bounds x="0" y="46" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="47"><bounds x="0" y="47" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="48"><bounds x="0" y="48" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="49"><bounds x="0" y="49" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="50"><bounds x="0" y="50" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="51"><bounds x="0" y="51" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="52"><bounds x="0" y="52" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="53"><bounds x="0" y="53" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="54"><bounds x="0" y="54" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="55"><bounds x="0" y="55" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="56"><bounds x="0" y="56" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="57"><bounds x="0" y="57" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="58"><bounds x="0" y="58" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="59"><bounds x="0" y="59" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="60"><bounds x="0" y="60" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="61"><bounds x="0" y="61" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="62"><bounds x="0" y="62" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="63"><bounds x="0" y="63" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="64"><bounds x="0" y="64" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="65"><bounds x="0" y="65" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="66"><bounds x="0" y="66" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="67"><bounds x="0" y="67" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="68"><bounds x="0" y="68" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="69"><bounds x="0" y="69" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="70"><bounds x="0" y="70" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="71"><bounds x="0" y="71" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="72"><bounds x="0" y="72" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="73"><bounds x="0" y="73" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="74"><bounds x="0" y="74" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="75"><bounds x="0" y="75" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="76"><bounds x="0" y="76" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="77"><bounds x="0" y="77" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="78"><bounds x="0" y="78" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="79"><bounds x="0" y="79" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="80"><bounds x="0" y="80" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="81"><bounds x="0" y="81" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="82"><bounds x="0" y="82" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="83"><bounds x="0" y="83" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="84"><bounds x="0" y="84" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="85"><bounds x="0" y="85" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="86"><bounds x="0" y="86" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="87"><bounds x="0" y="87" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="88"><bounds x="0" y="88" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="89"><bounds x="0" y="89" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="90"><bounds x="0" y="90" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="91"><bounds x="0" y="91" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="92"><bounds x="0" y="92" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="93"><bounds x="0" y="93" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="94"><bounds x="0" y="94" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="95"><bounds x="0" y="95" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="96"><bounds x="0" y="96" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="97"><bounds x="0" y="97" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="98"><bounds x="0" y="98" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="99"><bounds x="0" y="99" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<rect state="100"><bounds x="0" y="100" width="1" height="10" /><color red="0.75" green="0.1" blue="0.15" /></rect>
<element name="door" defstate="0">
<rect><color red="0.75" green="0.75" blue="0.75" /></rect>
</element>
@ -525,37 +324,48 @@ license:CC0
<element ref="blue"><bounds x="7" y="5" width="48" height="3" /></element>
<element ref="black"><bounds x="7" y="5" width="48" height="1.5" /></element>
<!-- unable to move the cosmogangs with artwork, have to do it like this with 'fishing lines' -->
<repeat count="5">
<param name="x" start="12.6" increment="9" />
<param name="i" start="0" increment="1" />
<element ref="gray2"><bounds x="~x~" y="17" width="0.8" height="38.5" /></element>
<element name="cg_count~i~" ref="ani_white"><bounds x="~x~" y="17" width="0.8" height="35" /><color alpha="0.5" /></element>
</repeat>
<repeat count="5">
<param name="x" start="10" increment="9" />
<param name="i" start="0" increment="1" />
<param name="mask" start="0x01" lshift="1" />
<element name="cg_sol~i~" ref="cosmo">
<animate name="cg_count~i~" />
<bounds state="0" x="~x~" y="10" width="6" height="7" />
<bounds state="100" x="~x~" y="48.5" width="6" height="7" />
</element>
<element ref="nothing" inputtag="FAKE1" inputmask="~mask~">
<animate name="cg_count~i~" />
<bounds state="0" x="~x~" y="10" width="6" height="7" />
<bounds state="100" x="~x~" y="48.5" width="6" height="7" />
</element>
</repeat>
<repeat count="5">
<param name="x" start="11.2" increment="9" />
<param name="i" start="0" increment="1" />
<element name="en_count~i~" ref="ani_crate"><bounds x="~x~" y="17" width="3.6" height="38.5" /></element>
<element ref="crate">
<animate name="en_count~i~" />
<bounds state="0" x="~x~" y="13.5" width="3.6" height="3.5" />
<bounds state="100" x="~x~" y="52" width="3.6" height="3.5" />
</element>
</repeat>
<repeat count="5">
<param name="x" start="10" increment="9" />
<param name="i" start="0" increment="1" />
<element name="cg_sol~i~" ref="cosmo"><bounds x="~x~" y="10" width="6" height="7" /></element>
</repeat>
<repeat count="5">
<param name="x" start="10" increment="9" />
<param name="mask" start="0x01" lshift="1" />
<element ref="nothing" blend="add" inputtag="FAKE1" inputmask="~mask~"><bounds x="~x~" y="10" width="6" height="45.5" /></element>
</repeat>
<element name="door_count" ref="ani_white"><bounds x="8.5" y="8" width="45" height="9" /><color alpha="0.3" /></element>
<element ref="door">
<animate name="door_count" />
<bounds state="0" x="8.5" y="8" width="45" height="0" />
<bounds state="100" x="8.5" y="8" width="45" height="9" />
<color alpha="0.6" />
</element>
</group>