mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
Generate layouts for systems with three or more screens
This commit is contained in:
parent
dcc1c1ead5
commit
b75264927b
@ -60,7 +60,7 @@ public:
|
||||
static void draw_user_interface(running_machine& machine);
|
||||
static void periodic_check();
|
||||
static bool frame_hook();
|
||||
static void layout_file_cb(util::xml::data_node &layout);
|
||||
static void layout_file_cb(util::xml::data_node const &layout);
|
||||
static bool standalone();
|
||||
};
|
||||
|
||||
|
@ -1575,9 +1575,10 @@ void render_target::update_layer_config()
|
||||
void render_target::load_layout_files(const internal_layout *layoutfile, bool singlefile)
|
||||
{
|
||||
bool have_default = false;
|
||||
|
||||
// if there's an explicit file, load that first
|
||||
const char *basename = m_manager.machine().basename();
|
||||
if (layoutfile != nullptr)
|
||||
if (layoutfile)
|
||||
have_default |= load_layout_file(basename, layoutfile);
|
||||
|
||||
// if we're only loading this file, we know our final result
|
||||
@ -1606,7 +1607,8 @@ void render_target::load_layout_files(const internal_layout *layoutfile, bool si
|
||||
have_default |= true;
|
||||
}
|
||||
screen_device_iterator iter(m_manager.machine().root_device());
|
||||
int screens = iter.count();
|
||||
unsigned const screens = iter.count();
|
||||
|
||||
// now do the built-in layouts for single-screen games
|
||||
if (screens == 1)
|
||||
{
|
||||
@ -1617,6 +1619,7 @@ void render_target::load_layout_files(const internal_layout *layoutfile, bool si
|
||||
if (m_filelist.empty())
|
||||
throw emu_fatalerror("Couldn't parse default layout??");
|
||||
}
|
||||
|
||||
if (!have_default)
|
||||
{
|
||||
if (screens == 0)
|
||||
@ -1631,18 +1634,157 @@ void render_target::load_layout_files(const internal_layout *layoutfile, bool si
|
||||
if (m_filelist.empty())
|
||||
throw emu_fatalerror("Couldn't parse default layout??");
|
||||
}
|
||||
else if (screens == 3)
|
||||
}
|
||||
|
||||
// generate default layouts for larger numbers of screens
|
||||
if (screens >= 3)
|
||||
{
|
||||
util::xml::file::ptr const root(util::xml::file::create());
|
||||
if (!root)
|
||||
throw emu_fatalerror("Couldn't create XML document??");
|
||||
util::xml::data_node *const layoutnode(root->add_child("mamelayout", nullptr));
|
||||
if (!layoutnode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
layoutnode->set_attribute_int("version", 2);
|
||||
|
||||
// get standard width/height assuming 4:3 screens
|
||||
unsigned const stdwidth((system.flags & ORIENTATION_SWAP_XY) ? 3 : 4);
|
||||
unsigned const stdheight((system.flags & ORIENTATION_SWAP_XY) ? 4 : 3);
|
||||
|
||||
// generate individual 4:3 views
|
||||
for (unsigned i = 0; screens > i; ++i)
|
||||
{
|
||||
load_layout_file(nullptr, &layout_triphsxs);
|
||||
if (m_filelist.empty())
|
||||
throw emu_fatalerror("Couldn't parse default layout??");
|
||||
util::xml::data_node *const viewnode(layoutnode->add_child("view", nullptr));
|
||||
if (!viewnode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
viewnode->set_attribute("name", util::xml::normalize_string(util::string_format("Screen %1$u Standard (%2$u:%3$u)", i, stdwidth, stdheight).c_str()));
|
||||
util::xml::data_node *const screennode(viewnode->add_child("screen", nullptr));
|
||||
if (!screennode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
screennode->set_attribute_int("index", i);
|
||||
util::xml::data_node *const boundsnode(screennode->add_child("bounds", nullptr));
|
||||
if (!boundsnode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
boundsnode->set_attribute_int("x", 0);
|
||||
boundsnode->set_attribute_int("y", 0);
|
||||
boundsnode->set_attribute_int("width", stdwidth);
|
||||
boundsnode->set_attribute_int("height", stdheight);
|
||||
}
|
||||
else if (screens == 4)
|
||||
|
||||
// generate individual pixel aspect views
|
||||
for (unsigned i = 0; screens > i; ++i)
|
||||
{
|
||||
load_layout_file(nullptr, &layout_quadhsxs);
|
||||
if (m_filelist.empty())
|
||||
throw emu_fatalerror("Couldn't parse default layout??");
|
||||
util::xml::data_node *const viewnode(layoutnode->add_child("view", nullptr));
|
||||
if (!viewnode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
viewnode->set_attribute("name", util::xml::normalize_string(util::string_format("Screen %1$u Pixel Aspect (~scr%1$unativexaspect~:~scr%1$unativeyaspect~)", i).c_str()));
|
||||
util::xml::data_node *const screennode(viewnode->add_child("screen", nullptr));
|
||||
if (!screennode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
screennode->set_attribute_int("index", i);
|
||||
util::xml::data_node *const boundsnode(screennode->add_child("bounds", nullptr));
|
||||
if (!boundsnode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
boundsnode->set_attribute_int("x", 0);
|
||||
boundsnode->set_attribute_int("y", 0);
|
||||
boundsnode->set_attribute("width", util::xml::normalize_string(util::string_format("~scr%1$uwidth~", i).c_str()));
|
||||
boundsnode->set_attribute("height", util::xml::normalize_string(util::string_format("~scr%1$uheight~", i).c_str()));
|
||||
}
|
||||
|
||||
// helper for generating a view since we do this a lot
|
||||
auto const generate_view =
|
||||
[&layoutnode, screens, stdwidth, stdheight] (char const *title, auto &&bounds_callback)
|
||||
{
|
||||
util::xml::data_node *viewnode = layoutnode->add_child("view", nullptr);
|
||||
if (!viewnode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
viewnode->set_attribute("name", util::xml::normalize_string(title));
|
||||
for (unsigned i = 0; screens > i; ++i)
|
||||
{
|
||||
util::xml::data_node *const screennode(viewnode->add_child("screen", nullptr));
|
||||
if (!screennode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
screennode->set_attribute_int("index", i);
|
||||
util::xml::data_node *const boundsnode(screennode->add_child("bounds", nullptr));
|
||||
if (!boundsnode)
|
||||
throw emu_fatalerror("Couldn't create XML node??");
|
||||
bounds_callback(*boundsnode, i);
|
||||
boundsnode->set_attribute_int("width", stdwidth);
|
||||
boundsnode->set_attribute_int("height", stdheight);
|
||||
}
|
||||
};
|
||||
|
||||
// generate linear views
|
||||
generate_view(
|
||||
"Left-to-Right",
|
||||
[stdwidth] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_float("x", i * (stdwidth + 0.03f));
|
||||
boundsnode.set_attribute_int("y", 0);
|
||||
});
|
||||
generate_view(
|
||||
"Left-to-Right (Gapless)",
|
||||
[stdwidth] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_int("x", i * stdwidth);
|
||||
boundsnode.set_attribute_int("y", 0);
|
||||
});
|
||||
generate_view(
|
||||
"Top-to-Bottom",
|
||||
[stdheight] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_int("x", 0);
|
||||
boundsnode.set_attribute_float("y", i * (stdheight + 0.03f));
|
||||
});
|
||||
generate_view(
|
||||
"Top-to-Bottom (Gapless)",
|
||||
[stdheight] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_int("x", 0);
|
||||
boundsnode.set_attribute_int("y", i * stdheight);
|
||||
});
|
||||
|
||||
// generate tiled views
|
||||
for (unsigned minor = 2; ((screens + minor - 1) / minor) >= minor; ++minor)
|
||||
{
|
||||
unsigned const major((screens + minor - 1) / minor);
|
||||
unsigned const remainder(screens % major);
|
||||
if (!remainder || (((major + 1) / 2) <= remainder))
|
||||
{
|
||||
generate_view(
|
||||
util::string_format("%1$u\xC3\x97%2$u Left-to-Right, Top-to-Bottom", major, minor).c_str(),
|
||||
[major, stdwidth, stdheight] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_float("x", (i % major) * (stdwidth + 0.03f));
|
||||
boundsnode.set_attribute_float("y", (i / major) * (stdheight + 0.03f));
|
||||
});
|
||||
generate_view(
|
||||
util::string_format("%1$u\xC3\x97%2$u Left-to-Right, Top-to-Bottom (Gapless)", major, minor).c_str(),
|
||||
[major, stdwidth, stdheight] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_int("x", (i % major) * stdwidth);
|
||||
boundsnode.set_attribute_int("y", (i / major) * stdheight);
|
||||
});
|
||||
generate_view(
|
||||
util::string_format("%1$u\xC3\x97%2$u Top-to-Bottom, Left-to-Right", minor, major).c_str(),
|
||||
[major, stdwidth, stdheight] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_float("x", (i / major) * (stdwidth + 0.03f));
|
||||
boundsnode.set_attribute_float("y", (i % major) * (stdheight + 0.03f));
|
||||
});
|
||||
generate_view(
|
||||
util::string_format("%1$u\xC3\x97%2$u Top-to-Bottom, Left-to-Right (Gapless)", minor, major).c_str(),
|
||||
[major, stdwidth, stdheight] (util::xml::data_node &boundsnode, unsigned i)
|
||||
{
|
||||
boundsnode.set_attribute_int("x", (i / major) * stdwidth);
|
||||
boundsnode.set_attribute_int("y", (i % major) * stdheight);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// try to parse it
|
||||
if (!load_layout_file(nullptr, *root))
|
||||
throw emu_fatalerror("Couldn't parse generated layout??");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1729,7 +1871,7 @@ bool render_target::load_layout_file(const char *dirname, const char *filename)
|
||||
}
|
||||
|
||||
// if we didn't get a properly-formatted XML file, record a warning and exit
|
||||
if (rootnode == nullptr)
|
||||
if (!load_layout_file(dirname, *rootnode))
|
||||
{
|
||||
if (filename[0] != '<')
|
||||
osd_printf_warning("Improperly formatted XML file '%s', ignoring\n", filename);
|
||||
@ -1738,25 +1880,24 @@ bool render_target::load_layout_file(const char *dirname, const char *filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool render_target::load_layout_file(const char *dirname, util::xml::data_node const &rootnode)
|
||||
{
|
||||
// parse and catch any errors
|
||||
bool result = true;
|
||||
try
|
||||
{
|
||||
m_filelist.emplace_back(m_manager.machine(), *rootnode, dirname);
|
||||
m_filelist.emplace_back(m_manager.machine(), rootnode, dirname);
|
||||
}
|
||||
catch (emu_fatalerror &err)
|
||||
{
|
||||
if (filename[0] != '<')
|
||||
osd_printf_warning("Error in XML file '%s': %s\n", filename, err.string());
|
||||
else
|
||||
osd_printf_warning("Error in XML string: %s\n", err.string());
|
||||
result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
emulator_info::layout_file_cb(*rootnode);
|
||||
emulator_info::layout_file_cb(rootnode);
|
||||
|
||||
// free the root node
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1016,6 +1016,7 @@ private:
|
||||
void load_layout_files(const internal_layout *layoutfile, bool singlefile);
|
||||
bool load_layout_file(const char *dirname, const char *filename);
|
||||
bool load_layout_file(const char *dirname, const internal_layout *layout_data);
|
||||
bool load_layout_file(const char *dirname, util::xml::data_node const &rootnode);
|
||||
void add_container_primitives(render_primitive_list &list, const object_transform &root_xform, const object_transform &xform, render_container &container, int blendmode);
|
||||
void add_element_primitives(render_primitive_list &list, const object_transform &xform, layout_element &element, int state, int blendmode);
|
||||
bool map_point_internal(s32 target_x, s32 target_y, render_container *container, float &mapped_x, float &mapped_y, ioport_port *&mapped_input_port, ioport_value &mapped_input_mask);
|
||||
|
@ -350,13 +350,13 @@ bool emulator_info::frame_hook()
|
||||
return mame_machine_manager::instance()->lua()->frame_hook();
|
||||
}
|
||||
|
||||
void emulator_info::layout_file_cb(util::xml::data_node &layout)
|
||||
void emulator_info::layout_file_cb(util::xml::data_node const &layout)
|
||||
{
|
||||
util::xml::data_node const *const mamelayout = layout.get_child("mamelayout");
|
||||
if (mamelayout)
|
||||
{
|
||||
util::xml::data_node const *const script = mamelayout->get_child("script");
|
||||
if(script)
|
||||
if (script)
|
||||
mame_machine_manager::instance()->lua()->call_plugin_set("layout", script->get_value());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user