Replace mjs_detachBody and mjs_detachDefault with mjs_detach.

In a follow-up, mjs_detach will be changed to only remove without deleting an element.

PiperOrigin-RevId: 773637351
Change-Id: I9ee4d3584ba88ccc225591337cf036bab806e25c
This commit is contained in:
Alessio Quaglino
2025-06-20 04:11:14 -07:00
committed by Copybara-Service
parent 4ce6293217
commit 0488d9f4eb
15 changed files with 177 additions and 179 deletions
+25 -33
View File
@@ -284,35 +284,18 @@ const char* mjs_getError(mjSpec* s) {
// detach body from mjSpec, return 0 on success
int mjs_detachBody(mjSpec* s, mjsBody* b) {
int mjs_detach(mjSpec* s, mjsElement* element) {
mjCModel* model = static_cast<mjCModel*>(s->element);
mjCBody* body = static_cast<mjCBody*>(b->element);
try {
*model -= *body;
} catch (mjCError& e) {
model->SetError(e);
if (!element) {
model->SetError(mjCError(0, "Element is null."));
return -1;
}
model->Detach(body);
return 0;
mjCError e(0, "Detach is not implemented yet.");
model->SetError(e);
return -1;
}
// detach default from mjSpec, return 0 on success
int mjs_detachDefault(mjSpec* s, mjsDefault* def) {
mjCModel* modelC = static_cast<mjCModel*>(s->element);
if (!def) {
modelC->SetError(mjCError(0, "Cannot detach, default is null"));
return -1;
}
mjCDef* defC = static_cast<mjCDef*>(def->element);
try {
*modelC -= *defC;
} catch (mjCError& e) {
modelC->SetError(e);
return -1;
}
return 0;
}
// check if model has warnings
int mjs_isWarning(mjSpec* s) {
@@ -372,15 +355,24 @@ int mj_copyBack(mjSpec* s, const mjModel* m) {
// delete object, return 0 on success
int mjs_delete(mjsElement* element) {
mjCModel* model;
if (element->elemtype == mjOBJ_DEFAULT)
model = static_cast<mjCDef*>(element)->model;
else
model = static_cast<mjCBase*>(element)->model;
int mjs_delete(mjSpec* s, mjsElement* element) {
mjCModel* model = static_cast<mjCModel*>(s->element);
if (!element) {
model->SetError(mjCError(0, "Element is null."));
return -1;
}
try {
// it will call the appropriate destructor since ~mjCBase is virtual
model->DeleteElement(element);
if (element->elemtype == mjOBJ_BODY) {
mjCBody* body = static_cast<mjCBody*>(element);
*model -= *body;
model->DeleteElement(body);
} else if (element->elemtype == mjOBJ_DEFAULT) {
mjCDef* def = static_cast<mjCDef*>(element);
*model -= *def;
} else {
// it will call the appropriate destructor since ~mjCBase is virtual
model->DeleteElement(element);
}
return 0;
} catch (mjCError& e) {
model->SetError(e);
@@ -1035,7 +1027,7 @@ const char* mjs_resolveOrientation(double quat[4], mjtByte degree, const char* s
mjsFrame* mjs_bodyToFrame(mjsBody** body) {
mjCBody* bodyC = static_cast<mjCBody*>((*body)->element);
mjCFrame* frameC = bodyC->ToFrame();
bodyC->model->Detach(bodyC);
bodyC->model->DeleteElement((*body)->element);
*body = nullptr;
return &frameC->spec;
}
+3 -6
View File
@@ -76,11 +76,8 @@ MJAPI int mj_copyBack(mjSpec* s, const mjModel* m);
MJAPI mjsElement* mjs_attach(mjsElement* parent, const mjsElement* child,
const char* prefix, const char* suffix);
// Detach body from mjSpec, remove all references and delete the body, return 0 on success.
MJAPI int mjs_detachBody(mjSpec* s, mjsBody* b);
// Detach default from mjSpec, remove all references and delete the default, return 0 on success.
MJAPI int mjs_detachDefault(mjSpec* s, mjsDefault* d);
// Detach but not delete object corresponding to the given element, return 0 on success.
MJAPI int mjs_detach(mjSpec* s, mjsElement* element);
//---------------------------------- Add tree elements ---------------------------------------------
@@ -109,7 +106,7 @@ MJAPI mjsLight* mjs_addLight(mjsBody* body, const mjsDefault* def);
MJAPI mjsFrame* mjs_addFrame(mjsBody* body, mjsFrame* parentframe);
// Delete object corresponding to the given element, return 0 on success.
MJAPI int mjs_delete(mjsElement* element);
MJAPI int mjs_delete(mjSpec* s, mjsElement* element);
//---------------------------------- Add non-tree elements -----------------------------------------
+30 -24
View File
@@ -742,15 +742,44 @@ void deletefromlist(std::vector<T*>* list, mjsElement* element) {
// recursively delete all plugins in the subtree
static void deletesubtreeplugin(mjCBody* subtree, mjCModel* model) {
mjsPlugin* plugin = &(subtree->spec.plugin);
if (plugin->active && plugin->name->empty()) {
model->DeleteElement(plugin->element);
}
for (auto* body : subtree->Bodies()) {
deletesubtreeplugin(body, model);
}
}
// discard all invalid elements from all lists
void mjCModel::DeleteElement(mjsElement* el) {
ResetTreeLists();
if (el->elemtype != mjOBJ_DEFAULT) {
if (static_cast<mjCBase*>(el)->model != this) {
throw mjCError(nullptr, "element is not in this model");
}
} else {
if (static_cast<mjCDef*>(el)->model != this) {
throw mjCError(nullptr, "default is not in this model");
}
}
switch (el->elemtype) {
case mjOBJ_BODY:
{
MakeTreeLists(); // rebuild lists that were reset at the beginning of the function
throw mjCError(nullptr, "bodies cannot be deleted, use detach instead");
mjCBody* subtree = static_cast<mjCBody*>(el);
if (subtree->GetRef() == 1) {
deletesubtreeplugin(subtree, this);
}
subtree->Release();
break;
}
case mjOBJ_DEFAULT:
MakeTreeLists(); // rebuild lists that were reset at the beginning of the function
@@ -828,29 +857,6 @@ void mjCModel::DeleteElement(mjsElement* el) {
// recursively delete all plugins in the subtree
void deletesubtreeplugin(mjCBody* subtree, mjCModel* model) {
mjsPlugin* plugin = &(subtree->spec.plugin);
if (plugin->active && plugin->name->empty()) {
model->DeleteElement(plugin->element);
}
for (auto* body : subtree->Bodies()) {
deletesubtreeplugin(body, model);
}
}
// deletes all plugins in the subtree and then the subtree itself
void mjCModel::Detach(mjCBody* subtree) {
if (subtree->GetRef() == 1) {
deletesubtreeplugin(subtree, this);
}
subtree->Release();
}
// TODO: we should not use C-type casting with multiple C++ inheritance
void mjCModel::CreateObjectLists() {
for (int i = 0; i < mjNOBJECT; ++i) {
-3
View File
@@ -232,9 +232,6 @@ class mjCModel : public mjCModel_, private mjSpec {
// delete default and all descendants
void RemoveDefault(mjCDef* def);
// detach subtree from model
void Detach(mjCBody* subtree);
// API for access to model elements (outside tree)
int NumObjects(mjtObj type); // number of objects in specified list
mjCBase* GetObject(mjtObj type, int id); // pointer to specified object
+1 -1
View File
@@ -3554,7 +3554,7 @@ void mjXReader::Body(XMLElement* section, mjsBody* body, mjsFrame* frame,
}
// delete subtree
if (mjs_detachBody(spec, subtree)) {
if (mjs_delete(spec, subtree->element)) {
throw mjXError(elem, mjs_getError(spec));
}
}