diff --git a/doc/changelog.rst b/doc/changelog.rst index e7bbc3a5..5d4eb3d8 100644 --- a/doc/changelog.rst +++ b/doc/changelog.rst @@ -17,6 +17,9 @@ General - The :el:`attach` element now supports self-attachment (attaching elements of the current model to itself) by omitting the :at:`model` attribute. It also supports attaching a frame via the new :at:`frame` attribute, which is mutually exclusive with :at:`body`. +- Fixed loading of ``.mjz`` archives in :ref:`simulate`: the archive was unmounted before model compilation, + so assets contained in it failed to load. Failures in the ``mjz`` decoder now emit a warning with the underlying + error instead of the generic "could not decode content" message. .. admonition:: Breaking API changes :class: attention diff --git a/simulate/main.cc b/simulate/main.cc index f7f1c3f4..e5605407 100644 --- a/simulate/main.cc +++ b/simulate/main.cc @@ -241,13 +241,21 @@ mjModel* LoadModel(const char* file, mj::Simulate& sim) { } else if (extension == ".xml") { mnew = mj_loadXML(filename, nullptr, loadError, kErrorLength); } else { - mjSpec* spec = mj_parse(filename, nullptr, nullptr, loadError, kErrorLength); + mjVFS vfs; + mj_defaultVFS(&vfs); + mjSpec* spec = mj_parse(filename, nullptr, &vfs, loadError, kErrorLength); if (!spec) { - mju::strcpy_arr(loadError, "could not parse model"); + if (!loadError[0]) { + mju::strcpy_arr(loadError, "could not parse model"); + } } else { - mnew = mj_compile(spec, nullptr); + mnew = mj_compile(spec, &vfs); + if (!mnew) { + mju::strcpy_arr(loadError, mjs_getError(spec)); + } mj_deleteSpec(spec); } + mj_deleteVFS(&vfs); } // remove trailing newline character from loadError diff --git a/src/xml/mjz/mjz_decoder.cc b/src/xml/mjz/mjz_decoder.cc index eec6a5ba..20c83dc7 100644 --- a/src/xml/mjz/mjz_decoder.cc +++ b/src/xml/mjz/mjz_decoder.cc @@ -233,9 +233,14 @@ mjPLUGIN_LIB_INIT(mjz_decoder) { if (size <= 0) { return nullptr; } - char error[1024]; - return ParseZipBuffer(buffer, size, resource->name, const_cast(vfs), - error, sizeof(error)); + char error[1024] = ""; + mjSpec* spec = ParseZipBuffer(buffer, size, resource->name, + const_cast(vfs), error, + sizeof(error)); + if (!spec && error[0]) { + mju_warning("%s", error); + } + return spec; }; mjp_registerDecoder(&decoder); }