Add aliases for MjModel loading functions and expose string constants as properties.

Introduces `from_xml_path` and `from_binary_path` as more idiomatic aliases for `mj_loadXML` and `mj_loadModel` respectively. Refactors the binding of `mj*STRING` constants. Instead of exposing `get_mj*STRING` functions, these constants are now available as properties on the `Module` object. Runtime getters are added via EM_ASM to lazily call the underlying C++ functions.

PiperOrigin-RevId: 882566011
Change-Id: Id3bd5c23704fd122af30a50aed089bd3143fbc96
This commit is contained in:
Google DeepMind
2026-03-12 06:58:20 -07:00
committed by Copybara-Service
parent a62501f305
commit df0bc58578
5 changed files with 85 additions and 14 deletions
+29 -1
View File
@@ -11597,8 +11597,11 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
.property("uselimit", &MjLROpt::uselimit, &MjLROpt::set_uselimit, reference());
emscripten::class_<MjModel>("MjModel")
.class_function("mj_loadXML", emscripten::select_overload<std::unique_ptr<MjModel>(std::string)>(&mj_loadXML_wrapper_1))
.class_function("from_xml_path", emscripten::select_overload<std::unique_ptr<MjModel>(std::string)>(&mj_loadXML_wrapper_1))
.class_function("mj_loadXML", emscripten::select_overload<std::unique_ptr<MjModel>(std::string, const MjVFS&)>(&mj_loadXML_wrapper_2))
.class_function("from_xml_path", emscripten::select_overload<std::unique_ptr<MjModel>(std::string, const MjVFS&)>(&mj_loadXML_wrapper_2))
.class_function("mj_loadModel", &mj_loadModel_wrapper)
.class_function("from_binary_path", &mj_loadModel_wrapper)
.constructor<const MjModel &>()
// Binds the functions on MjModel that return accessors.
#define X_ACCESSOR(NAME, Name, OBJTYPE, field_name, nfield) \
@@ -13409,6 +13412,7 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
.function("GetView", &WasmBuffer<uint8_t>::GetView);
emscripten::register_vector<std::string>("mjStringVec");
emscripten::register_vector<std::vector<std::string>>("mjStringVecVec");
emscripten::register_vector<int>("mjIntVec");
emscripten::register_vector<mjIntVec>("mjIntVecVec");
emscripten::register_vector<float>("mjFloatVec");
@@ -13453,7 +13457,6 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
emscripten::constant("mjPI", mjPI);
emscripten::constant("mjVERSION_HEADER", mjVERSION_HEADER);
// These complex constants are bound using function() rather than constant()
emscripten::function("get_mjDISABLESTRING", &get_mjDISABLESTRING);
emscripten::function("get_mjENABLESTRING", &get_mjENABLESTRING);
emscripten::function("get_mjFRAMESTRING", &get_mjFRAMESTRING);
@@ -13461,6 +13464,31 @@ EMSCRIPTEN_BINDINGS(mujoco_bindings) {
emscripten::function("get_mjRNDSTRING", &get_mjRNDSTRING);
emscripten::function("get_mjTIMERSTRING", &get_mjTIMERSTRING);
emscripten::function("get_mjVISSTRING", &get_mjVISSTRING);
// Bind these complex constants as properties on the module object.
// We use emscripten::constant with emscripten::val::array() to type them
// as `any` in TypeScript. At runtime, the EM_ASM block below overrides
// these properties with getters that return native JavaScript arrays
// (string[] or string[][]) via the get_ functions above, which is more
// performant and idiomatic than vector wrappers.
emscripten::constant("mjDISABLESTRING", emscripten::val::array());
emscripten::constant("mjENABLESTRING", emscripten::val::array());
emscripten::constant("mjFRAMESTRING", emscripten::val::array());
emscripten::constant("mjLABELSTRING", emscripten::val::array());
emscripten::constant("mjRNDSTRING", emscripten::val::array());
emscripten::constant("mjTIMERSTRING", emscripten::val::array());
emscripten::constant("mjVISSTRING", emscripten::val::array());
EM_ASM({
if (typeof Module !== "undefined") {
"mjDISABLESTRING mjENABLESTRING mjFRAMESTRING mjLABELSTRING mjRNDSTRING mjTIMERSTRING mjVISSTRING".split(" ").forEach(function(name) {
Object.defineProperty(Module, name, {
get: function() { return Module["get_" + name](); },
set: function(v) { },
enumerable: true,
configurable: true
});
});
}
});
}
} // namespace mujoco::wasm