diff --git a/src/user/user_objects.cc b/src/user/user_objects.cc index 066b7159..4c084b22 100644 --- a/src/user/user_objects.cc +++ b/src/user/user_objects.cc @@ -845,6 +845,12 @@ mjCBody& mjCBody::operator+=(const mjCBody& other) { // attach frame to body mjCBody& mjCBody::operator+=(const mjCFrame& other) { + // append a copy of the attached spec + if (other.model != model && !model->FindSpec(mjs_getString(other.model->spec.modelname))) { + model->AppendSpec(mj_copySpec(&other.model->spec)); + } + + // create a copy of the subtree that contains the frame mjCBody* subtree = other.body; other.model->prefix = other.prefix; other.model->suffix = other.suffix; @@ -1805,6 +1811,12 @@ mjCFrame& mjCFrame::operator=(const mjCFrame& other) { // attach body to frame mjCFrame& mjCFrame::operator+=(const mjCBody& other) { + // append a copy of the attached spec + if (other.model != model && !model->FindSpec(mjs_getString(other.model->spec.modelname))) { + model->AppendSpec(mj_copySpec(&other.model->spec)); + } + + // apply namespace and store keyframes in the source model other.model->prefix = other.prefix; other.model->suffix = other.suffix; other.model->StoreKeyframes(model); diff --git a/test/user/user_api_test.cc b/test/user/user_api_test.cc index 23521001..7922d1d8 100644 --- a/test/user/user_api_test.cc +++ b/test/user/user_api_test.cc @@ -624,7 +624,7 @@ TEST_F(PluginTest, TextureFromBuffer) { // -------------------------------- test attach -------------------------------- static constexpr char xml_child[] = R"( - + @@ -691,7 +691,7 @@ TEST_F(MujocoTest, AttachSame) { std::string field = ""; static constexpr char xml_result[] = R"( - + @@ -781,6 +781,9 @@ TEST_F(MujocoTest, AttachSame) { mjsBody* attached = mjs_attachBody(frame, body, "attached-", "-1"); EXPECT_THAT(attached, mjs_findBody(parent, "attached-body-1")); + // check that the spec was not copied + EXPECT_THAT(mjs_findSpec(parent, "child"), IsNull()); + // compile new model mjModel* m_attached = mj_compile(parent, 0); EXPECT_THAT(m_attached, NotNull()); @@ -912,6 +915,9 @@ TEST_F(MujocoTest, AttachDifferent) { mjsBody* attached = mjs_attachBody(frame, body, "attached-", "-1"); EXPECT_THAT(attached, mjs_findBody(parent, "attached-body-1")); + // check that the spec was copied + EXPECT_THAT(mjs_findSpec(parent, "child"), NotNull()); + // compile new model mjModel* m_attached = mj_compile(parent, 0); EXPECT_THAT(m_attached, NotNull()); @@ -1043,6 +1049,9 @@ TEST_F(MujocoTest, AttachFrame) { mjsFrame* attached = mjs_attachFrame(body, frame, "attached-", "-1"); EXPECT_THAT(attached, mjs_findFrame(parent, "attached-pframe-1")); + // check that the spec was copied + EXPECT_THAT(mjs_findSpec(parent, "child"), NotNull()); + // compile new model mjModel* m_attached = mj_compile(parent, 0); EXPECT_THAT(m_attached, NotNull()); @@ -1073,7 +1082,7 @@ void TestDetachBody(bool compile) { std::string field = ""; static constexpr char xml_result[] = R"( - +