diff options
author | Vas Crabb <vas@vastheman.com> | 2017-09-29 19:57:47 +1000 |
---|---|---|
committer | Vas Crabb <vas@vastheman.com> | 2017-09-29 19:57:47 +1000 |
commit | b75264927beafd7e872e0f5f7c70c1dee8365136 (patch) | |
tree | 3c7693be6f1a98eb8fd62cc21208dd51298e1810 | |
parent | dcc1c1ead5cd2bbb4227da17c614351f370cda66 (diff) |
Generate layouts for systems with three or more screens
-rw-r--r-- | src/emu/main.h | 2 | ||||
-rw-r--r-- | src/emu/render.cpp | 183 | ||||
-rw-r--r-- | src/emu/render.h | 1 | ||||
-rw-r--r-- | src/frontend/mame/mame.cpp | 4 |
4 files changed, 166 insertions, 24 deletions
diff --git a/src/emu/main.h b/src/emu/main.h index 9a01a73af24..0bc95eb036b 100644 --- a/src/emu/main.h +++ b/src/emu/main.h @@ -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(); }; diff --git a/src/emu/render.cpp b/src/emu/render.cpp index 31994f19595..5fa3fb5a32b 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -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; } diff --git a/src/emu/render.h b/src/emu/render.h index 9dbbb385cb2..e7ac98e8dfb 100644 --- a/src/emu/render.h +++ b/src/emu/render.h @@ -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); diff --git a/src/frontend/mame/mame.cpp b/src/frontend/mame/mame.cpp index bc9d9b334b7..8e6a0614260 100644 --- a/src/frontend/mame/mame.cpp +++ b/src/frontend/mame/mame.cpp @@ -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()); } } |